KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sch_editor_control.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) 2019-2023 CERN
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
26
27#include <clipboard.h>
28#include <core/base64.h>
29#include <algorithm>
30#include <chrono>
31#include <confirm.h>
32#include <connection_graph.h>
33#include <design_block.h>
43#include <project_rescue.h>
44#include <erc/erc.h>
45#include <invoke_sch_dialog.h>
46#include <locale_io.h>
47#include <string_utils.h>
48#include <kiway.h>
49#include <kiplatform/ui.h>
51#include <paths.h>
52#include <pgm_base.h>
55#include <project_sch.h>
57#include <richio.h>
59#include <sch_edit_frame.h>
61#include <sch_bitmap.h>
62#include <sch_group.h>
63#include <sch_line.h>
64#include <sch_junction.h>
65#include <sch_bus_entry.h>
66#include <sch_shape.h>
67#include <sch_painter.h>
68#include <sch_sheet_pin.h>
69#include <sch_table.h>
70#include <sch_tablecell.h>
71#include <sch_commit.h>
72#include <sim/simulator_frame.h>
74#include <symbol_viewer_frame.h>
75#include <tool/picker_tool.h>
76#include <tool/tool_manager.h>
77#include <tools/sch_actions.h>
78#include <tools/sch_selection.h>
84#include <view/view_controls.h>
85#include <widgets/wx_infobar.h>
87#include <wx_filename.h>
88#include <wx/filedlg.h>
89#include <wx/log.h>
90#include <wx/treectrl.h>
91#include <wx/msgdlg.h>
96#include <view/view.h>
97#include <zoom_defines.h>
99#include <gal/gal_print.h>
101#include <wx/ffile.h>
102#include <wx/filefn.h>
103#include <wx/mstream.h>
104#include <wx/clipbrd.h>
105#include <wx/imagpng.h>
106
107#ifdef KICAD_IPC_API
109#endif
110
111
117static const wxChar traceSchPaste[] = wxT( "KICAD_SCH_PASTE" );
118
119namespace
120{
121constexpr int clipboardMaxBitmapSize = 4096;
122constexpr double clipboardBboxInflation = 0.02; // Small padding around selection
123
124
125bool loadFileToBuffer( const wxString& aFileName, wxMemoryBuffer& aBuffer )
126{
127 wxFFile file( aFileName, wxS( "rb" ) );
128
129 if( !file.IsOpened() )
130 return false;
131
132 wxFileOffset size = file.Length();
133
134 if( size <= 0 )
135 return false;
136
137 void* data = aBuffer.GetWriteBuf( size );
138
139 if( file.Read( data, size ) != static_cast<size_t>( size ) )
140 {
141 aBuffer.UngetWriteBuf( 0 );
142 return false;
143 }
144
145 aBuffer.UngetWriteBuf( size );
146 return true;
147}
148
149
150std::vector<SCH_ITEM*> collectSelectionItems( const SCH_SELECTION& aSelection )
151{
152 std::vector<SCH_ITEM*> items;
153 items.reserve( aSelection.GetSize() );
154
155 for( EDA_ITEM* item : aSelection.GetItems() )
156 {
157 SCH_ITEM* schItem = dynamic_cast<SCH_ITEM*>( item );
158
159 if( schItem )
160 items.push_back( schItem );
161 }
162
163 return items;
164}
165
166
167BOX2I expandedSelectionBox( const SCH_SELECTION& aSelection )
168{
169 BOX2I bbox = aSelection.GetBoundingBox();
170
171 if( bbox.GetWidth() > 0 && bbox.GetHeight() > 0 )
172 bbox.Inflate( bbox.GetWidth() * clipboardBboxInflation,
173 bbox.GetHeight() * clipboardBboxInflation );
174
175 return bbox;
176}
177
178
179bool generateHtmlFromPngData( const wxMemoryBuffer& aPngData, wxMemoryBuffer& aHtmlBuffer )
180{
181 if( aPngData.GetDataLen() == 0 )
182 return false;
183
184 std::vector<uint8_t> pngVec( static_cast<const uint8_t*>( aPngData.GetData() ),
185 static_cast<const uint8_t*>( aPngData.GetData() ) + aPngData.GetDataLen() );
186
187 std::vector<uint8_t> base64Data;
188 base64::encode( pngVec, base64Data );
189
190 std::string html = "<img src=\"data:image/png;base64,";
191 html.append( reinterpret_cast<const char*>( base64Data.data() ), base64Data.size() );
192 html.append( "\" />" );
193
194 aHtmlBuffer.SetDataLen( 0 );
195 aHtmlBuffer.AppendData( html.data(), html.size() );
196
197 return true;
198}
199
200
201bool plotSelectionToSvg( SCH_EDIT_FRAME* aFrame, const SCH_SELECTION& aSelection, const BOX2I& aBBox,
202 wxMemoryBuffer& aBuffer )
203{
204 SCH_RENDER_SETTINGS renderSettings( *aFrame->GetRenderSettings() );
205 renderSettings.LoadColors( aFrame->GetColorSettings() );
206 renderSettings.SetDefaultFont( aFrame->eeconfig()->m_Appearance.default_font );
207 renderSettings.m_ShowHiddenPins = false;
208 renderSettings.m_ShowHiddenFields = false;
209
210 std::unique_ptr<SVG_PLOTTER> plotter = std::make_unique<SVG_PLOTTER>();
211 plotter->SetRenderSettings( &renderSettings );
212
213 PAGE_INFO pageInfo = aFrame->GetScreen()->GetPageSettings();
214 pageInfo.SetWidthMils( schIUScale.IUToMils( aBBox.GetWidth() ) );
215 pageInfo.SetHeightMils( schIUScale.IUToMils( aBBox.GetHeight() ) );
216
217 plotter->SetPageSettings( pageInfo );
218 plotter->SetColorMode( true );
219
220 VECTOR2I plot_offset = aBBox.GetOrigin();
221 plotter->SetViewport( plot_offset, schIUScale.IU_PER_MILS / 10, 1.0, false );
222 plotter->SetCreator( wxT( "Eeschema-SVG" ) );
223
224 wxFileName tempFile( wxFileName::CreateTempFileName( wxS( "kicad_svg" ) ) );
225
226 if( !plotter->OpenFile( tempFile.GetFullPath() ) )
227 {
228 wxRemoveFile( tempFile.GetFullPath() );
229 return false;
230 }
231
232 LOCALE_IO toggle;
233 SCH_PLOT_OPTS plotOpts;
234 plotOpts.m_plotHopOver = aFrame->Schematic().Settings().m_HopOverScale > 0.0;
235
236 plotter->StartPlot( wxT( "1" ) );
237 aFrame->GetScreen()->Plot( plotter.get(), plotOpts, collectSelectionItems( aSelection ) );
238 plotter->EndPlot();
239 plotter.reset();
240
241 bool ok = loadFileToBuffer( tempFile.GetFullPath(), aBuffer );
242 wxRemoveFile( tempFile.GetFullPath() );
243 return ok;
244}
245
246
252wxImage renderSelectionToBitmap( SCH_EDIT_FRAME* aFrame, const SCH_SELECTION& aSelection, const BOX2I& aBBox,
253 int aWidth, int aHeight, bool aUseAlpha, bool aIncludeDrawingSheet )
254{
255 wxImage image( aWidth, aHeight, false );
256 image.SetAlpha();
257
258 double actualPPI_x = (double) aWidth / schIUScale.IUTomm( aBBox.GetWidth() ) * 25.4;
259 double actualPPI_y = (double) aHeight / schIUScale.IUTomm( aBBox.GetHeight() ) * 25.4;
260 double actualPPI = std::max( actualPPI_x, actualPPI_y );
261
262 VECTOR2D pageSizeIn( (double) aWidth / actualPPI, (double) aHeight / actualPPI );
263
264 {
267
268 std::unique_ptr<KIGFX::CAIRO_PRINT_GAL> gal = KIGFX::CAIRO_PRINT_GAL::Create( options, &image, actualPPI );
269
270 if( !gal )
271 return wxImage();
272
273 KIGFX::PRINT_CONTEXT* printCtx = gal->GetPrintCtx();
274 std::unique_ptr<KIGFX::SCH_PAINTER> painter = std::make_unique<KIGFX::SCH_PAINTER>( gal.get() );
275 std::unique_ptr<KIGFX::VIEW> view = std::make_unique<KIGFX::VIEW>();
276
277 painter->SetSchematic( &aFrame->Schematic() );
278 view->SetGAL( gal.get() );
279 view->SetPainter( painter.get() );
280 view->SetScaleLimits( ZOOM_MAX_LIMIT_EESCHEMA, ZOOM_MIN_LIMIT_EESCHEMA );
281 view->SetScale( 1.0 );
282
283 gal->SetWorldUnitLength( SCH_WORLD_UNIT );
284 gal->SetSheetSize( pageSizeIn );
285 gal->SetNativePaperSize( pageSizeIn, printCtx->HasNativeLandscapeRotation() );
286
287 // Clone items and add to view
288 std::vector<std::unique_ptr<SCH_ITEM>> clonedItems;
289 clonedItems.reserve( aSelection.GetSize() );
290
291 for( EDA_ITEM* item : aSelection.GetItems() )
292 {
293 SCH_ITEM* schItem = dynamic_cast<SCH_ITEM*>( item );
294
295 if( !schItem )
296 continue;
297
298 SCH_ITEM* clone = static_cast<SCH_ITEM*>( schItem->Clone() );
299 clonedItems.emplace_back( clone );
300 view->Add( clone );
301 }
302
303 SCH_RENDER_SETTINGS* dstSettings = painter->GetSettings();
304 *dstSettings = *aFrame->GetRenderSettings();
305 dstSettings->m_ShowPinsElectricalType = false;
306 dstSettings->LoadColors( aFrame->GetColorSettings( false ) );
308 dstSettings->SetDefaultFont( aFrame->eeconfig()->m_Appearance.default_font );
309 dstSettings->SetIsPrinting( true );
310
311 if( aUseAlpha )
312 dstSettings->SetBackgroundColor( COLOR4D::CLEAR );
313
314 for( int i = 0; i < KIGFX::VIEW::VIEW_MAX_LAYERS; ++i )
315 {
316 view->SetLayerVisible( i, true );
317 view->SetLayerTarget( i, KIGFX::TARGET_NONCACHED );
318 }
319
320 view->SetLayerVisible( LAYER_DRAWINGSHEET, aIncludeDrawingSheet );
321
322 // Create and add drawing sheet proxy view item if requested
323 std::unique_ptr<DS_PROXY_VIEW_ITEM> drawingSheet;
324
325 if( aIncludeDrawingSheet )
326 {
327 SCH_SCREEN* screen = aFrame->GetScreen();
328
329 drawingSheet.reset( new DS_PROXY_VIEW_ITEM( schIUScale, &screen->GetPageSettings(),
330 &screen->Schematic()->Project(), &screen->GetTitleBlock(),
331 screen->Schematic()->GetProperties() ) );
332 drawingSheet->SetPageNumber( TO_UTF8( screen->GetPageNumber() ) );
333 drawingSheet->SetSheetCount( screen->GetPageCount() );
334 drawingSheet->SetFileName( TO_UTF8( screen->GetFileName() ) );
335 drawingSheet->SetColorLayer( LAYER_SCHEMATIC_DRAWINGSHEET );
336 drawingSheet->SetPageBorderColorLayer( LAYER_SCHEMATIC_PAGE_LIMITS );
337 drawingSheet->SetIsFirstPage( screen->GetVirtualPageNumber() == 1 );
338 drawingSheet->SetSheetName( TO_UTF8( aFrame->GetScreenDesc() ) );
339 drawingSheet->SetSheetPath( TO_UTF8( aFrame->GetFullScreenDesc() ) );
340
341 view->Add( drawingSheet.get() );
342 }
343
344 view->SetCenter( aBBox.Centre() );
345 view->UseDrawPriority( true );
346
347 gal->SetClearColor( dstSettings->GetBackgroundColor() );
348 gal->ClearScreen();
349
350 {
351 KIGFX::GAL_DRAWING_CONTEXT ctx( gal.get() );
352 view->Redraw();
353 }
354 }
355
356 return image;
357}
358
359
360wxImage renderSelectionToImageForClipboard( SCH_EDIT_FRAME* aFrame, const SCH_SELECTION& aSelection,
361 const BOX2I& aBBox, bool aUseAlpha, bool aIncludeDrawingSheet )
362{
363 const double c_targetPPI = 300;
364 const double c_targetPixelsPerMM = c_targetPPI / 25.4;
365
366 VECTOR2I size = aBBox.GetSize();
367
368 if( size.x <= 0 || size.y <= 0 )
369 return wxImage();
370
371 int bitmapWidth = KiROUND( schIUScale.IUTomm( size.x ) * c_targetPixelsPerMM );
372 int bitmapHeight = KiROUND( schIUScale.IUTomm( size.y ) * c_targetPixelsPerMM );
373
374 // Clamp to maximum size while preserving aspect ratio
375 if( bitmapWidth > clipboardMaxBitmapSize || bitmapHeight > clipboardMaxBitmapSize )
376 {
377 double scaleDown = (double) clipboardMaxBitmapSize / std::max( bitmapWidth, bitmapHeight );
378 bitmapWidth = KiROUND( bitmapWidth * scaleDown );
379 bitmapHeight = KiROUND( bitmapHeight * scaleDown );
380 }
381
382 if( bitmapWidth <= 0 || bitmapHeight <= 0 )
383 return wxImage();
384
385 wxImage result = renderSelectionToBitmap( aFrame, aSelection, aBBox, bitmapWidth, bitmapHeight, aUseAlpha,
386 aIncludeDrawingSheet );
387
388 return result;
389}
390} // namespace
391
392
394{
395 m_frame->NewProject();
396 return 0;
397}
398
399
401{
402 m_frame->LoadProject();
403 return 0;
404}
405
406
408{
409 m_frame->SaveProject();
410 return 0;
411}
412
413
415{
416 m_frame->SaveProject( true );
417 return 0;
418}
419
420
422{
423 SCH_SHEET* curr_sheet = m_frame->GetCurrentSheet().Last();
424 wxFileName curr_fn = curr_sheet->GetFileName();
425 wxFileDialog dlg( m_frame, _( "Schematic Files" ), curr_fn.GetPath(), curr_fn.GetFullName(),
426 FILEEXT::KiCadSchematicFileWildcard(), wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
427
429
430 if( dlg.ShowModal() == wxID_CANCEL )
431 return false;
432
433 wxString newFilename = EnsureFileExtension( dlg.GetPath(), FILEEXT::KiCadSchematicFileExtension );
434
435 m_frame->saveSchematicFile( curr_sheet, newFilename );
436 return 0;
437}
438
439
441{
442 SCHEMATIC& schematic = m_frame->Schematic();
443 SCH_SHEET& root = schematic.Root();
444
445 // Save original sheet path to restore if user cancels
446 SCH_SHEET_PATH originalSheet = m_frame->GetCurrentSheet();
447 bool wasOnSubsheet = ( m_frame->GetCurrentSheet().Last() != &root );
448
449 // Navigate to root sheet first (needed for proper reload), but don't repaint yet
450 if( wasOnSubsheet )
451 {
452 // Use the properly constructed root sheet path from the hierarchy
453 // (manually pushing root creates a path with empty KIID which causes assertions)
454 SCH_SHEET_PATH rootSheetPath = schematic.Hierarchy().at( 0 );
455
456 m_frame->GetToolManager()->RunAction<SCH_SHEET_PATH*>( SCH_ACTIONS::changeSheet,
457 &rootSheetPath );
458 // Don't call wxSafeYield() here - avoid repainting the root sheet before the dialog
459 }
460
461 wxString msg;
462 msg.Printf( _( "Revert '%s' (and all sub-sheets) to last version saved?" ), schematic.GetFileName() );
463
464 if( !IsOK( m_frame, msg ) )
465 {
466 // User cancelled - navigate back to original sheet
467 if( wasOnSubsheet )
468 {
469 m_frame->GetToolManager()->RunAction<SCH_SHEET_PATH*>( SCH_ACTIONS::changeSheet,
470 &originalSheet );
471 wxSafeYield();
472 }
473
474 return false;
475 }
476
477 SCH_SCREENS screenList( schematic.Root() );
478
479 for( SCH_SCREEN* screen = screenList.GetFirst(); screen; screen = screenList.GetNext() )
480 screen->SetContentModified( false ); // do not prompt the user for changes
481
482 m_frame->ReleaseFile();
483 m_frame->OpenProjectFiles( std::vector<wxString>( 1, schematic.GetFileName() ), KICTL_REVERT );
484
485 return 0;
486}
487
488
490{
491 m_frame->ShowSchematicSetupDialog();
492 return 0;
493}
494
495
497{
498 PICKED_ITEMS_LIST undoCmd;
500 ITEM_PICKER wrapper( m_frame->GetScreen(), undoItem, UNDO_REDO::PAGESETTINGS );
501
502 undoCmd.PushItem( wrapper );
503 undoCmd.SetDescription( _( "Page Settings" ) );
504 m_frame->SaveCopyInUndoList( undoCmd, UNDO_REDO::PAGESETTINGS, false );
505
506 DIALOG_EESCHEMA_PAGE_SETTINGS dlg( m_frame, m_frame->Schematic().GetEmbeddedFiles(),
509
510 if( dlg.ShowModal() == wxID_OK )
511 {
512 // Update text variables
513 m_frame->GetCanvas()->GetView()->MarkDirty();
514 m_frame->GetCanvas()->GetView()->UpdateAllItems( KIGFX::REPAINT );
515 m_frame->GetCanvas()->Refresh();
516
517 m_frame->OnModify();
518 }
519 else
520 {
521 m_frame->RollbackSchematicFromUndo();
522 }
523
524 return 0;
525}
526
527
529{
530 SCH_SCREENS schematic( m_frame->Schematic().Root() );
531
532 if( schematic.HasNoFullyDefinedLibIds() )
533 RescueLegacyProject( true );
534 else
536
537 return 0;
538}
539
540
541bool SCH_EDITOR_CONTROL::RescueLegacyProject( bool aRunningOnDemand )
542{
543 LEGACY_RESCUER rescuer( m_frame->Prj(), &m_frame->Schematic(), &m_frame->GetCurrentSheet(),
544 m_frame->GetCanvas()->GetBackend() );
545
546 return rescueProject( rescuer, aRunningOnDemand );
547}
548
549
551{
552 SYMBOL_LIB_TABLE_RESCUER rescuer( m_frame->Prj(), &m_frame->Schematic(), &m_frame->GetCurrentSheet(),
553 m_frame->GetCanvas()->GetBackend() );
554
555 return rescueProject( rescuer, aRunningOnDemand );
556}
557
558
559bool SCH_EDITOR_CONTROL::rescueProject( RESCUER& aRescuer, bool aRunningOnDemand )
560{
561 if( !RESCUER::RescueProject( m_frame, aRescuer, aRunningOnDemand ) )
562 return false;
563
564 if( aRescuer.GetCandidateCount() )
565 {
566 KIWAY_PLAYER* viewer = m_frame->Kiway().Player( FRAME_SCH_VIEWER, false );
567
568 if( viewer )
569 static_cast<SYMBOL_VIEWER_FRAME*>( viewer )->ReCreateLibList();
570
571 if( aRunningOnDemand )
572 {
573 SCH_SCREENS schematic( m_frame->Schematic().Root() );
574
575 schematic.UpdateSymbolLinks();
576 m_frame->RecalculateConnections( nullptr, GLOBAL_CLEANUP );
577 }
578
579 m_frame->ClearUndoRedoList();
580 m_frame->SyncView();
581 m_frame->GetCanvas()->Refresh();
582 m_frame->OnModify();
583 }
584
585 return true;
586}
587
588
590{
591 DIALOG_SYMBOL_REMAP dlgRemap( m_frame );
592
593 dlgRemap.ShowQuasiModal();
594
595 m_frame->GetCanvas()->Refresh( true );
596
597 return 0;
598}
599
600
602{
603 DIALOG_PRINT dlg( m_frame );
604
605 dlg.ShowModal();
606
607 return 0;
608}
609
610
612{
614
615 dlg.ShowModal();
616
617 return 0;
618}
619
620
622{
623 doCrossProbeSchToPcb( aEvent, false );
624 return 0;
625}
626
627
629{
630 doCrossProbeSchToPcb( aEvent, true );
631 return 0;
632}
633
634
635void SCH_EDITOR_CONTROL::doCrossProbeSchToPcb( const TOOL_EVENT& aEvent, bool aForce )
636{
637 // Don't get in an infinite loop SCH -> PCB -> SCH -> PCB -> SCH -> ...
638 if( m_probingPcbToSch || m_frame->IsSyncingSelection() )
639 return;
640
641 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
642 SCH_SELECTION& selection = aForce ? selTool->RequestSelection() : selTool->GetSelection();
643
644 m_frame->SendSelectItemsToPcb( selection.GetItemsSortedBySelectionOrder(), aForce );
645}
646
647
649{
650 bool savePowerSymbols = false;
651 bool map = false;
653 wxString targetLib;
654 wxString msg;
655
656 targetLib = m_frame->SelectLibrary( _( "Export Symbols" ), _( "Export symbols to library:" ),
657 { { _( "Include power symbols in export" ), &savePowerSymbols },
658 { _( "Update schematic symbols to link to exported symbols" ), &map }
659 } );
660
661 if( targetLib.empty() )
662 return 0;
663
664 SCH_SHEET_LIST sheets = m_frame->Schematic().BuildSheetListSortedByPageNumbers();
665 SCH_REFERENCE_LIST symbols;
666 sheets.GetSymbols( symbols, savePowerSymbols );
667
668 std::map<LIB_ID, LIB_SYMBOL*> libSymbols;
669 std::map<LIB_ID, std::vector<SCH_SYMBOL*>> symbolMap;
670
671 for( size_t i = 0; i < symbols.GetCount(); ++i )
672 {
673 SCH_SYMBOL* symbol = symbols[i].GetSymbol();
674 LIB_SYMBOL* libSymbol = symbol->GetLibSymbolRef().get();
675 LIB_ID id = libSymbol->GetLibId();
676
677 if( libSymbols.count( id ) )
678 {
679 wxASSERT_MSG( libSymbols[id]->Compare( *libSymbol, SCH_ITEM::COMPARE_FLAGS::ERC ) == 0,
680 "Two symbols have the same LIB_ID but are different!" );
681 }
682 else
683 {
684 libSymbols[id] = libSymbol;
685 }
686
687 symbolMap[id].emplace_back( symbol );
688 }
689
690 bool append = false;
691 SCH_COMMIT commit( m_frame );
693
694 auto optRow = adapter->GetRow( targetLib );
695 wxCHECK( optRow, 0 );
696 const LIBRARY_TABLE_ROW* row = *optRow;
697
698 SCH_IO_MGR::SCH_FILE_T type = SCH_IO_MGR::EnumFromStr( row->Type() );
699 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( type ) );
700
701 wxFileName dest = LIBRARY_MANAGER::GetFullURI( row );
702 dest.Normalize( FN_NORMALIZE_FLAGS | wxPATH_NORM_ENV_VARS );
703
704 for( const std::pair<const LIB_ID, LIB_SYMBOL*>& it : libSymbols )
705 {
706 LIB_SYMBOL* origSym = it.second;
707 LIB_SYMBOL* newSym = origSym->Flatten().release();
708
709 try
710 {
711 pi->SaveSymbol( dest.GetFullPath(), newSym );
712 }
713 catch( const IO_ERROR& ioe )
714 {
715 msg.Printf( _( "Error saving symbol %s to library '%s'." ), newSym->GetName(), row->Nickname() );
716 msg += wxS( "\n\n" ) + ioe.What();
717 wxLogWarning( msg );
718 return 0;
719 }
720
721 if( map )
722 {
723 LIB_ID id = it.first;
724 id.SetLibNickname( targetLib );
725
726 for( SCH_SYMBOL* symbol : symbolMap[it.first] )
727 {
728 SCH_SCREEN* parentScreen = static_cast<SCH_SCREEN*>( symbol->GetParent() );
729
730 wxCHECK2( parentScreen, continue );
731
732 commit.Modify( symbol, parentScreen, RECURSE_MODE::NO_RECURSE );
733 symbol->SetLibId( id );
734 append = true;
735 }
736 }
737 }
738
739 if( append )
740 {
741 std::set<SCH_SCREEN*> processedScreens;
742
743 for( SCH_SHEET_PATH& sheet : sheets )
744 {
745 SCH_SCREEN* screen = sheet.LastScreen();
746
747 if( processedScreens.find( ( screen ) ) == processedScreens.end() )
748 {
749 processedScreens.insert( screen );
750 screen->UpdateSymbolLinks();
751 }
752 }
753
754 commit.Push( wxS( "Update Library Identifiers" ) );
755 }
756
757 return 0;
758}
759
760
761#define HITTEST_THRESHOLD_PIXELS 5
762
764{
765 PICKER_TOOL* picker = m_toolMgr->GetTool<PICKER_TOOL>();
766 KIWAY_PLAYER* sim_player = m_frame->Kiway().Player( FRAME_SIMULATOR, false );
767 SIMULATOR_FRAME* sim_Frame = static_cast<SIMULATOR_FRAME*>( sim_player );
768
769 if( !sim_Frame ) // Defensive coding; shouldn't happen.
770 return 0;
771
772 if( wxWindow* blocking_win = sim_Frame->Kiway().GetBlockingDialog() )
773 blocking_win->Close( true );
774
775 // Deactivate other tools; particularly important if another PICKER is currently running
776 Activate();
777
779 picker->SetSnapping( false );
780 picker->ClearHandlers();
781
782 picker->SetClickHandler(
783 [this]( const VECTOR2D& aPosition )
784 {
785 KIWAY_PLAYER* player = m_frame->Kiway().Player( FRAME_SIMULATOR, false );
786 SIMULATOR_FRAME* simFrame = static_cast<SIMULATOR_FRAME*>( player );
787 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
788
789 // We do not really want to keep an item selected in schematic,
790 // so clear the current selection
791 selTool->ClearSelection();
792
793 EDA_ITEM* item = selTool->GetNode( aPosition );
794 SCH_SHEET_PATH& sheet = m_frame->GetCurrentSheet();
795 wxString variant = m_frame->Schematic().GetCurrentVariant();
796
797 if( !item )
798 return false;
799
800 if( item->Type() == SCH_PIN_T )
801 {
802 SCH_PIN* schPin = static_cast<SCH_PIN*>( item );
803 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( schPin->GetParentSymbol() );
804 SCH_PIN* libPin = schPin->GetLibPin();
805
806 if( !symbol || !libPin )
807 return false;
808
809 try
810 {
811 WX_STRING_REPORTER reporter;
812 SIM_LIB_MGR mgr( &m_frame->Prj() );
813
814 std::vector<EMBEDDED_FILES*> embeddedFilesStack;
815 embeddedFilesStack.push_back( m_frame->Schematic().GetEmbeddedFiles() );
816
817 if( EMBEDDED_FILES* symbolEmbeddedFile = symbol->GetEmbeddedFiles() )
818 embeddedFilesStack.push_back( symbolEmbeddedFile );
819
820 mgr.SetFilesStack( std::move( embeddedFilesStack ) );
821
822 SIM_MODEL& model = mgr.CreateModel( &sheet, *symbol, true, 0, variant, reporter ).model;
823
824 if( reporter.HasMessage() )
825 THROW_IO_ERROR( reporter.GetMessages() );
826
827 SPICE_ITEM spiceItem;
828 spiceItem.refName = symbol->GetRef( &sheet ).ToStdString();
829 std::vector<std::string> currentNames = model.SpiceGenerator().CurrentNames( spiceItem );
830
831 if( currentNames.size() == 0 )
832 {
833 return true;
834 }
835 else if( currentNames.size() == 1 )
836 {
837 if( simFrame )
838 simFrame->AddCurrentTrace( currentNames.at( 0 ) );
839
840 return true;
841 }
842
843 int modelPinIndex = model.FindModelPinIndex( libPin->GetNumber().ToStdString() );
844
845 if( modelPinIndex != SIM_MODEL_PIN::NOT_CONNECTED )
846 {
847 wxString name = currentNames.at( modelPinIndex );
848
849 if( simFrame )
850 simFrame->AddCurrentTrace( name );
851 }
852 }
853 catch( const IO_ERROR& e )
854 {
856 }
857 }
858 else if( item->IsType( { SCH_ITEM_LOCATE_WIRE_T } ) || item->IsType( { SCH_JUNCTION_T } ) )
859 {
860 if( SCH_CONNECTION* conn = static_cast<SCH_ITEM*>( item )->Connection() )
861 {
862 wxString spiceNet = UnescapeString( conn->Name() );
864
865 if( simFrame )
866 simFrame->AddVoltageTrace( wxString::Format( "V(%s)", spiceNet ) );
867 }
868 }
869
870 return true;
871 } );
872
873 picker->SetMotionHandler(
874 [this]( const VECTOR2D& aPos )
875 {
876 SCH_COLLECTOR collector;
877 collector.m_Threshold = KiROUND( getView()->ToWorld( HITTEST_THRESHOLD_PIXELS ) );
878 collector.Collect( m_frame->GetScreen(), { SCH_ITEM_LOCATE_WIRE_T,
879 SCH_PIN_T,
880 SCH_SHEET_PIN_T }, aPos );
881
882 SCH_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
883 selectionTool->GuessSelectionCandidates( collector, aPos );
884
885 EDA_ITEM* item = collector.GetCount() == 1 ? collector[0] : nullptr;
886 SCH_LINE* wire = dynamic_cast<SCH_LINE*>( item );
887
888 const SCH_CONNECTION* conn = nullptr;
889
890 if( wire )
891 {
892 item = nullptr;
893 conn = wire->Connection();
894 }
895
896 if( item && item->Type() == SCH_PIN_T )
897 m_toolMgr->GetTool<PICKER_TOOL>()->SetCursor( KICURSOR::CURRENT_PROBE );
898 else
899 m_toolMgr->GetTool<PICKER_TOOL>()->SetCursor( KICURSOR::VOLTAGE_PROBE );
900
901 if( m_pickerItem != item )
902 {
903 if( m_pickerItem )
904 selectionTool->UnbrightenItem( m_pickerItem );
905
906 m_pickerItem = item;
907
908 if( m_pickerItem )
909 selectionTool->BrightenItem( m_pickerItem );
910 }
911
912 wxString connectionName = ( conn ) ? conn->Name() : wxString( wxS( "" ) );
913
914 if( m_frame->GetHighlightedConnection() != connectionName )
915 {
916 m_frame->SetHighlightedConnection( connectionName );
917
918 TOOL_EVENT dummyEvent;
919 UpdateNetHighlighting( dummyEvent );
920 }
921 } );
922
923 picker->SetFinalizeHandler(
924 [this]( const int& aFinalState )
925 {
926 if( m_pickerItem )
927 m_toolMgr->GetTool<SCH_SELECTION_TOOL>()->UnbrightenItem( m_pickerItem );
928
929 if( !m_frame->GetHighlightedConnection().IsEmpty() )
930 {
931 m_frame->SetHighlightedConnection( wxEmptyString );
932
933 TOOL_EVENT dummyEvent;
934 UpdateNetHighlighting( dummyEvent );
935 }
936
937 // Wake the selection tool after exiting to ensure the cursor gets updated
938 // and deselect previous selection from simulator to avoid any issue
939 // ( avoid crash in some cases when the SimProbe tool is deselected )
940 SCH_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
941 selectionTool->ClearSelection();
943 } );
944
945 m_toolMgr->RunAction( ACTIONS::pickerTool, &aEvent );
946
947 return 0;
948}
949
950
952{
953 PICKER_TOOL* picker = m_toolMgr->GetTool<PICKER_TOOL>();
954
955 // Deactivate other tools; particularly important if another PICKER is currently running
956 Activate();
957
958 picker->SetCursor( KICURSOR::TUNE );
959 picker->SetSnapping( false );
960 picker->ClearHandlers();
961
962 picker->SetClickHandler(
963 [this]( const VECTOR2D& aPosition )
964 {
965 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
966 EDA_ITEM* item = nullptr;
967 selTool->SelectPoint( aPosition, { SCH_SYMBOL_T, SCH_FIELD_T }, &item );
968
969 if( !item )
970 return false;
971
972 if( item->Type() != SCH_SYMBOL_T )
973 {
974 item = item->GetParent();
975
976 if( item->Type() != SCH_SYMBOL_T )
977 return false;
978 }
979
980 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
981 SCH_SHEET_PATH sheetPath = symbol->Schematic()->CurrentSheet();
982 KIWAY_PLAYER* simFrame = m_frame->Kiway().Player( FRAME_SIMULATOR, false );
983
984 if( simFrame )
985 {
986 if( wxWindow* blocking_win = simFrame->Kiway().GetBlockingDialog() )
987 blocking_win->Close( true );
988
989 static_cast<SIMULATOR_FRAME*>( simFrame )->AddTuner( sheetPath, symbol );
990 }
991
992 // We do not really want to keep a symbol selected in schematic,
993 // so clear the current selection
994 selTool->ClearSelection();
995 return true;
996 } );
997
998 picker->SetMotionHandler(
999 [this]( const VECTOR2D& aPos )
1000 {
1001 SCH_COLLECTOR collector;
1002 collector.m_Threshold = KiROUND( getView()->ToWorld( HITTEST_THRESHOLD_PIXELS ) );
1003 collector.Collect( m_frame->GetScreen(), { SCH_SYMBOL_T, SCH_FIELD_T }, aPos );
1004
1005 SCH_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
1006 selectionTool->GuessSelectionCandidates( collector, aPos );
1007
1008 EDA_ITEM* item = collector.GetCount() == 1 ? collector[0] : nullptr;
1009
1010 if( item && item->Type() == SCH_FIELD_T )
1011 item = static_cast<SCH_FIELD*>( item )->GetParentSymbol();
1012
1013 if( m_pickerItem != item )
1014 {
1015 if( m_pickerItem )
1016 selectionTool->UnbrightenItem( m_pickerItem );
1017
1018 m_pickerItem = item;
1019
1020 if( m_pickerItem )
1021 selectionTool->BrightenItem( m_pickerItem );
1022 }
1023 } );
1024
1025 picker->SetFinalizeHandler(
1026 [this]( const int& aFinalState )
1027 {
1028 if( m_pickerItem )
1029 m_toolMgr->GetTool<SCH_SELECTION_TOOL>()->UnbrightenItem( m_pickerItem );
1030
1031 // Wake the selection tool after exiting to ensure the cursor gets updated
1032 // and deselect previous selection from simulator to avoid any issue
1033 // ( avoid crash in some cases when the SimTune tool is deselected )
1034 SCH_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
1035 selectionTool->ClearSelection();
1037 } );
1038
1039 m_toolMgr->RunAction( ACTIONS::pickerTool, &aEvent );
1040
1041 return 0;
1042}
1043
1044
1045// A singleton reference for clearing the highlight
1047
1048
1049static bool highlightNet( TOOL_MANAGER* aToolMgr, const VECTOR2D& aPosition )
1050{
1051 SCH_EDIT_FRAME* editFrame = static_cast<SCH_EDIT_FRAME*>( aToolMgr->GetToolHolder() );
1052 SCH_SELECTION_TOOL* selTool = aToolMgr->GetTool<SCH_SELECTION_TOOL>();
1053 SCH_EDITOR_CONTROL* editorControl = aToolMgr->GetTool<SCH_EDITOR_CONTROL>();
1054 SCH_CONNECTION* conn = nullptr;
1055 SCH_ITEM* item = nullptr;
1056 bool retVal = true;
1057
1058 if( aPosition != CLEAR )
1059 {
1060 ERC_TESTER erc( &editFrame->Schematic() );
1061
1062 if( erc.TestDuplicateSheetNames( false ) > 0 )
1063 {
1064 wxMessageBox( _( "Error: duplicate sub-sheet names found in current sheet." ) );
1065 retVal = false;
1066 }
1067 else
1068 {
1069 item = static_cast<SCH_ITEM*>( selTool->GetNode( aPosition ) );
1070 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( item );
1071
1072 if( item )
1073 {
1074 if( item->IsConnectivityDirty() )
1075 editFrame->RecalculateConnections( nullptr, NO_CLEANUP );
1076
1077 if( item->Type() == SCH_FIELD_T )
1078 symbol = dynamic_cast<SCH_SYMBOL*>( item->GetParent() );
1079
1080 if( symbol && symbol->GetLibSymbolRef() && symbol->GetLibSymbolRef()->IsPower() )
1081 {
1082 std::vector<SCH_PIN*> pins = symbol->GetPins();
1083
1084 if( pins.size() == 1 )
1085 conn = pins[0]->Connection();
1086 }
1087 else
1088 {
1089 conn = item->Connection();
1090 }
1091 }
1092 }
1093 }
1094
1095 wxString connName = ( conn ) ? conn->Name() : wxString( wxS( "" ) );
1096
1097 if( !conn )
1098 {
1099 editFrame->SetStatusText( wxT( "" ) );
1100 editFrame->SendCrossProbeClearHighlight();
1101 editFrame->SetHighlightedConnection( wxEmptyString );
1102 editorControl->SetHighlightBusMembers( false );
1103 }
1104 else
1105 {
1106 NET_NAVIGATOR_ITEM_DATA itemData( editFrame->GetCurrentSheet(), item );
1107
1108 if( connName != editFrame->GetHighlightedConnection() )
1109 {
1110 editorControl->SetHighlightBusMembers( false );
1111 editFrame->SetCrossProbeConnection( conn );
1112 editFrame->SetHighlightedConnection( connName, &itemData );
1113 }
1114 else
1115 {
1116 editorControl->SetHighlightBusMembers( !editorControl->GetHighlightBusMembers() );
1117
1118 if( item != editFrame->GetSelectedNetNavigatorItem() )
1119 editFrame->SelectNetNavigatorItem( &itemData );
1120 }
1121 }
1122
1123 editFrame->UpdateNetHighlightStatus();
1124
1126 editorControl->UpdateNetHighlighting( dummy );
1127
1128 return retVal;
1129}
1130
1131
1133{
1135 VECTOR2D cursorPos = controls->GetCursorPosition( !aEvent.DisableGridSnapping() );
1136
1137 highlightNet( m_toolMgr, cursorPos );
1138
1139 return 0;
1140}
1141
1142
1144{
1146
1147 return 0;
1148}
1149
1150
1152{
1153 SCH_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
1154 SCHEMATIC& schematic = m_frame->Schematic();
1155 SCH_SCREEN* screen = m_frame->GetCurrentSheet().LastScreen();
1156
1157 std::vector<std::pair<SCH_CONNECTION*, VECTOR2D>> selectedConns;
1158
1159 for( EDA_ITEM* item : selectionTool->GetSelection() )
1160 {
1161 SCH_CONNECTION* conn = static_cast<SCH_ITEM*>( item )->Connection();
1162
1163 if( !conn )
1164 continue;
1165
1166 selectedConns.emplace_back( conn, item->GetPosition() );
1167 }
1168
1169 if( selectedConns.empty() )
1170 {
1171 m_frame->ShowInfoBarError( _( "No nets selected." ) );
1172 return 0;
1173 }
1174
1175 // Remove selection in favor of highlighting so the whole net is highlighted
1176 selectionTool->ClearSelection();
1177
1178 const auto getNetNamePattern =
1179 []( const SCH_CONNECTION& aConn ) -> std::optional<wxString>
1180 {
1181 wxString netName = aConn.Name();
1182
1183 if( aConn.IsBus() )
1184 {
1185 wxString prefix;
1186
1187 if( NET_SETTINGS::ParseBusVector( netName, &prefix, nullptr ) )
1188 return prefix + wxT( "*" );
1189 else if( NET_SETTINGS::ParseBusGroup( netName, &prefix, nullptr ) )
1190 return prefix + wxT( ".*" );
1191 }
1192 else if( !aConn.Driver() || CONNECTION_SUBGRAPH::GetDriverPriority( aConn.Driver() )
1194 {
1195 return std::nullopt;
1196 }
1197
1198 return netName;
1199 };
1200
1201 std::set<wxString> netNames;
1202
1203 for( const auto& [conn, pos] : selectedConns )
1204 {
1205 std::optional<wxString> netNamePattern = getNetNamePattern( *conn );
1206
1207 if( !netNamePattern )
1208 {
1209 // This is a choice, we can also allow some un-labeled nets as long as some are labeled.
1210 m_frame->ShowInfoBarError( _( "All selected nets must be labeled to assign a netclass." ) );
1211 return 0;
1212 }
1213
1214 netNames.insert( *netNamePattern );
1215 }
1216
1217 wxCHECK( !netNames.empty(), 0 );
1218
1219 DIALOG_ASSIGN_NETCLASS dlg( m_frame, netNames, schematic.GetNetClassAssignmentCandidates(),
1220 [&]( const std::vector<wxString>& aNetNames )
1221 {
1222 for( SCH_ITEM* item : screen->Items() )
1223 {
1224 bool redraw = item->IsBrightened();
1225 SCH_CONNECTION* itemConn = item->Connection();
1226
1227 if( itemConn && alg::contains( aNetNames, itemConn->Name() ) )
1228 item->SetBrightened();
1229 else
1230 item->ClearBrightened();
1231
1232 redraw |= item->IsBrightened();
1233
1234 if( item->Type() == SCH_SYMBOL_T )
1235 {
1236 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1237
1238 redraw |= symbol->HasBrightenedPins();
1239
1240 symbol->ClearBrightenedPins();
1241
1242 for( SCH_PIN* pin : symbol->GetPins() )
1243 {
1244 SCH_CONNECTION* pin_conn = pin->Connection();
1245
1246 if( pin_conn && alg::contains( aNetNames, pin_conn->Name() ) )
1247 {
1248 pin->SetBrightened();
1249 redraw = true;
1250 }
1251 }
1252 }
1253 else if( item->Type() == SCH_SHEET_T )
1254 {
1255 for( SCH_SHEET_PIN* pin : static_cast<SCH_SHEET*>( item )->GetPins() )
1256 {
1257 SCH_CONNECTION* pin_conn = pin->Connection();
1258
1259 redraw |= pin->IsBrightened();
1260
1261 if( pin_conn && alg::contains( aNetNames, pin_conn->Name() ) )
1262 pin->SetBrightened();
1263 else
1264 pin->ClearBrightened();
1265
1266 redraw |= pin->IsBrightened();
1267 }
1268 }
1269
1270 if( redraw )
1271 getView()->Update( item, KIGFX::VIEW_UPDATE_FLAGS::REPAINT );
1272 }
1273
1274 m_frame->GetCanvas()->ForceRefresh();
1275 } );
1276
1277 if( dlg.ShowModal() )
1278 {
1279 getView()->UpdateAllItemsConditionally(
1280 [&]( KIGFX::VIEW_ITEM* aItem ) -> int
1281 {
1282 int flags = 0;
1283
1284 auto invalidateTextVars =
1285 [&flags]( EDA_TEXT* text )
1286 {
1287 if( text->HasTextVars() )
1288 {
1289 text->ClearRenderCache();
1290 text->ClearBoundingBoxCache();
1292 }
1293 };
1294
1295 // Netclass coloured items
1296 //
1297 if( dynamic_cast<SCH_LINE*>( aItem ) )
1298 flags |= KIGFX::REPAINT;
1299 else if( dynamic_cast<SCH_JUNCTION*>( aItem ) )
1300 flags |= KIGFX::REPAINT;
1301 else if( dynamic_cast<SCH_BUS_ENTRY_BASE*>( aItem ) )
1302 flags |= KIGFX::REPAINT;
1303
1304 // Items that might reference an item's netclass name
1305 //
1306 if( SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( aItem ) )
1307 {
1308 item->RunOnChildren(
1309 [&invalidateTextVars]( SCH_ITEM* aChild )
1310 {
1311 if( EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( aChild ) )
1312 invalidateTextVars( text );
1313 },
1315
1316 if( flags & KIGFX::GEOMETRY )
1317 m_frame->GetScreen()->Update( item, false ); // Refresh RTree
1318 }
1319
1320 if( EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( aItem ) )
1321 invalidateTextVars( text );
1322
1323 return flags;
1324 } );
1325 }
1326
1327 highlightNet( m_toolMgr, CLEAR );
1328 return 0;
1329}
1330
1331
1333{
1334 SCH_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
1335
1336 if( !selectionTool )
1337 return 0;
1338
1339 wxString netName;
1340
1341 for( EDA_ITEM* item : selectionTool->GetSelection() )
1342 {
1343 if( SCH_ITEM* schItem = dynamic_cast<SCH_ITEM*>( item ) )
1344 {
1345 if( SCH_CONNECTION* conn = schItem->Connection() )
1346 {
1347 if( !conn->GetNetName().IsEmpty() )
1348 {
1349 netName = conn->GetNetName();
1350 break;
1351 }
1352 }
1353 }
1354 }
1355
1356 if( netName.IsEmpty() )
1357 netName = m_frame->GetHighlightedConnection();
1358
1359 if( netName.IsEmpty() )
1360 {
1361 m_frame->ShowInfoBarError( _( "No connected net selected." ) );
1362 return 0;
1363 }
1364
1365 m_frame->FindNetInInspector( netName );
1366
1367 return 0;
1368}
1369
1370
1372{
1373 wxCHECK( m_frame, 0 );
1374
1375 const SCH_SHEET_PATH& sheetPath = m_frame->GetCurrentSheet();
1376 SCH_SCREEN* screen = m_frame->GetCurrentSheet().LastScreen();
1377 CONNECTION_GRAPH* connectionGraph = m_frame->Schematic().ConnectionGraph();
1378 wxString selectedName = m_frame->GetHighlightedConnection();
1379
1380 std::set<wxString> connNames;
1381 std::vector<EDA_ITEM*> itemsToRedraw;
1382
1383 wxCHECK( screen && connectionGraph, 0 );
1384
1385 if( !selectedName.IsEmpty() )
1386 {
1387 connNames.emplace( selectedName );
1388
1389 if( CONNECTION_SUBGRAPH* sg = connectionGraph->FindSubgraphByName( selectedName, sheetPath ) )
1390 {
1392 {
1393 for( const SCH_ITEM* item : sg->GetItems() )
1394 {
1395 wxCHECK2( item, continue );
1396
1397 if( SCH_CONNECTION* connection = item->Connection() )
1398 {
1399 for( const std::shared_ptr<SCH_CONNECTION>& member : connection->AllMembers() )
1400 {
1401 if( member )
1402 connNames.emplace( member->Name() );
1403 }
1404 }
1405 }
1406 }
1407 }
1408
1409 // Place all bus names that are connected to the selected net in the set, regardless of
1410 // their sheet. This ensures that nets that are connected to a bus on a different sheet
1411 // get their buses highlighted as well.
1412 for( CONNECTION_SUBGRAPH* sg : connectionGraph->GetAllSubgraphs( selectedName ) )
1413 {
1414 for( const auto& [_, bus_sgs] : sg->GetBusParents() )
1415 {
1416 for( CONNECTION_SUBGRAPH* bus_sg : bus_sgs )
1417 connNames.emplace( bus_sg->GetNetName() );
1418 }
1419 }
1420 }
1421
1422 for( SCH_ITEM* item : screen->Items() )
1423 {
1424 if( !item || !item->IsConnectable() )
1425 continue;
1426
1427 SCH_ITEM* redrawItem = nullptr;
1428
1429 if( item->Type() == SCH_SYMBOL_T )
1430 {
1431 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1432
1433 for( SCH_PIN* pin : symbol->GetPins() )
1434 {
1435 SCH_CONNECTION* pin_conn = pin->Connection();
1436
1437 if( pin_conn )
1438 {
1439 if( !pin->IsBrightened() && connNames.count( pin_conn->Name() ) )
1440 {
1441 pin->SetBrightened();
1442 redrawItem = symbol;
1443 }
1444 else if( pin->IsBrightened() && !connNames.count( pin_conn->Name() ) )
1445 {
1446 pin->ClearBrightened();
1447 redrawItem = symbol;
1448 }
1449 }
1450 else if( pin->IsBrightened() )
1451 {
1452 pin->ClearBrightened();
1453 redrawItem = symbol;
1454 }
1455 }
1456
1457 if( symbol->IsPower() && symbol->GetPins().size() )
1458 {
1459 SCH_CONNECTION* pinConn = symbol->GetPins()[0]->Connection();
1460
1462 {
1463 SCH_FIELD* field = symbol->GetField( id );
1464
1465 if( !field->IsVisible() )
1466 continue;
1467
1468 if( pinConn )
1469 {
1470 if( !field->IsBrightened() && connNames.count( pinConn->Name() ) )
1471 {
1472 field->SetBrightened();
1473 redrawItem = symbol;
1474 }
1475 else if( field->IsBrightened() && !connNames.count( pinConn->Name() ) )
1476 {
1477 field->ClearBrightened();
1478 redrawItem = symbol;
1479 }
1480 }
1481 else if( field->IsBrightened() )
1482 {
1483 field->ClearBrightened();
1484 redrawItem = symbol;
1485 }
1486 }
1487 }
1488 }
1489 else if( item->Type() == SCH_SHEET_T )
1490 {
1491 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
1492
1493 for( SCH_SHEET_PIN* pin : sheet->GetPins() )
1494 {
1495 wxCHECK2( pin, continue );
1496
1497 SCH_CONNECTION* pin_conn = pin->Connection();
1498
1499 if( pin_conn )
1500 {
1501 if( !pin->IsBrightened() && connNames.count( pin_conn->Name() ) )
1502 {
1503 pin->SetBrightened();
1504 redrawItem = sheet;
1505 }
1506 else if( pin->IsBrightened() && !connNames.count( pin_conn->Name() ) )
1507 {
1508 pin->ClearBrightened();
1509 redrawItem = sheet;
1510 }
1511 }
1512 else if( pin->IsBrightened() )
1513 {
1514 pin->ClearBrightened();
1515 redrawItem = sheet;
1516 }
1517 }
1518 }
1519 else
1520 {
1521 SCH_CONNECTION* itemConn = item->Connection();
1522
1523 if( itemConn )
1524 {
1525 if( !item->IsBrightened() && connNames.count( itemConn->Name() ) )
1526 {
1527 item->SetBrightened();
1528 redrawItem = item;
1529 }
1530 else if( item->IsBrightened() && !connNames.count( itemConn->Name() ) )
1531 {
1532 item->ClearBrightened();
1533 redrawItem = item;
1534 }
1535 }
1536 else if( item->IsBrightened() )
1537 {
1538 item->ClearBrightened();
1539 redrawItem = item;
1540 }
1541 }
1542
1543 if( redrawItem )
1544 itemsToRedraw.push_back( redrawItem );
1545 }
1546
1547 if( itemsToRedraw.size() )
1548 {
1549 // Be sure highlight change will be redrawn
1550 KIGFX::VIEW* view = getView();
1551
1552 for( EDA_ITEM* redrawItem : itemsToRedraw )
1554
1555 m_frame->GetCanvas()->Refresh();
1556 }
1557
1558 return 0;
1559}
1560
1561
1563{
1564 PICKER_TOOL* picker = m_toolMgr->GetTool<PICKER_TOOL>();
1565
1566 // Deactivate other tools; particularly important if another PICKER is currently running
1567 Activate();
1568
1569 picker->SetCursor( KICURSOR::BULLSEYE );
1570 picker->SetSnapping( false );
1571 picker->ClearHandlers();
1572
1573 picker->SetClickHandler(
1574 [this]( const VECTOR2D& aPos )
1575 {
1576 return highlightNet( m_toolMgr, aPos );
1577 } );
1578
1579 m_toolMgr->RunAction( ACTIONS::pickerTool, &aEvent );
1580
1581 return 0;
1582}
1583
1584
1586{
1587 wxCHECK( m_frame, 0 );
1588
1589 if( m_frame->GetUndoCommandCount() <= 0 )
1590 return 0;
1591
1592 // Inform tools that undo command was issued
1593 m_toolMgr->ProcessEvent( { TC_MESSAGE, TA_UNDO_REDO_PRE, AS_GLOBAL } );
1594
1595 // Get the old list
1596 PICKED_ITEMS_LIST* undo_list = m_frame->PopCommandFromUndoList();
1597
1598 wxCHECK( undo_list, 0 );
1599
1600 m_frame->PutDataInPreviousState( undo_list );
1601
1602 // Now push the old command to the RedoList
1603 undo_list->ReversePickersListOrder();
1604 m_frame->PushCommandToRedoList( undo_list );
1605
1606 m_toolMgr->GetTool<SCH_SELECTION_TOOL>()->RebuildSelection();
1607
1608 m_frame->GetCanvas()->Refresh();
1609 m_frame->OnModify();
1610
1611 return 0;
1612}
1613
1614
1616{
1617 wxCHECK( m_frame, 0 );
1618
1619 if( m_frame->GetRedoCommandCount() == 0 )
1620 return 0;
1621
1622 // Inform tools that undo command was issued
1623 m_toolMgr->ProcessEvent( { TC_MESSAGE, TA_UNDO_REDO_PRE, AS_GLOBAL } );
1624
1625 /* Get the old list */
1626 PICKED_ITEMS_LIST* list = m_frame->PopCommandFromRedoList();
1627
1628 wxCHECK( list, 0 );
1629
1630 /* Redo the command: */
1631 m_frame->PutDataInPreviousState( list );
1632
1633 /* Put the old list in UndoList */
1634 list->ReversePickersListOrder();
1635 m_frame->PushCommandToUndoList( list );
1636
1637 m_toolMgr->GetTool<SCH_SELECTION_TOOL>()->RebuildSelection();
1638
1639 m_frame->GetCanvas()->Refresh();
1640 m_frame->OnModify();
1641
1642 return 0;
1643}
1644
1645
1646bool SCH_EDITOR_CONTROL::doCopy( bool aUseDuplicateClipboard )
1647{
1648 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
1649 SCH_SELECTION& selection = selTool->RequestSelection();
1650 SCHEMATIC& schematic = m_frame->Schematic();
1651
1652 if( selection.Empty() )
1653 return false;
1654
1655 if( aUseDuplicateClipboard )
1656 m_duplicateIsHoverSelection = selection.IsHover();
1657
1658 selection.SetScreen( m_frame->GetScreen() );
1660
1661 for( EDA_ITEM* item : selection.GetItems() )
1662 {
1663 if( item->Type() == SCH_SHEET_T )
1664 {
1665 SCH_SHEET* sheet = (SCH_SHEET*) item;
1666 m_supplementaryClipboard[sheet->GetFileName()] = sheet->GetScreen();
1667 }
1668 else if( item->Type() == SCH_FIELD_T && selection.IsHover() )
1669 {
1670 // Most of the time the user is trying to duplicate the parent symbol
1671 // and the field text is in it
1672 selection.Add( item->GetParent() );
1673 }
1674 else if( item->Type() == SCH_MARKER_T )
1675 {
1676 // Don't let the markers be copied
1677 selection.Remove( item );
1678 }
1679 else if( item->Type() == SCH_GROUP_T )
1680 {
1681 // Groups need to have all their items selected
1682 static_cast<SCH_ITEM*>( item )->RunOnChildren(
1683 [&]( EDA_ITEM* aChild )
1684 {
1685 selection.Add( aChild );
1686 },
1688 }
1689 }
1690
1691 bool result = true;
1692 STRING_FORMATTER formatter;
1693 SCH_IO_KICAD_SEXPR plugin;
1694 SCH_SHEET_PATH selPath = m_frame->GetCurrentSheet();
1695
1696 plugin.Format( &selection, &selPath, schematic, &formatter, true );
1697
1698 std::string prettyData = formatter.GetString();
1699 KICAD_FORMAT::Prettify( prettyData, KICAD_FORMAT::FORMAT_MODE::COMPACT_TEXT_PROPERTIES );
1700
1701 if( !aUseDuplicateClipboard )
1702 {
1703 wxLogNull doNotLog; // disable logging of failed clipboard actions
1704
1705 result &= wxTheClipboard->Open();
1706
1707 if( result )
1708 {
1709 wxDataObjectComposite* data = new wxDataObjectComposite();
1710
1711 // Add KiCad data
1712 wxCustomDataObject* kicadObj = new wxCustomDataObject( wxDataFormat( "application/kicad" ) );
1713 kicadObj->SetData( prettyData.size(), prettyData.data() );
1714 data->Add( kicadObj );
1715
1716 BOX2I selectionBox = expandedSelectionBox( selection );
1717
1718 if( selectionBox.GetWidth() > 0 && selectionBox.GetHeight() > 0 )
1719 {
1720 // Add bitmap data (encoded once, used for both PNG clipboard and HTML)
1721 wxImage image = renderSelectionToImageForClipboard( m_frame, selection, selectionBox, true, false );
1722 wxMemoryBuffer pngBuffer;
1723
1724 if( image.IsOk() && EncodeImageToPng( image, pngBuffer ) )
1725 {
1726 AddPngToClipboardData( data, pngBuffer, &image );
1727
1728 // Add HTML with embedded base64 PNG for pasting into documents
1729 wxMemoryBuffer htmlBuffer;
1730
1731 if( generateHtmlFromPngData( pngBuffer, htmlBuffer ) )
1732 {
1733 wxCustomDataObject* htmlObj = new wxCustomDataObject( wxDF_HTML );
1734 htmlObj->SetData( htmlBuffer.GetDataLen(), htmlBuffer.GetData() );
1735 data->Add( htmlObj );
1736 }
1737 }
1738 else
1739 {
1740 wxLogDebug( wxS( "Failed to generate bitmap for clipboard" ) );
1741 }
1742
1743 // Add SVG data
1744 wxMemoryBuffer svgBuffer;
1745
1746 if( plotSelectionToSvg( m_frame, selection, selectionBox, svgBuffer ) )
1747 {
1748 wxCustomDataObject* svgObj = new wxCustomDataObject( wxDataFormat( "image/svg+xml" ) );
1749 svgObj->SetData( svgBuffer.GetDataLen(), svgBuffer.GetData() );
1750 data->Add( svgObj );
1751 }
1752 else
1753 {
1754 wxLogDebug( wxS( "Failed to generate SVG for clipboard" ) );
1755 }
1756 }
1757
1758 // Finally add text data
1759 data->Add( new wxTextDataObject( wxString::FromUTF8( prettyData ) ) );
1760
1761 result &= wxTheClipboard->SetData( data );
1762 result &= wxTheClipboard->Flush(); // Allow data to be available after closing KiCad
1763 wxTheClipboard->Close();
1764 }
1765 }
1766
1767 if( selection.IsHover() )
1768 m_toolMgr->RunAction( ACTIONS::selectionClear );
1769
1770 if( aUseDuplicateClipboard )
1771 {
1772 m_duplicateClipboard = prettyData;
1773 return true;
1774 }
1775
1776 return result;
1777}
1778
1779
1780bool SCH_EDITOR_CONTROL::searchSupplementaryClipboard( const wxString& aSheetFilename, SCH_SCREEN** aScreen )
1781{
1782 if( m_supplementaryClipboard.count( aSheetFilename ) > 0 )
1783 {
1784 *aScreen = m_supplementaryClipboard[aSheetFilename];
1785 return true;
1786 }
1787
1788 return false;
1789}
1790
1791
1793{
1794 doCopy( true ); // Use the local clipboard
1795 Paste( aEvent );
1796
1797 return 0;
1798}
1799
1800
1802{
1803 wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( wxWindow::FindFocus() );
1804
1805 if( textEntry )
1806 {
1807 textEntry->Cut();
1808 return 0;
1809 }
1810
1811 if( doCopy() )
1812 m_toolMgr->RunAction( ACTIONS::doDelete );
1813
1814 return 0;
1815}
1816
1817
1819{
1820 wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( wxWindow::FindFocus() );
1821
1822 if( textEntry )
1823 {
1824 textEntry->Copy();
1825 return 0;
1826 }
1827
1828 doCopy();
1829
1830 return 0;
1831}
1832
1833
1835{
1836 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
1837 SCH_SELECTION& selection = selTool->RequestSelection();
1838
1839 if( selection.Empty() )
1840 return false;
1841
1842 wxString itemsAsText = GetSelectedItemsAsText( selection );
1843
1844 if( selection.IsHover() )
1845 m_toolMgr->RunAction( ACTIONS::selectionClear );
1846
1847 return SaveClipboard( itemsAsText.ToStdString() );
1848}
1849
1850
1852 const KIID_PATH& aClipPath, bool aForceKeepAnnotations )
1853{
1854 wxCHECK( m_frame && aSymbol, /* void */ );
1855
1856 SCH_SYMBOL_INSTANCE newInstance;
1857 bool instanceFound = false;
1858 KIID_PATH pasteLookupPath = aClipPath;
1859
1860 m_pastedSymbols.insert( aSymbol );
1861
1862 for( const SCH_SYMBOL_INSTANCE& tmp : aSymbol->GetInstances() )
1863 {
1864 if( ( tmp.m_Path.empty() && aClipPath.empty() ) || ( !aClipPath.empty() && tmp.m_Path.EndsWith( aClipPath ) ) )
1865 {
1866 newInstance = tmp;
1867 instanceFound = true;
1868
1869 wxLogTrace( traceSchPaste, wxS( "Pasting found symbol instance with reference %s, unit %d:\n"
1870 "\tClipboard path: %s\n"
1871 "\tSymbol UUID: %s." ),
1872 tmp.m_Reference,
1873 tmp.m_Unit,
1874 aClipPath.AsString(),
1875 aSymbol->m_Uuid.AsString() );
1876
1877 break;
1878 }
1879 }
1880
1881 // The pasted symbol look up paths include the symbol UUID.
1882 pasteLookupPath.push_back( aSymbol->m_Uuid );
1883
1884 if( !instanceFound )
1885 {
1886 wxLogTrace( traceSchPaste, wxS( "Clipboard symbol instance **not** found:\n\tClipboard path: %s\n"
1887 "\tSymbol UUID: %s." ),
1888 aClipPath.AsString(),
1889 aSymbol->m_Uuid.AsString() );
1890
1891 // Some legacy versions saved value fields escaped. While we still do in the symbol
1892 // editor, we don't anymore in the schematic, so be sure to unescape them.
1893 SCH_FIELD* valueField = aSymbol->GetField( FIELD_T::VALUE );
1894 valueField->SetText( UnescapeString( valueField->GetText() ) );
1895
1896 // Pasted from notepad or an older instance of eeschema. Use the values in the fields
1897 // instead.
1898 newInstance.m_Reference = aSymbol->GetField( FIELD_T::REFERENCE )->GetText();
1899 newInstance.m_Unit = aSymbol->GetUnit();
1900 }
1901
1902 newInstance.m_Path = aPastePath.Path();
1903 newInstance.m_ProjectName = m_frame->Prj().GetProjectName();
1904
1905 aSymbol->AddHierarchicalReference( newInstance );
1906
1907 if( !aForceKeepAnnotations )
1908 aSymbol->ClearAnnotation( &aPastePath, false );
1909
1910 // We might clear annotations but always leave the original unit number from the paste.
1911 aSymbol->SetUnit( newInstance.m_Unit );
1912}
1913
1914
1916 const KIID_PATH& aClipPath, bool aForceKeepAnnotations,
1917 SCH_SHEET_LIST* aPastedSheets, std::map<SCH_SHEET_PATH,
1918 SCH_REFERENCE_LIST>& aPastedSymbols )
1919{
1920 wxCHECK( aSheet && aPastedSheets, aPastePath );
1921
1922 SCH_SHEET_PATH sheetPath = aPastePath;
1923 sheetPath.push_back( aSheet );
1924
1925 aPastedSheets->push_back( sheetPath );
1926
1927 if( aSheet->GetScreen() == nullptr )
1928 return sheetPath; // We can only really set the page number but not load any items
1929
1930 for( SCH_ITEM* item : aSheet->GetScreen()->Items() )
1931 {
1932 if( item->IsConnectable() )
1933 item->SetConnectivityDirty();
1934
1935 if( item->Type() == SCH_SYMBOL_T )
1936 {
1937 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1938
1939 wxCHECK2( symbol, continue );
1940
1941 // Only do this once if the symbol is shared across multiple sheets.
1942 if( !m_pastedSymbols.count( symbol ) )
1943 {
1944 for( SCH_PIN* pin : symbol->GetPins() )
1945 {
1946 const_cast<KIID&>( pin->m_Uuid ) = KIID();
1947 pin->SetConnectivityDirty();
1948 }
1949 }
1950
1951 updatePastedSymbol( symbol, sheetPath, aClipPath, aForceKeepAnnotations );
1952 }
1953 else if( item->Type() == SCH_SHEET_T )
1954 {
1955 SCH_SHEET* subsheet = static_cast<SCH_SHEET*>( item );
1956
1957 wxCHECK2( subsheet, continue );
1958
1959 // Make sure pins get a new UUID and set the dirty connectivity flag.
1960 if( !aPastedSheets->ContainsSheet( subsheet ) )
1961 {
1962 for( SCH_SHEET_PIN* pin : subsheet->GetPins() )
1963 {
1964 const_cast<KIID&>( pin->m_Uuid ) = KIID();
1965 pin->SetConnectivityDirty();
1966 }
1967 }
1968
1969 KIID_PATH newClipPath = aClipPath;
1970 newClipPath.push_back( subsheet->m_Uuid );
1971
1972 updatePastedSheet( subsheet, sheetPath, newClipPath, aForceKeepAnnotations, aPastedSheets, aPastedSymbols );
1973 }
1974 }
1975
1976 sheetPath.GetSymbols( aPastedSymbols[aPastePath] );
1977
1978 return sheetPath;
1979}
1980
1981
1983{
1984 wxCHECK( aScreen, /* void */ );
1985
1986 for( const SCH_ITEM* item : aScreen->Items() )
1987 {
1988 if( item->Type() == SCH_SYMBOL_T )
1989 {
1990 const SCH_SYMBOL* symbol = static_cast<const SCH_SYMBOL*>( item );
1991
1992 wxCHECK2( symbol, continue );
1993
1994 for( const SCH_SYMBOL_INSTANCE& symbolInstance : symbol->GetInstances() )
1995 {
1996 KIID_PATH pathWithSymbol = symbolInstance.m_Path;
1997
1998 pathWithSymbol.push_back( symbol->m_Uuid );
1999
2000 m_clipboardSymbolInstances[pathWithSymbol] = symbolInstance;
2001 }
2002 }
2003 }
2004}
2005
2006
2008{
2009 wxCHECK( m_frame, /* void */ );
2010
2011 for( SCH_SYMBOL* symbol : m_pastedSymbols )
2012 {
2013 wxCHECK2( symbol, continue );
2014
2015 std::vector<KIID_PATH> instancePathsToRemove;
2016
2017 for( const SCH_SYMBOL_INSTANCE& instance : symbol->GetInstances() )
2018 {
2019 if( instance.m_ProjectName != m_frame->Prj().GetProjectName() || instance.m_Path.empty() )
2020 instancePathsToRemove.emplace_back( instance.m_Path );
2021 }
2022
2023 for( const KIID_PATH& path : instancePathsToRemove )
2024 symbol->RemoveInstance( path );
2025 }
2026}
2027
2028
2030{
2031 wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( wxWindow::FindFocus() );
2032
2033 if( textEntry )
2034 {
2035 textEntry->Paste();
2036 return 0;
2037 }
2038
2039 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
2040 std::string content;
2041 VECTOR2I eventPos;
2042
2043 SCH_SHEET tempSheet;
2044
2045 // Priority for paste:
2046 // 1. application/kicad format (handled by GetClipboardUTF8 which checks this first)
2047 // 2. Text data that can be parsed as KiCad S-expressions
2048 // 3. Bitmap/image data (fallback only if no valid text content)
2049 if( aEvent.IsAction( &ACTIONS::duplicate ) )
2050 content = m_duplicateClipboard;
2051 else
2052 content = GetClipboardUTF8();
2053
2054 // Only fall back to image data if there's no text content
2055 if( content.empty() )
2056 {
2057 std::unique_ptr<wxBitmap> clipImg = GetImageFromClipboard();
2058
2059 if( clipImg )
2060 {
2061 auto bitmap = std::make_unique<SCH_BITMAP>();
2062
2063 if( bitmap->GetReferenceImage().SetImage( clipImg->ConvertToImage() ) )
2064 return m_toolMgr->RunAction( SCH_ACTIONS::placeImage, bitmap.release() );
2065 }
2066
2067 return 0;
2068 }
2069
2070 if( aEvent.IsAction( &ACTIONS::duplicate ) )
2071 eventPos = getViewControls()->GetCursorPosition( false );
2072
2073 STRING_LINE_READER reader( content, "Clipboard" );
2074 SCH_IO_KICAD_SEXPR plugin;
2075
2076 // Screen object on heap is owned by the sheet.
2077 SCH_SCREEN* tempScreen = new SCH_SCREEN( &m_frame->Schematic() );
2078 tempSheet.SetScreen( tempScreen );
2079
2080 try
2081 {
2082 plugin.LoadContent( reader, &tempSheet );
2083 }
2084 catch( IO_ERROR& )
2085 {
2086 // If it wasn't schematic content, paste as a text object
2087 {
2088 if( content.size() > static_cast<size_t>( ADVANCED_CFG::GetCfg().m_MaxPastedTextLength ) )
2089 {
2090 int result = IsOK( m_frame, _( "Pasting a long text text string may be very slow. "
2091 "Do you want to continue?" ) );
2092 if( !result )
2093 return 0;
2094 }
2095
2096 SCH_TEXT* text_item = new SCH_TEXT( VECTOR2I( 0, 0 ), content );
2097 tempScreen->Append( text_item );
2098 }
2099 }
2100
2101 SELECTION& currentSelection = selTool->GetSelection();
2102
2103 bool hasTableCells = false;
2104
2105 for( EDA_ITEM* item : currentSelection )
2106 {
2107 if( item->Type() == SCH_TABLECELL_T )
2108 {
2109 hasTableCells = true;
2110 break;
2111 }
2112 }
2113
2114 if( hasTableCells )
2115 {
2116 SCH_TABLE* clipboardTable = nullptr;
2117
2118 for( SCH_ITEM* item : tempScreen->Items() )
2119 {
2120 if( item->Type() == SCH_TABLE_T )
2121 {
2122 clipboardTable = static_cast<SCH_TABLE*>( item );
2123 break;
2124 }
2125 }
2126
2127 if( clipboardTable )
2128 {
2129 SCH_EDIT_TABLE_TOOL* tableEditTool = m_toolMgr->GetTool<SCH_EDIT_TABLE_TOOL>();
2130
2131 if( tableEditTool )
2132 {
2133 wxString errorMsg;
2134
2135 if( !tableEditTool->validatePasteIntoSelection( currentSelection, errorMsg ) )
2136 {
2137 DisplayError( m_frame, errorMsg );
2138 return 0;
2139 }
2140
2141 SCH_COMMIT commit( m_toolMgr );
2142
2143 if( tableEditTool->pasteCellsIntoSelection( currentSelection, clipboardTable, commit ) )
2144 {
2145 commit.Push( _( "Paste Cells" ) );
2146 return 0;
2147 }
2148 else
2149 {
2150 DisplayError( m_frame, _( "Failed to paste cells" ) );
2151 return 0;
2152 }
2153 }
2154 }
2155 }
2156
2157 m_pastedSymbols.clear();
2159
2160 // Save pasted symbol instances in case the user chooses to keep existing symbol annotation.
2161 setPastedSymbolInstances( tempScreen );
2162
2163 tempScreen->MigrateSimModels();
2164
2165 bool annotateAutomatic = m_frame->eeconfig()->m_AnnotatePanel.automatic;
2166 SCHEMATIC_SETTINGS& schematicSettings = m_frame->Schematic().Settings();
2167 int annotateStartNum = schematicSettings.m_AnnotateStartNum;
2168
2170 bool forceRemoveAnnotations = false;
2171
2172 if( aEvent.IsAction( &ACTIONS::pasteSpecial ) )
2173 {
2174 PASTE_MODE defaultPasteMode = pasteMode;
2175 DIALOG_PASTE_SPECIAL dlg( m_frame, &pasteMode );
2176
2177 if( dlg.ShowModal() == wxID_CANCEL )
2178 return 0;
2179
2180 // We have to distinguish if removing was explicit
2181 forceRemoveAnnotations = pasteMode == PASTE_MODE::REMOVE_ANNOTATIONS && pasteMode != defaultPasteMode;
2182 }
2183
2184 bool forceKeepAnnotations = pasteMode != PASTE_MODE::REMOVE_ANNOTATIONS;
2185
2186 // SCH_SEXP_PLUGIN added the items to the paste screen, but not to the view or anything
2187 // else. Pull them back out to start with.
2188 SCH_COMMIT commit( m_toolMgr );
2189 EDA_ITEMS loadedItems;
2190 std::vector<SCH_ITEM*> sortedLoadedItems;
2191 bool sheetsPasted = false;
2192 SCH_SHEET_LIST hierarchy = m_frame->Schematic().Hierarchy();
2193 SCH_SHEET_PATH& pasteRoot = m_frame->GetCurrentSheet();
2194 wxFileName destFn = pasteRoot.Last()->GetFileName();
2195
2196 if( destFn.IsRelative() )
2197 destFn.MakeAbsolute( m_frame->Prj().GetProjectPath() );
2198
2199 // List of paths in the hierarchy that refer to the destination sheet of the paste
2200 SCH_SHEET_LIST sheetPathsForScreen = hierarchy.FindAllSheetsForScreen( pasteRoot.LastScreen() );
2201 sheetPathsForScreen.SortByPageNumbers();
2202
2203 // Build a list of screens from the current design (to avoid loading sheets that already exist)
2204 std::map<wxString, SCH_SCREEN*> loadedScreens;
2205
2206 for( const SCH_SHEET_PATH& item : hierarchy )
2207 {
2208 if( item.LastScreen() )
2209 loadedScreens[item.Last()->GetFileName()] = item.LastScreen();
2210 }
2211
2212 // Get set of sheet names in the current schematic to prevent duplicate sheet names on paste.
2213 std::set<wxString> existingSheetNames = pasteRoot.LastScreen()->GetSheetNames();
2214
2215 // Build symbol list for reannotation of duplicates
2216 SCH_REFERENCE_LIST existingRefs;
2217 hierarchy.GetSymbols( existingRefs );
2218 existingRefs.SortByReferenceOnly();
2219
2220 std::set<wxString> existingRefsSet;
2221
2222 for( const SCH_REFERENCE& ref : existingRefs )
2223 existingRefsSet.insert( ref.GetRef() );
2224
2225 // Build UUID map for fetching last-resolved-properties
2226 std::map<KIID, EDA_ITEM*> itemMap;
2227 hierarchy.FillItemMap( itemMap );
2228
2229 // Keep track of pasted sheets and symbols for the different paths to the hierarchy.
2230 std::map<SCH_SHEET_PATH, SCH_REFERENCE_LIST> pastedSymbols;
2231 std::map<SCH_SHEET_PATH, SCH_SHEET_LIST> pastedSheets;
2232
2233 for( SCH_ITEM* item : tempScreen->Items() )
2234 {
2235 if( item->Type() == SCH_SHEET_T )
2236 sortedLoadedItems.push_back( item );
2237 else
2238 loadedItems.push_back( item );
2239 }
2240
2241 sort( sortedLoadedItems.begin(), sortedLoadedItems.end(),
2242 []( SCH_ITEM* firstItem, SCH_ITEM* secondItem )
2243 {
2244 SCH_SHEET* firstSheet = static_cast<SCH_SHEET*>( firstItem );
2245 SCH_SHEET* secondSheet = static_cast<SCH_SHEET*>( secondItem );
2246 return StrNumCmp( firstSheet->GetName(), secondSheet->GetName(), false ) < 0;
2247 } );
2248
2249
2250 for( SCH_ITEM* item : sortedLoadedItems )
2251 {
2252 loadedItems.push_back( item );
2253
2254 if( item->Type() == SCH_SHEET_T )
2255 {
2256 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
2257 wxFileName srcFn = sheet->GetFileName();
2258
2259 if( srcFn.IsRelative() )
2260 srcFn.MakeAbsolute( m_frame->Prj().GetProjectPath() );
2261
2262 SCH_SHEET_LIST sheetHierarchy( sheet );
2263
2264 if( hierarchy.TestForRecursion( sheetHierarchy, destFn.GetFullPath( wxPATH_UNIX ) ) )
2265 {
2266 auto msg = wxString::Format( _( "The pasted sheet '%s'\n"
2267 "was dropped because the destination already has "
2268 "the sheet or one of its subsheets as a parent." ),
2269 sheet->GetFileName() );
2270 DisplayError( m_frame, msg );
2271 loadedItems.pop_back();
2272 }
2273 }
2274 }
2275
2276 // Remove the references from our temporary screen to prevent freeing on the DTOR
2277 tempScreen->Clear( false );
2278
2279 for( EDA_ITEM* item : loadedItems )
2280 {
2281 KIID_PATH clipPath( wxT( "/" ) ); // clipboard is at root
2282
2283 SCH_ITEM* schItem = static_cast<SCH_ITEM*>( item );
2284
2285 wxCHECK2( schItem, continue );
2286
2287 if( schItem->IsConnectable() )
2288 schItem->SetConnectivityDirty();
2289
2290 if( item->Type() == SCH_SYMBOL_T )
2291 {
2292 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
2293
2294 // The library symbol gets set from the cached library symbols in the current
2295 // schematic not the symbol libraries. The cached library symbol may have
2296 // changed from the original library symbol which would cause the copy to
2297 // be incorrect.
2298 SCH_SCREEN* currentScreen = m_frame->GetScreen();
2299
2300 wxCHECK2( currentScreen, continue );
2301
2302 // First get the library symbol from the clipboard (if available)
2303 auto clipIt = tempScreen->GetLibSymbols().find( symbol->GetSchSymbolLibraryName() );
2304 LIB_SYMBOL* clipLibSymbol = ( clipIt != tempScreen->GetLibSymbols().end() )
2305 ? clipIt->second
2306 : nullptr;
2307
2308 // Then check the current screen
2309 auto it = currentScreen->GetLibSymbols().find( symbol->GetSchSymbolLibraryName() );
2310 auto end = currentScreen->GetLibSymbols().end();
2311
2312 LIB_SYMBOL* libSymbol = nullptr;
2313
2314 if( it != end && clipLibSymbol )
2315 {
2316 // Both exist - check if power types match. If they differ (e.g., one is
2317 // local power and the other is global power), use the clipboard version
2318 // to preserve the copied symbol's power type.
2319 if( clipLibSymbol->IsLocalPower() != it->second->IsLocalPower()
2320 || clipLibSymbol->IsGlobalPower() != it->second->IsGlobalPower() )
2321 {
2322 libSymbol = new LIB_SYMBOL( *clipLibSymbol );
2323 }
2324 else
2325 {
2326 libSymbol = new LIB_SYMBOL( *it->second );
2327 }
2328 }
2329 else if( it != end )
2330 {
2331 libSymbol = new LIB_SYMBOL( *it->second );
2332 }
2333 else if( clipLibSymbol )
2334 {
2335 libSymbol = new LIB_SYMBOL( *clipLibSymbol );
2336 }
2337
2338 if( libSymbol )
2339 symbol->SetLibSymbol( libSymbol );
2340
2341 // If the symbol is already in the schematic we have to always keep the annotations. The exception
2342 // is if the user has chosen to remove them.
2343 for( const SCH_SYMBOL_INSTANCE& instance : symbol->GetInstances() )
2344 {
2345 if( !existingRefsSet.contains( instance.m_Reference ) )
2346 {
2347 forceKeepAnnotations = !forceRemoveAnnotations;
2348 break;
2349 }
2350 }
2351
2352 for( SCH_SHEET_PATH& sheetPath : sheetPathsForScreen )
2353 updatePastedSymbol( symbol, sheetPath, clipPath, forceKeepAnnotations );
2354
2355 // Most modes will need new KIIDs for the symbol and its pins. However, if we are pasting
2356 // unique annotations, we need to check if the symbol is not already in the hierarchy. If we
2357 // don't already have a copy of the symbol, we just keep the existing KIID data as it is likely
2358 // the same symbol being moved around the schematic.
2359 bool needsNewKiid = ( pasteMode == PASTE_MODE::UNIQUE_ANNOTATIONS );
2360
2361 for( const SCH_SYMBOL_INSTANCE& instance : symbol->GetInstances() )
2362 {
2363 if( existingRefsSet.contains( instance.m_Reference ) )
2364 {
2365 needsNewKiid = true;
2366 break;
2367 }
2368 }
2369
2370 if( needsNewKiid )
2371 {
2372 // Assign a new KIID
2373 const_cast<KIID&>( item->m_Uuid ) = KIID();
2374
2375 // Make sure pins get a new UUID
2376 for( SCH_PIN* pin : symbol->GetPins() )
2377 {
2378 const_cast<KIID&>( pin->m_Uuid ) = KIID();
2379 pin->SetConnectivityDirty();
2380 }
2381
2382 for( SCH_SHEET_PATH& sheetPath : sheetPathsForScreen )
2383 {
2384 // Ignore symbols from a non-existant library.
2385 if( libSymbol )
2386 {
2387 SCH_REFERENCE schReference( symbol, sheetPath );
2388 schReference.SetSheetNumber( sheetPath.GetPageNumberAsInt() );
2389 pastedSymbols[sheetPath].AddItem( schReference );
2390 }
2391 }
2392 }
2393 }
2394 else if( item->Type() == SCH_SHEET_T )
2395 {
2396 SCH_SHEET* sheet = (SCH_SHEET*) item;
2397 SCH_FIELD* nameField = sheet->GetField( FIELD_T::SHEET_NAME );
2398 wxString baseName = nameField->GetText();
2399 wxString candidateName = baseName;
2400 wxString number;
2401
2402 while( !baseName.IsEmpty() && wxIsdigit( baseName.Last() ) )
2403 {
2404 number = baseName.Last() + number;
2405 baseName.RemoveLast();
2406 }
2407
2408 // Update hierarchy to include any other sheets we already added, avoiding
2409 // duplicate sheet names
2410 hierarchy = m_frame->Schematic().Hierarchy();
2411
2412 int uniquifier = std::max( 0, wxAtoi( number ) ) + 1;
2413
2414 while( existingSheetNames.count( candidateName ) )
2415 candidateName = wxString::Format( wxT( "%s%d" ), baseName, uniquifier++ );
2416
2417 nameField->SetText( candidateName );
2418 existingSheetNames.emplace( candidateName );
2419
2420 wxFileName fn = sheet->GetFileName();
2421 SCH_SCREEN* existingScreen = nullptr;
2422
2423 sheet->SetParent( pasteRoot.Last() );
2424 sheet->SetScreen( nullptr );
2425
2426 if( !fn.IsAbsolute() )
2427 {
2428 wxFileName currentSheetFileName = pasteRoot.LastScreen()->GetFileName();
2429 fn.Normalize( FN_NORMALIZE_FLAGS | wxPATH_NORM_ENV_VARS, currentSheetFileName.GetPath() );
2430 }
2431
2432 // Try to find the screen for the pasted sheet by several means
2433 if( !m_frame->Schematic().Root().SearchHierarchy( fn.GetFullPath( wxPATH_UNIX ), &existingScreen ) )
2434 {
2435 if( loadedScreens.count( sheet->GetFileName() ) > 0 )
2436 existingScreen = loadedScreens.at( sheet->GetFileName() );
2437 else
2438 searchSupplementaryClipboard( sheet->GetFileName(), &existingScreen );
2439 }
2440
2441 if( existingScreen )
2442 {
2443 sheet->SetScreen( existingScreen );
2444 }
2445 else
2446 {
2447 if( !m_frame->LoadSheetFromFile( sheet, &pasteRoot, fn.GetFullPath() ) )
2448 m_frame->InitSheet( sheet, sheet->GetFileName() );
2449 }
2450
2451 // Save the symbol instances in case the user chooses to keep the existing
2452 // symbol annotation.
2454 sheetsPasted = true;
2455
2456 // Push it to the clipboard path while it still has its old KIID
2457 clipPath.push_back( sheet->m_Uuid );
2458
2459 // Assign a new KIID to the pasted sheet
2460 const_cast<KIID&>( sheet->m_Uuid ) = KIID();
2461
2462 // Make sure pins get a new UUID
2463 for( SCH_SHEET_PIN* pin : sheet->GetPins() )
2464 {
2465 const_cast<KIID&>( pin->m_Uuid ) = KIID();
2466 pin->SetConnectivityDirty();
2467 }
2468
2469 // Once we have our new KIID we can update all pasted instances. This will either
2470 // reset the annotations or copy "kept" annotations from the supplementary clipboard.
2471 for( SCH_SHEET_PATH& sheetPath : sheetPathsForScreen )
2472 {
2473 SCH_SHEET_PATH subPath = updatePastedSheet( sheet, sheetPath, clipPath,
2474 ( forceKeepAnnotations && annotateAutomatic ),
2475 &pastedSheets[sheetPath], pastedSymbols );
2476 }
2477 }
2478 else
2479 {
2480 SCH_ITEM* srcItem = dynamic_cast<SCH_ITEM*>( itemMap[item->m_Uuid] );
2481 SCH_ITEM* destItem = dynamic_cast<SCH_ITEM*>( item );
2482
2483 // Everything gets a new KIID
2484 const_cast<KIID&>( item->m_Uuid ) = KIID();
2485
2486 if( srcItem && destItem )
2487 {
2488 destItem->SetConnectivityDirty( true );
2489 destItem->SetLastResolvedState( srcItem );
2490 }
2491 }
2492
2493 // Lines need both ends selected for a move after paste so the whole line moves.
2494 if( item->Type() == SCH_LINE_T )
2495 item->SetFlags( STARTPOINT | ENDPOINT );
2496
2497 item->SetFlags( IS_NEW | IS_PASTED | IS_MOVING );
2498
2499 if( !m_frame->GetScreen()->CheckIfOnDrawList( (SCH_ITEM*) item ) ) // don't want a loop!
2500 m_frame->AddToScreen( item, m_frame->GetScreen() );
2501
2502 commit.Added( (SCH_ITEM*) item, m_frame->GetScreen() );
2503
2504 // Start out hidden so the pasted items aren't "ghosted" in their original location
2505 // before being moved to the current location.
2506 getView()->Hide( item, true );
2507 }
2508
2509 if( sheetsPasted )
2510 {
2511 // The full schematic hierarchy need to be update before assigning new annotation and
2512 // page numbers.
2513 m_frame->Schematic().RefreshHierarchy();
2514
2515 // Update page numbers: Find next free numeric page number
2516 for( SCH_SHEET_PATH& sheetPath : sheetPathsForScreen )
2517 {
2518 for( SCH_SHEET_PATH& pastedSheet : pastedSheets[sheetPath] )
2519 {
2520 int page = 1;
2521 wxString pageNum = wxString::Format( "%d", page );
2522
2523 while( hierarchy.PageNumberExists( pageNum ) )
2524 pageNum = wxString::Format( "%d", ++page );
2525
2526 SCH_SHEET_INSTANCE sheetInstance;
2527
2528 sheetInstance.m_Path = pastedSheet.Path();
2529
2530 // Don't include the actual sheet in the instance path.
2531 sheetInstance.m_Path.pop_back();
2532 sheetInstance.m_PageNumber = pageNum;
2533 sheetInstance.m_ProjectName = m_frame->Prj().GetProjectName();
2534
2535 SCH_SHEET* sheet = pastedSheet.Last();
2536
2537 wxCHECK2( sheet, continue );
2538
2539 sheet->AddInstance( sheetInstance );
2540 hierarchy.push_back( pastedSheet );
2541
2542 // Remove all pasted sheet instance data that is not part of the current project.
2543 std::vector<KIID_PATH> instancesToRemove;
2544
2545 for( const SCH_SHEET_INSTANCE& instance : sheet->GetInstances() )
2546 {
2547 if( !hierarchy.HasPath( instance.m_Path ) )
2548 instancesToRemove.push_back( instance.m_Path );
2549 }
2550
2551 for( const KIID_PATH& instancePath : instancesToRemove )
2552 sheet->RemoveInstance( instancePath );
2553 }
2554 }
2555
2556 m_frame->SetSheetNumberAndCount();
2557
2558 // Get a version with correct sheet numbers since we've pasted sheets,
2559 // we'll need this when annotating next
2560 hierarchy = m_frame->Schematic().Hierarchy();
2561 }
2562
2563 std::map<SCH_SHEET_PATH, SCH_REFERENCE_LIST> annotatedSymbols;
2564
2565 // Update the list of symbol instances that satisfy the annotation criteria.
2566 for( const SCH_SHEET_PATH& sheetPath : sheetPathsForScreen )
2567 {
2568 for( size_t i = 0; i < pastedSymbols[sheetPath].GetCount(); i++ )
2569 {
2570 if( pasteMode == PASTE_MODE::UNIQUE_ANNOTATIONS || pastedSymbols[sheetPath][i].AlwaysAnnotate() )
2571 annotatedSymbols[sheetPath].AddItem( pastedSymbols[sheetPath][i] );
2572 }
2573
2574 for( const SCH_SHEET_PATH& pastedSheetPath : pastedSheets[sheetPath] )
2575 {
2576 for( size_t i = 0; i < pastedSymbols[pastedSheetPath].GetCount(); i++ )
2577 {
2578 if( pasteMode == PASTE_MODE::UNIQUE_ANNOTATIONS || pastedSymbols[pastedSheetPath][i].AlwaysAnnotate() )
2579 annotatedSymbols[pastedSheetPath].AddItem( pastedSymbols[pastedSheetPath][i] );
2580 }
2581 }
2582 }
2583
2584 if( !annotatedSymbols.empty() )
2585 {
2586 ANNOTATE_ORDER_T annotateOrder = static_cast<ANNOTATE_ORDER_T>( schematicSettings.m_AnnotateSortOrder );
2587 ANNOTATE_ALGO_T annotateAlgo = static_cast<ANNOTATE_ALGO_T>( schematicSettings.m_AnnotateMethod );
2588
2589 for( SCH_SHEET_PATH& path : sheetPathsForScreen )
2590 {
2591 annotatedSymbols[path].SortByReferenceOnly();
2592 annotatedSymbols[path].SetRefDesTracker( schematicSettings.m_refDesTracker );
2593
2594 if( pasteMode == PASTE_MODE::UNIQUE_ANNOTATIONS )
2595 {
2596 annotatedSymbols[path].ReannotateDuplicates( existingRefs, annotateAlgo );
2597 }
2598 else
2599 {
2600 annotatedSymbols[path].ReannotateByOptions( annotateOrder, annotateAlgo, annotateStartNum,
2601 existingRefs, false, &hierarchy );
2602 }
2603
2604 annotatedSymbols[path].UpdateAnnotation();
2605
2606 // Update existing refs for next iteration
2607 for( size_t i = 0; i < annotatedSymbols[path].GetCount(); i++ )
2608 existingRefs.AddItem( annotatedSymbols[path][i] );
2609
2610 for( const SCH_SHEET_PATH& pastedSheetPath : pastedSheets[path] )
2611 {
2612 annotatedSymbols[pastedSheetPath].SortByReferenceOnly();
2613 annotatedSymbols[pastedSheetPath].SetRefDesTracker( schematicSettings.m_refDesTracker );
2614
2615 if( pasteMode == PASTE_MODE::UNIQUE_ANNOTATIONS )
2616 {
2617 annotatedSymbols[pastedSheetPath].ReannotateDuplicates( existingRefs, annotateAlgo );
2618 }
2619 else
2620 {
2621 annotatedSymbols[pastedSheetPath].ReannotateByOptions( annotateOrder, annotateAlgo,
2622 annotateStartNum, existingRefs,
2623 false, &hierarchy );
2624 }
2625
2626 annotatedSymbols[pastedSheetPath].UpdateAnnotation();
2627
2628 // Update existing refs for next iteration
2629 for( size_t i = 0; i < annotatedSymbols[pastedSheetPath].GetCount(); i++ )
2630 existingRefs.AddItem( annotatedSymbols[pastedSheetPath][i] );
2631 }
2632 }
2633 }
2634
2635 m_frame->GetCurrentSheet().UpdateAllScreenReferences();
2636
2637 // The copy operation creates instance paths that are not valid for the current project or
2638 // saved as part of another project. Prune them now so they do not accumulate in the saved
2639 // schematic file.
2641
2642 SCH_SHEET_LIST sheets = m_frame->Schematic().Hierarchy();
2643 SCH_SCREENS allScreens( m_frame->Schematic().Root() );
2644
2645 allScreens.PruneOrphanedSymbolInstances( m_frame->Prj().GetProjectName(), sheets );
2646 allScreens.PruneOrphanedSheetInstances( m_frame->Prj().GetProjectName(), sheets );
2647
2648 // Now clear the previous selection, select the pasted items, and fire up the "move" tool.
2649 m_toolMgr->RunAction( ACTIONS::selectionClear );
2650
2651 // If the item has a parent group, it will be part of the loadedItems, and will handle
2652 // the move action. Iterate backwards to avoid invalidating the iterator.
2653 for( int i = loadedItems.size() - 1; i >= 0; i-- )
2654 {
2655 EDA_ITEM* item = loadedItems[i];
2656
2657 if( item->GetParentGroup() )
2658 {
2659 loadedItems.erase( loadedItems.begin() + i );
2660 // These were hidden before because they would be added to the move preview,
2661 // but now they need to be shown as a preview so they appear to move when
2662 // the group moves.
2663 getView()->SetVisible( item );
2664 getView()->AddToPreview( item, false );
2665 }
2666 }
2667
2668 m_toolMgr->RunAction<EDA_ITEMS*>( ACTIONS::selectItems, &loadedItems );
2669
2670 SCH_SELECTION& selection = selTool->GetSelection();
2671
2672 if( !selection.Empty() )
2673 {
2674 if( aEvent.IsAction( &ACTIONS::duplicate ) )
2675 {
2676 int closest_dist = INT_MAX;
2677
2678 auto processPt =
2679 [&]( const VECTOR2I& pt )
2680 {
2681 int dist = ( eventPos - pt ).EuclideanNorm();
2682
2683 if( dist < closest_dist )
2684 {
2685 selection.SetReferencePoint( pt );
2686 closest_dist = dist;
2687 }
2688 };
2689
2690 // Prefer connection points (which should remain on grid)
2691 for( EDA_ITEM* item : selection.Items() )
2692 {
2693 SCH_ITEM* sch_item = dynamic_cast<SCH_ITEM*>( item );
2694 SCH_PIN* pin = dynamic_cast<SCH_PIN*>( item );
2695
2696 if( sch_item && sch_item->IsConnectable() )
2697 {
2698 for( const VECTOR2I& pt : sch_item->GetConnectionPoints() )
2699 processPt( pt );
2700 }
2701 else if( pin )
2702 {
2703 processPt( pin->GetPosition() );
2704 }
2705
2706 // Symbols need to have their center point added since often users are trying to
2707 // move parts from their center.
2708 if( dynamic_cast<SCH_SYMBOL*>( item ) )
2709 processPt( item->GetPosition() );
2710 }
2711
2712 // Only process other points if we didn't find any connection points
2713 if( closest_dist == INT_MAX )
2714 {
2715 for( EDA_ITEM* item : selection.Items() )
2716 {
2717 switch( item->Type() )
2718 {
2719 case SCH_LINE_T:
2720 processPt( static_cast<SCH_LINE*>( item )->GetStartPoint() );
2721 processPt( static_cast<SCH_LINE*>( item )->GetEndPoint() );
2722 break;
2723
2724 case SCH_SHAPE_T:
2725 {
2726 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( item );
2727
2728 switch( shape->GetShape() )
2729 {
2730 case SHAPE_T::RECTANGLE:
2731 for( const VECTOR2I& pt : shape->GetRectCorners() )
2732 processPt( pt );
2733
2734 break;
2735
2736 case SHAPE_T::CIRCLE:
2737 processPt( shape->GetCenter() );
2738 break;
2739
2740 case SHAPE_T::POLY:
2741 for( int ii = 0; ii < shape->GetPolyShape().TotalVertices(); ++ii )
2742 processPt( shape->GetPolyShape().CVertex( ii ) );
2743
2744 break;
2745
2746 default:
2747 processPt( shape->GetStart() );
2748 processPt( shape->GetEnd() );
2749 break;
2750 }
2751
2752 break;
2753 }
2754
2755 default:
2756 processPt( item->GetPosition() );
2757 break;
2758 }
2759 }
2760 }
2761
2762 selection.SetIsHover( m_duplicateIsHoverSelection );
2763 }
2764 // We want to the first non-group item in the selection to be the reference point.
2765 else if( selection.GetTopLeftItem()->Type() == SCH_GROUP_T )
2766 {
2767 SCH_GROUP* group = static_cast<SCH_GROUP*>( selection.GetTopLeftItem() );
2768
2769 bool found = false;
2770 SCH_ITEM* item = nullptr;
2771
2772 group->RunOnChildren(
2773 [&]( SCH_ITEM* schItem )
2774 {
2775 if( !found && schItem->Type() != SCH_GROUP_T )
2776 {
2777 item = schItem;
2778 found = true;
2779 }
2780 },
2782
2783 if( found )
2784 selection.SetReferencePoint( item->GetPosition() );
2785 else
2786 selection.SetReferencePoint( group->GetPosition() );
2787 }
2788 else
2789 {
2790 SCH_ITEM* item = static_cast<SCH_ITEM*>( selection.GetTopLeftItem() );
2791
2792 selection.SetReferencePoint( item->GetPosition() );
2793 }
2794
2795 if( m_toolMgr->RunSynchronousAction( SCH_ACTIONS::move, &commit ) )
2796 {
2797 // Pushing the commit will update the connectivity.
2798 commit.Push( _( "Paste" ) );
2799
2800 if( sheetsPasted )
2801 {
2802 m_frame->UpdateHierarchyNavigator();
2803 // UpdateHierarchyNavigator() will call RefreshNetNavigator()
2804 }
2805 else
2806 {
2807 m_frame->RefreshNetNavigator();
2808 }
2809 }
2810 else
2811 {
2812 commit.Revert();
2813 }
2814
2815 getView()->ClearPreview();
2816 }
2817
2818 return 0;
2819}
2820
2821
2823{
2824 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
2825 SCH_SELECTION& selection = selTool->RequestSelection( { SCH_SYMBOL_T } );
2826 SCH_SYMBOL* symbol = nullptr;
2827 SYMBOL_EDIT_FRAME* symbolEditor;
2828
2829 if( selection.GetSize() >= 1 )
2830 symbol = (SCH_SYMBOL*) selection.Front();
2831
2832 if( selection.IsHover() )
2833 m_toolMgr->RunAction( ACTIONS::selectionClear );
2834
2835 if( !symbol )
2836 {
2837 // Giant hack: by default we assign Edit Table to the same hotkey, so give the table
2838 // tool a chance to handle it if we can't.
2839 if( SCH_EDIT_TABLE_TOOL* tableTool = m_toolMgr->GetTool<SCH_EDIT_TABLE_TOOL>() )
2840 tableTool->EditTable( aEvent );
2841
2842 return 0;
2843 }
2844
2845 if( symbol->GetEditFlags() != 0 )
2846 return 0;
2847
2848 if( symbol->IsMissingLibSymbol() )
2849 {
2850 m_frame->ShowInfoBarError( _( "Symbols with broken library symbol links cannot be edited." ) );
2851 return 0;
2852 }
2853
2855 symbolEditor = (SYMBOL_EDIT_FRAME*) m_frame->Kiway().Player( FRAME_SCH_SYMBOL_EDITOR, false );
2856
2857 if( symbolEditor )
2858 {
2859 if( wxWindow* blocking_win = symbolEditor->Kiway().GetBlockingDialog() )
2860 blocking_win->Close( true );
2861
2862 if( aEvent.IsAction( &SCH_ACTIONS::editWithLibEdit ) )
2863 {
2864 symbolEditor->LoadSymbolFromSchematic( symbol );
2865 }
2867 {
2868 symbolEditor->LoadSymbol( symbol->GetLibId(), symbol->GetUnit(), symbol->GetBodyStyle() );
2869
2870 if( !symbolEditor->IsLibraryTreeShown() )
2871 symbolEditor->ToggleLibraryTree();
2872 }
2873 }
2874
2875 return 0;
2876}
2877
2878
2880{
2881 m_frame->OnAnnotate();
2882 return 0;
2883}
2884
2885
2887{
2889 dlg.m_FirstRefDes->SetValidator( wxTextValidator( wxFILTER_EMPTY ) );
2890
2891 dlg.SetInitialFocus( dlg.m_FirstRefDes );
2892
2893 if( dlg.ShowModal() == wxID_OK )
2894 {
2895 SCH_REFERENCE startRef;
2896 startRef.SetRef( dlg.m_FirstRefDes->GetValue() );
2897
2898 if( startRef.IsSplitNeeded() )
2899 startRef.Split();
2900 else
2901 return 0;
2902
2903 int startNum = atoi( startRef.GetRefNumber().utf8_string().c_str() );
2904
2905 SCH_COMMIT commit( m_frame );
2906 SCHEMATIC* schematic = m_frame->m_schematic;
2907 SCH_REFERENCE_LIST references;
2908
2909 if( dlg.m_AllSheets->GetValue() )
2910 schematic->Hierarchy().GetSymbols( references );
2911 else
2912 schematic->CurrentSheet().GetSymbols( references );
2913
2914 references.SplitReferences();
2915
2916 for( SCH_REFERENCE& ref : references )
2917 {
2918 if( ref.GetRef() == startRef.GetRef() )
2919 {
2920 int num = atoi( ref.GetRefNumber().utf8_string().c_str() );
2921
2922 if( num >= startNum )
2923 {
2924 const SCH_SHEET_PATH& sheet = ref.GetSheetPath();
2925 wxString fullRef = ref.GetRef();
2926
2927 num += dlg.m_Increment->GetValue();
2928 fullRef << num;
2929
2930 commit.Modify( ref.GetSymbol(), sheet.LastScreen(), RECURSE_MODE::NO_RECURSE );
2931 ref.GetSymbol()->SetRef( &sheet, From_UTF8( fullRef.c_str() ) );
2932 }
2933 }
2934 }
2935
2936 if( !commit.Empty() )
2937 commit.Push( _( "Increment Annotations" ) );
2938 }
2939
2940 return 0;
2941}
2942
2943
2945{
2946 m_frame->OnOpenCvpcb();
2947 return 0;
2948}
2949
2950
2952{
2953 DIALOG_SYMBOL_FIELDS_TABLE* dlg = m_frame->GetSymbolFieldsTableDialog();
2954
2955 wxCHECK( dlg, 0 );
2956
2957 // Needed at least on Windows. Raise() is not enough
2958 dlg->Show( true );
2959
2960 // Bring it to the top if already open. Dual monitor users need this.
2961 dlg->Raise();
2962
2963 return 0;
2964}
2965
2966
2968{
2970 m_frame->HardRedraw();
2971
2972 return 0;
2973}
2974
2975
2977{
2978 m_frame->OnOpenPcbnew();
2979 return 0;
2980}
2981
2982
2984{
2985 m_frame->OnUpdatePCB();
2986 return 0;
2987}
2988
2989
2991{
2993 dlg.ShowModal();
2994 return 0;
2995}
2996
2997
2999{
3001
3002 // If a plugin is removed or added, rebuild and reopen the new dialog
3003 while( result == NET_PLUGIN_CHANGE )
3005
3006 return 0;
3007}
3008
3009
3011{
3012 DIALOG_SYMBOL_FIELDS_TABLE* dlg = m_frame->GetSymbolFieldsTableDialog();
3013
3014 wxCHECK( dlg, 0 );
3015
3016 // Needed at least on Windows. Raise() is not enough
3017 dlg->Show( true );
3018
3019 // Bring it to the top if already open. Dual monitor users need this.
3020 dlg->Raise();
3021
3022 dlg->ShowExportTab();
3023
3024 return 0;
3025}
3026
3027
3029{
3031 return 0;
3032}
3033
3034
3036{
3037 m_frame->RecalculateConnections( nullptr, LOCAL_CLEANUP );
3038
3039 // Create a selection with all items from the current sheet
3040 SCH_SELECTION sheetSelection;
3041 SCH_SCREEN* screen = m_frame->GetScreen();
3042
3043 for( SCH_ITEM* item : screen->Items() )
3044 {
3045 sheetSelection.Add( item );
3046 }
3047
3048 // Get the full page bounding box for rendering the complete sheet
3049 BOX2I pageBBox( VECTOR2I( 0, 0 ), m_frame->GetPageSizeIU() );
3050
3051 // Render the full sheet selection including the worksheet
3052 wxImage image = renderSelectionToImageForClipboard( m_frame, sheetSelection, pageBBox, true, true );
3053
3054 if( image.IsOk() )
3055 {
3056 wxLogNull doNotLog; // disable logging of failed clipboard actions
3057
3058 if( wxTheClipboard->Open() )
3059 {
3060 wxDataObjectComposite* data = new wxDataObjectComposite();
3061
3063
3064 wxTheClipboard->SetData( data );
3065 wxTheClipboard->Flush(); // Allow data to be available after closing KiCad
3066 wxTheClipboard->Close();
3067 }
3068 }
3069 else
3070 {
3071 wxLogMessage( _( "Cannot create the schematic image" ) );
3072 }
3073
3074 return 0;
3075}
3076
3077
3079{
3081 return 0;
3082}
3083
3084
3090
3091
3097
3098
3104
3105
3111
3112
3118
3119
3121{
3122 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3124
3126 m_frame->GetCanvas()->Refresh();
3127
3128 return 0;
3129}
3130
3131
3133{
3134 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3136
3137 m_frame->GetRenderSettings()->m_ShowHiddenFields = cfg->m_Appearance.show_hidden_fields;
3138
3140 m_frame->GetCanvas()->Refresh();
3141
3142 return 0;
3143}
3144
3145
3147{
3148 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3150
3152 m_frame->GetCanvas()->Refresh();
3153
3154 return 0;
3155}
3156
3157
3159{
3160 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3162
3164 m_frame->GetCanvas()->Refresh();
3165
3166 return 0;
3167}
3168
3169
3171{
3172 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3174
3176 m_frame->GetCanvas()->Refresh();
3177
3178 return 0;
3179}
3180
3181
3183{
3184 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3186
3187 m_frame->GetCanvas()->Refresh();
3188
3189 return 0;
3190}
3191
3192
3194{
3195 SCH_SHEET_PATH* sheetPath = &m_frame->GetCurrentSheet();
3196 wxString variant = m_frame->Schematic().GetCurrentVariant();
3197 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3199
3200 m_frame->GetCanvas()->GetView()->UpdateAllItemsConditionally(
3201 [&]( KIGFX::VIEW_ITEM* aItem ) -> int
3202 {
3203 int flags = 0;
3204
3205 auto invalidateTextVars =
3206 [&flags]( EDA_TEXT* text )
3207 {
3208 if( text->HasTextVars() )
3209 {
3210 text->ClearRenderCache();
3211 text->ClearBoundingBoxCache();
3213 }
3214 };
3215
3216 if( SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( aItem ) )
3217 {
3218 item->RunOnChildren(
3219 [&invalidateTextVars]( SCH_ITEM* aChild )
3220 {
3221 if( EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( aChild ) )
3222 invalidateTextVars( text );
3223 },
3225
3226 if( item->GetExcludedFromSim( sheetPath, variant ) )
3228 }
3229
3230 if( EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( aItem ) )
3231 invalidateTextVars( text );
3232
3233 return flags;
3234 } );
3235
3236 m_frame->GetCanvas()->Refresh();
3237
3238 return 0;
3239}
3240
3241
3243{
3244 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3246
3248 m_frame->RefreshOperatingPointDisplay();
3249 m_frame->GetCanvas()->Refresh();
3250
3251 return 0;
3252}
3253
3254
3256{
3257 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3259
3261 m_frame->RefreshOperatingPointDisplay();
3262 m_frame->GetCanvas()->Refresh();
3263
3264 return 0;
3265}
3266
3267
3269{
3270 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3272
3273 m_frame->GetRenderSettings()->m_ShowPinAltIcons = cfg->m_Appearance.show_pin_alt_icons;
3274
3276 m_frame->GetCanvas()->Refresh();
3277
3278 return 0;
3279}
3280
3281
3283{
3284 m_frame->eeconfig()->m_Drawing.line_mode = aEvent.Parameter<LINE_MODE>();
3285 m_toolMgr->PostAction( ACTIONS::refreshPreview );
3286 // Notify toolbar to update selection
3288 return 0;
3289}
3290
3291
3293{
3294 m_frame->eeconfig()->m_Drawing.line_mode++;
3295 m_frame->eeconfig()->m_Drawing.line_mode %= LINE_MODE::LINE_MODE_COUNT;
3296 m_toolMgr->PostAction( ACTIONS::refreshPreview );
3297 // Notify toolbar to update selection
3299 return 0;
3300}
3301
3302
3304{
3305 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3307 return 0;
3308}
3309
3310
3312{
3313 m_frame->ScriptingConsoleEnableDisable();
3314 return 0;
3315}
3316
3317
3319{
3320#ifdef KICAD_IPC_API
3321 if( Pgm().GetCommonSettings()->m_Api.enable_server )
3322 Pgm().GetPluginManager().ReloadPlugins();
3323#endif
3324 return 0;
3325}
3326
3328{
3329 // Update the left toolbar Line modes group icon to match current mode
3330 switch( static_cast<LINE_MODE>( m_frame->eeconfig()->m_Drawing.line_mode ) )
3331 {
3332 case LINE_MODE::LINE_MODE_FREE: m_frame->SelectToolbarAction( SCH_ACTIONS::lineModeFree ); break;
3333 case LINE_MODE::LINE_MODE_90: m_frame->SelectToolbarAction( SCH_ACTIONS::lineMode90 ); break;
3334 default:
3335 case LINE_MODE::LINE_MODE_45: m_frame->SelectToolbarAction( SCH_ACTIONS::lineMode45 ); break;
3336 }
3337
3338 return 0;
3339}
3340
3341
3343{
3344 if( !Pgm().GetCommonSettings()->m_Input.hotkey_feedback )
3345 return 0;
3346
3347 GRID_SETTINGS& gridSettings = m_toolMgr->GetSettings()->m_Window.grid;
3348 int currentIdx = m_toolMgr->GetSettings()->m_Window.grid.last_size_idx;
3349
3350 wxArrayString gridsLabels;
3351
3352 for( const GRID& grid : gridSettings.grids )
3353 gridsLabels.Add( grid.UserUnitsMessageText( m_frame ) );
3354
3355 if( !m_frame->GetHotkeyPopup() )
3356 m_frame->CreateHotkeyPopup();
3357
3358 HOTKEY_CYCLE_POPUP* popup = m_frame->GetHotkeyPopup();
3359
3360 if( popup )
3361 popup->Popup( _( "Grid" ), gridsLabels, currentIdx );
3362
3363 return 0;
3364}
3365
3366
3368{
3369 SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
3370
3371 if( !editFrame )
3372 return 1;
3373
3374 // Need to have a group selected and it needs to have a linked design block
3375 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
3376 SCH_SELECTION selection = selTool->GetSelection();
3377
3378 if( selection.Size() != 1 || selection[0]->Type() != SCH_GROUP_T )
3379 return 1;
3380
3381 SCH_GROUP* group = static_cast<SCH_GROUP*>( selection[0] );
3382
3383 if( !group->HasDesignBlockLink() )
3384 return 1;
3385
3386 // Get the associated design block
3387 DESIGN_BLOCK_PANE* designBlockPane = editFrame->GetDesignBlockPane();
3388 std::unique_ptr<DESIGN_BLOCK> designBlock( designBlockPane->GetDesignBlock( group->GetDesignBlockLibId(),
3389 true, true ) );
3390
3391 if( !designBlock )
3392 {
3393 wxString msg;
3394 msg.Printf( _( "Could not find design block %s." ), group->GetDesignBlockLibId().GetUniStringLibId() );
3395 m_frame->GetInfoBar()->ShowMessageFor( msg, 5000, wxICON_WARNING );
3396 return 1;
3397 }
3398
3399 if( designBlock->GetSchematicFile().IsEmpty() )
3400 {
3401 wxString msg;
3402 msg.Printf( _( "Design block %s does not have a schematic file." ),
3403 group->GetDesignBlockLibId().GetUniStringLibId() );
3404 m_frame->GetInfoBar()->ShowMessageFor( msg, 5000, wxICON_WARNING );
3405 return 1;
3406 }
3407
3408 editFrame->GetDesignBlockPane()->SelectLibId( group->GetDesignBlockLibId() );
3409
3410 return m_toolMgr->RunAction( SCH_ACTIONS::placeDesignBlock, designBlock.release() );
3411}
3412
3413
3415{
3416 SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
3417
3418 if( !editFrame )
3419 return 1;
3420
3421 // Need to have a group selected and it needs to have a linked design block
3422 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
3423 SCH_SELECTION selection = selTool->GetSelection();
3424
3425 if( selection.Size() != 1 || selection[0]->Type() != SCH_GROUP_T )
3426 return 1;
3427
3428 SCH_GROUP* group = static_cast<SCH_GROUP*>( selection[0] );
3429
3430 if( !group->HasDesignBlockLink() )
3431 return 1;
3432
3433 // Get the associated design block
3434 DESIGN_BLOCK_PANE* designBlockPane = editFrame->GetDesignBlockPane();
3435 std::unique_ptr<DESIGN_BLOCK> designBlock( designBlockPane->GetDesignBlock( group->GetDesignBlockLibId(),
3436 true, true ) );
3437
3438 if( !designBlock )
3439 {
3440 wxString msg;
3441 msg.Printf( _( "Could not find design block %s." ), group->GetDesignBlockLibId().GetUniStringLibId() );
3442 m_frame->GetInfoBar()->ShowMessageFor( msg, 5000, wxICON_WARNING );
3443 return 1;
3444 }
3445
3446 editFrame->GetDesignBlockPane()->SelectLibId( group->GetDesignBlockLibId() );
3447
3448 return m_toolMgr->RunAction( SCH_ACTIONS::updateDesignBlockFromSelection ) ? 1 : 0;
3449}
3450
3451
3453{
3454 SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
3455
3456 if( !editFrame )
3457 return 1;
3458
3459 editFrame->AddVariant();
3460
3461 return 0;
3462}
3463
3464
3466{
3467 SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
3468
3469 if( !editFrame )
3470 return 1;
3471
3472 editFrame->RemoveVariant();
3473 return 0;
3474}
3475
3476
3478{
3479 Go( &SCH_EDITOR_CONTROL::New, ACTIONS::doNew.MakeEvent() );
3480 Go( &SCH_EDITOR_CONTROL::Open, ACTIONS::open.MakeEvent() );
3481 Go( &SCH_EDITOR_CONTROL::Save, ACTIONS::save.MakeEvent() );
3488 Go( &SCH_EDITOR_CONTROL::Plot, ACTIONS::plot.MakeEvent() );
3489
3492
3498
3501
3507
3510
3511 Go( &SCH_EDITOR_CONTROL::Undo, ACTIONS::undo.MakeEvent() );
3512 Go( &SCH_EDITOR_CONTROL::Redo, ACTIONS::redo.MakeEvent() );
3513 Go( &SCH_EDITOR_CONTROL::Cut, ACTIONS::cut.MakeEvent() );
3514 Go( &SCH_EDITOR_CONTROL::Copy, ACTIONS::copy.MakeEvent() );
3519
3521
3537
3545
3562
3564
3566
3569
3572}
const char * name
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:114
BOX2< VECTOR2I > BOX2I
Definition box2.h:922
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:990
static TOOL_ACTION updatePcbFromSchematic
Definition actions.h:264
static TOOL_ACTION paste
Definition actions.h:80
static TOOL_ACTION revert
Definition actions.h:62
static TOOL_ACTION saveAs
Definition actions.h:59
static TOOL_ACTION copy
Definition actions.h:78
static TOOL_ACTION pluginsReload
Definition actions.h:294
static TOOL_ACTION pickerTool
Definition actions.h:253
static TOOL_ACTION showSymbolEditor
Definition actions.h:260
static TOOL_ACTION pasteSpecial
Definition actions.h:81
static TOOL_ACTION plot
Definition actions.h:65
static TOOL_ACTION open
Definition actions.h:57
static TOOL_ACTION pageSettings
Definition actions.h:63
static TOOL_ACTION showSearch
Definition actions.h:116
static TOOL_ACTION undo
Definition actions.h:75
static TOOL_ACTION selectionActivate
Activation of the selection tool.
Definition actions.h:214
static TOOL_ACTION duplicate
Definition actions.h:84
static TOOL_ACTION doDelete
Definition actions.h:85
static TOOL_ACTION save
Definition actions.h:58
static TOOL_ACTION redo
Definition actions.h:76
static TOOL_ACTION updateSchematicFromPcb
Definition actions.h:265
static TOOL_ACTION selectionClear
Clear the current selection.
Definition actions.h:224
static TOOL_ACTION print
Definition actions.h:64
static TOOL_ACTION showProperties
Definition actions.h:266
static TOOL_ACTION doNew
Definition actions.h:54
static TOOL_ACTION cut
Definition actions.h:77
static TOOL_ACTION copyAsText
Definition actions.h:79
static TOOL_ACTION refreshPreview
Definition actions.h:159
static TOOL_ACTION selectItems
Select a list of items (specified as the event parameter)
Definition actions.h:232
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
int GetPageCount() const
Definition base_screen.h:72
int GetVirtualPageNumber() const
Definition base_screen.h:75
static wxString m_DrawingSheetFileName
the name of the drawing sheet file, or empty to use the default drawing sheet
Definition base_screen.h:85
const wxString & GetPageNumber() const
void SetContentModified(bool aModified=true)
Definition base_screen.h:59
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 size_type GetWidth() const
Definition box2.h:214
constexpr Vec Centre() const
Definition box2.h:97
constexpr size_type GetHeight() const
Definition box2.h:215
constexpr const Vec & GetOrigin() const
Definition box2.h:210
constexpr const SizeVec & GetSize() const
Definition box2.h:206
int GetCount() const
Return the number of objects in the list.
Definition collector.h:83
int m_Threshold
Definition collector.h:236
static const COLOR4D CLEAR
Definition color4d.h:407
COMMIT & Added(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Notify observers that aItem has been added.
Definition commit.h:84
bool Empty() const
Definition commit.h:137
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr, RECURSE_MODE aRecurse=RECURSE_MODE::NO_RECURSE)
Modify a given item in the model.
Definition commit.h:106
Calculate the connectivity of a schematic and generates netlists.
CONNECTION_SUBGRAPH * FindSubgraphByName(const wxString &aNetName, const SCH_SHEET_PATH &aPath)
Return the subgraph for a given net name on a given sheet.
const std::vector< CONNECTION_SUBGRAPH * > & GetAllSubgraphs(const wxString &aNetName) const
A subgraph is a set of items that are electrically connected on a single sheet.
static PRIORITY GetDriverPriority(SCH_ITEM *aDriver)
Return the priority (higher is more important) of a candidate driver.
void SelectLibId(const LIB_ID &aLibId)
DESIGN_BLOCK * GetDesignBlock(const LIB_ID &aLibId, bool aUseCacheLib, bool aShowErrorMsg)
Load design block from design block library table.
Class DIALOG_INCREMENT_ANNOTATIONS_BASE.
void SetWksFileName(const wxString &aFilename)
bool Show(bool show) override
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition dialog_shim.h:82
int ShowModal() override
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:99
virtual VECTOR2I GetPosition() const
Definition eda_item.h:278
EDA_ITEM_FLAGS GetEditFlags() const
Definition eda_item.h:154
const KIID m_Uuid
Definition eda_item.h:522
virtual EDA_GROUP * GetParentGroup() const
Definition eda_item.h:117
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:111
virtual bool IsType(const std::vector< KICAD_T > &aScanTypes) const
Check whether the item is one of the listed types.
Definition eda_item.h:198
void ClearBrightened()
Definition eda_item.h:144
void SetBrightened()
Definition eda_item.h:141
EDA_ITEM * GetParent() const
Definition eda_item.h:113
virtual EDA_ITEM * Clone() const
Create a duplicate of this item with linked list members set to NULL.
Definition eda_item.cpp:128
bool IsBrightened() const
Definition eda_item.h:130
virtual void SetParent(EDA_ITEM *aParent)
Definition eda_item.cpp:93
SHAPE_POLY_SET & GetPolyShape()
Definition eda_shape.h:337
SHAPE_T GetShape() const
Definition eda_shape.h:169
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition eda_shape.h:216
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Definition eda_shape.h:174
std::vector< VECTOR2I > GetRectCorners() const
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition eda_text.h:80
virtual bool IsVisible() const
Definition eda_text.h:187
bool validatePasteIntoSelection(const SELECTION &aSel, wxString &aErrorMsg)
Validate if paste-into-cells is possible for the given selection.
bool pasteCellsIntoSelection(const SELECTION &aSel, T_TABLE *aSourceTable, T_COMMIT &aCommit)
Paste text content from source table into selected cells.
PANEL_ANNOTATE m_AnnotatePanel
static const TOOL_EVENT ClearedEvent
Definition actions.h:347
static const TOOL_EVENT GridChangedByKeyEvent
Definition actions.h:365
static const TOOL_EVENT SelectedEvent
Definition actions.h:345
static const TOOL_EVENT SelectedItemsModified
Selected items were moved, this can be very high frequency on the canvas, use with care.
Definition actions.h:352
static const TOOL_EVENT PointSelectedEvent
Definition actions.h:344
static const TOOL_EVENT UnselectedEvent
Definition actions.h:346
Similar to EDA_VIEW_SWITCHER, this dialog is a popup that shows feedback when using a hotkey to cycle...
void Popup(const wxString &aTitle, const wxArrayString &aItems, int aSelection)
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()
static std::unique_ptr< CAIRO_PRINT_GAL > Create(GAL_DISPLAY_OPTIONS &aOptions, wxImage *aImage, double aDPI)
GAL_ANTIALIASING_MODE antialiasing_mode
The grid style to draw the grid in.
virtual bool HasNativeLandscapeRotation() const =0
void SetLayerColor(int aLayer, const COLOR4D &aColor)
Change the color used to draw a layer.
void SetDefaultFont(const wxString &aFont)
const COLOR4D & GetLayerColor(int aLayer) const
Return the color used to draw a layer.
void SetIsPrinting(bool isPrinting)
An interface for classes handling user events controlling the view behavior such as zooming,...
VECTOR2D GetCursorPosition() const
Return the current cursor position in world coordinates.
An abstract base class for deriving all objects that can be added to a VIEW.
Definition view_item.h:86
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition view.h:67
virtual void Update(const VIEW_ITEM *aItem, int aUpdateFlags) const
For dynamic VIEWs, inform the associated VIEW that the graphical representation of this item has chan...
Definition view.cpp:1700
void SetLayerVisible(int aLayer, bool aVisible=true)
Control the visibility of a particular layer.
Definition view.h:401
void ClearPreview()
Definition view.cpp:1722
static constexpr int VIEW_MAX_LAYERS
Maximum number of layers that may be shown.
Definition view.h:746
void UpdateAllItems(int aUpdateFlags)
Update all items in the view according to the given flags.
Definition view.cpp:1576
void Hide(VIEW_ITEM *aItem, bool aHide=true, bool aHideOverlay=false)
Temporarily hide the item in the view (e.g.
Definition view.cpp:1648
void AddToPreview(VIEW_ITEM *aItem, bool aTakeOwnership=true)
Definition view.cpp:1744
void SetVisible(VIEW_ITEM *aItem, bool aIsVisible=true)
Set the item visibility.
Definition view.cpp:1627
bool EndsWith(const KIID_PATH &aPath) const
Test if aPath from the last path towards the first path.
Definition kiid.cpp:344
wxString AsString() const
Definition kiid.cpp:365
Definition kiid.h:49
wxString AsString() const
Definition kiid.cpp:244
KIWAY & Kiway() const
Return a reference to the KIWAY that this object has an opportunity to participate in.
A wxFrame capable of the OpenProjectFiles function, meaning it can load a portion of a KiCad project.
wxWindow * GetBlockingDialog()
Gets the window pointer to the blocking dialog (to send it signals)
Definition kiway.cpp:684
std::optional< LIBRARY_TABLE_ROW * > GetRow(const wxString &aNickname, LIBRARY_TABLE_SCOPE aScope=LIBRARY_TABLE_SCOPE::BOTH) const
Like LIBRARY_MANAGER::GetRow but filtered to the LIBRARY_TABLE_TYPE of this adapter.
std::optional< wxString > GetFullURI(LIBRARY_TABLE_TYPE aType, const wxString &aNickname, bool aSubstituted=false) const
Return the full location specifying URI for the LIB, either in original UI form or in environment var...
const wxString & Type() const
const wxString & Nickname() const
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
Define a library symbol object.
Definition lib_symbol.h:83
const LIB_ID & GetLibId() const override
Definition lib_symbol.h:152
bool IsPower() const override
wxString GetName() const override
Definition lib_symbol.h:145
bool IsLocalPower() const override
bool IsGlobalPower() const override
std::unique_ptr< LIB_SYMBOL > Flatten() const
Return a flattened symbol inheritance to the caller.
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition locale_io.h:41
static void ConvertToSpiceMarkup(wxString *aNetName)
Remove formatting wrappers and replace illegal spice net name characters with underscores.
Tree view item data for the net navigator.
static bool ParseBusGroup(const wxString &aGroup, wxString *name, std::vector< wxString > *aMemberList)
Parse a bus group label into the name and a list of components.
static bool ParseBusVector(const wxString &aBus, wxString *aName, std::vector< wxString > *aMemberList)
Parse a bus vector (e.g.
Describe the page size and margins of a paper page on which to eventually print or plot.
Definition page_info.h:79
void SetHeightMils(double aHeightInMils)
void SetWidthMils(double aWidthInMils)
A holder to handle information on schematic or board items.
void PushItem(const ITEM_PICKER &aItem)
Push aItem to the top of the list.
void SetDescription(const wxString &aDescription)
void ReversePickersListOrder()
Reverse the order of pickers stored in this list.
void SetMotionHandler(MOTION_HANDLER aHandler)
Set a handler for mouse motion.
Definition picker_tool.h:92
void SetClickHandler(CLICK_HANDLER aHandler)
Set a handler for mouse click event.
Definition picker_tool.h:81
void SetSnapping(bool aSnap)
Definition picker_tool.h:66
void SetCursor(KICURSOR aCursor)
Definition picker_tool.h:64
void SetFinalizeHandler(FINALIZE_HANDLER aHandler)
Set a handler for the finalize event.
static SYMBOL_LIBRARY_ADAPTER * SymbolLibAdapter(PROJECT *aProject)
Accessor for project symbol library manager adapter.
virtual bool HasMessage() const
Returns true if any messages were reported.
Definition reporter.h:134
static bool RescueProject(wxWindow *aParent, RESCUER &aRescuer, bool aRunningOnDemand)
size_t GetCandidateCount()
Return the number of rescue candidates found.
These are loaded from Eeschema settings but then overwritten by the project settings.
std::shared_ptr< REFDES_TRACKER > m_refDesTracker
A list of previously used schematic reference designators.
Holds all the data relating to one schematic.
Definition schematic.h:88
wxString GetFileName() const
Helper to retrieve the filename from the root sheet screen.
SCHEMATIC_SETTINGS & Settings() const
SCH_SHEET_LIST Hierarchy() const
Return the full schematic flattened hierarchical sheet list.
PROJECT & Project() const
Return a reference to the project this schematic is part of.
Definition schematic.h:103
const std::map< wxString, wxString > * GetProperties()
Definition schematic.h:106
SCH_SHEET & Root() const
Definition schematic.h:132
SCH_SHEET_PATH & CurrentSheet() const
Definition schematic.h:187
static TOOL_ACTION showPcbNew
static TOOL_ACTION assignFootprints
static TOOL_ACTION lineModeNext
static TOOL_ACTION toggleOPCurrents
static TOOL_ACTION saveToLinkedDesignBlock
Definition sch_actions.h:71
static TOOL_ACTION clearHighlight
static TOOL_ACTION removeVariant
static TOOL_ACTION editSymbolFields
static TOOL_ACTION importFPAssignments
static TOOL_ACTION toggleAnnotateAuto
static TOOL_ACTION editLibSymbolWithLibEdit
static TOOL_ACTION toggleERCWarnings
static TOOL_ACTION schematicSetup
static TOOL_ACTION toggleDirectiveLabels
static TOOL_ACTION highlightNetTool
static TOOL_ACTION findNetInInspector
static TOOL_ACTION toggleHiddenFields
static TOOL_ACTION saveCurrSheetCopyAs
Definition sch_actions.h:43
static TOOL_ACTION showRemoteSymbolPanel
static TOOL_ACTION remapSymbols
static TOOL_ACTION lineMode45
static TOOL_ACTION editSymbolLibraryLinks
static TOOL_ACTION simTune
static TOOL_ACTION generateBOM
static TOOL_ACTION showHierarchy
static TOOL_ACTION showNetNavigator
static TOOL_ACTION markSimExclusions
static TOOL_ACTION placeImage
static TOOL_ACTION editWithLibEdit
static TOOL_ACTION toggleERCErrors
static TOOL_ACTION incrementAnnotations
static TOOL_ACTION rescueSymbols
static TOOL_ACTION angleSnapModeChanged
static TOOL_ACTION placeLinkedDesignBlock
Definition sch_actions.h:70
static TOOL_ACTION generateBOMLegacy
static TOOL_ACTION placeDesignBlock
Definition sch_actions.h:69
static TOOL_ACTION toggleOPVoltages
static TOOL_ACTION simProbe
static TOOL_ACTION lineMode90
static TOOL_ACTION lineModeFree
static TOOL_ACTION changeSheet
static TOOL_ACTION highlightNet
static TOOL_ACTION assignNetclass
static TOOL_ACTION annotate
static TOOL_ACTION showDesignBlockPanel
static TOOL_ACTION updateDesignBlockFromSelection
static TOOL_ACTION togglePinAltIcons
static TOOL_ACTION toggleERCExclusions
static TOOL_ACTION updateNetHighlighting
static TOOL_ACTION exportNetlist
static TOOL_ACTION drawSheetOnClipboard
static TOOL_ACTION exportSymbolsToLibrary
static TOOL_ACTION toggleHiddenPins
static TOOL_ACTION selectOnPCB
static TOOL_ACTION addVariant
static TOOL_ACTION move
SCH_RENDER_SETTINGS * GetRenderSettings()
EESCHEMA_SETTINGS * eeconfig() const
COLOR_SETTINGS * GetColorSettings(bool aForceRefresh=false) const override
Returns a pointer to the active color theme settings.
Base class for a bus or wire entry.
void Collect(SCH_SCREEN *aScreen, const std::vector< KICAD_T > &aScanTypes, const VECTOR2I &aPos, int aUnit=0, int aBodyStyle=0)
Scan a EDA_ITEM using this class's Inspector method which does the collection.
virtual void Push(const wxString &aMessage=wxT("A commit"), int aCommitFlags=0) override
Execute the changes.
virtual void Revert() override
Revert the commit by restoring the modified items state.
Each graphical item can have a SCH_CONNECTION describing its logical connection (to a bus or net).
wxString Name(bool aIgnoreSheet=false) const
Handle actions specific to the schematic editor.
int PageSetup(const TOOL_EVENT &aEvent)
bool RescueLegacyProject(bool aRunningOnDemand)
int ToggleDirectiveLabels(const TOOL_EVENT &aEvent)
int SaveAs(const TOOL_EVENT &aEvent)
int MarkSimExclusions(const TOOL_EVENT &aEvent)
int Annotate(const TOOL_EVENT &aEvent)
int ShowSchematicSetup(const TOOL_EVENT &aEvent)
int HighlightNet(const TOOL_EVENT &aEvent)
Remove any net highlighting.
int ClearHighlight(const TOOL_EVENT &aEvent)
Update net highlighting after an edit.
int FindNetInInspector(const TOOL_EVENT &aEvent)
int EditSymbolFields(const TOOL_EVENT &aEvent)
int GenerateBOMLegacy(const TOOL_EVENT &aEvent)
int HighlightNetCursor(const TOOL_EVENT &aEvent)
int CopyAsText(const TOOL_EVENT &aEvent)
int AddVariant(const TOOL_EVENT &aEvent)
int ImportFPAssignments(const TOOL_EVENT &aEvent)
int ChangeLineMode(const TOOL_EVENT &aEvent)
void doCrossProbeSchToPcb(const TOOL_EVENT &aEvent, bool aForce)
int ExportSymbolsToLibrary(const TOOL_EVENT &aEvent)
int SaveCurrSheetCopyAs(const TOOL_EVENT &aEvent)
Saves the currently-open schematic sheet to an other name.
bool rescueProject(RESCUER &aRescuer, bool aRunningOnDemand)
int CrossProbeToPcb(const TOOL_EVENT &aEvent)
Equivalent to the above, but initiated by the user.
int PlaceLinkedDesignBlock(const TOOL_EVENT &aEvent)
int ToggleRemoteSymbolPanel(const TOOL_EVENT &aEvent)
int RemapSymbols(const TOOL_EVENT &aEvent)
int DrawSheetOnClipboard(const TOOL_EVENT &aEvent)
SCH_SHEET_PATH updatePastedSheet(SCH_SHEET *aSheet, const SCH_SHEET_PATH &aPastePath, const KIID_PATH &aClipPath, bool aForceKeepAnnotations, SCH_SHEET_LIST *aPastedSheets, std::map< SCH_SHEET_PATH, SCH_REFERENCE_LIST > &aPastedSymbols)
int TogglePinAltIcons(const TOOL_EVENT &aEvent)
int RescueSymbols(const TOOL_EVENT &aEvent)
Perform rescue operations to recover old projects from before certain changes were made.
int AssignNetclass(const TOOL_EVENT &aEvent)
std::string m_duplicateClipboard
int ExportNetlist(const TOOL_EVENT &aEvent)
int Open(const TOOL_EVENT &aEvent)
int Paste(const TOOL_EVENT &aEvent)
int ToggleOPVoltages(const TOOL_EVENT &aEvent)
int Copy(const TOOL_EVENT &aEvent)
int SaveToLinkedDesignBlock(const TOOL_EVENT &aEvent)
int ToggleERCWarnings(const TOOL_EVENT &aEvent)
int NextLineMode(const TOOL_EVENT &aEvent)
int Redo(const TOOL_EVENT &aEvent)
Clipboard support.
int UpdatePCB(const TOOL_EVENT &aEvent)
int RemoveVariant(const TOOL_EVENT &aEvent)
int UpdateFromPCB(const TOOL_EVENT &aEvent)
int ToggleAnnotateAuto(const TOOL_EVENT &aEvent)
int ToggleHiddenPins(const TOOL_EVENT &aEvent)
int Duplicate(const TOOL_EVENT &aEvent)
int IncrementAnnotations(const TOOL_EVENT &aEvent)
bool searchSupplementaryClipboard(const wxString &aSheetFilename, SCH_SCREEN **aScreen)
int GridFeedback(const TOOL_EVENT &aEvent)
int ShowSearch(const TOOL_EVENT &aEvent)
int EditWithSymbolEditor(const TOOL_EVENT &aEvent)
int SimTune(const TOOL_EVENT &aEvent)
Highlight net under the cursor.
int EditSymbolLibraryLinks(const TOOL_EVENT &aEvent)
int New(const TOOL_EVENT &aEvent)
std::map< wxString, SCH_SCREEN * > m_supplementaryClipboard
int ExplicitCrossProbeToPcb(const TOOL_EVENT &aEvent)
int ToggleOPCurrents(const TOOL_EVENT &aEvent)
int ShowPcbNew(const TOOL_EVENT &aEvent)
int UpdateNetHighlighting(const TOOL_EVENT &aEvent)
Launch a tool to highlight nets.
int ToggleERCErrors(const TOOL_EVENT &aEvent)
int TogglePythonConsole(const TOOL_EVENT &aEvent)
int ShowHierarchy(const TOOL_EVENT &aEvent)
int OnAngleSnapModeChanged(const TOOL_EVENT &aEvent)
void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
int ShowNetNavigator(const TOOL_EVENT &aEvent)
int SimProbe(const TOOL_EVENT &aEvent)
void updatePastedSymbol(SCH_SYMBOL *aSymbol, const SCH_SHEET_PATH &aPastePath, const KIID_PATH &aClipPath, bool aForceKeepAnnotations)
int ShowCvpcb(const TOOL_EVENT &aEvent)
int ToggleLibraryTree(const TOOL_EVENT &aEvent)
std::set< SCH_SYMBOL * > m_pastedSymbols
void prunePastedSymbolInstances()
Remove all pasted symbol instances that do not belong to the current project.
int Cut(const TOOL_EVENT &aEvent)
int ToggleProperties(const TOOL_EVENT &aEvent)
std::map< KIID_PATH, SCH_SYMBOL_INSTANCE > m_clipboardSymbolInstances
int Save(const TOOL_EVENT &aEvent)
bool RescueSymbolLibTableProject(bool aRunningOnDemand)
Notifies pcbnew about the selected item.
bool doCopy(bool aUseDuplicateClipboard=false)
< copy selection to clipboard or to m_duplicateClipboard
int Undo(const TOOL_EVENT &aEvent)
int ToggleERCExclusions(const TOOL_EVENT &aEvent)
int Plot(const TOOL_EVENT &aEvent)
int Print(const TOOL_EVENT &aEvent)
int Revert(const TOOL_EVENT &aEvent)
int GenerateBOM(const TOOL_EVENT &aEvent)
int ReloadPlugins(const TOOL_EVENT &aEvent)
void setPastedSymbolInstances(const SCH_SCREEN *aScreen)
int ToggleHiddenFields(const TOOL_EVENT &aEvent)
Schematic editor (Eeschema) main window.
void ToggleProperties() override
SCH_DESIGN_BLOCK_PANE * GetDesignBlockPane() const
void ToggleLibraryTree() override
void SetHighlightedConnection(const wxString &aConnection, const NET_NAVIGATOR_ITEM_DATA *aSelection=nullptr)
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
void SendCrossProbeClearHighlight()
Tell Pcbnew to clear the existing highlighted net, if one exists.
SCH_SHEET_PATH & GetCurrentSheet() const
void RecalculateConnections(SCH_COMMIT *aCommit, SCH_CLEANUP_FLAGS aCleanupFlags, PROGRESS_REPORTER *aProgressReporter=nullptr)
Generate the connection data for the entire schematic hierarchy.
const SCH_ITEM * GetSelectedNetNavigatorItem() const
SCHEMATIC & Schematic() const
void ToggleSearch()
Toggle the show/hide state of Search pane.
wxString GetFullScreenDesc() const override
void ToggleSchematicHierarchy()
Toggle the show/hide state of the left side schematic navigation panel.
const wxString & GetHighlightedConnection() const
void UpdateNetHighlightStatus()
wxString GetScreenDesc() const override
Return a human-readable description of the current screen.
void SelectNetNavigatorItem(const NET_NAVIGATOR_ITEM_DATA *aSelection=nullptr)
void SetCrossProbeConnection(const SCH_CONNECTION *aConnection)
Send a connection (net or bus) to Pcbnew for highlighting.
virtual const wxString & GetText() const override
Return the string associated with the text object.
Definition sch_field.h:116
void SetText(const wxString &aText) override
A set of SCH_ITEMs (i.e., without duplicates).
Definition sch_group.h:52
A SCH_IO derivation for loading schematic files using the new s-expression file format.
void LoadContent(LINE_READER &aReader, SCH_SHEET *aSheet, int aVersion=SEXPR_SCHEMATIC_FILE_VERSION)
void Format(SCH_SHEET *aSheet)
static SCH_FILE_T EnumFromStr(const wxString &aFileType)
Return the #SCH_FILE_T from the corresponding plugin type name: "kicad", "legacy",...
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:168
virtual bool IsConnectable() const
Definition sch_item.h:527
const SYMBOL * GetParentSymbol() const
Definition sch_item.cpp:260
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition sch_item.cpp:254
virtual void SetLastResolvedState(const SCH_ITEM *aItem)
Definition sch_item.h:619
int GetBodyStyle() const
Definition sch_item.h:248
int GetUnit() const
Definition sch_item.h:239
void SetConnectivityDirty(bool aDirty=true)
Definition sch_item.h:590
bool IsConnectivityDirty() const
Definition sch_item.h:588
virtual void SetUnit(int aUnit)
Definition sch_item.h:238
SCH_CONNECTION * Connection(const SCH_SHEET_PATH *aSheet=nullptr) const
Retrieve the connection associated with this object in the given sheet.
Definition sch_item.cpp:473
virtual std::vector< VECTOR2I > GetConnectionPoints() const
Add all the connection points for this item to aPoints.
Definition sch_item.h:542
Segment description base class to describe items which have 2 end points (track, wire,...
Definition sch_line.h:42
SCH_PIN * GetLibPin() const
Definition sch_pin.h:89
const wxString & GetNumber() const
Definition sch_pin.h:124
Container to create a flattened list of symbols because in a complex hierarchy, a symbol can be used ...
void SortByReferenceOnly()
Sort the list of references by reference.
void SplitReferences()
Attempt to split all reference designators into a name (U) and number (1).
void AddItem(const SCH_REFERENCE &aItem)
A helper to define a symbol's reference designator in a schematic.
void SetRef(const wxString &aReference)
void Split()
Attempt to split the reference designator into a name (U) and number (1).
bool IsSplitNeeded()
Determine if this reference needs to be split or if it likely already has been.
wxString GetRef() const
void SetSheetNumber(int aSheetNumber)
wxString GetRefNumber() const
void SetBackgroundColor(const COLOR4D &aColor) override
Set the background color.
const KIGFX::COLOR4D & GetBackgroundColor() const override
Return current background color settings.
void LoadColors(const COLOR_SETTINGS *aSettings) override
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition sch_screen.h:749
SCH_SCREEN * GetNext()
void UpdateSymbolLinks(REPORTER *aReporter=nullptr)
Initialize the LIB_SYMBOL reference for each SCH_SYMBOL found in the full schematic.
SCH_SCREEN * GetFirst()
void PruneOrphanedSheetInstances(const wxString &aProjectName, const SCH_SHEET_LIST &aValidSheetPaths)
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.
const PAGE_INFO & GetPageSettings() const
Definition sch_screen.h:141
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
void Clear(bool aFree=true)
Delete all draw items and clears the project settings.
void UpdateSymbolLinks(REPORTER *aReporter=nullptr)
Initialize the LIB_SYMBOL reference for each SCH_SYMBOL found in this schematic from the project #SYM...
std::set< wxString > GetSheetNames() const
const std::map< wxString, LIB_SYMBOL * > & GetLibSymbols() const
Fetch a list of unique LIB_SYMBOL object pointers required to properly render each SCH_SYMBOL in this...
Definition sch_screen.h:497
EE_RTREE & Items()
Get the full RTree, usually for iterating.
Definition sch_screen.h:119
const wxString & GetFileName() const
Definition sch_screen.h:154
SCHEMATIC * Schematic() const
const TITLE_BLOCK & GetTitleBlock() const
Definition sch_screen.h:165
void Plot(PLOTTER *aPlotter, const SCH_PLOT_OPTS &aPlotOpts) const
Plot all the schematic objects to aPlotter.
void MigrateSimModels()
Migrate any symbols having V6 simulation models to their V7 equivalents.
EDA_ITEM * GetNode(const VECTOR2I &aPosition)
Finds a connected item at a point (usually the cursor position).
bool SelectPoint(const VECTOR2I &aWhere, const std::vector< KICAD_T > &aScanTypes={ SCH_LOCATE_ANY_T }, EDA_ITEM **aItem=nullptr, bool *aSelectionCancelledFlag=nullptr, bool aCheckLocked=false, bool aAdd=false, bool aSubtract=false, bool aExclusiveOr=false)
Perform a click-type selection at a point (usually the cursor position).
int ClearSelection(const TOOL_EVENT &aEvent)
Select all visible items in sheet.
void GuessSelectionCandidates(SCH_COLLECTOR &collector, const VECTOR2I &aPos)
Apply heuristics to try and determine a single object when multiple are found under the cursor.
SCH_SELECTION & GetSelection()
SCH_SELECTION & RequestSelection(const std::vector< KICAD_T > &aScanTypes={ SCH_LOCATE_ANY_T }, bool aPromoteCellSelections=false, bool aPromoteGroups=false)
Return either an existing selection (filtered), or the selection at the current cursor position if th...
BOX2I GetBoundingBox() const override
VECTOR2I GetCenter() const
Definition sch_shape.h:88
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
void FillItemMap(std::map< KIID, EDA_ITEM * > &aMap)
Fill an item cache for temporary use when many items need to be fetched.
void SortByPageNumbers(bool aUpdateVirtualPageNums=true)
Sort the list of sheets by page number.
SCH_SHEET_LIST FindAllSheetsForScreen(const SCH_SCREEN *aScreen) const
Return a SCH_SHEET_LIST with a copy of all the SCH_SHEET_PATH using a particular screen.
void GetSymbols(SCH_REFERENCE_LIST &aReferences, bool aIncludePowerSymbols=true, bool aForceIncludeOrphanSymbols=false) const
Add a SCH_REFERENCE object to aReferences for each symbol in the list of sheets.
bool PageNumberExists(const wxString &aPageNumber) const
bool ContainsSheet(const SCH_SHEET *aSheet) const
bool HasPath(const KIID_PATH &aPath) const
bool TestForRecursion(const SCH_SHEET_LIST &aSrcSheetHierarchy, const wxString &aDestFileName)
Test every SCH_SHEET_PATH in this SCH_SHEET_LIST to verify if adding the sheets stored in aSrcSheetHi...
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
void GetSymbols(SCH_REFERENCE_LIST &aReferences, bool aIncludePowerSymbols=true, bool aForceIncludeOrphanSymbols=false) const
Adds SCH_REFERENCE object to aReferences for each symbol in the sheet.
KIID_PATH Path() const
Get the sheet path as an KIID_PATH.
SCH_SCREEN * LastScreen()
SCH_SHEET * Last() const
Return a pointer to the last SCH_SHEET of the list.
void push_back(SCH_SHEET *aSheet)
Forwarded method from std::vector.
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition sch_sheet.h:48
wxString GetFileName() const
Return the filename corresponding to this sheet.
Definition sch_sheet.h:376
void RemoveInstance(const KIID_PATH &aInstancePath)
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this sheet.
void AddInstance(const SCH_SHEET_INSTANCE &aInstance)
SCH_SCREEN * GetScreen() const
Definition sch_sheet.h:145
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
std::vector< SCH_SHEET_PIN * > & GetPins()
Definition sch_sheet.h:233
const std::vector< SCH_SHEET_INSTANCE > & GetInstances() const
Definition sch_sheet.h:511
Schematic symbol object.
Definition sch_symbol.h:76
EMBEDDED_FILES * GetEmbeddedFiles() override
SCH_SYMBOLs don't currently support embedded files, but their LIB_SYMBOL counterparts do.
const std::vector< SCH_SYMBOL_INSTANCE > & GetInstances() const
Definition sch_symbol.h:135
wxString GetSchSymbolLibraryName() const
std::vector< const SCH_PIN * > GetPins(const SCH_SHEET_PATH *aSheet) const
Retrieve a list of the SCH_PINs for the given sheet path.
void ClearAnnotation(const SCH_SHEET_PATH *aSheetPath, bool aResetPrefix)
Clear exiting symbol annotation.
void AddHierarchicalReference(const KIID_PATH &aPath, const wxString &aRef, int aUnit)
Add a full hierarchical reference to this symbol.
bool IsMissingLibSymbol() const
Check to see if the library symbol is set to the dummy library symbol.
const LIB_ID & GetLibId() const override
Definition sch_symbol.h:165
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.
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const override
bool IsPower() const override
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this symbol.
void BrightenItem(EDA_ITEM *aItem)
void UnbrightenItem(EDA_ITEM *aItem)
virtual void Add(EDA_ITEM *aItem)
Definition selection.cpp:42
const std::deque< EDA_ITEM * > GetItems() const
Definition selection.h:126
virtual unsigned int GetSize() const override
Return the number of stored items.
Definition selection.h:105
const VECTOR2I & CVertex(int aIndex, int aOutline, int aHole) const
Return the index-th vertex in a given hole outline within a given outline.
The SIMULATOR_FRAME holds the main user-interface for running simulations.
void AddCurrentTrace(const wxString &aDeviceName)
Add a current trace for a given device to the current plot.
void AddVoltageTrace(const wxString &aNetName)
Add a voltage trace for a given net to the current plot.
SIM_MODEL & CreateModel(SIM_MODEL::TYPE aType, const std::vector< SCH_PIN * > &aPins, REPORTER &aReporter)
void SetFilesStack(std::vector< EMBEDDED_FILES * > aFilesStack)
Definition sim_lib_mgr.h:48
Implement an OUTPUTFORMATTER to a memory buffer.
Definition richio.h:422
const std::string & GetString()
Definition richio.h:445
Is a LINE_READER that reads from a multiline 8 bit wide std::string.
Definition richio.h:226
The symbol library editor main window.
bool IsLibraryTreeShown() const override
void LoadSymbol(const wxString &aLibrary, const wxString &aSymbol, int Unit)
void LoadSymbolFromSchematic(SCH_SYMBOL *aSymbol)
Load a symbol from the schematic to edit in place.
void ToggleLibraryTree() override
An interface to the global shared library manager that is schematic-specific and linked to one projec...
Class to handle modifications to the symbol libraries.
Symbol library viewer main window.
SCH_EDIT_FRAME * getEditFrame() const
Definition tool_base.h:186
KIGFX::VIEW_CONTROLS * getViewControls() const
Definition tool_base.cpp:44
KIGFX::VIEW * getView() const
Definition tool_base.cpp:38
Generic, UI-independent tool event.
Definition tool_event.h:171
bool DisableGridSnapping() const
Definition tool_event.h:371
bool IsAction(const TOOL_ACTION *aAction) const
Test if the event contains an action issued upon activation of the given TOOL_ACTION.
T Parameter() const
Return a parameter assigned to the event.
Definition tool_event.h:473
void Go(int(SCH_EDIT_FRAME::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Master controller class:
TOOLS_HOLDER * GetToolHolder() const
A wrapper for reporting to a wxString object.
Definition reporter.h:191
const wxString & GetMessages() const
Definition reporter.cpp:78
std::unique_ptr< wxBitmap > GetImageFromClipboard()
Get image data from the clipboard, if there is any.
bool EncodeImageToPng(const wxImage &aImage, wxMemoryBuffer &aOutput)
Encode an image to PNG format with fast compression settings optimized for clipboard use.
bool AddTransparentImageToClipboardData(wxDataObjectComposite *aData, wxImage aImage)
Adds an image to clipboard data in a platform-specific way such that transparency is supported.
bool SaveClipboard(const std::string &aTextUTF8)
Store information to the system clipboard.
Definition clipboard.cpp:36
std::string GetClipboardUTF8()
Return the information currently stored in the system clipboard.
bool AddPngToClipboardData(wxDataObjectComposite *aData, const wxMemoryBuffer &aPngData, const wxImage *aFallbackImage)
Adds pre-encoded PNG data to clipboard in a platform-specific way.
wxString EnsureFileExtension(const wxString &aFilename, const wxString &aExtension)
It's annoying to throw up nag dialogs when the extension isn't right.
Definition common.cpp:629
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition confirm.cpp:259
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition confirm.cpp:202
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
Definition confirm.cpp:177
This file is part of the common library.
@ VOLTAGE_PROBE
Definition cursors.h:60
@ CURRENT_PROBE
Definition cursors.h:62
@ BULLSEYE
Definition cursors.h:58
int InvokeDialogCreateBOM(SCH_EDIT_FRAME *aCaller)
Create and show DIALOG_BOM and return whatever DIALOG_BOM::ShowModal() returns.
bool InvokeDialogEditSymbolsLibId(SCH_EDIT_FRAME *aCaller)
Run a dialog to modify the LIB_ID of symbols for instance when a symbol has moved from a symbol libra...
int InvokeDialogNetList(SCH_EDIT_FRAME *aCaller)
#define _(s)
@ RECURSE
Definition eda_item.h:52
@ NO_RECURSE
Definition eda_item.h:53
#define IS_PASTED
Modifier on IS_NEW which indicates it came from clipboard.
#define IS_NEW
New item, just created.
#define ENDPOINT
ends. (Used to support dragging.)
#define IS_MOVING
Item being moved.
#define STARTPOINT
When a line is selected, these flags indicate which.
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
Definition eda_shape.h:46
@ LINE_MODE_90
@ LINE_MODE_45
@ LINE_MODE_FREE
@ LINE_MODE_COUNT
@ FRAME_SCH_SYMBOL_EDITOR
Definition frame_type.h:35
@ FRAME_SCH_VIEWER
Definition frame_type.h:36
@ FRAME_SIMULATOR
Definition frame_type.h:38
static const std::string KiCadSchematicFileExtension
static wxString KiCadSchematicFileWildcard()
static const wxChar traceSchPaste[]
Flag to enable schematic paste debugging output.
#define NET_PLUGIN_CHANGE
Create and shows DIALOG_EXPORT_NETLIST and returns whatever DIALOG_EXPORT_NETLIST::ShowModal() return...
std::unique_ptr< T > IO_RELEASER
Helper to hold and release an IO_BASE object when exceptions are thrown.
Definition io_mgr.h:33
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
#define KICTL_REVERT
reverting to a previously-saved (KiCad) file.
@ LAYER_DRAWINGSHEET
Sheet frame and title block.
Definition layer_ids.h:278
@ LAYER_ERC_WARN
Definition layer_ids.h:479
@ LAYER_ERC_ERR
Definition layer_ids.h:480
@ LAYER_SCHEMATIC_DRAWINGSHEET
Definition layer_ids.h:496
@ LAYER_OP_CURRENTS
Definition layer_ids.h:502
@ LAYER_SCHEMATIC_PAGE_LIMITS
Definition layer_ids.h:497
@ LAYER_OP_VOLTAGES
Definition layer_ids.h:501
void Prettify(std::string &aSource, FORMAT_MODE aMode)
Pretty-prints s-expression text according to KiCad format rules.
@ REPAINT
Item needs to be redrawn.
Definition view_item.h:58
@ GEOMETRY
Position or shape has changed.
Definition view_item.h:55
@ TARGET_NONCACHED
Auxiliary rendering target (noncached)
Definition definitions.h:38
void AllowNetworkFileSystems(wxDialog *aDialog)
Configure a file dialog to show network and virtual file systems.
Definition wxgtk/ui.cpp:435
void encode(const std::vector< uint8_t > &aInput, std::vector< uint8_t > &aOutput)
Definition base64.cpp:76
#define MAX_PAGE_SIZE_EESCHEMA_MILS
Definition page_info.h:36
PGM_BASE & Pgm()
The global program "get" accessor.
see class PGM_BASE
Plotting engines similar to ps (PostScript, Gerber, svg)
static bool highlightNet(TOOL_MANAGER *aToolMgr, const VECTOR2D &aPosition)
#define HITTEST_THRESHOLD_PIXELS
static VECTOR2D CLEAR
Class to handle a set of SCH_ITEMs.
std::vector< EDA_ITEM * > EDA_ITEMS
ANNOTATE_ORDER_T
Schematic annotation order options.
ANNOTATE_ALGO_T
Schematic annotation type options.
wxString GetSelectedItemsAsText(const SELECTION &aSel)
constexpr double SCH_WORLD_UNIT(1e-7/0.0254)
@ LOCAL_CLEANUP
Definition schematic.h:76
@ NO_CLEANUP
Definition schematic.h:75
@ GLOBAL_CLEANUP
Definition schematic.h:77
std::vector< FAB_LAYER_COLOR > dummy
wxString UnescapeString(const wxString &aSource)
wxString From_UTF8(const char *cstring)
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
std::vector< GRID > grids
Common grid settings, available to every frame.
A simple container for sheet instance information.
A simple container for schematic symbol instance information.
static constexpr auto NOT_CONNECTED
Definition sim_model.h:73
std::string refName
FIELD_T
The set of all field indices assuming an array like sequence that a SCH_COMPONENT or LIB_PART can hol...
@ REFERENCE
Field Reference of part, i.e. "IC21".
@ VALUE
Field Value of part, i.e. "3.3K".
std::string path
KIBIS_MODEL * model
KIBIS_PIN * pin
VECTOR2I end
wxString result
Test unit parsing edge cases and error handling.
@ AS_GLOBAL
Global action (toolbar/main menu event, global shortcut)
Definition tool_action.h:49
@ TA_UNDO_REDO_PRE
This event is sent before undo/redo command is performed.
Definition tool_event.h:106
@ TC_MESSAGE
Definition tool_event.h:58
@ SCH_GROUP_T
Definition typeinfo.h:177
@ SCH_TABLE_T
Definition typeinfo.h:169
@ SCH_LINE_T
Definition typeinfo.h:167
@ SCH_SYMBOL_T
Definition typeinfo.h:176
@ SCH_TABLECELL_T
Definition typeinfo.h:170
@ SCH_FIELD_T
Definition typeinfo.h:154
@ SCH_SHEET_T
Definition typeinfo.h:179
@ SCH_MARKER_T
Definition typeinfo.h:162
@ SCH_SHAPE_T
Definition typeinfo.h:153
@ SCH_PIN_T
Definition typeinfo.h:157
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695
VECTOR2< double > VECTOR2D
Definition vector2d.h:694
Definition of file extensions used in Kicad.
#define FN_NORMALIZE_FLAGS
Default flags to pass to wxFileName::Normalize().
Definition wx_filename.h:39
#define ZOOM_MIN_LIMIT_EESCHEMA
#define ZOOM_MAX_LIMIT_EESCHEMA