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, see <https://www.gnu.org/licenses/>.
19 */
20
21#include <advanced_config.h>
22#include <symbol_edit_frame.h>
24
25#include <algorithm>
26#include <unordered_set>
27
28#include <wx_filename.h>
29#include <wx/clipbrd.h>
30#include <wx/buffer.h>
31#include <wx/filedlg.h>
32#include <wx/filefn.h>
33#include <wx/imagpng.h>
34#include <wx/log.h>
35#include <wx/log.h>
36#include <wx/msgdlg.h>
37#include <wx/mstream.h>
38#include <wx/textdlg.h>
39#include <wx/treectrl.h>
40
42#include <core/base64.h>
43#include <clipboard.h>
44#include <confirm.h>
45#include <connection_graph.h>
49#include <design_block.h>
60#include <project_rescue.h>
61#include <erc/erc.h>
62#include <invoke_sch_dialog.h>
63#include <locale_io.h>
64#include <string_utils.h>
65#include <kiway.h>
66#include <kiplatform/ui.h>
68#include <paths.h>
69#include <pgm_base.h>
72#include <project_sch.h>
74#include <richio.h>
76#include <sch_edit_frame.h>
78#include <sch_bitmap.h>
79#include <sch_group.h>
80#include <sch_line.h>
81#include <sch_junction.h>
82#include <sch_bus_entry.h>
83#include <sch_shape.h>
84#include <sch_painter.h>
85#include <sch_sheet_pin.h>
86#include <sch_table.h>
87#include <sch_tablecell.h>
88#include <sch_label.h>
89#include <sch_commit.h>
90#include <sim/simulator_frame.h>
92#include <symbol_viewer_frame.h>
93#include <tool/picker_tool.h>
94#include <tool/tool_manager.h>
95#include <tools/sch_actions.h>
96#include <tools/sch_selection.h>
102#include <view/view_controls.h>
103#include <widgets/wx_infobar.h>
109#include <view/view.h>
110#include <zoom_defines.h>
112#include <gal/gal_print.h>
114
120static const wxChar traceSchPaste[] = wxT( "KICAD_SCH_PASTE" );
121
122namespace
123{
124constexpr int clipboardMaxBitmapSize = 4096;
125constexpr double clipboardBboxInflation = 0.02; // Small padding around selection
126
127
128std::vector<SCH_ITEM*> collectSelectionItems( const SCH_SELECTION& aSelection )
129{
130 std::vector<SCH_ITEM*> items;
131 items.reserve( aSelection.GetSize() );
132
133 for( EDA_ITEM* item : aSelection.GetItems() )
134 {
135 SCH_ITEM* schItem = dynamic_cast<SCH_ITEM*>( item );
136
137 if( schItem )
138 items.push_back( schItem );
139 }
140
141 return items;
142}
143
144
145BOX2I expandedSelectionBox( const SCH_SELECTION& aSelection )
146{
147 BOX2I bbox = aSelection.GetBoundingBox();
148
149 if( bbox.GetWidth() > 0 && bbox.GetHeight() > 0 )
150 bbox.Inflate( bbox.GetWidth() * clipboardBboxInflation,
151 bbox.GetHeight() * clipboardBboxInflation );
152
153 return bbox;
154}
155
156
157bool generateHtmlFromPngData( const wxMemoryBuffer& aPngData, wxMemoryBuffer& aHtmlBuffer )
158{
159 if( aPngData.GetDataLen() == 0 )
160 return false;
161
162 std::vector<uint8_t> pngVec( static_cast<const uint8_t*>( aPngData.GetData() ),
163 static_cast<const uint8_t*>( aPngData.GetData() ) + aPngData.GetDataLen() );
164
165 std::vector<uint8_t> base64Data;
166 base64::encode( pngVec, base64Data );
167
168 std::string html = "<img src=\"data:image/png;base64,";
169 html.append( reinterpret_cast<const char*>( base64Data.data() ), base64Data.size() );
170 html.append( "\" />" );
171
172 aHtmlBuffer.SetDataLen( 0 );
173 aHtmlBuffer.AppendData( html.data(), html.size() );
174
175 return true;
176}
177
178
179bool plotSelectionToSvg( SCH_EDIT_FRAME* aFrame, const SCH_SELECTION& aSelection, const BOX2I& aBBox,
180 wxMemoryBuffer& aBuffer )
181{
182 SCH_RENDER_SETTINGS renderSettings( *aFrame->GetRenderSettings() );
183 renderSettings.LoadColors( aFrame->GetColorSettings() );
184 renderSettings.SetDefaultFont( aFrame->eeconfig()->m_Appearance.default_font );
185 renderSettings.m_ShowHiddenPins = false;
186 renderSettings.m_ShowHiddenFields = false;
187
188 std::unique_ptr<SVG_PLOTTER> plotter = std::make_unique<SVG_PLOTTER>();
189 plotter->SetRenderSettings( &renderSettings );
190
191 PAGE_INFO pageInfo = aFrame->GetScreen()->GetPageSettings();
192 pageInfo.SetWidthMils( schIUScale.IUToMils( aBBox.GetWidth() ) );
193 pageInfo.SetHeightMils( schIUScale.IUToMils( aBBox.GetHeight() ) );
194
195 plotter->SetPageSettings( pageInfo );
196 plotter->SetColorMode( true );
197
198 VECTOR2I plot_offset = aBBox.GetOrigin();
199 plotter->SetViewport( plot_offset, schIUScale.IU_PER_MILS / 10, 1.0, false );
200 plotter->SetCreator( wxT( "Eeschema-SVG" ) );
201
202 wxFileName tempFile( wxFileName::CreateTempFileName( wxS( "kicad_svg" ) ) );
203
204 if( !plotter->OpenFile( tempFile.GetFullPath() ) )
205 {
206 wxRemoveFile( tempFile.GetFullPath() );
207 return false;
208 }
209
210 LOCALE_IO toggle;
211 SCH_PLOT_OPTS plotOpts;
212 plotOpts.m_plotHopOver = aFrame->Schematic().Settings().GetHopOverScale() > 0.0;
213
214 plotter->StartPlot( wxT( "1" ) );
215 aFrame->GetScreen()->Plot( plotter.get(), plotOpts, collectSelectionItems( aSelection ) );
216 plotter->EndPlot();
217 plotter.reset();
218
219 bool ok = LoadFileToMemory( tempFile.GetFullPath(), aBuffer );
220 wxRemoveFile( tempFile.GetFullPath() );
221 return ok;
222}
223
224
230wxImage renderSelectionToBitmap( SCH_EDIT_FRAME* aFrame, const SCH_SELECTION& aSelection, const BOX2I& aBBox,
231 int aWidth, int aHeight, bool aUseAlpha, bool aIncludeDrawingSheet )
232{
233 wxImage image( aWidth, aHeight, false );
234 image.SetAlpha();
235
236 double actualPPI_x = (double) aWidth / schIUScale.IUTomm( aBBox.GetWidth() ) * 25.4;
237 double actualPPI_y = (double) aHeight / schIUScale.IUTomm( aBBox.GetHeight() ) * 25.4;
238 double actualPPI = std::max( actualPPI_x, actualPPI_y );
239
240 VECTOR2D pageSizeIn( (double) aWidth / actualPPI, (double) aHeight / actualPPI );
241
242 {
245
246 std::unique_ptr<KIGFX::CAIRO_PRINT_GAL> gal = KIGFX::CAIRO_PRINT_GAL::Create( options, &image, actualPPI );
247
248 if( !gal )
249 return wxImage();
250
251 KIGFX::PRINT_CONTEXT* printCtx = gal->GetPrintCtx();
252 std::unique_ptr<KIGFX::SCH_PAINTER> painter = std::make_unique<KIGFX::SCH_PAINTER>( gal.get() );
253 std::unique_ptr<KIGFX::VIEW> view = std::make_unique<KIGFX::VIEW>();
254
255 painter->SetSchematic( &aFrame->Schematic() );
256 view->SetGAL( gal.get() );
257 view->SetPainter( painter.get() );
258 view->SetScaleLimits( ZOOM_MAX_LIMIT_EESCHEMA, ZOOM_MIN_LIMIT_EESCHEMA );
259 view->SetScale( 1.0 );
260
261 gal->SetWorldUnitLength( SCH_WORLD_UNIT );
262 gal->SetSheetSize( pageSizeIn );
263 gal->SetNativePaperSize( pageSizeIn, printCtx->HasNativeLandscapeRotation() );
264
265 // Clone items and add to view
266 std::vector<std::unique_ptr<SCH_ITEM>> clonedItems;
267 clonedItems.reserve( aSelection.GetSize() );
268
269 for( EDA_ITEM* item : aSelection.GetItems() )
270 {
271 SCH_ITEM* schItem = dynamic_cast<SCH_ITEM*>( item );
272
273 if( !schItem )
274 continue;
275
276 SCH_ITEM* clone = static_cast<SCH_ITEM*>( schItem->Clone() );
277 clonedItems.emplace_back( clone );
278 view->Add( clone );
279 }
280
281 SCH_RENDER_SETTINGS* dstSettings = painter->GetSettings();
282 *dstSettings = *aFrame->GetRenderSettings();
283 dstSettings->m_ShowPinsElectricalType = false;
284 dstSettings->LoadColors( aFrame->GetColorSettings( false ) );
286 dstSettings->SetDefaultFont( aFrame->eeconfig()->m_Appearance.default_font );
287 dstSettings->SetIsPrinting( true );
288
289 if( aUseAlpha )
290 dstSettings->SetBackgroundColor( COLOR4D::CLEAR );
291
292 for( int i = 0; i < KIGFX::VIEW::VIEW_MAX_LAYERS; ++i )
293 {
294 view->SetLayerVisible( i, true );
295 view->SetLayerTarget( i, KIGFX::TARGET_NONCACHED );
296 }
297
298 view->SetLayerVisible( LAYER_DRAWINGSHEET, aIncludeDrawingSheet );
299
300 // Create and add drawing sheet proxy view item if requested
301 std::unique_ptr<DS_PROXY_VIEW_ITEM> drawingSheet;
302
303 if( aIncludeDrawingSheet )
304 {
305 SCH_SCREEN* screen = aFrame->GetScreen();
306
307 drawingSheet.reset( new DS_PROXY_VIEW_ITEM( schIUScale, &screen->GetPageSettings(),
308 &screen->Schematic()->Project(), &screen->GetTitleBlock(),
309 screen->Schematic()->GetProperties() ) );
310 drawingSheet->SetPageNumber( TO_UTF8( screen->GetPageNumber() ) );
311 drawingSheet->SetSheetCount( screen->GetPageCount() );
312 drawingSheet->SetFileName( TO_UTF8( screen->GetFileName() ) );
313 drawingSheet->SetColorLayer( LAYER_SCHEMATIC_DRAWINGSHEET );
314 drawingSheet->SetPageBorderColorLayer( LAYER_SCHEMATIC_PAGE_LIMITS );
315 drawingSheet->SetIsFirstPage( screen->GetVirtualPageNumber() == 1 );
316 drawingSheet->SetSheetName( TO_UTF8( aFrame->GetScreenDesc() ) );
317 drawingSheet->SetSheetPath( TO_UTF8( aFrame->GetFullScreenDesc() ) );
318
319 wxString currentVariant = screen->Schematic()->GetCurrentVariant();
320 wxString variantDesc = screen->Schematic()->GetVariantDescription( currentVariant );
321 drawingSheet->SetVariantName( TO_UTF8( currentVariant ) );
322 drawingSheet->SetVariantDesc( TO_UTF8( variantDesc ) );
323
324 view->Add( drawingSheet.get() );
325 }
326
327 view->SetCenter( aBBox.Centre() );
328 view->UseDrawPriority( true );
329
330 gal->SetClearColor( dstSettings->GetBackgroundColor() );
331 gal->ClearScreen();
332
333 {
334 KIGFX::GAL_DRAWING_CONTEXT ctx( gal.get() );
335 view->Redraw();
336 }
337 }
338
339 return image;
340}
341
342
343wxImage renderSelectionToImageForClipboard( SCH_EDIT_FRAME* aFrame, const SCH_SELECTION& aSelection,
344 const BOX2I& aBBox, bool aUseAlpha, bool aIncludeDrawingSheet )
345{
346 const double c_targetPPI = 300;
347 const double c_targetPixelsPerMM = c_targetPPI / 25.4;
348
349 VECTOR2I size = aBBox.GetSize();
350
351 if( size.x <= 0 || size.y <= 0 )
352 return wxImage();
353
354 int bitmapWidth = KiROUND( schIUScale.IUTomm( size.x ) * c_targetPixelsPerMM );
355 int bitmapHeight = KiROUND( schIUScale.IUTomm( size.y ) * c_targetPixelsPerMM );
356
357 // Clamp to maximum size while preserving aspect ratio
358 if( bitmapWidth > clipboardMaxBitmapSize || bitmapHeight > clipboardMaxBitmapSize )
359 {
360 double scaleDown = (double) clipboardMaxBitmapSize / std::max( bitmapWidth, bitmapHeight );
361 bitmapWidth = KiROUND( bitmapWidth * scaleDown );
362 bitmapHeight = KiROUND( bitmapHeight * scaleDown );
363 }
364
365 if( bitmapWidth <= 0 || bitmapHeight <= 0 )
366 return wxImage();
367
368 wxImage result = renderSelectionToBitmap( aFrame, aSelection, aBBox, bitmapWidth, bitmapHeight, aUseAlpha,
369 aIncludeDrawingSheet );
370
371 return result;
372}
373} // namespace
374
375
377{
378 m_frame->NewProject();
379 return 0;
380}
381
382
384{
385 m_frame->LoadProject();
386 return 0;
387}
388
389
391{
392 m_frame->SaveProject();
393 return 0;
394}
395
396
398{
399 m_frame->SaveProject( true );
400 return 0;
401}
402
403
405{
406 SCH_SHEET* curr_sheet = m_frame->GetCurrentSheet().Last();
407 wxFileName curr_fn = curr_sheet->GetFileName();
408 wxFileDialog dlg( m_frame, _( "Schematic Files" ), curr_fn.GetPath(), curr_fn.GetFullName(),
409 FILEEXT::KiCadSchematicFileWildcard(), wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
410
412
413 if( dlg.ShowModal() == wxID_CANCEL )
414 return false;
415
416 wxString newFilename = EnsureFileExtension( dlg.GetPath(), FILEEXT::KiCadSchematicFileExtension );
417
418 m_frame->saveSchematicFile( curr_sheet, newFilename, true );
419 return 0;
420}
421
422
424{
425 SCHEMATIC& schematic = m_frame->Schematic();
426 SCH_SHEET& root = schematic.Root();
427
428 // Save original sheet path to restore if user cancels
429 SCH_SHEET_PATH originalSheet = m_frame->GetCurrentSheet();
430 bool wasOnSubsheet = ( m_frame->GetCurrentSheet().Last() != &root );
431
432 // Navigate to root sheet first (needed for proper reload), but don't repaint yet
433 if( wasOnSubsheet )
434 {
435 // Use the properly constructed root sheet path from the hierarchy
436 // (manually pushing root creates a path with empty KIID which causes assertions)
437 SCH_SHEET_PATH rootSheetPath = schematic.Hierarchy().at( 0 );
438
439 m_frame->GetToolManager()->RunAction<SCH_SHEET_PATH*>( SCH_ACTIONS::changeSheet,
440 &rootSheetPath );
441 // Don't call wxSafeYield() here - avoid repainting the root sheet before the dialog
442 }
443
444 wxString msg;
445 msg.Printf( _( "Revert '%s' (and all sub-sheets) to last version saved?" ), schematic.GetFileName() );
446
447 if( !IsOK( m_frame, msg ) )
448 {
449 // User cancelled - navigate back to original sheet
450 if( wasOnSubsheet )
451 {
452 m_frame->GetToolManager()->RunAction<SCH_SHEET_PATH*>( SCH_ACTIONS::changeSheet,
453 &originalSheet );
454 wxSafeYield();
455 }
456
457 return false;
458 }
459
460 SCH_SCREENS screenList( schematic.Root() );
461
462 for( SCH_SCREEN* screen = screenList.GetFirst(); screen; screen = screenList.GetNext() )
463 screen->SetContentModified( false ); // do not prompt the user for changes
464
465 m_frame->ReleaseFile();
466 m_frame->OpenProjectFiles( std::vector<wxString>( 1, schematic.GetFileName() ), KICTL_REVERT );
467
468 return 0;
469}
470
471
473{
474 m_frame->ShowSchematicSetupDialog();
475 return 0;
476}
477
478
480{
481 PICKED_ITEMS_LIST undoCmd;
483 ITEM_PICKER wrapper( m_frame->GetScreen(), undoItem, UNDO_REDO::PAGESETTINGS );
484
485 undoCmd.PushItem( wrapper );
486 undoCmd.SetDescription( _( "Page Settings" ) );
487 m_frame->SaveCopyInUndoList( undoCmd, UNDO_REDO::PAGESETTINGS, false );
488
489 DIALOG_EESCHEMA_PAGE_SETTINGS dlg( m_frame, m_frame->Schematic().GetEmbeddedFiles(),
492
493 if( dlg.ShowModal() == wxID_OK )
494 {
495 // Update text variables
496 m_frame->GetCanvas()->GetView()->MarkDirty();
497 m_frame->GetCanvas()->GetView()->UpdateAllItems( KIGFX::REPAINT );
498 m_frame->GetCanvas()->Refresh();
499
500 m_frame->OnModify();
501 }
502 else
503 {
504 m_frame->RollbackSchematicFromUndo();
505 }
506
507 return 0;
508}
509
510
512{
513 SCH_SCREENS schematic( m_frame->Schematic().Root() );
514
515 if( schematic.HasNoFullyDefinedLibIds() )
516 RescueLegacyProject( true );
517 else
519
520 return 0;
521}
522
523
524bool SCH_EDITOR_CONTROL::RescueLegacyProject( bool aRunningOnDemand )
525{
526 LEGACY_RESCUER rescuer( m_frame->Prj(), &m_frame->Schematic(), &m_frame->GetCurrentSheet(),
527 m_frame->GetCanvas()->GetBackend() );
528
529 return rescueProject( rescuer, aRunningOnDemand );
530}
531
532
534{
535 SYMBOL_LIB_TABLE_RESCUER rescuer( m_frame->Prj(), &m_frame->Schematic(), &m_frame->GetCurrentSheet(),
536 m_frame->GetCanvas()->GetBackend() );
537
538 return rescueProject( rescuer, aRunningOnDemand );
539}
540
541
542bool SCH_EDITOR_CONTROL::rescueProject( RESCUER& aRescuer, bool aRunningOnDemand )
543{
544 if( !RESCUER::RescueProject( m_frame, aRescuer, aRunningOnDemand ) )
545 return false;
546
547 if( aRescuer.GetCandidateCount() )
548 {
549 KIWAY_PLAYER* viewer = m_frame->Kiway().Player( FRAME_SCH_VIEWER, false );
550
551 if( viewer )
552 static_cast<SYMBOL_VIEWER_FRAME*>( viewer )->ReCreateLibList();
553
554 if( aRunningOnDemand )
555 {
556 SCH_SCREENS schematic( m_frame->Schematic().Root() );
557
558 schematic.UpdateSymbolLinks();
559 m_frame->RecalculateConnections( nullptr, GLOBAL_CLEANUP );
560 }
561
562 m_frame->ClearUndoRedoList();
563 m_frame->SyncView();
564 m_frame->GetCanvas()->Refresh();
565 m_frame->OnModify();
566 }
567
568 return true;
569}
570
571
573{
574 DIALOG_SYMBOL_REMAP dlgRemap( m_frame );
575
576 dlgRemap.ShowQuasiModal();
577
578 m_frame->GetCanvas()->Refresh( true );
579
580 return 0;
581}
582
583
585{
586 DIALOG_PRINT dlg( m_frame );
587
588 dlg.ShowModal();
589
590 return 0;
591}
592
593
595{
597
598 dlg.ShowModal();
599
600 return 0;
601}
602
603
605{
606 m_frame->Schematic().OnSchSelectionChanged();
607 doCrossProbeSchToPcb( aEvent, false );
608 return 0;
609}
610
611
613{
614 doCrossProbeSchToPcb( aEvent, true );
615 return 0;
616}
617
618
619void SCH_EDITOR_CONTROL::doCrossProbeSchToPcb( const TOOL_EVENT& aEvent, bool aForce )
620{
621 // Don't get in an infinite loop SCH -> PCB -> SCH -> PCB -> SCH -> ...
622 if( m_probingPcbToSch || m_frame->IsSyncingSelection() )
623 return;
624
625 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
626 SCH_SELECTION& selection = aForce ? selTool->RequestSelection() : selTool->GetSelection();
627
628 m_frame->SendSelectItemsToPcb( selection.GetItemsSortedBySelectionOrder(), aForce );
629}
630
631
633{
634 bool savePowerSymbols = false;
635 bool map = false;
637 wxString targetLib;
638 wxString msg;
639
640 targetLib = m_frame->SelectLibrary( _( "Export Symbols" ), _( "Export symbols to library:" ),
641 { { _( "Include power symbols in export" ), &savePowerSymbols },
642 { _( "Update schematic symbols to link to exported symbols" ), &map }
643 } );
644
645 if( targetLib.empty() )
646 return 0;
647
648 SCH_SHEET_LIST sheets = m_frame->Schematic().BuildSheetListSortedByPageNumbers();
649 SCH_REFERENCE_LIST symbols;
650 sheets.GetSymbols( symbols, savePowerSymbols ? SYMBOL_FILTER_ALL : SYMBOL_FILTER_NON_POWER );
651
652 std::map<LIB_ID, LIB_SYMBOL*> libSymbols;
653 std::map<LIB_ID, std::vector<SCH_SYMBOL*>> symbolMap;
654
655 for( size_t i = 0; i < symbols.GetCount(); ++i )
656 {
657 SCH_SYMBOL* symbol = symbols[i].GetSymbol();
658 LIB_SYMBOL* libSymbol = symbol->GetLibSymbolRef().get();
659 LIB_ID id = libSymbol->GetLibId();
660
661 if( libSymbols.count( id ) )
662 {
663 wxASSERT_MSG( libSymbols[id]->Compare( *libSymbol, ~SCH_ITEM::COMPARE_FLAGS::UUID ) == 0,
664 "Two symbols have the same LIB_ID but are different!" );
665 }
666 else
667 {
668 libSymbols[id] = libSymbol;
669 }
670
671 symbolMap[id].emplace_back( symbol );
672 }
673
674 bool append = false;
675 SCH_COMMIT commit( m_frame );
677
678 auto optRow = adapter->GetRow( targetLib );
679 wxCHECK( optRow, 0 );
680 const LIBRARY_TABLE_ROW* row = *optRow;
681
682 SCH_IO_MGR::SCH_FILE_T type = SCH_IO_MGR::EnumFromStr( row->Type() );
683 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( type ) );
684
685 wxFileName dest = LIBRARY_MANAGER::GetFullURI( row );
686 dest.Normalize( FN_NORMALIZE_FLAGS | wxPATH_NORM_ENV_VARS );
687
688 for( const std::pair<const LIB_ID, LIB_SYMBOL*>& it : libSymbols )
689 {
690 LIB_SYMBOL* origSym = it.second;
691 std::unique_ptr<LIB_SYMBOL> newSym = origSym->Flatten();
692 const wxString newSymName = newSym->GetName();
693
694 try
695 {
696 pi->SaveSymbol( dest.GetFullPath(), std::move( newSym ) );
697 }
698 catch( const IO_ERROR& ioe )
699 {
700 msg.Printf( _( "Error saving symbol %s to library '%s'." ), newSymName, row->Nickname() );
701 msg += wxS( "\n\n" ) + ioe.What();
702 wxLogWarning( msg );
703 return 0;
704 }
705
706 if( map )
707 {
708 LIB_ID id = it.first;
709 id.SetLibNickname( targetLib );
710
711 for( SCH_SYMBOL* symbol : symbolMap[it.first] )
712 {
713 SCH_SCREEN* parentScreen = static_cast<SCH_SCREEN*>( symbol->GetParent() );
714
715 wxCHECK2( parentScreen, continue );
716
717 commit.Modify( symbol, parentScreen, RECURSE_MODE::NO_RECURSE );
718 symbol->SetLibId( id );
719 append = true;
720 }
721 }
722 }
723
724 if( append )
725 {
726 std::set<SCH_SCREEN*> processedScreens;
727
728 for( SCH_SHEET_PATH& sheet : sheets )
729 {
730 SCH_SCREEN* screen = sheet.LastScreen();
731
732 if( processedScreens.find( ( screen ) ) == processedScreens.end() )
733 {
734 processedScreens.insert( screen );
735 screen->UpdateSymbolLinks();
736 }
737 }
738
739 commit.Push( wxS( "Update Library Identifiers" ) );
740 }
741
742 return 0;
743}
744
745
746#define HITTEST_THRESHOLD_PIXELS 5
747
749{
750 static const std::vector<KICAD_T> voltageProbeTypes = {
753 };
754
755 PICKER_TOOL* picker = m_toolMgr->GetTool<PICKER_TOOL>();
756 KIWAY_PLAYER* sim_player = m_frame->Kiway().Player( FRAME_SIMULATOR, false );
757 SIMULATOR_FRAME* sim_Frame = static_cast<SIMULATOR_FRAME*>( sim_player );
758
759 if( !sim_Frame ) // Defensive coding; shouldn't happen.
760 return 0;
761
762 if( wxWindow* blocking_win = sim_Frame->Kiway().GetBlockingDialog() )
763 blocking_win->Close( true );
764
765 if( ADVANCED_CFG::GetCfg().m_ConnectivityEngine && !m_frame->RecalculateConnections( nullptr, NO_CLEANUP ) )
766 return 0;
767
768 // Deactivate other tools; particularly important if another PICKER is currently running
769 Activate();
770
772 picker->SetSnapping( false );
773 picker->ClearHandlers();
774
775 picker->SetClickHandler(
776 [this]( const VECTOR2D& aPosition )
777 {
778 KIWAY_PLAYER* player = m_frame->Kiway().Player( FRAME_SIMULATOR, false );
779 SIMULATOR_FRAME* simFrame = static_cast<SIMULATOR_FRAME*>( player );
780 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
781
782 // We do not really want to keep an item selected in schematic,
783 // so clear the current selection
784 selTool->ClearSelection();
785
786 EDA_ITEM* item = selTool->GetNode( aPosition );
787 SCH_SHEET_PATH& sheet = m_frame->GetCurrentSheet();
788 wxString variant = m_frame->Schematic().GetCurrentVariant();
789
790 if( !item )
791 return false;
792
793 if( item->Type() == SCH_PIN_T )
794 {
795 SCH_PIN* schPin = static_cast<SCH_PIN*>( item );
796 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( schPin->GetParentSymbol() );
797 SCH_PIN* libPin = schPin->GetLibPin();
798
799 if( !symbol || !libPin )
800 return false;
801
802 try
803 {
805 SIM_LIB_MGR mgr( &m_frame->Prj() );
806
807 std::vector<EMBEDDED_FILES*> embeddedFilesStack;
808 embeddedFilesStack.push_back( m_frame->Schematic().GetEmbeddedFiles() );
809
810 if( EMBEDDED_FILES* symbolEmbeddedFile = symbol->GetEmbeddedFiles() )
811 embeddedFilesStack.push_back( symbolEmbeddedFile );
812
813 mgr.SetFilesStack( std::move( embeddedFilesStack ) );
814
815 SIM_MODEL& model = mgr.CreateModel( &sheet, *symbol, true, 0, variant, reporter ).model;
816
817 if( reporter.HasMessage() )
818 THROW_IO_ERROR( reporter.GetMessages() );
819
820 SPICE_ITEM spiceItem;
821 spiceItem.refName = symbol->GetRef( &sheet ).ToStdString();
822 std::vector<std::string> currentNames = model.SpiceGenerator().CurrentNames( spiceItem );
823
824 if( currentNames.size() == 0 )
825 {
826 return true;
827 }
828 else if( currentNames.size() == 1 )
829 {
830 if( simFrame )
831 simFrame->AddCurrentTrace( currentNames.at( 0 ) );
832
833 return true;
834 }
835
836 int modelPinIndex = model.FindModelPinIndex( libPin->GetNumber().ToStdString() );
837
838 if( modelPinIndex != SIM_MODEL_PIN::NOT_CONNECTED )
839 {
840 wxString name = currentNames.at( modelPinIndex );
841
842 if( simFrame )
843 simFrame->AddCurrentTrace( name );
844 }
845 }
846 catch( const IO_ERROR& e )
847 {
849 }
850 }
851 else if( item->IsType( voltageProbeTypes ) )
852 {
853 const SCH_ITEM* schItem = static_cast<const SCH_ITEM*>( item );
854
855 if( schItem->HasBusConnection( &sheet ) )
856 return true;
857
858 if( const auto name = schItem->GetConnectionName( &sheet );
859 name && !name->IsEmpty() )
860 {
861 wxString spiceNet = *name;
863
864 if( simFrame )
865 simFrame->AddVoltageTrace( wxString::Format( "V(%s)", spiceNet ) );
866 }
867 }
868
869 return true;
870 } );
871
872 picker->SetMotionHandler(
873 [this]( const VECTOR2D& aPos )
874 {
875 SCH_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
876 EDA_ITEM* item = selectionTool->GetNode( aPos );
877 wxString connectionName;
878
879 if( item && item->IsType( voltageProbeTypes ) )
880 {
881 const SCH_ITEM* schItem = static_cast<const SCH_ITEM*>( item );
882 const SCH_SHEET_PATH& sheet = m_frame->GetCurrentSheet();
883 item = nullptr;
884
885 if( !schItem->HasBusConnection( &sheet ) )
886 connectionName = schItem->GetConnectionName( &sheet ).value_or( wxString() );
887 }
888 else if( item && item->Type() != SCH_PIN_T )
889 {
890 item = nullptr;
891 }
892
893 if( item && item->Type() == SCH_PIN_T )
894 m_toolMgr->GetTool<PICKER_TOOL>()->SetCursor( KICURSOR::CURRENT_PROBE );
895 else
896 m_toolMgr->GetTool<PICKER_TOOL>()->SetCursor( KICURSOR::VOLTAGE_PROBE );
897
898 if( m_pickerItem != item )
899 {
900 if( m_pickerItem )
901 selectionTool->UnbrightenItem( m_pickerItem );
902
903 m_pickerItem = item;
904
905 if( m_pickerItem )
906 selectionTool->BrightenItem( m_pickerItem );
907 }
908
909 if( m_frame->GetHighlightedConnection() != connectionName )
910 {
911 m_frame->SetHighlightedConnection( connectionName );
912
913 TOOL_EVENT dummyEvent;
914 UpdateNetHighlighting( dummyEvent );
915 }
916 } );
917
918 picker->SetFinalizeHandler(
919 [this]( const int& aFinalState )
920 {
921 if( m_pickerItem )
922 m_toolMgr->GetTool<SCH_SELECTION_TOOL>()->UnbrightenItem( m_pickerItem );
923
924 if( !m_frame->GetHighlightedConnection().IsEmpty() )
925 {
926 m_frame->SetHighlightedConnection( wxEmptyString );
927
928 TOOL_EVENT dummyEvent;
929 UpdateNetHighlighting( dummyEvent );
930 }
931
932 // Wake the selection tool after exiting to ensure the cursor gets updated
933 // and deselect previous selection from simulator to avoid any issue
934 // ( avoid crash in some cases when the SimProbe tool is deselected )
935 SCH_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
936 selectionTool->ClearSelection();
938 } );
939
940 m_toolMgr->RunAction( ACTIONS::pickerTool, &aEvent );
941
942 return 0;
943}
944
945
947{
948 PICKER_TOOL* picker = m_toolMgr->GetTool<PICKER_TOOL>();
949
950 // Deactivate other tools; particularly important if another PICKER is currently running
951 Activate();
952
953 picker->SetCursor( KICURSOR::TUNE );
954 picker->SetSnapping( false );
955 picker->ClearHandlers();
956
957 picker->SetClickHandler(
958 [this]( const VECTOR2D& aPosition )
959 {
960 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
961 EDA_ITEM* item = nullptr;
962 selTool->SelectPoint( aPosition, { SCH_SYMBOL_T, SCH_FIELD_T }, &item );
963
964 if( !item )
965 return false;
966
967 if( item->Type() != SCH_SYMBOL_T )
968 {
969 item = item->GetParent();
970
971 if( item->Type() != SCH_SYMBOL_T )
972 return false;
973 }
974
975 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
976 SCH_SHEET_PATH sheetPath = symbol->Schematic()->CurrentSheet();
977 KIWAY_PLAYER* simFrame = m_frame->Kiway().Player( FRAME_SIMULATOR, false );
978
979 if( simFrame )
980 {
981 if( wxWindow* blocking_win = simFrame->Kiway().GetBlockingDialog() )
982 blocking_win->Close( true );
983
984 static_cast<SIMULATOR_FRAME*>( simFrame )->AddTuner( sheetPath, symbol );
985 }
986
987 // We do not really want to keep a symbol selected in schematic,
988 // so clear the current selection
989 selTool->ClearSelection();
990 return true;
991 } );
992
993 picker->SetMotionHandler(
994 [this]( const VECTOR2D& aPos )
995 {
996 SCH_COLLECTOR collector;
997 collector.m_Threshold = KiROUND( getView()->ToWorld( HITTEST_THRESHOLD_PIXELS ) );
998 collector.Collect( m_frame->GetScreen(), { SCH_SYMBOL_T, SCH_FIELD_T }, aPos );
999
1000 SCH_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
1001 selectionTool->GuessSelectionCandidates( collector, aPos );
1002
1003 EDA_ITEM* item = collector.GetCount() == 1 ? collector[0] : nullptr;
1004
1005 if( item && item->Type() == SCH_FIELD_T )
1006 item = static_cast<SCH_FIELD*>( item )->GetParentSymbol();
1007
1008 if( m_pickerItem != item )
1009 {
1010 if( m_pickerItem )
1011 selectionTool->UnbrightenItem( m_pickerItem );
1012
1013 m_pickerItem = item;
1014
1015 if( m_pickerItem )
1016 selectionTool->BrightenItem( m_pickerItem );
1017 }
1018 } );
1019
1020 picker->SetFinalizeHandler(
1021 [this]( const int& aFinalState )
1022 {
1023 if( m_pickerItem )
1024 m_toolMgr->GetTool<SCH_SELECTION_TOOL>()->UnbrightenItem( m_pickerItem );
1025
1026 // Wake the selection tool after exiting to ensure the cursor gets updated
1027 // and deselect previous selection from simulator to avoid any issue
1028 // ( avoid crash in some cases when the SimTune tool is deselected )
1029 SCH_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
1030 selectionTool->ClearSelection();
1032 } );
1033
1034 m_toolMgr->RunAction( ACTIONS::pickerTool, &aEvent );
1035
1036 return 0;
1037}
1038
1039
1040// A singleton reference for clearing the highlight
1042
1043
1044static void recalculateIfStale( SCH_EDIT_FRAME* aFrame, SCH_ITEM* aItem )
1045{
1046 if( ( aItem && aItem->IsConnectivityDirty() ) || !aFrame->Schematic().NetChains().NetChainsBuilt() )
1047 aFrame->RecalculateConnections( nullptr, NO_CLEANUP );
1048}
1049
1050
1051static bool setNetHighlight( SCH_ITEM* aItem, bool aHighlight )
1052{
1053 if( aItem->IsNetHighlighted() == aHighlight )
1054 return false;
1055
1056 aItem->SetNetHighlighted( aHighlight );
1057 return true;
1058}
1059
1060
1061static bool highlightNet( TOOL_MANAGER* aToolMgr, const SCH_SHEET_PATH& aSheetPath, const VECTOR2D& aPosition )
1062{
1063 wxLogTrace( "KICAD_SCH_HIGHLIGHT", "highlightNet: pos=(%f,%f) clear=%d", aPosition.x, aPosition.y,
1064 ( aPosition == CLEAR ) );
1065 SCH_EDIT_FRAME* editFrame = static_cast<SCH_EDIT_FRAME*>( aToolMgr->GetToolHolder() );
1066 SCH_SELECTION_TOOL* selTool = aToolMgr->GetTool<SCH_SELECTION_TOOL>();
1067 SCH_EDITOR_CONTROL* editorControl = aToolMgr->GetTool<SCH_EDITOR_CONTROL>();
1068 std::optional<wxString> connName;
1069 SCH_ITEM* item = nullptr;
1070 bool retVal = true;
1071
1072 if( aPosition != CLEAR )
1073 {
1074 ERC_TESTER erc( &editFrame->Schematic() );
1075
1076 if( erc.TestDuplicateSheetNames( false ) > 0 )
1077 {
1078 wxMessageBox( _( "Error: duplicate sub-sheet names found in current sheet." ) );
1079 retVal = false;
1080 }
1081 else
1082 {
1083 item = static_cast<SCH_ITEM*>( selTool->GetNode( aPosition ) );
1084 wxLogTrace( "KICAD_SCH_HIGHLIGHT", "highlightNet: item=%p type=%d", (void*) item, item ? (int) item->Type()
1085 : -1 );
1086 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( item );
1087
1088 if( item )
1089 {
1090 recalculateIfStale( editFrame, item );
1091
1092 if( item->Type() == SCH_FIELD_T )
1093 symbol = dynamic_cast<SCH_SYMBOL*>( item->GetParent() );
1094
1095 if( symbol && symbol->GetLibSymbolRef() && symbol->GetLibSymbolRef()->IsPower() )
1096 {
1097 std::vector<SCH_PIN*> pins = symbol->GetPins( &aSheetPath );
1098
1099 if( pins.size() == 1 )
1100 connName = pins[0]->GetConnectionName( &editFrame->GetCurrentSheet() );
1101 }
1102 else
1103 {
1104 connName = item->GetConnectionName( &editFrame->GetCurrentSheet() );
1105 }
1106 }
1107 }
1108 }
1109
1110 if( !connName || connName->IsEmpty() )
1111 {
1112 wxLogTrace( "KICAD_SCH_HIGHLIGHT", "highlightNet: no connection under cursor" );
1113 editFrame->SetStatusText( wxT( "" ) );
1114 editFrame->SendCrossProbeClearHighlight();
1115 editFrame->SetHighlightedConnection( wxEmptyString );
1116 // Also clear any highlighted net chain so ESC or clicking empty space clears both modes
1117 editFrame->SetHighlightedNetChain( wxEmptyString );
1118 editorControl->SetHighlightBusMembers( false );
1119 }
1120 else
1121 {
1122 NET_NAVIGATOR_ITEM_DATA itemData( editFrame->GetCurrentSheet(), item );
1123
1124 if( *connName != editFrame->GetHighlightedConnection() )
1125 {
1126 wxLogTrace( "KICAD_SCH_HIGHLIGHT", "highlightNet: setting highlighted connection to %s", *connName );
1127 editorControl->SetHighlightBusMembers( false );
1128 // Clear any previous chain highlight when switching to net highlight
1129 editFrame->SetHighlightedNetChain( wxEmptyString );
1130 editFrame->SetCrossProbeConnection( *connName );
1131 editFrame->SetHighlightedConnection( *connName, &itemData );
1132 }
1133 else
1134 {
1135 auto& chains = editFrame->Schematic().NetChains();
1136
1137 if( SCH_NETCHAIN* chain = chains.GetNetChainForNet( *connName ) )
1138 {
1139 editFrame->SetHighlightedConnection( wxEmptyString );
1140 editFrame->SetHighlightedNetChain( chain->GetName() );
1141 editorControl->SetHighlightBusMembers( false );
1142 }
1143 else
1144 {
1145 editorControl->SetHighlightBusMembers( !editorControl->GetHighlightBusMembers() );
1146
1147 if( item != editFrame->GetSelectedNetNavigatorItem() )
1148 editFrame->SelectNetNavigatorItem( &itemData );
1149 }
1150 }
1151 }
1152
1153 editFrame->UpdateNetHighlightStatus();
1154
1156 editorControl->UpdateNetHighlighting( dummy );
1157 wxLogTrace( "KICAD_SCH_HIGHLIGHT", "highlightNet: done" );
1158
1159 return retVal;
1160}
1161
1162
1164{
1166 VECTOR2D cursorPos = controls->GetCursorPosition( !aEvent.DisableGridSnapping() );
1167
1168 highlightNet( m_toolMgr, m_frame->GetCurrentSheet(), cursorPos );
1169
1170 return 0;
1171}
1172
1173
1175{
1177 const VECTOR2D cursorPos = controls->GetCursorPosition( !aEvent.DisableGridSnapping() );
1178 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
1179 SCH_ITEM* item = static_cast<SCH_ITEM*>( selTool->GetNode( cursorPos ) );
1180 auto& chains = m_frame->Schematic().NetChains();
1181
1182 recalculateIfStale( m_frame, item );
1183
1184 const auto name = item ? item->GetConnectionName( &m_frame->GetCurrentSheet() ) : std::nullopt;
1185 wxString newChain;
1186 wxString newConnection;
1187
1188 if( name && !name->IsEmpty() )
1189 {
1190 if( SCH_NETCHAIN* chain = chains.GetNetChainForNet( *name ) )
1191 {
1192 newChain = chain->GetName();
1193
1194 if( !chain->GetNets().empty() )
1195 m_frame->SendCrossProbeNetName( *chain->GetNets().begin() );
1196 }
1197 else
1198 {
1199 newConnection = *name;
1200 m_frame->SetCrossProbeConnection( *name );
1201 }
1202 }
1203 else
1204 {
1205 m_frame->SendCrossProbeClearHighlight();
1206 }
1207
1208 SetHighlightBusMembers( false );
1209 m_frame->SetHighlightedNetChain( newChain );
1210 m_frame->SetHighlightedConnection( newConnection );
1211 m_frame->UpdateNetHighlightStatus();
1214 return 0;
1215}
1216
1218{
1219 SCH_EDIT_FRAME* editFrame = static_cast<SCH_EDIT_FRAME*>( m_toolMgr->GetToolHolder() );
1220 if( !editFrame )
1221 return 0;
1222
1223 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
1225 VECTOR2D cursorPos = controls->GetCursorPosition( !aEvent.DisableGridSnapping() );
1226
1227 SCH_ITEM* target = nullptr;
1228
1229 // Prefer current selection; otherwise, use item under cursor
1230 if( selTool && selTool->GetSelection().GetSize() == 1 )
1231 target = static_cast<SCH_ITEM*>( selTool->GetSelection().Front() );
1232 else if( selTool )
1233 target = static_cast<SCH_ITEM*>( selTool->GetNode( cursorPos ) );
1234
1235 if( !target )
1236 return 0;
1237
1238 auto& chains = editFrame->Schematic().NetChains();
1239 const wxString net = SCH_CONNECTIVITY::NETCHAIN_MANAGER::NetKeyForItem( *target, editFrame->GetCurrentSheet() );
1240 const SCH_NETCHAIN* chain = chains.GetNetChainForNet( net );
1241
1242 if( !chain )
1243 return 0;
1244
1245 SCH_COMMIT commit( editFrame );
1246
1247 for( const auto& [symbol, screen] : chains.GetBridgeSymbols( *chain, net ) )
1248 {
1249 commit.Modify( symbol, screen );
1250 symbol->SetPassthroughMode( SCH_SYMBOL::PASSTHROUGH_MODE::BLOCK );
1251 }
1252
1253 commit.Push( _( "Remove from Net Chain" ) );
1254
1255 return 0;
1256}
1257
1258
1260{
1261 highlightNet( m_toolMgr, m_frame->GetCurrentSheet(), CLEAR );
1262
1263 // Also clear any highlighted chain explicitly
1264 if( m_frame )
1265 m_frame->SetHighlightedNetChain( wxEmptyString );
1266
1267 return 0;
1268}
1269
1270
1272{
1273 SCH_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
1274 SCHEMATIC& schematic = m_frame->Schematic();
1275 const SCH_SHEET_PATH path = m_frame->GetCurrentSheet();
1276 SCH_SCREEN* screen = path.LastScreen();
1277 const bool usePublished = ADVANCED_CFG::GetCfg().m_ConnectivityEngine;
1278
1279 if( usePublished && !m_frame->RecalculateConnections( nullptr, NO_CLEANUP ) )
1280 return 0;
1281
1282 const auto getNetNamePattern =
1283 []( const auto& aConn ) -> std::optional<wxString>
1284 {
1285 wxString netName = aConn.Name();
1286
1287 if( aConn.IsBus() )
1288 {
1289 wxString prefix;
1290
1291 if( NET_SETTINGS::ParseBusVector( netName, &prefix, nullptr ) )
1292 return prefix + wxT( "*" );
1293 else if( NET_SETTINGS::ParseBusGroup( netName, &prefix, nullptr ) )
1294 return prefix + wxT( ".*" );
1295 }
1296 else if( !aConn.Driver() || CONNECTION_SUBGRAPH::GetDriverPriority( aConn.Driver() )
1298 {
1299 return std::nullopt;
1300 }
1301
1302 return netName;
1303 };
1304
1305 std::set<wxString> netNames;
1306
1307 for( EDA_ITEM* item : selectionTool->GetSelection() )
1308 {
1309 SCH_ITEM* schItem = static_cast<SCH_ITEM*>( item );
1310 std::optional<wxString> netNamePattern;
1311
1312 if( usePublished )
1313 {
1314 const auto connection = schematic.Connectivity().Connection( schItem->m_Uuid, path.PathRef() );
1315
1316 if( !connection )
1317 continue;
1318
1319 netNamePattern = getNetNamePattern( *connection );
1320 }
1321 else
1322 {
1323 const SCH_CONNECTION* connection = schItem->Connection( &path );
1324
1325 if( !connection )
1326 continue;
1327
1328 netNamePattern = getNetNamePattern( *connection );
1329 }
1330
1331 if( !netNamePattern )
1332 {
1333 // This is a choice, we can also allow some un-labeled nets as long as some are labeled.
1334 m_frame->ShowInfoBarError( _( "All selected nets must be labeled to assign a netclass." ) );
1335 return 0;
1336 }
1337
1338 netNames.insert( *netNamePattern );
1339 }
1340
1341 if( netNames.empty() )
1342 {
1343 m_frame->ShowInfoBarError( _( "No nets selected." ) );
1344 return 0;
1345 }
1346
1347 selectionTool->ClearSelection();
1348
1349 DIALOG_ASSIGN_NETCLASS dlg( m_frame, netNames, schematic.GetNetClassAssignmentCandidates(),
1350 [&]( const std::vector<wxString>& aNetNames )
1351 {
1352 std::unordered_set<SCH_ITEM*> highlighted;
1353 const SCH_CONNECTIVITY::NAVIGATION_QUERY query( schematic );
1354
1355 for( const wxString& name : aNetNames )
1356 query.CollectNetItems( name, path, highlighted );
1357
1358 for( SCH_ITEM* item : screen->Items() )
1359 {
1360 bool redraw = setNetHighlight( item, highlighted.contains( item ) );
1361
1362 item->RunOnChildren(
1363 [&]( SCH_ITEM* aChild )
1364 {
1365 redraw |= setNetHighlight( aChild, highlighted.contains( aChild ) );
1366 },
1367 RECURSE_MODE::NO_RECURSE );
1368
1369 if( redraw )
1370 getView()->Update( item, KIGFX::VIEW_UPDATE_FLAGS::REPAINT );
1371 }
1372
1373 m_frame->GetCanvas()->ForceRefresh();
1374 } );
1375
1376 if( dlg.ShowModal() )
1377 {
1378 getView()->UpdateAllItemsConditionally(
1379 [&]( KIGFX::VIEW_ITEM* aItem ) -> int
1380 {
1381 int flags = 0;
1382
1383 auto invalidateTextVars =
1384 [&flags]( EDA_TEXT* text )
1385 {
1386 if( text->HasTextVars() )
1387 {
1388 text->ClearRenderCache();
1389 text->ClearBoundingBoxCache();
1391 }
1392 };
1393
1394 // Netclass coloured items
1395 //
1396 if( dynamic_cast<SCH_LINE*>( aItem ) )
1397 flags |= KIGFX::REPAINT;
1398 else if( dynamic_cast<SCH_JUNCTION*>( aItem ) )
1399 flags |= KIGFX::REPAINT;
1400 else if( dynamic_cast<SCH_BUS_ENTRY_BASE*>( aItem ) )
1401 flags |= KIGFX::REPAINT;
1402
1403 // Items that might reference an item's netclass name
1404 //
1405 if( EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( aItem ) )
1406 invalidateTextVars( text );
1407
1408 if( SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( aItem ) )
1409 {
1410 item->RunOnChildren(
1411 [&invalidateTextVars]( SCH_ITEM* aChild )
1412 {
1413 if( EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( aChild ) )
1414 invalidateTextVars( text );
1415 },
1417
1418 if( flags & KIGFX::GEOMETRY )
1419 m_frame->GetScreen()->UpdateDisplayBounds( item );
1420 }
1421
1422 return flags;
1423 } );
1424 }
1425
1426 highlightNet( m_toolMgr, m_frame->GetCurrentSheet(), CLEAR );
1427 return 0;
1428}
1429
1430
1432{
1433 SCH_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
1434
1435 if( !selectionTool )
1436 return 0;
1437
1438 const SCH_SHEET_PATH path = m_frame->GetCurrentSheet();
1439 const bool usePublished = ADVANCED_CFG::GetCfg().m_ConnectivityEngine;
1440
1441 if( usePublished && !m_frame->RecalculateConnections( nullptr, NO_CLEANUP ) )
1442 return 0;
1443
1444 wxString netName;
1445
1446 for( EDA_ITEM* item : selectionTool->GetSelection() )
1447 {
1448 if( SCH_ITEM* schItem = dynamic_cast<SCH_ITEM*>( item ) )
1449 {
1450 if( usePublished )
1451 {
1452 const auto connection = m_frame->Schematic().Connectivity().Connection(
1453 schItem->m_Uuid, path.PathRef() );
1454
1455 if( connection && !connection->IsUnconnected() )
1456 netName = connection->Name();
1457 }
1458 else if( const SCH_CONNECTION* connection = schItem->Connection( &path ) )
1459 {
1460 netName = connection->GetNetName();
1461 }
1462
1463 if( !netName.IsEmpty() )
1464 break;
1465 }
1466 }
1467
1468 if( netName.IsEmpty() )
1469 netName = m_frame->GetHighlightedConnection();
1470
1471 if( netName.IsEmpty() )
1472 {
1473 m_frame->ShowInfoBarError( _( "No connected net selected." ) );
1474 return 0;
1475 }
1476
1477 m_frame->FindNetInInspector( netName );
1478
1479 return 0;
1480}
1481
1482
1484{
1485 wxCHECK( m_frame, 0 );
1486
1487 const SCH_SHEET_PATH& sheetPath = m_frame->GetCurrentSheet();
1488 SCH_SCREEN* screen = sheetPath.LastScreen();
1489 wxCHECK( screen, 0 );
1490
1491 const wxString selectedName = m_frame->GetHighlightedConnection();
1492 const wxString chainName = m_frame->GetHighlightedNetChain();
1493 SCH_NETCHAIN* chain = chainName.IsEmpty() ? nullptr
1494 : m_frame->Schematic().NetChains().GetNetChainByName( chainName );
1495 std::unordered_set<SCH_ITEM*> highlighted;
1496
1497 if( !selectedName.IsEmpty() || chain )
1498 {
1499 const SCH_CONNECTIVITY::NAVIGATION_QUERY query( m_frame->Schematic() );
1500
1501 if( !selectedName.IsEmpty() )
1502 query.CollectNetItems( selectedName, sheetPath, highlighted, true, m_highlightBusMembers );
1503
1504 if( chain )
1505 {
1506 for( const wxString& name : chain->GetNets() )
1507 query.CollectNetItems( name, sheetPath, highlighted );
1508 }
1509 }
1510
1511 bool changed = false;
1512
1513 for( SCH_ITEM* item : screen->Items() )
1514 {
1515 if( !item )
1516 continue;
1517
1518 bool redraw = setNetHighlight( item, highlighted.contains( item ) );
1519 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( item );
1520 bool powerHighlight = false;
1521
1522 if( symbol && symbol->IsPower() )
1523 {
1524 std::vector<SCH_PIN*> pins = symbol->GetPins( &sheetPath );
1525 powerHighlight = !pins.empty() && highlighted.contains( pins.front() );
1526 }
1527
1528 item->RunOnChildren(
1529 [&]( SCH_ITEM* child )
1530 {
1531 bool highlight = highlighted.contains( child );
1532
1533 if( powerHighlight && child->Type() == SCH_FIELD_T )
1534 {
1535 const auto* field = static_cast<SCH_FIELD*>( child );
1536 highlight = field->IsVisible() && ( field->GetId() == FIELD_T::REFERENCE
1537 || field->GetId() == FIELD_T::VALUE );
1538 }
1539
1540 redraw |= setNetHighlight( child, highlight );
1542
1543 if( redraw )
1544 {
1545 getView()->Update( item, KIGFX::REPAINT );
1546 changed = true;
1547 }
1548 }
1549
1550 if( changed )
1551 m_frame->GetCanvas()->Refresh();
1552
1553 return 0;
1554}
1555
1556
1558{
1559 PICKER_TOOL* picker = m_toolMgr->GetTool<PICKER_TOOL>();
1560
1561 // Deactivate other tools; particularly important if another PICKER is currently running
1562 Activate();
1563
1564 picker->SetCursor( KICURSOR::BULLSEYE );
1565 picker->SetSnapping( false );
1566 picker->ClearHandlers();
1567
1568 picker->SetClickHandler(
1569 [this]( const VECTOR2D& aPos )
1570 {
1571 return highlightNet( m_toolMgr, m_frame->GetCurrentSheet(), aPos );
1572 } );
1573
1574 m_toolMgr->RunAction( ACTIONS::pickerTool, &aEvent );
1575
1576 return 0;
1577}
1578
1579
1581{
1582 SCH_EDIT_FRAME* editFrame = static_cast<SCH_EDIT_FRAME*>( m_toolMgr->GetToolHolder() );
1584
1585 if( editFrame->Schematic().NetChains().ReplaceNetChainTerminalPin( change ) )
1586 {
1587 editFrame->OnModify();
1588 editFrame->GetCanvas()->Refresh();
1589 }
1590 else
1591 {
1592 DisplayError( editFrame, _( "Unable to replace the net chain terminal pin." ) );
1593 }
1594
1595 return 0;
1596}
1597
1598
1600{
1601 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
1602 SCH_ITEM* item = static_cast<SCH_ITEM*>( selTool->GetSelection().Front() );
1603 SCH_PIN* pin = dynamic_cast<SCH_PIN*>( item );
1604
1605 if( !pin )
1606 return 0;
1607
1608 SCH_EDIT_FRAME* editFrame = static_cast<SCH_EDIT_FRAME*>( m_toolMgr->GetToolHolder() );
1609 auto& chains = editFrame->Schematic().NetChains();
1610 const auto netName = pin->GetConnectionName( &editFrame->GetCurrentSheet() );
1611
1612 if( !netName )
1613 return 0;
1614
1615 if( SCH_NETCHAIN* sig = chains.GetNetChainForNet( *netName ) )
1616 {
1617 const wxString oldName = sig->GetName();
1618 const wxString newName = wxGetTextFromUser( _( "Net chain name:" ), _( "Name Net Chain" ), oldName );
1619
1620 if( newName.IsEmpty() || newName == oldName )
1621 return 0;
1622
1623 if( !SCH_NETCHAIN::IsValidName( newName ) )
1624 {
1625 DisplayError( editFrame, _( "Chain name cannot contain spaces, quotes, or parentheses." ) );
1626 return 0;
1627 }
1628
1629 if( !chains.RenameCommittedNetChain( oldName, newName ) )
1630 {
1631 DisplayError( editFrame, wxString::Format( _( "Unable to rename net chain '%s' to '%s'." ),
1632 oldName, newName ) );
1633 return 0;
1634 }
1635
1636 editFrame->OnModify();
1637 editFrame->SetHighlightedNetChain( newName );
1640 editFrame->UpdateNetHighlightStatus();
1641 }
1642
1643 return 0;
1644}
1645
1647{
1648 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
1649 auto& selection = selTool->GetSelection();
1650
1651 if( selection.GetSize() != 2 )
1652 return 0;
1653
1654 SCH_PIN* pinA = dynamic_cast<SCH_PIN*>( static_cast<SCH_ITEM*>( selection[0] ) );
1655 SCH_PIN* pinB = dynamic_cast<SCH_PIN*>( static_cast<SCH_ITEM*>( selection[1] ) );
1656
1657 if( !pinA || !pinB )
1658 return 0;
1659
1660 SCH_EDIT_FRAME* editFrame = static_cast<SCH_EDIT_FRAME*>( m_toolMgr->GetToolHolder() );
1661 auto& chains = editFrame->Schematic().NetChains();
1662 const SCH_SHEET_PATH& path = editFrame->GetCurrentSheet();
1663
1664 SCH_NETCHAIN* potential = chains.FindPotentialNetChainBetweenPins( pinA, path, pinB, path );
1665 if( !potential )
1666 {
1667 DisplayError( editFrame, _( "No potential net chain connects the selected pins." ) );
1668 return 0;
1669 }
1670
1671 // Potentials are rebuilt regardless of commitment and GetNetChainForNet() returns the first owner
1672 for( const wxString& net : potential->GetNets() )
1673 {
1674 if( SCH_NETCHAIN* owner = chains.GetNetChainForNet( net ) )
1675 {
1676 DisplayError( editFrame, wxString::Format( _( "The selected pins are already in net chain '%s'." ),
1677 owner->GetName() ) );
1678 return 0;
1679 }
1680 }
1681
1682 // Build default suggestion name
1683 wxString suggestion = wxString::Format( wxS( "%s_%s" ), pinA->GetParentSymbol()->GetRef( &editFrame->GetCurrentSheet() ), pinB->GetParentSymbol()->GetRef( &editFrame->GetCurrentSheet() ) );
1684
1685 // Compose display text for dialog
1686 wxString msg = wxString::Format( _( "Create Net Chain between %s:%s and %s:%s" ),
1687 pinA->GetParentSymbol()->GetRef( &editFrame->GetCurrentSheet() ), pinA->GetNumber(),
1688 pinB->GetParentSymbol()->GetRef( &editFrame->GetCurrentSheet() ), pinB->GetNumber() );
1689
1690 // Temporary highlight preview: highlight all nets in potential (reuse SetHighlightedNetChain with temp name)
1691 // We use the potential's current name as a temporary highlight identifier
1692 wxString prevHighlightedChain = editFrame->GetHighlightedNetChain();
1693 wxString prevHighlightedConn = editFrame->GetHighlightedConnection();
1694
1695 editFrame->SetHighlightedConnection( wxEmptyString );
1696 editFrame->SetHighlightedNetChain( potential->GetName() );
1699 editFrame->UpdateNetHighlightStatus();
1700
1701 // Zoom to bounding box of the two pins (union) expanded slightly
1702 BOX2I bbox = pinA->GetBoundingBox();
1703 bbox.Merge( pinB->GetBoundingBox() );
1704 // Expand by 25% for context
1705 int dx = bbox.GetWidth() / 4; if( dx < 100 ) dx = 100;
1706 int dy = bbox.GetHeight() / 4; if( dy < 100 ) dy = 100;
1707 bbox.Inflate( dx, dy );
1708 if( auto canvas = editFrame->GetCanvas() )
1709 {
1710 canvas->GetView()->SetCenter( bbox.GetCenter() );
1711 // Compute scale so bbox roughly fits viewport height
1712 auto view = canvas->GetView();
1713 if( view )
1714 {
1715 BOX2D viewBox = view->GetBoundary();
1716 double scaleX = (double) viewBox.GetWidth() / (double) bbox.GetWidth();
1717 double scaleY = (double) viewBox.GetHeight() / (double) bbox.GetHeight();
1718 double scale = std::min( scaleX, scaleY );
1719 if( scale > 0 )
1720 view->SetScale( scale );
1721 }
1722 }
1723
1724 const auto restoreHighlight =
1725 [&]()
1726 {
1727 editFrame->SetHighlightedNetChain( prevHighlightedChain );
1728 editFrame->SetHighlightedConnection( prevHighlightedConn );
1730 editFrame->UpdateNetHighlightStatus();
1731 };
1732
1733 wxString name = wxGetTextFromUser( msg, _( "Create Net Chain" ), suggestion, editFrame );
1734
1735 if( name.IsEmpty() )
1736 {
1737 restoreHighlight();
1738 return 0; // cancelled
1739 }
1740
1742 {
1743 restoreHighlight();
1744 DisplayError( editFrame, _( "Chain name cannot contain spaces, quotes, or parentheses." ) );
1745 return 0;
1746 }
1747
1748 if( chains.GetNetChainByName( name ) )
1749 {
1750 restoreHighlight();
1751 DisplayError( editFrame, wxString::Format( _( "A net chain named '%s' already exists." ), name ) );
1752 return 0;
1753 }
1754
1755 if( !chains.CreateNetChainFromPotential( potential, name ) )
1756 {
1757 restoreHighlight();
1758 DisplayError( editFrame, wxString::Format( _( "Unable to create net chain '%s'." ), name ) );
1759 return 0;
1760 }
1761
1762 editFrame->OnModify();
1763
1764 // Replace temporary highlight with new chain name
1765 editFrame->SetHighlightedNetChain( name );
1766 editFrame->SetHighlightedConnection( wxEmptyString );
1768 editFrame->UpdateNetHighlightStatus();
1769 editFrame->Refresh();
1770
1771 return 0;
1772}
1773
1774
1776{
1777 SCH_EDIT_FRAME* editFrame = static_cast<SCH_EDIT_FRAME*>( m_toolMgr->GetToolHolder() );
1778
1779 editFrame->RecalculateConnections( nullptr, NO_CLEANUP );
1780
1782
1783 if( SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>() )
1784 {
1785 const SCH_SELECTION& sel = selTool->GetSelection();
1786
1787 std::vector<SCH_SYMBOL*> symbols;
1788
1789 for( EDA_ITEM* item : sel )
1790 {
1791 if( SCH_SYMBOL* sym = dynamic_cast<SCH_SYMBOL*>( static_cast<SCH_ITEM*>( item ) ) )
1792 symbols.push_back( sym );
1793 }
1794
1795 if( symbols.size() >= 1 )
1796 hint.fromRef = symbols[0]->GetRef( &editFrame->GetCurrentSheet() );
1797
1798 if( symbols.size() >= 2 )
1799 hint.toRef = symbols[1]->GetRef( &editFrame->GetCurrentSheet() );
1800
1801 // Single pin or single wire/bus → use its connection's net name as the focus hint.
1802 if( symbols.empty() && sel.GetSize() == 1 )
1803 {
1804 SCH_ITEM* schItem = static_cast<SCH_ITEM*>( sel.Front() );
1805
1806 if( schItem && schItem->IsType( { SCH_PIN_T, SCH_ITEM_LOCATE_WIRE_T, SCH_ITEM_LOCATE_BUS_T } ) )
1807 {
1808 if( const auto name = schItem->GetConnectionName( &editFrame->GetCurrentSheet() ) )
1809 hint.netName = *name;
1810 }
1811 }
1812 }
1813
1814 DIALOG_CREATE_NET_CHAIN dlg( editFrame, hint );
1815 dlg.ShowModal();
1816
1817 return 0;
1818}
1819
1820
1822{
1823 wxCHECK( m_frame, 0 );
1824
1825 if( m_frame->GetUndoCommandCount() <= 0 )
1826 return 0;
1827
1828 // Inform tools that undo command was issued
1829 m_toolMgr->ProcessEvent( { TC_MESSAGE, TA_UNDO_REDO_PRE, AS_GLOBAL } );
1830
1831 // Get the old list
1832 PICKED_ITEMS_LIST* undo_list = m_frame->PopCommandFromUndoList();
1833
1834 wxCHECK( undo_list, 0 );
1835
1836 m_frame->PutDataInPreviousState( undo_list );
1837
1838 // Now push the old command to the RedoList
1839 undo_list->ReversePickersListOrder();
1840 m_frame->PushCommandToRedoList( undo_list );
1841
1842 m_toolMgr->GetTool<SCH_SELECTION_TOOL>()->RebuildSelection();
1843
1844 m_frame->GetCanvas()->Refresh();
1845 m_frame->OnModify();
1846
1847 return 0;
1848}
1849
1850
1852{
1853 wxCHECK( m_frame, 0 );
1854
1855 if( m_frame->GetRedoCommandCount() == 0 )
1856 return 0;
1857
1858 // Inform tools that undo command was issued
1859 m_toolMgr->ProcessEvent( { TC_MESSAGE, TA_UNDO_REDO_PRE, AS_GLOBAL } );
1860
1861 /* Get the old list */
1862 PICKED_ITEMS_LIST* list = m_frame->PopCommandFromRedoList();
1863
1864 wxCHECK( list, 0 );
1865
1866 /* Redo the command: */
1867 m_frame->PutDataInPreviousState( list );
1868
1869 /* Put the old list in UndoList */
1870 list->ReversePickersListOrder();
1871 m_frame->PushCommandToUndoList( list );
1872
1873 m_toolMgr->GetTool<SCH_SELECTION_TOOL>()->RebuildSelection();
1874
1875 m_frame->GetCanvas()->Refresh();
1876 m_frame->OnModify();
1877
1878 return 0;
1879}
1880
1881
1882bool SCH_EDITOR_CONTROL::doCopy( bool aUseDuplicateClipboard )
1883{
1884 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
1885 SCH_SELECTION& selection = selTool->RequestSelection();
1886 SCHEMATIC& schematic = m_frame->Schematic();
1887
1888 if( selection.Empty() )
1889 return false;
1890
1891 if( aUseDuplicateClipboard )
1892 m_duplicateIsHoverSelection = selection.IsHover();
1893
1894 selection.SetScreen( m_frame->GetScreen() );
1896
1897 for( EDA_ITEM* item : selection.GetItems() )
1898 {
1899 if( item->Type() == SCH_SHEET_T )
1900 {
1901 SCH_SHEET* sheet = (SCH_SHEET*) item;
1902 m_supplementaryClipboard[sheet->GetFileName()] = sheet->GetScreen();
1903 }
1904 else if( item->Type() == SCH_FIELD_T && selection.IsHover() )
1905 {
1906 // Most of the time the user is trying to duplicate the parent symbol
1907 // and the field text is in it
1908 selection.Add( item->GetParent() );
1909 }
1910 else if( item->Type() == SCH_MARKER_T )
1911 {
1912 // Don't let the markers be copied
1913 selection.Remove( item );
1914 }
1915 else if( item->Type() == SCH_GROUP_T )
1916 {
1917 // Groups need to have all their items selected
1918 static_cast<SCH_ITEM*>( item )->RunOnChildren(
1919 [&]( EDA_ITEM* aChild )
1920 {
1921 selection.Add( aChild );
1922 },
1924 }
1925 }
1926
1927 bool result = true;
1928 STRING_FORMATTER formatter;
1929 SCH_IO_KICAD_SEXPR plugin;
1930 SCH_SHEET_PATH selPath = m_frame->GetCurrentSheet();
1931
1932 plugin.Format( &selection, &selPath, schematic, &formatter, true );
1933
1934 std::string prettyData = formatter.GetString();
1935 KICAD_FORMAT::Prettify( prettyData, KICAD_FORMAT::FORMAT_MODE::COMPACT_TEXT_PROPERTIES );
1936
1937 if( !aUseDuplicateClipboard )
1938 {
1939 wxLogNull doNotLog; // disable logging of failed clipboard actions
1940
1941 result &= wxTheClipboard->Open();
1942
1943 if( result )
1944 {
1945 wxDataObjectComposite* data = new wxDataObjectComposite();
1946
1947 // Add KiCad data
1948 wxCustomDataObject* kicadObj = new wxCustomDataObject( wxDataFormat( "application/kicad" ) );
1949 kicadObj->SetData( prettyData.size(), prettyData.data() );
1950 data->Add( kicadObj );
1951
1952 BOX2I selectionBox = expandedSelectionBox( selection );
1953
1954 if( selectionBox.GetWidth() > 0 && selectionBox.GetHeight() > 0 )
1955 {
1956 // Add bitmap data (encoded once, used for both PNG clipboard and HTML)
1957 wxImage image = renderSelectionToImageForClipboard( m_frame, selection, selectionBox, true, false );
1958 wxMemoryBuffer pngBuffer;
1959
1960 if( image.IsOk() && EncodeImageToPng( image, pngBuffer ) )
1961 {
1962 AddPngToClipboardData( data, pngBuffer, &image );
1963
1964 // Add HTML with embedded base64 PNG for pasting into documents
1965 wxMemoryBuffer htmlBuffer;
1966
1967 if( generateHtmlFromPngData( pngBuffer, htmlBuffer ) )
1968 {
1969 wxCustomDataObject* htmlObj = new wxCustomDataObject( wxDF_HTML );
1970 htmlObj->SetData( htmlBuffer.GetDataLen(), htmlBuffer.GetData() );
1971 data->Add( htmlObj );
1972 }
1973 }
1974 else
1975 {
1976 wxLogDebug( wxS( "Failed to generate bitmap for clipboard" ) );
1977 }
1978
1979 // Add SVG data
1980 wxMemoryBuffer svgBuffer;
1981
1982 if( plotSelectionToSvg( m_frame, selection, selectionBox, svgBuffer ) )
1983 {
1984 wxCustomDataObject* svgObj = new wxCustomDataObject( wxDataFormat( "image/svg+xml" ) );
1985 svgObj->SetData( svgBuffer.GetDataLen(), svgBuffer.GetData() );
1986 data->Add( svgObj );
1987 }
1988 else
1989 {
1990 wxLogDebug( wxS( "Failed to generate SVG for clipboard" ) );
1991 }
1992 }
1993
1994 // Finally add text data
1995 data->Add( new wxTextDataObject( wxString::FromUTF8( prettyData ) ) );
1996
1997 result &= wxTheClipboard->SetData( data );
1998 result &= wxTheClipboard->Flush(); // Allow data to be available after closing KiCad
1999 wxTheClipboard->Close();
2000 }
2001 }
2002
2003 if( selection.IsHover() )
2004 m_toolMgr->RunAction( ACTIONS::selectionClear );
2005
2006 if( aUseDuplicateClipboard )
2007 {
2008 m_duplicateClipboard = prettyData;
2009 return true;
2010 }
2011
2012 return result;
2013}
2014
2015
2016bool SCH_EDITOR_CONTROL::searchSupplementaryClipboard( const wxString& aSheetFilename, SCH_SCREEN** aScreen )
2017{
2018 if( m_supplementaryClipboard.count( aSheetFilename ) > 0 )
2019 {
2020 *aScreen = m_supplementaryClipboard[aSheetFilename];
2021 return true;
2022 }
2023
2024 return false;
2025}
2026
2027
2029{
2030 doCopy( true ); // Use the local clipboard
2031 Paste( aEvent );
2032
2033 return 0;
2034}
2035
2036
2038{
2039 wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( wxWindow::FindFocus() );
2040
2041 if( textEntry )
2042 {
2043 textEntry->Cut();
2044 return 0;
2045 }
2046
2047 if( doCopy() )
2048 m_toolMgr->RunAction( ACTIONS::doDelete );
2049
2050 return 0;
2051}
2052
2053
2055{
2056 wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( wxWindow::FindFocus() );
2057
2058 if( textEntry )
2059 {
2060 textEntry->Copy();
2061 return 0;
2062 }
2063
2064 doCopy();
2065
2066 return 0;
2067}
2068
2069
2071{
2072 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
2073 SCH_SELECTION& selection = selTool->RequestSelection();
2074
2075 if( selection.Empty() )
2076 return false;
2077
2078 wxString itemsAsText = GetSelectedItemsAsText( selection );
2079
2080 if( selection.IsHover() )
2081 m_toolMgr->RunAction( ACTIONS::selectionClear );
2082
2083 return SaveClipboard( itemsAsText.ToStdString() );
2084}
2085
2086
2088 const KIID_PATH& aClipPath, bool aForceKeepAnnotations )
2089{
2090 wxCHECK( m_frame && aSymbol, /* void */ );
2091
2092 SCH_SYMBOL_INSTANCE newInstance;
2093 bool instanceFound = false;
2094 KIID_PATH pasteLookupPath = aClipPath;
2095
2096 m_pastedSymbols.insert( aSymbol );
2097
2098 for( const SCH_SYMBOL_INSTANCE& tmp : aSymbol->GetInstances() )
2099 {
2100 if( ( tmp.m_Path.empty() && aClipPath.empty() ) || ( !aClipPath.empty() && tmp.m_Path.EndsWith( aClipPath ) ) )
2101 {
2102 newInstance = tmp;
2103 instanceFound = true;
2104
2105 wxLogTrace( traceSchPaste, wxS( "Pasting found symbol instance with reference %s, unit %d:\n"
2106 "\tClipboard path: %s\n"
2107 "\tSymbol UUID: %s." ),
2108 tmp.m_Reference,
2109 tmp.m_Unit,
2110 aClipPath.AsString(),
2111 aSymbol->m_Uuid.AsString() );
2112
2113 break;
2114 }
2115 }
2116
2117 // The pasted symbol look up paths include the symbol UUID.
2118 pasteLookupPath.push_back( aSymbol->m_Uuid );
2119
2120 if( !instanceFound )
2121 {
2122 wxLogTrace( traceSchPaste, wxS( "Clipboard symbol instance **not** found:\n\tClipboard path: %s\n"
2123 "\tSymbol UUID: %s." ),
2124 aClipPath.AsString(),
2125 aSymbol->m_Uuid.AsString() );
2126
2127 // Some legacy versions saved value fields escaped. While we still do in the symbol
2128 // editor, we don't anymore in the schematic, so be sure to unescape them.
2129 SCH_FIELD* valueField = aSymbol->GetField( FIELD_T::VALUE );
2130 valueField->SetText( UnescapeString( valueField->GetText() ) );
2131
2132 // Pasted from notepad or an older instance of eeschema. Use the values in the fields
2133 // instead.
2134 newInstance.m_Reference = aSymbol->GetField( FIELD_T::REFERENCE )->GetText();
2135 newInstance.m_Unit = aSymbol->GetUnit();
2136 }
2137
2138 newInstance.m_Path = aPastePath.Path();
2139 newInstance.m_ProjectName = m_frame->Prj().GetProjectName();
2140
2141 aSymbol->AddHierarchicalReference( newInstance );
2142
2143 if( !aForceKeepAnnotations )
2144 aSymbol->ClearAnnotation( &aPastePath, false );
2145
2146 // We might clear annotations but always leave the original unit number from the paste.
2147 aSymbol->SetUnit( newInstance.m_Unit );
2148}
2149
2150
2152 const KIID_PATH& aClipPath, bool aForceKeepAnnotations,
2153 SCH_SHEET_LIST* aPastedSheets, std::map<SCH_SHEET_PATH,
2154 SCH_REFERENCE_LIST>& aPastedSymbols )
2155{
2156 wxCHECK( aSheet && aPastedSheets, aPastePath );
2157
2158 SCH_SHEET_PATH sheetPath = aPastePath;
2159 sheetPath.push_back( aSheet );
2160
2161 aPastedSheets->push_back( sheetPath );
2162
2163 if( aSheet->GetScreen() == nullptr )
2164 return sheetPath; // We can only really set the page number but not load any items
2165
2166 bool isSharedPath = sheetPath.IsSharedPath();
2167
2168 for( SCH_ITEM* item : aSheet->GetScreen()->Items() )
2169 {
2170 if( item->IsConnectable() )
2171 item->SetConnectivityDirty();
2172
2173 if( item->Type() == SCH_SYMBOL_T )
2174 {
2175 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
2176
2177 wxCHECK2( symbol, continue );
2178
2179 // Only do this once if the symbol is shared across multiple sheets.
2180 if( !m_pastedSymbols.count( symbol ) )
2181 {
2182 if( !isSharedPath )
2183 const_cast<KIID&>( symbol->m_Uuid ) = KIID();
2184
2186 {
2187 // Only update the UUID if the symbol is not in a shared sheet.
2188 if( !isSharedPath )
2189 const_cast<KIID&>( pin->m_Uuid ) = KIID();
2190
2191 pin->SetConnectivityDirty();
2192 }
2193 }
2194
2195 updatePastedSymbol( symbol, sheetPath, aClipPath, aForceKeepAnnotations );
2196 }
2197 else if( item->Type() == SCH_SHEET_T )
2198 {
2199 SCH_SHEET* subsheet = static_cast<SCH_SHEET*>( item );
2200
2201 wxCHECK2( subsheet, continue );
2202
2203 // Make sure pins get a new UUID and set the dirty connectivity flag.
2204 if( !aPastedSheets->ContainsSheet( subsheet ) )
2205 {
2206 if( !isSharedPath )
2207 const_cast<KIID&>( subsheet->m_Uuid ) = KIID();
2208
2209 for( SCH_SHEET_PIN* pin : subsheet->GetPins() )
2210 {
2211 if( !isSharedPath )
2212 const_cast<KIID&>( pin->m_Uuid ) = KIID();
2213
2214 pin->SetConnectivityDirty();
2215 }
2216 }
2217
2218 KIID_PATH newClipPath = aClipPath;
2219 newClipPath.push_back( subsheet->m_Uuid );
2220
2221 updatePastedSheet( subsheet, sheetPath, newClipPath, aForceKeepAnnotations, aPastedSheets, aPastedSymbols );
2222 }
2223 }
2224
2225 sheetPath.GetSymbols( aPastedSymbols[aPastePath], SYMBOL_FILTER_ALL );
2226
2227 return sheetPath;
2228}
2229
2230
2232{
2233 wxCHECK( aScreen, /* void */ );
2234
2235 for( const SCH_ITEM* item : aScreen->Items() )
2236 {
2237 if( item->Type() == SCH_SYMBOL_T )
2238 {
2239 const SCH_SYMBOL* symbol = static_cast<const SCH_SYMBOL*>( item );
2240
2241 wxCHECK2( symbol, continue );
2242
2243 for( const SCH_SYMBOL_INSTANCE& symbolInstance : symbol->GetInstances() )
2244 {
2245 KIID_PATH pathWithSymbol = symbolInstance.m_Path;
2246
2247 pathWithSymbol.push_back( symbol->m_Uuid );
2248
2249 m_clipboardSymbolInstances[pathWithSymbol] = symbolInstance;
2250 }
2251 }
2252 }
2253}
2254
2255
2257{
2258 wxCHECK( m_frame, /* void */ );
2259
2260 for( SCH_SYMBOL* symbol : m_pastedSymbols )
2261 {
2262 wxCHECK2( symbol, continue );
2263
2264 PrunePastedSymbolInstances( symbol, m_frame->Schematic() );
2265 }
2266}
2267
2268
2270 const SCH_SCREEN* aDestScreen,
2271 const wxString& aLibSymbolName )
2272{
2273 // The clipboard's cached library symbol is a matched pair with the pasted instance, so it
2274 // must win over the destination's same-named cache. Pasting from the destination cache would
2275 // silently remap the instance to a different definition and drop in-place edits such as
2276 // renumbered pins (issue 21401) or a changed power type (issue 22162). Fall back to the
2277 // destination cache only when the clipboard carries no copy.
2278 if( aClipboardScreen )
2279 {
2280 auto clipIt = aClipboardScreen->GetLibSymbols().find( aLibSymbolName );
2281
2282 if( clipIt != aClipboardScreen->GetLibSymbols().end() )
2283 return clipIt->second;
2284 }
2285
2286 if( aDestScreen )
2287 {
2288 auto destIt = aDestScreen->GetLibSymbols().find( aLibSymbolName );
2289
2290 if( destIt != aDestScreen->GetLibSymbols().end() )
2291 return destIt->second;
2292 }
2293
2294 return nullptr;
2295}
2296
2297
2299{
2300 wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( wxWindow::FindFocus() );
2301
2302 if( textEntry )
2303 {
2304 textEntry->Paste();
2305 return 0;
2306 }
2307
2308 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
2309 std::string content;
2310 VECTOR2I eventPos;
2311
2312 SCH_SHEET tempSheet;
2313
2314 // Priority for paste:
2315 // 1. application/kicad format (handled by GetClipboardUTF8 which checks this first)
2316 // 2. Text data that can be parsed as KiCad S-expressions
2317 // 3. Bitmap/image data (fallback only if no valid text content)
2318 if( aEvent.IsAction( &ACTIONS::duplicate ) )
2319 content = m_duplicateClipboard;
2320 else
2321 content = GetClipboardUTF8();
2322
2323 // Only fall back to image data if there's no text content
2324 if( content.empty() )
2325 {
2326 std::unique_ptr<wxBitmap> clipImg = GetImageFromClipboard();
2327
2328 if( clipImg )
2329 {
2330 auto bitmap = std::make_unique<SCH_BITMAP>();
2331
2332 if( bitmap->GetReferenceImage().SetImage( clipImg->ConvertToImage() ) )
2333 return m_toolMgr->RunAction( SCH_ACTIONS::placeImage, bitmap.release() );
2334 }
2335
2336 return 0;
2337 }
2338
2339 if( aEvent.IsAction( &ACTIONS::duplicate ) )
2340 eventPos = getViewControls()->GetCursorPosition( false );
2341
2342 STRING_LINE_READER reader( content, "Clipboard" );
2343 SCH_IO_KICAD_SEXPR plugin;
2344
2345 // Screen object on heap is owned by the sheet.
2346 SCH_SCREEN* tempScreen = new SCH_SCREEN( &m_frame->Schematic() );
2347 tempSheet.SetScreen( tempScreen );
2348
2349 try
2350 {
2351 plugin.LoadContent( reader, &tempSheet );
2352 }
2353 catch( IO_ERROR& )
2354 {
2355 // If it wasn't schematic content, paste as a text object
2356 {
2357 if( content.size() > static_cast<size_t>( ADVANCED_CFG::GetCfg().m_MaxPastedTextLength ) )
2358 {
2359 int result = IsOK( m_frame, _( "Pasting a long text text string may be very slow. "
2360 "Do you want to continue?" ) );
2361 if( !result )
2362 return 0;
2363 }
2364
2365 SCH_TEXT* text_item = new SCH_TEXT( VECTOR2I( 0, 0 ), content );
2366 tempScreen->Append( text_item );
2367 }
2368 }
2369
2370 SELECTION& currentSelection = selTool->GetSelection();
2371
2372 bool hasTableCells = false;
2373
2374 for( EDA_ITEM* item : currentSelection )
2375 {
2376 if( item->Type() == SCH_TABLECELL_T )
2377 {
2378 hasTableCells = true;
2379 break;
2380 }
2381 }
2382
2383 if( hasTableCells )
2384 {
2385 SCH_TABLE* clipboardTable = nullptr;
2386
2387 for( SCH_ITEM* item : tempScreen->Items() )
2388 {
2389 if( item->Type() == SCH_TABLE_T )
2390 {
2391 clipboardTable = static_cast<SCH_TABLE*>( item );
2392 break;
2393 }
2394 }
2395
2396 if( clipboardTable )
2397 {
2398 SCH_EDIT_TABLE_TOOL* tableEditTool = m_toolMgr->GetTool<SCH_EDIT_TABLE_TOOL>();
2399
2400 if( tableEditTool )
2401 {
2402 wxString errorMsg;
2403
2404 if( !tableEditTool->validatePasteIntoSelection( currentSelection, errorMsg ) )
2405 {
2406 DisplayError( m_frame, errorMsg );
2407 return 0;
2408 }
2409
2410 SCH_COMMIT commit( m_toolMgr );
2411
2412 if( tableEditTool->pasteCellsIntoSelection( currentSelection, clipboardTable, commit ) )
2413 {
2414 commit.Push( _( "Paste Cells" ) );
2415 return 0;
2416 }
2417 else
2418 {
2419 DisplayError( m_frame, _( "Failed to paste cells" ) );
2420 return 0;
2421 }
2422 }
2423 }
2424 }
2425
2426 m_pastedSymbols.clear();
2428
2429 // Save pasted symbol instances in case the user chooses to keep existing symbol annotation.
2430 setPastedSymbolInstances( tempScreen );
2431
2432 tempScreen->MigrateSimModels();
2433
2434 bool annotateAutomatic = m_frame->eeconfig()->m_AnnotatePanel.automatic;
2435 SCHEMATIC_SETTINGS& schematicSettings = m_frame->Schematic().Settings();
2436 int annotateStartNum = schematicSettings.m_AnnotateStartNum;
2437
2439 bool forceRemoveAnnotations = false;
2440
2441 if( aEvent.IsAction( &ACTIONS::pasteSpecial ) )
2442 {
2443 PASTE_MODE defaultPasteMode = pasteMode;
2444 DIALOG_PASTE_SPECIAL dlg( m_frame, &pasteMode );
2445
2446 if( dlg.ShowModal() == wxID_CANCEL )
2447 return 0;
2448
2449 // We have to distinguish if removing was explicit
2450 forceRemoveAnnotations = pasteMode == PASTE_MODE::REMOVE_ANNOTATIONS && pasteMode != defaultPasteMode;
2451 }
2452
2453 bool forceKeepAnnotations = pasteMode != PASTE_MODE::REMOVE_ANNOTATIONS;
2454
2455 // SCH_SEXP_PLUGIN added the items to the paste screen, but not to the view or anything
2456 // else. Pull them back out to start with.
2457 SCH_COMMIT commit( m_toolMgr );
2458 EDA_ITEMS loadedItems;
2459 std::vector<SCH_ITEM*> sortedLoadedItems;
2460 bool sheetsPasted = false;
2461 SCH_SHEET_LIST hierarchy = m_frame->Schematic().Hierarchy();
2462 SCH_SHEET_PATH& pasteRoot = m_frame->GetCurrentSheet();
2463 wxFileName destFn = pasteRoot.Last()->GetFileName();
2464
2465 if( destFn.IsRelative() )
2466 destFn.MakeAbsolute( m_frame->Prj().GetProjectPath() );
2467
2468 // List of paths in the hierarchy that refer to the destination sheet of the paste
2469 SCH_SHEET_LIST sheetPathsForScreen = hierarchy.FindAllSheetsForScreen( pasteRoot.LastScreen() );
2470 sheetPathsForScreen.SortByPageNumbers();
2471
2472 // Build a list of screens from the current design (to avoid loading sheets that already exist)
2473 std::map<wxString, SCH_SCREEN*> loadedScreens;
2474
2475 for( const SCH_SHEET_PATH& item : hierarchy )
2476 {
2477 if( item.LastScreen() )
2478 loadedScreens[item.Last()->GetFileName()] = item.LastScreen();
2479 }
2480
2481 // Get set of sheet names in the current schematic to prevent duplicate sheet names on paste.
2482 std::set<wxString> existingSheetNames = pasteRoot.LastScreen()->GetSheetNames();
2483
2484 // Build symbol list for reannotation of duplicates
2485 SCH_REFERENCE_LIST existingRefs;
2486 hierarchy.GetSymbols( existingRefs, SYMBOL_FILTER_ALL );
2487 existingRefs.SortByReferenceOnly();
2488
2489 std::set<wxString> existingRefsSet;
2490
2491 for( const SCH_REFERENCE& ref : existingRefs )
2492 existingRefsSet.insert( ref.GetRef() );
2493
2494 // Build UUID map for fetching last-resolved-properties
2495 std::map<KIID, EDA_ITEM*> itemMap;
2496 hierarchy.FillItemMap( itemMap );
2497
2498 // Keep track of pasted sheets and symbols for the different paths to the hierarchy.
2499 std::map<SCH_SHEET_PATH, SCH_REFERENCE_LIST> pastedSymbols;
2500 std::map<SCH_SHEET_PATH, SCH_SHEET_LIST> pastedSheets;
2501
2502 for( SCH_ITEM* item : tempScreen->Items() )
2503 {
2504 if( item->Type() == SCH_SHEET_T )
2505 sortedLoadedItems.push_back( item );
2506 else
2507 loadedItems.push_back( item );
2508 }
2509
2510 sort( sortedLoadedItems.begin(), sortedLoadedItems.end(),
2511 []( SCH_ITEM* firstItem, SCH_ITEM* secondItem )
2512 {
2513 SCH_SHEET* firstSheet = static_cast<SCH_SHEET*>( firstItem );
2514 SCH_SHEET* secondSheet = static_cast<SCH_SHEET*>( secondItem );
2515 return StrNumCmp( firstSheet->GetName(), secondSheet->GetName(), false ) < 0;
2516 } );
2517
2518
2519 for( SCH_ITEM* item : sortedLoadedItems )
2520 {
2521 loadedItems.push_back( item );
2522
2523 if( item->Type() == SCH_SHEET_T )
2524 {
2525 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
2526 wxFileName srcFn = sheet->GetFileName();
2527
2528 if( srcFn.IsRelative() )
2529 srcFn.MakeAbsolute( m_frame->Prj().GetProjectPath() );
2530
2531 SCH_SHEET_LIST sheetHierarchy( sheet );
2532
2533 if( hierarchy.TestForRecursion( sheetHierarchy, destFn.GetFullPath( wxPATH_UNIX ) ) )
2534 {
2535 auto msg = wxString::Format( _( "The pasted sheet '%s'\n"
2536 "was dropped because the destination already has "
2537 "the sheet or one of its subsheets as a parent." ),
2538 sheet->GetFileName() );
2539 DisplayError( m_frame, msg );
2540 loadedItems.pop_back();
2541 }
2542 }
2543 }
2544
2545 // Remove the references from our temporary screen to prevent freeing on the DTOR
2546 tempScreen->Clear( false );
2547
2548 for( EDA_ITEM* item : loadedItems )
2549 {
2550 KIID_PATH clipPath( wxT( "/" ) ); // clipboard is at root
2551
2552 SCH_ITEM* schItem = static_cast<SCH_ITEM*>( item );
2553
2554 wxCHECK2( schItem, continue );
2555
2556 if( schItem->IsConnectable() )
2557 schItem->SetConnectivityDirty();
2558
2559 // Clear lock state on paste to match PCB editor behavior
2560 schItem->SetLocked( false );
2561
2562 if( item->Type() == SCH_SYMBOL_T )
2563 {
2564 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
2565
2566 SCH_SCREEN* currentScreen = m_frame->GetScreen();
2567
2568 wxCHECK2( currentScreen, continue );
2569
2570 const LIB_SYMBOL* source = ChoosePasteLibSymbol( tempScreen, currentScreen,
2571 symbol->GetSchSymbolLibraryName() );
2572
2573 if( source )
2574 symbol->SetLibSymbol( new LIB_SYMBOL( *source ) );
2575
2576 // If the symbol is already in the schematic we have to always keep the annotations. The exception
2577 // is if the user has chosen to remove them.
2578 for( const SCH_SYMBOL_INSTANCE& instance : symbol->GetInstances() )
2579 {
2580 if( !existingRefsSet.contains( instance.m_Reference ) )
2581 {
2582 forceKeepAnnotations = !forceRemoveAnnotations;
2583 break;
2584 }
2585 }
2586
2587 for( SCH_SHEET_PATH& sheetPath : sheetPathsForScreen )
2588 updatePastedSymbol( symbol, sheetPath, clipPath, forceKeepAnnotations );
2589
2590 // Most modes will need new KIIDs for the symbol and its pins. However, if we are pasting
2591 // unique annotations, we need to check if the symbol is not already in the hierarchy. If we
2592 // don't already have a copy of the symbol, we just keep the existing KIID data as it is likely
2593 // the same symbol being moved around the schematic.
2594 bool needsNewKiid = ( pasteMode == PASTE_MODE::UNIQUE_ANNOTATIONS );
2595
2596 for( const SCH_SYMBOL_INSTANCE& instance : symbol->GetInstances() )
2597 {
2598 if( existingRefsSet.contains( instance.m_Reference ) )
2599 {
2600 needsNewKiid = true;
2601 break;
2602 }
2603 }
2604
2605 if( needsNewKiid )
2606 {
2607 // Assign a new KIID
2608 const_cast<KIID&>( item->m_Uuid ) = KIID();
2609
2610 // Make sure pins get a new UUID
2612 {
2613 const_cast<KIID&>( pin->m_Uuid ) = KIID();
2614 pin->SetConnectivityDirty();
2615 }
2616
2617 for( SCH_SHEET_PATH& sheetPath : sheetPathsForScreen )
2618 {
2619 // Ignore symbols from a non-existant library.
2620 if( source )
2621 {
2622 SCH_REFERENCE schReference( symbol, sheetPath );
2623 schReference.SetSheetNumber( sheetPath.GetPageNumberAsInt() );
2624 pastedSymbols[sheetPath].AddItem( schReference );
2625 }
2626 }
2627 }
2628 }
2629 else if( item->Type() == SCH_SHEET_T )
2630 {
2631 SCH_SHEET* sheet = (SCH_SHEET*) item;
2632 SCH_FIELD* nameField = sheet->GetField( FIELD_T::SHEET_NAME );
2633 wxString baseName = nameField->GetText();
2634 wxString candidateName = baseName;
2635 wxString number;
2636
2637 while( !baseName.IsEmpty() && wxIsdigit( baseName.Last() ) )
2638 {
2639 number = baseName.Last() + number;
2640 baseName.RemoveLast();
2641 }
2642
2643 // Update hierarchy to include any other sheets we already added, avoiding
2644 // duplicate sheet names
2645 hierarchy = m_frame->Schematic().Hierarchy();
2646
2647 int uniquifier = std::max( 0, wxAtoi( number ) ) + 1;
2648
2649 while( existingSheetNames.count( candidateName ) )
2650 candidateName = wxString::Format( wxT( "%s%d" ), baseName, uniquifier++ );
2651
2652 nameField->SetText( candidateName );
2653 existingSheetNames.emplace( candidateName );
2654
2655 wxFileName fn = sheet->GetFileName();
2656 SCH_SCREEN* existingScreen = nullptr;
2657
2658 sheet->SetParent( pasteRoot.Last() );
2659 sheet->SetScreen( nullptr );
2660
2661 if( !fn.IsAbsolute() )
2662 {
2663 wxFileName currentSheetFileName = pasteRoot.LastScreen()->GetFileName();
2664 fn.Normalize( FN_NORMALIZE_FLAGS | wxPATH_NORM_ENV_VARS, currentSheetFileName.GetPath() );
2665 }
2666
2667 // Try to find the screen for the pasted sheet by several means
2668 if( !m_frame->Schematic().Root().SearchHierarchy( fn.GetFullPath( wxPATH_UNIX ), &existingScreen ) )
2669 {
2670 if( loadedScreens.count( sheet->GetFileName() ) > 0 )
2671 existingScreen = loadedScreens.at( sheet->GetFileName() );
2672 else
2673 searchSupplementaryClipboard( sheet->GetFileName(), &existingScreen );
2674 }
2675
2676 if( existingScreen )
2677 {
2678 sheet->SetScreen( existingScreen );
2679 }
2680 else
2681 {
2682 if( !m_frame->LoadSheetFromFile( sheet, &pasteRoot, fn.GetFullPath() ) )
2683 m_frame->InitSheet( sheet, sheet->GetFileName() );
2684 }
2685
2686 // Save the symbol instances in case the user chooses to keep the existing
2687 // symbol annotation.
2689 sheetsPasted = true;
2690
2691 // Push it to the clipboard path while it still has its old KIID
2692 clipPath.push_back( sheet->m_Uuid );
2693
2694 // Assign a new KIID to the pasted sheet
2695 const_cast<KIID&>( sheet->m_Uuid ) = KIID();
2696
2697 // Make sure pins get a new UUID
2698 for( SCH_SHEET_PIN* pin : sheet->GetPins() )
2699 {
2700 const_cast<KIID&>( pin->m_Uuid ) = KIID();
2701 pin->SetConnectivityDirty();
2702 }
2703
2704 // Once we have our new KIID we can update all pasted instances. This will either
2705 // reset the annotations or copy "kept" annotations from the supplementary clipboard.
2706 for( SCH_SHEET_PATH& sheetPath : sheetPathsForScreen )
2707 {
2708 SCH_SHEET_PATH subPath = updatePastedSheet( sheet, sheetPath, clipPath,
2709 ( forceKeepAnnotations && annotateAutomatic ),
2710 &pastedSheets[sheetPath], pastedSymbols );
2711 }
2712 }
2713 else
2714 {
2715 SCH_ITEM* srcItem = dynamic_cast<SCH_ITEM*>( itemMap[item->m_Uuid] );
2716 SCH_ITEM* destItem = dynamic_cast<SCH_ITEM*>( item );
2717
2718 // Everything gets a new KIID
2719 const_cast<KIID&>( item->m_Uuid ) = KIID();
2720
2721 if( srcItem && destItem )
2722 {
2723 destItem->SetConnectivityDirty( true );
2724 destItem->SetLastResolvedState( srcItem );
2725 }
2726
2727 // Pasted named groups need a unique name, the multichannel tool matches groups by name.
2728 if( item->Type() == SCH_GROUP_T )
2729 {
2730 SCH_GROUP* group = static_cast<SCH_GROUP*>( item );
2731
2732 if( !group->GetName().IsEmpty() )
2733 group->SetName( UniqueGroupName( m_frame->GetScreen(), group->GetName() ) );
2734 }
2735 }
2736
2737 // Lines need both ends selected for a move after paste so the whole line moves.
2738 if( item->Type() == SCH_LINE_T )
2739 item->SetFlags( STARTPOINT | ENDPOINT );
2740
2741 item->SetFlags( IS_NEW | IS_PASTED | IS_MOVING );
2742
2743 if( !m_frame->GetScreen()->CheckIfOnDrawList( (SCH_ITEM*) item ) ) // don't want a loop!
2744 m_frame->AddToScreen( item, m_frame->GetScreen() );
2745
2746 commit.Added( (SCH_ITEM*) item, m_frame->GetScreen() );
2747
2748 // Start out hidden so the pasted items aren't "ghosted" in their original location
2749 // before being moved to the current location.
2750 getView()->Hide( item, true );
2751 }
2752
2753 if( sheetsPasted )
2754 {
2755 // The full schematic hierarchy need to be update before assigning new annotation and page numbers.
2756 m_frame->Schematic().RefreshHierarchy();
2757
2758 // Update sheet instance page and virtual page numbers to ensure annotation works correctly.
2759 for( SCH_SHEET_PATH& sheetPath : sheetPathsForScreen )
2760 {
2761 for( SCH_SHEET_PATH& pastedSheet : pastedSheets[sheetPath] )
2762 {
2763 // Find next free string page number for the sheet instance.
2764 int page = 1;
2765 wxString pageNum = wxString::Format( "%d", page );
2766
2767 while( hierarchy.PageNumberExists( pageNum ) )
2768 pageNum = wxString::Format( "%d", ++page );
2769
2770 int virtualPageNumber = page;
2771
2772 // The virtual page and sheet instance page numbers do not necessarily track. Increment by one
2773 // to ensure the annotation sheet paths all have unique virtual page numbers.
2774 if( page == hierarchy.GetLastVirtualPageNumber() )
2775 virtualPageNumber = hierarchy.GetLastVirtualPageNumber() + 1;
2776
2777 pastedSheet.SetVirtualPageNumber( virtualPageNumber );
2778
2779 SCH_SHEET_INSTANCE sheetInstance;
2780
2781 sheetInstance.m_Path = pastedSheet.Path();
2782
2783 // Don't include the actual sheet in the instance path.
2784 sheetInstance.m_Path.pop_back();
2785 sheetInstance.m_PageNumber = pageNum;
2786 sheetInstance.m_ProjectName = m_frame->Prj().GetProjectName();
2787
2788 SCH_SHEET* sheet = pastedSheet.Last();
2789
2790 wxCHECK2( sheet, continue );
2791
2792 sheet->AddInstance( sheetInstance );
2793 hierarchy.push_back( pastedSheet );
2794
2795 // Remove all pasted sheet instance data that is not part of the current project.
2796 std::vector<KIID_PATH> instancesToRemove;
2797
2798 for( const SCH_SHEET_INSTANCE& instance : sheet->GetInstances() )
2799 {
2800 if( !hierarchy.HasPath( instance.m_Path ) )
2801 instancesToRemove.push_back( instance.m_Path );
2802 }
2803
2804 for( const KIID_PATH& instancePath : instancesToRemove )
2805 sheet->RemoveInstance( instancePath );
2806
2807 // The sheet paths for the annotation code where copied in updatePastedSheets() when the virtual
2808 // page number was still 1. Set the virtual page number in the copied sheet paths.
2809 for( auto&[path, refs] : pastedSymbols )
2810 {
2811 for( SCH_REFERENCE& ref : refs )
2812 {
2813 if( ref.GetSheetPath() == pastedSheet )
2814 {
2815 ref.GetSheetPath().SetVirtualPageNumber( virtualPageNumber );
2816 ref.SetSheetNumber( virtualPageNumber );
2817 }
2818 }
2819 }
2820 }
2821 }
2822
2823 m_frame->SetSheetNumberAndCount();
2824
2825 // Get a version with correct sheet numbers since we've pasted sheets,
2826 // we'll need this when annotating next
2827 hierarchy = m_frame->Schematic().Hierarchy();
2828 }
2829
2830 std::map<SCH_SHEET_PATH, SCH_REFERENCE_LIST> annotatedSymbols;
2831
2832 // Update the list of symbol instances that satisfy the annotation criteria.
2833 for( const SCH_SHEET_PATH& sheetPath : sheetPathsForScreen )
2834 {
2835 for( size_t i = 0; i < pastedSymbols[sheetPath].GetCount(); i++ )
2836 {
2837 if( pasteMode == PASTE_MODE::UNIQUE_ANNOTATIONS || pastedSymbols[sheetPath][i].AlwaysAnnotate() )
2838 annotatedSymbols[sheetPath].AddItem( pastedSymbols[sheetPath][i] );
2839 }
2840
2841 for( const SCH_SHEET_PATH& pastedSheetPath : pastedSheets[sheetPath] )
2842 {
2843 for( size_t i = 0; i < pastedSymbols[pastedSheetPath].GetCount(); i++ )
2844 {
2845 if( pasteMode == PASTE_MODE::UNIQUE_ANNOTATIONS || pastedSymbols[pastedSheetPath][i].AlwaysAnnotate() )
2846 annotatedSymbols[pastedSheetPath].AddItem( pastedSymbols[pastedSheetPath][i] );
2847 }
2848 }
2849 }
2850
2851 if( !annotatedSymbols.empty() )
2852 {
2853 ANNOTATE_ORDER_T annotateOrder = static_cast<ANNOTATE_ORDER_T>( schematicSettings.m_AnnotateSortOrder );
2854 ANNOTATE_ALGO_T annotateAlgo = static_cast<ANNOTATE_ALGO_T>( schematicSettings.m_AnnotateMethod );
2855
2856 for( SCH_SHEET_PATH& path : sheetPathsForScreen )
2857 {
2858 annotatedSymbols[path].SortByReferenceOnly();
2859 annotatedSymbols[path].SetRefDesTracker( schematicSettings.m_refDesTracker );
2860
2861 if( pasteMode == PASTE_MODE::UNIQUE_ANNOTATIONS )
2862 {
2863 annotatedSymbols[path].ReannotateDuplicates( existingRefs, annotateAlgo );
2864 }
2865 else
2866 {
2867 annotatedSymbols[path].ReannotateByOptions( annotateOrder, annotateAlgo, annotateStartNum,
2868 existingRefs, false, &hierarchy );
2869 }
2870
2871 annotatedSymbols[path].UpdateAnnotation();
2872
2873 // Update existing refs for next iteration
2874 for( size_t i = 0; i < annotatedSymbols[path].GetCount(); i++ )
2875 existingRefs.AddItem( annotatedSymbols[path][i] );
2876
2877 for( const SCH_SHEET_PATH& pastedSheetPath : pastedSheets[path] )
2878 {
2879 annotatedSymbols[pastedSheetPath].SortByReferenceOnly();
2880 annotatedSymbols[pastedSheetPath].SetRefDesTracker( schematicSettings.m_refDesTracker );
2881
2882 if( pasteMode == PASTE_MODE::UNIQUE_ANNOTATIONS )
2883 {
2884 annotatedSymbols[pastedSheetPath].ReannotateDuplicates( existingRefs, annotateAlgo );
2885 }
2886 else
2887 {
2888 annotatedSymbols[pastedSheetPath].ReannotateByOptions( annotateOrder, annotateAlgo,
2889 annotateStartNum, existingRefs,
2890 false, &hierarchy );
2891 }
2892
2893 annotatedSymbols[pastedSheetPath].UpdateAnnotation();
2894
2895 // Update existing refs for next iteration
2896 for( size_t i = 0; i < annotatedSymbols[pastedSheetPath].GetCount(); i++ )
2897 existingRefs.AddItem( annotatedSymbols[pastedSheetPath][i] );
2898 }
2899 }
2900 }
2901
2902 m_frame->GetCurrentSheet().UpdateAllScreenReferences();
2903
2904 // The copy operation creates instance paths that are not valid for the current project or
2905 // saved as part of another project. Prune them now so they do not accumulate in the saved
2906 // schematic file.
2908
2909 SCH_SHEET_LIST sheets = m_frame->Schematic().Hierarchy();
2910 SCH_SCREENS allScreens( m_frame->Schematic().Root() );
2911
2912 allScreens.PruneOrphanedSymbolInstances( m_frame->Prj().GetProjectName(), sheets );
2913 allScreens.PruneOrphanedSheetInstances( m_frame->Prj().GetProjectName(), sheets );
2914
2915 // Now clear the previous selection, select the pasted items, and fire up the "move" tool.
2916 m_toolMgr->RunAction( ACTIONS::selectionClear );
2917
2918 // If the item has a parent group, it will be part of the loadedItems, and will handle
2919 // the move action. Iterate backwards to avoid invalidating the iterator.
2920 for( int i = loadedItems.size() - 1; i >= 0; i-- )
2921 {
2922 EDA_ITEM* item = loadedItems[i];
2923
2924 if( item->GetParentGroup() )
2925 {
2926 loadedItems.erase( loadedItems.begin() + i );
2927 // These were hidden before because they would be added to the move preview,
2928 // but now they need to be shown as a preview so they appear to move when
2929 // the group moves.
2930 getView()->SetVisible( item );
2931 getView()->AddToPreview( item, false );
2932 }
2933 }
2934
2935 m_toolMgr->RunAction<EDA_ITEMS*>( ACTIONS::selectItems, &loadedItems );
2936
2937 SCH_SELECTION& selection = selTool->GetSelection();
2938
2939 if( !selection.Empty() )
2940 {
2941 if( aEvent.IsAction( &ACTIONS::duplicate ) )
2942 {
2943 int closest_dist = INT_MAX;
2944
2945 auto processPt =
2946 [&]( const VECTOR2I& pt )
2947 {
2948 int dist = ( eventPos - pt ).EuclideanNorm();
2949
2950 if( dist < closest_dist )
2951 {
2952 selection.SetReferencePoint( pt );
2953 closest_dist = dist;
2954 }
2955 };
2956
2957 std::vector<SCH_ITEM*> anchorCandidates = FlattenGroups( selection.Items() );
2958
2959 // Prefer connection points (which should remain on grid)
2960 for( EDA_ITEM* item : anchorCandidates )
2961 {
2962 SCH_ITEM* sch_item = dynamic_cast<SCH_ITEM*>( item );
2963 SCH_PIN* pin = dynamic_cast<SCH_PIN*>( item );
2964
2965 if( sch_item && sch_item->IsConnectable() )
2966 {
2967 for( const VECTOR2I& pt : sch_item->GetConnectionPoints() )
2968 processPt( pt );
2969 }
2970 else if( pin )
2971 {
2972 processPt( pin->GetPosition() );
2973 }
2974
2975 // Symbols need to have their center point added since often users are trying to
2976 // move parts from their center.
2977 if( dynamic_cast<SCH_SYMBOL*>( item ) )
2978 processPt( item->GetPosition() );
2979 }
2980
2981 // Only process other points if we didn't find any connection points
2982 if( closest_dist == INT_MAX )
2983 {
2984 for( EDA_ITEM* item : anchorCandidates )
2985 {
2986 switch( item->Type() )
2987 {
2988 // A group's position is its bounding box centre, which is off grid
2989 case SCH_GROUP_T: break;
2990
2991 case SCH_LINE_T:
2992 processPt( static_cast<SCH_LINE*>( item )->GetStartPoint() );
2993 processPt( static_cast<SCH_LINE*>( item )->GetEndPoint() );
2994 break;
2995
2996 case SCH_SHAPE_T:
2997 {
2998 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( item );
2999
3000 switch( shape->GetShape() )
3001 {
3002 case SHAPE_T::RECTANGLE:
3003 for( const VECTOR2I& pt : shape->GetRectCorners() )
3004 processPt( pt );
3005
3006 break;
3007
3008 case SHAPE_T::CIRCLE:
3009 processPt( shape->GetCenter() );
3010 break;
3011
3012 case SHAPE_T::POLY:
3013 for( int ii = 0; ii < shape->GetPolyShape().TotalVertices(); ++ii )
3014 processPt( shape->GetPolyShape().CVertex( ii ) );
3015
3016 break;
3017
3018 default:
3019 processPt( shape->GetStart() );
3020 processPt( shape->GetEnd() );
3021 break;
3022 }
3023
3024 break;
3025 }
3026
3027 default:
3028 processPt( item->GetPosition() );
3029 break;
3030 }
3031 }
3032 }
3033
3034 selection.SetIsHover( m_duplicateIsHoverSelection );
3035 }
3036 // We want to the first non-group item in the selection to be the reference point.
3037 else if( selection.GetTopLeftItem()->Type() == SCH_GROUP_T )
3038 {
3039 SCH_GROUP* group = static_cast<SCH_GROUP*>( selection.GetTopLeftItem() );
3040
3041 bool found = false;
3042 SCH_ITEM* item = nullptr;
3043
3044 group->RunOnChildren(
3045 [&]( SCH_ITEM* schItem )
3046 {
3047 if( !found && schItem->Type() != SCH_GROUP_T )
3048 {
3049 item = schItem;
3050 found = true;
3051 }
3052 },
3054
3055 if( found )
3056 selection.SetReferencePoint( item->GetPosition() );
3057 else
3058 selection.SetReferencePoint( group->GetPosition() );
3059 }
3060 else
3061 {
3062 SCH_ITEM* item = static_cast<SCH_ITEM*>( selection.GetTopLeftItem() );
3063
3064 selection.SetReferencePoint( item->GetPosition() );
3065 }
3066
3067 if( m_toolMgr->RunSynchronousAction( SCH_ACTIONS::move, &commit ) )
3068 {
3069 // Pushing the commit will update the connectivity.
3070 commit.Push( _( "Paste" ) );
3071
3072 if( !sheetsPasted && !ADVANCED_CFG::GetCfg().m_ConnectivityEngine )
3073 m_frame->RefreshNetNavigator();
3074 }
3075 else
3076 {
3077 commit.Revert();
3078 }
3079
3080 getView()->ClearPreview();
3081 }
3082
3083 return 0;
3084}
3085
3086
3088{
3089 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
3090 SCH_SELECTION& selection = selTool->RequestSelection( { SCH_SYMBOL_T } );
3091 SCH_SYMBOL* symbol = nullptr;
3092 SYMBOL_EDIT_FRAME* symbolEditor;
3093
3094 if( selection.GetSize() >= 1 )
3095 symbol = (SCH_SYMBOL*) selection.Front();
3096
3097 if( selection.IsHover() )
3098 m_toolMgr->RunAction( ACTIONS::selectionClear );
3099
3100 if( !symbol )
3101 {
3102 // Giant hack: by default we assign Edit Table to the same hotkey, so give the table
3103 // tool a chance to handle it if we can't.
3104 if( SCH_EDIT_TABLE_TOOL* tableTool = m_toolMgr->GetTool<SCH_EDIT_TABLE_TOOL>() )
3105 tableTool->EditTable( aEvent );
3106
3107 return 0;
3108 }
3109
3110 if( symbol->GetEditFlags() != 0 )
3111 return 0;
3112
3113 if( symbol->IsMissingLibSymbol() )
3114 {
3115 m_frame->ShowInfoBarError( _( "Symbols with broken library symbol links cannot be edited." ) );
3116 return 0;
3117 }
3118
3120 symbolEditor = (SYMBOL_EDIT_FRAME*) m_frame->Kiway().Player( FRAME_SCH_SYMBOL_EDITOR, false );
3121
3122 if( symbolEditor )
3123 {
3124 if( wxWindow* blocking_win = symbolEditor->Kiway().GetBlockingDialog() )
3125 blocking_win->Close( true );
3126
3127 if( aEvent.IsAction( &SCH_ACTIONS::editWithLibEdit ) )
3128 {
3129 symbolEditor->LoadSymbolFromSchematic( symbol );
3130 }
3132 {
3133 symbolEditor->LoadSymbol( symbol->GetLibId(), symbol->GetUnit(), symbol->GetBodyStyle() );
3134
3135 if( !symbolEditor->IsLibraryTreeShown() )
3136 symbolEditor->ToggleLibraryTree();
3137 }
3138 }
3139
3140 return 0;
3141}
3142
3143
3145{
3146 m_frame->OnAnnotate();
3147 return 0;
3148}
3149
3150
3152{
3154 dlg.m_FirstRefDes->SetValidator( wxTextValidator( wxFILTER_EMPTY ) );
3155
3156 dlg.SetInitialFocus( dlg.m_FirstRefDes );
3157
3158 if( dlg.ShowModal() == wxID_OK )
3159 {
3160 SCH_REFERENCE startRef;
3161 startRef.SetRef( dlg.m_FirstRefDes->GetValue() );
3162
3163 if( startRef.IsSplitNeeded() )
3164 startRef.Split();
3165 else
3166 return 0;
3167
3168 int startNum = atoi( startRef.GetRefNumber().utf8_string().c_str() );
3169
3170 SCH_COMMIT commit( m_frame );
3171 SCHEMATIC* schematic = m_frame->m_schematic;
3172 SCH_REFERENCE_LIST references;
3173
3174 if( dlg.m_AllSheets->GetValue() )
3175 schematic->Hierarchy().GetSymbols( references, SYMBOL_FILTER_ALL );
3176 else
3177 schematic->CurrentSheet().GetSymbols( references, SYMBOL_FILTER_ALL );
3178
3179 references.SplitReferences();
3180
3181 for( SCH_REFERENCE& ref : references )
3182 {
3183 if( ref.GetRef() == startRef.GetRef() )
3184 {
3185 int num = atoi( ref.GetRefNumber().utf8_string().c_str() );
3186
3187 if( num >= startNum )
3188 {
3189 const SCH_SHEET_PATH& sheet = ref.GetSheetPath();
3190 wxString fullRef = ref.GetRef();
3191
3192 num += dlg.m_Increment->GetValue();
3193 fullRef << num;
3194
3195 commit.Modify( ref.GetSymbol(), sheet.LastScreen(), RECURSE_MODE::NO_RECURSE );
3196 ref.GetSymbol()->SetRef( &sheet, From_UTF8( fullRef.c_str() ) );
3197 }
3198 }
3199 }
3200
3201 if( !commit.Empty() )
3202 commit.Push( _( "Increment Annotations" ) );
3203 }
3204
3205 return 0;
3206}
3207
3208
3210{
3211 m_frame->OnOpenCvpcb();
3212 return 0;
3213}
3214
3215
3217{
3218 m_frame->OnImportProject();
3219 return 0;
3220}
3221
3222
3224{
3225 DIALOG_SYMBOL_FIELDS_TABLE* dlg = m_frame->GetSymbolFieldsTableDialog();
3226
3227 if( !dlg )
3228 return 0;
3229
3230 // Needed at least on Windows. Raise() is not enough
3231 dlg->Show( true );
3232
3233 // Bring it to the top if already open. Dual monitor users need this.
3234 dlg->Raise();
3235
3236 dlg->ShowEditTab();
3237
3238 return 0;
3239}
3240
3241
3243{
3244 if( !m_frame->Schematic().GetCurrentVariant().IsEmpty() )
3245 {
3247 _( "Bulk Edit Symbol Library Links is not available when a design variant is "
3248 "active. Switch to the default variant first." ) );
3249 return 0;
3250 }
3251
3253 m_frame->HardRedraw();
3254
3255 return 0;
3256}
3257
3258
3260{
3261 m_frame->OnOpenPcbnew();
3262 return 0;
3263}
3264
3265
3267{
3268 m_frame->OnUpdatePCB();
3269 return 0;
3270}
3271
3272
3274{
3276 dlg.ShowModal();
3277 return 0;
3278}
3279
3280
3282{
3284
3285 // If a plugin is removed or added, rebuild and reopen the new dialog
3286 while( result == NET_PLUGIN_CHANGE )
3288
3289 return 0;
3290}
3291
3292
3294{
3295 DIALOG_SYMBOL_FIELDS_TABLE* dlg = m_frame->GetSymbolFieldsTableDialog();
3296
3297 if( !dlg )
3298 return 0;
3299
3300 // Needed at least on Windows. Raise() is not enough
3301 dlg->Show( true );
3302
3303 // Bring it to the top if already open. Dual monitor users need this.
3304 dlg->Raise();
3305
3306 dlg->ShowExportTab();
3307
3308 return 0;
3309}
3310
3311
3313{
3315 return 0;
3316}
3317
3318
3320{
3321 m_frame->RecalculateConnections( nullptr, LOCAL_CLEANUP );
3322
3323 // Create a selection with all items from the current sheet
3324 SCH_SELECTION sheetSelection;
3325 SCH_SCREEN* screen = m_frame->GetScreen();
3326
3327 for( SCH_ITEM* item : screen->Items() )
3328 {
3329 sheetSelection.Add( item );
3330 }
3331
3332 // Get the full page bounding box for rendering the complete sheet
3333 BOX2I pageBBox( VECTOR2I( 0, 0 ), m_frame->GetPageSizeIU() );
3334
3335 // Render the full sheet selection including the worksheet
3336 wxImage image = renderSelectionToImageForClipboard( m_frame, sheetSelection, pageBBox, true, true );
3337
3338 if( image.IsOk() )
3339 {
3340 wxLogNull doNotLog; // disable logging of failed clipboard actions
3341
3342 if( wxTheClipboard->Open() )
3343 {
3344 wxDataObjectComposite* data = new wxDataObjectComposite();
3345
3347
3348 wxTheClipboard->SetData( data );
3349 wxTheClipboard->Flush(); // Allow data to be available after closing KiCad
3350 wxTheClipboard->Close();
3351 }
3352 }
3353 else
3354 {
3355 wxLogMessage( _( "Cannot create the schematic image" ) );
3356 }
3357
3358 return 0;
3359}
3360
3361
3363{
3365 return 0;
3366}
3367
3368
3374
3375
3381
3382
3388
3389
3395
3396
3402
3403
3405{
3406 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3408
3410 m_frame->GetCanvas()->Refresh();
3411
3412 return 0;
3413}
3414
3415
3417{
3418 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3420
3421 m_frame->GetRenderSettings()->m_ShowHiddenFields = cfg->m_Appearance.show_hidden_fields;
3422
3424 m_frame->GetCanvas()->Refresh();
3425
3426 return 0;
3427}
3428
3429
3431{
3432 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3434
3436 m_frame->GetCanvas()->Refresh();
3437
3438 return 0;
3439}
3440
3441
3443{
3444 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3446
3448 m_frame->GetCanvas()->Refresh();
3449
3450 return 0;
3451}
3452
3453
3455{
3456 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3458
3460 m_frame->GetCanvas()->Refresh();
3461
3462 return 0;
3463}
3464
3465
3467{
3468 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3470
3471 m_frame->GetCanvas()->Refresh();
3472
3473 return 0;
3474}
3475
3476
3478{
3479 SCH_SHEET_PATH* sheetPath = &m_frame->GetCurrentSheet();
3480 wxString variant = m_frame->Schematic().GetCurrentVariant();
3481 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3483
3484 m_frame->GetCanvas()->GetView()->UpdateAllItemsConditionally(
3485 [&]( KIGFX::VIEW_ITEM* aItem ) -> int
3486 {
3487 int flags = 0;
3488
3489 auto invalidateTextVars =
3490 [&flags]( EDA_TEXT* text )
3491 {
3492 if( text->HasTextVars() )
3493 {
3494 text->ClearRenderCache();
3495 text->ClearBoundingBoxCache();
3497 }
3498 };
3499
3500 if( SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( aItem ) )
3501 {
3502 item->RunOnChildren(
3503 [&invalidateTextVars]( SCH_ITEM* aChild )
3504 {
3505 if( EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( aChild ) )
3506 invalidateTextVars( text );
3507 },
3509
3510 if( item->GetExcludedFromSim( sheetPath, variant ) )
3512 }
3513
3514 if( EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( aItem ) )
3515 invalidateTextVars( text );
3516
3517 return flags;
3518 } );
3519
3520 m_frame->GetCanvas()->Refresh();
3521
3522 return 0;
3523}
3524
3525
3527{
3528 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3530
3532 m_frame->RefreshOperatingPointDisplay();
3533 m_frame->GetCanvas()->Refresh();
3534
3535 return 0;
3536}
3537
3538
3540{
3541 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3543
3545 m_frame->RefreshOperatingPointDisplay();
3546 m_frame->GetCanvas()->Refresh();
3547
3548 return 0;
3549}
3550
3551
3553{
3554 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3556
3557 m_frame->GetRenderSettings()->m_ShowPinAltIcons = cfg->m_Appearance.show_pin_alt_icons;
3558
3560 m_frame->GetCanvas()->Refresh();
3561
3562 return 0;
3563}
3564
3565
3567{
3568 m_frame->eeconfig()->m_Drawing.line_mode = aEvent.Parameter<LINE_MODE>();
3569 m_toolMgr->PostAction( ACTIONS::refreshPreview );
3570 // Notify toolbar to update selection
3572 return 0;
3573}
3574
3575
3577{
3578 m_frame->eeconfig()->m_Drawing.line_mode++;
3579 m_frame->eeconfig()->m_Drawing.line_mode %= LINE_MODE::LINE_MODE_COUNT;
3580 m_toolMgr->PostAction( ACTIONS::refreshPreview );
3581 // Notify toolbar to update selection
3583 return 0;
3584}
3585
3586
3588{
3589 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3591 return 0;
3592}
3593
3594
3596{
3597 // Update the left toolbar Line modes group icon to match current mode
3598 switch( static_cast<LINE_MODE>( m_frame->eeconfig()->m_Drawing.line_mode ) )
3599 {
3600 case LINE_MODE::LINE_MODE_FREE: m_frame->SelectToolbarAction( SCH_ACTIONS::lineModeFree ); break;
3601 case LINE_MODE::LINE_MODE_90: m_frame->SelectToolbarAction( SCH_ACTIONS::lineMode90 ); break;
3602 default:
3603 case LINE_MODE::LINE_MODE_45: m_frame->SelectToolbarAction( SCH_ACTIONS::lineMode45 ); break;
3604 }
3605
3606 return 0;
3607}
3608
3609
3611{
3612 if( !Pgm().GetCommonSettings()->m_Input.hotkey_feedback )
3613 return 0;
3614
3615 GRID_SETTINGS& gridSettings = m_toolMgr->GetSettings()->m_Window.grid;
3616 int currentIdx = m_toolMgr->GetSettings()->m_Window.grid.last_size_idx;
3617
3618 wxArrayString gridsLabels;
3619
3620 for( const GRID& grid : gridSettings.grids )
3621 gridsLabels.Add( grid.UserUnitsMessageText( m_frame ) );
3622
3623 if( !m_frame->GetHotkeyPopup() )
3624 m_frame->CreateHotkeyPopup();
3625
3626 HOTKEY_CYCLE_POPUP* popup = m_frame->GetHotkeyPopup();
3627
3628 if( popup )
3629 popup->Popup( _( "Grid" ), gridsLabels, currentIdx );
3630
3631 return 0;
3632}
3633
3634
3636{
3637 SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
3638
3639 if( !editFrame )
3640 return 1;
3641
3642 // Need to have a group selected and it needs to have a linked design block
3643 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
3644 SCH_SELECTION selection = selTool->GetSelection();
3645
3646 if( selection.Size() != 1 || selection[0]->Type() != SCH_GROUP_T )
3647 return 1;
3648
3649 SCH_GROUP* group = static_cast<SCH_GROUP*>( selection[0] );
3650
3651 if( !group->HasDesignBlockLink() )
3652 return 1;
3653
3654 // Get the associated design block
3655 DESIGN_BLOCK_PANE* designBlockPane = editFrame->GetDesignBlockPane();
3656 std::unique_ptr<DESIGN_BLOCK> designBlock( designBlockPane->GetDesignBlock( group->GetDesignBlockLibId(),
3657 true, true ) );
3658
3659 if( !designBlock )
3660 return 1;
3661
3662 if( designBlock->GetSchematicFile().IsEmpty() )
3663 {
3664 wxString msg;
3665 msg.Printf( _( "Design block %s does not have a schematic file." ),
3666 group->GetDesignBlockLibId().GetUniStringLibId() );
3667 m_frame->GetInfoBar()->ShowMessageFor( msg, 5000, wxICON_WARNING );
3668 return 1;
3669 }
3670
3671 editFrame->GetDesignBlockPane()->SelectLibId( group->GetDesignBlockLibId() );
3672
3673 return m_toolMgr->RunAction( SCH_ACTIONS::placeDesignBlock, designBlock.release() );
3674}
3675
3676
3678{
3679 SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
3680
3681 if( !editFrame )
3682 return 1;
3683
3684 // Need to have a group selected and it needs to have a linked design block
3685 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
3686 SCH_SELECTION selection = selTool->GetSelection();
3687
3688 if( selection.Size() != 1 || selection[0]->Type() != SCH_GROUP_T )
3689 return 1;
3690
3691 SCH_GROUP* group = static_cast<SCH_GROUP*>( selection[0] );
3692
3693 if( !group->HasDesignBlockLink() )
3694 return 1;
3695
3696 // Get the associated design block
3697 DESIGN_BLOCK_PANE* designBlockPane = editFrame->GetDesignBlockPane();
3698 std::unique_ptr<DESIGN_BLOCK> designBlock( designBlockPane->GetDesignBlock( group->GetDesignBlockLibId(),
3699 true, true ) );
3700
3701 if( !designBlock )
3702 return 1;
3703
3704 editFrame->GetDesignBlockPane()->SelectLibId( group->GetDesignBlockLibId() );
3705
3706 return m_toolMgr->RunAction( SCH_ACTIONS::updateDesignBlockFromSelection ) ? 1 : 0;
3707}
3708
3709
3711{
3712 SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
3713
3714 if( !editFrame )
3715 return 1;
3716
3717 editFrame->AddVariant();
3718
3719 return 0;
3720}
3721
3722
3724{
3725 SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
3726
3727 if( !editFrame )
3728 return 1;
3729
3730 editFrame->RemoveVariant();
3731 return 0;
3732}
3733
3734
3736{
3737 SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
3738
3739 if( !editFrame )
3740 return 1;
3741
3742 editFrame->EditVariantDescription();
3743 return 0;
3744}
3745
3746
3748{
3749 SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
3750
3751 if( !editFrame )
3752 return 1;
3753
3754 editFrame->RenameVariant();
3755 return 0;
3756}
3757
3758
3760{
3761 SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
3762
3763 if( !editFrame )
3764 return 1;
3765
3766 editFrame->CopyVariant();
3767 return 0;
3768}
3769
3770
3772{
3773 Go( &SCH_EDITOR_CONTROL::New, ACTIONS::doNew.MakeEvent() );
3774 Go( &SCH_EDITOR_CONTROL::Open, ACTIONS::open.MakeEvent() );
3775 Go( &SCH_EDITOR_CONTROL::Save, ACTIONS::save.MakeEvent() );
3782 Go( &SCH_EDITOR_CONTROL::Plot, ACTIONS::plot.MakeEvent() );
3783
3786
3792
3795
3807
3810
3811 Go( &SCH_EDITOR_CONTROL::Undo, ACTIONS::undo.MakeEvent() );
3812 Go( &SCH_EDITOR_CONTROL::Redo, ACTIONS::redo.MakeEvent() );
3813 Go( &SCH_EDITOR_CONTROL::Cut, ACTIONS::cut.MakeEvent() );
3814 Go( &SCH_EDITOR_CONTROL::Copy, ACTIONS::copy.MakeEvent() );
3819
3821
3838
3846
3863
3865
3868
3874}
const char * name
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:130
BOX2< VECTOR2I > BOX2I
Definition box2.h:914
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:982
BOX2< VECTOR2D > BOX2D
Definition box2.h:915
static TOOL_ACTION updatePcbFromSchematic
Definition actions.h:260
static TOOL_ACTION paste
Definition actions.h:76
static TOOL_ACTION revert
Definition actions.h:58
static TOOL_ACTION saveAs
Definition actions.h:55
static TOOL_ACTION copy
Definition actions.h:74
static TOOL_ACTION pickerTool
Definition actions.h:249
static TOOL_ACTION showSymbolEditor
Definition actions.h:256
static TOOL_ACTION pasteSpecial
Definition actions.h:77
static TOOL_ACTION plot
Definition actions.h:61
static TOOL_ACTION open
Definition actions.h:53
static TOOL_ACTION pageSettings
Definition actions.h:59
static TOOL_ACTION showSearch
Definition actions.h:112
static TOOL_ACTION undo
Definition actions.h:71
static TOOL_ACTION selectionActivate
Activation of the selection tool.
Definition actions.h:210
static TOOL_ACTION duplicate
Definition actions.h:80
static TOOL_ACTION doDelete
Definition actions.h:81
static TOOL_ACTION save
Definition actions.h:54
static TOOL_ACTION redo
Definition actions.h:72
static TOOL_ACTION updateSchematicFromPcb
Definition actions.h:261
static TOOL_ACTION selectionClear
Clear the current selection.
Definition actions.h:220
static TOOL_ACTION print
Definition actions.h:60
static TOOL_ACTION showProperties
Definition actions.h:262
static TOOL_ACTION doNew
Definition actions.h:50
static TOOL_ACTION cut
Definition actions.h:73
static TOOL_ACTION copyAsText
Definition actions.h:75
static TOOL_ACTION refreshPreview
Definition actions.h:155
static TOOL_ACTION selectItems
Select a list of items (specified as the event parameter)
Definition actions.h:228
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
int GetPageCount() const
Definition base_screen.h:68
int GetVirtualPageNumber() const
Definition base_screen.h:71
static wxString m_DrawingSheetFileName
the name of the drawing sheet file, or empty to use the default drawing sheet
Definition base_screen.h:81
const wxString & GetPageNumber() const
void SetContentModified(bool aModified=true)
Definition base_screen.h:55
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition box2.h:553
constexpr size_type GetWidth() const
Definition box2.h:211
constexpr Vec Centre() const
Definition box2.h:94
constexpr BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition box2.h:594
constexpr const Vec GetCenter() const
Definition box2.h:227
constexpr size_type GetHeight() const
Definition box2.h:212
constexpr const Vec & GetOrigin() const
Definition box2.h:207
constexpr const SizeVec & GetSize() const
Definition box2.h:203
int GetCount() const
Return the number of objects in the list.
Definition collector.h:79
int m_Threshold
Definition collector.h:234
static const COLOR4D CLEAR
Definition color4d.h:405
COMMIT & Added(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Notify observers that aItem has been added.
Definition commit.h:80
bool Empty() const
Definition commit.h:145
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:102
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, wxString *aErrorMsg=nullptr)
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:94
int ShowModal() override
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:98
virtual VECTOR2I GetPosition() const
Definition eda_item.h:348
EDA_ITEM_FLAGS GetEditFlags() const
Definition eda_item.h:170
const KIID m_Uuid
Definition eda_item.h:599
virtual EDA_GROUP * GetParentGroup() const
Definition eda_item.h:116
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
virtual bool IsType(const std::vector< KICAD_T > &aScanTypes) const
Check whether the item is one of the listed types.
Definition eda_item.h:214
void SetNetHighlighted(bool aHighlighted)
Definition eda_item.cpp:131
virtual EDA_ITEM * Clone() const
Create a duplicate of this item with linked list members set to NULL.
Definition eda_item.cpp:278
bool IsNetHighlighted() const
Net highlighting must not clear brightening owned by find or picker tools.
Definition eda_item.cpp:125
virtual void SetParent(EDA_ITEM *aParent)
Definition eda_item.cpp:153
SHAPE_POLY_SET & GetPolyShape()
SHAPE_T GetShape() const
Definition eda_shape.h:175
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition eda_shape.h:325
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Definition eda_shape.h:275
std::vector< VECTOR2I > GetRectCorners() const
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition eda_text.h:94
virtual bool IsVisible() const
Definition eda_text.h:226
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
Runs the electrical rules checks and adds a SCH_MARKER for each violation.
Definition erc.h:60
static const TOOL_EVENT ClearedEvent
Definition actions.h:347
static const TOOL_EVENT GridChangedByKeyEvent
Used for hotkey feedback.
Definition actions.h:365
static const TOOL_EVENT SelectedEvent
Definition actions.h:345
static const TOOL_EVENT SelectedItemsModified
Selected item had a property changed (except movement)
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
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:82
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:1892
void SetLayerVisible(int aLayer, bool aVisible=true)
Control the visibility of a particular layer.
Definition view.h:407
void ClearPreview()
Definition view.cpp:1915
static constexpr int VIEW_MAX_LAYERS
Maximum number of layers that may be shown.
Definition view.h:775
void UpdateAllItems(int aUpdateFlags)
Update all items in the view according to the given flags.
Definition view.cpp:1743
void Hide(VIEW_ITEM *aItem, bool aHide=true, bool aHideOverlay=false)
Temporarily hide the item in the view (e.g.
Definition view.cpp:1837
void AddToPreview(VIEW_ITEM *aItem, bool aTakeOwnership=true)
Definition view.cpp:1937
void SetVisible(VIEW_ITEM *aItem, bool aIsVisible=true)
Set the item visibility.
Definition view.cpp:1813
bool EndsWith(const KIID_PATH &aPath) const
Test if aPath from the last path towards the first path.
Definition kiid.cpp:402
wxString AsString() const
Definition kiid.cpp:423
Definition kiid.h:46
wxString AsString() const
Definition kiid.cpp:264
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:680
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)
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:45
int SetLibNickname(const UTF8 &aLibNickname)
Override the logical library name portion of the LIB_ID to aLibNickname.
Definition lib_id.cpp:113
Define a library symbol object.
Definition lib_symbol.h:114
const LIB_ID & GetLibId() const override
Definition lib_symbol.h:190
bool IsPower() 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:37
static void ConvertToSpiceMarkup(wxString *aNetName)
Convert an escaped schematic net name to SPICE, preserving literal slashes when mapping ground names.
Tree view item data for the net navigator.
static bool ParseBusGroup(const wxString &aGroup, wxString *name, std::vector< wxString > *aMemberList, size_t *aPrefixEnd=nullptr)
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:75
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:65
void SetCursor(KICURSOR aCursor)
Definition picker_tool.h:63
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.
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.
double GetHopOverScale()
Accessor that computes the current hop-over size.
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:149
SCH_CONNECTIVITY::NETCHAIN_MANAGER & NetChains() const
Definition schematic.h:317
wxString GetVariantDescription(const wxString &aVariantName) const
Return the description for a variant.
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:171
wxString GetCurrentVariant() const
Return the current variant being edited.
const std::map< wxString, wxString > * GetProperties()
Definition schematic.h:174
SCH_SHEET & Root() const
Definition schematic.h:200
SCH_SHEET_PATH & CurrentSheet() const
Definition schematic.h:304
static TOOL_ACTION showPcbNew
static TOOL_ACTION createNetChain
static TOOL_ACTION assignFootprints
static TOOL_ACTION copyVariant
static TOOL_ACTION lineModeNext
static TOOL_ACTION toggleOPCurrents
static TOOL_ACTION saveToLinkedDesignBlock
Definition sch_actions.h:77
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 editVariantDescription
static TOOL_ACTION schematicSetup
static TOOL_ACTION toggleDirectiveLabels
static TOOL_ACTION highlightNetTool
static TOOL_ACTION removeFromNetChain
static TOOL_ACTION findNetInInspector
static TOOL_ACTION toggleHiddenFields
static TOOL_ACTION saveCurrSheetCopyAs
Definition sch_actions.h:49
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 highlightNetChain
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:76
static TOOL_ACTION generateBOMLegacy
static TOOL_ACTION placeDesignBlock
Definition sch_actions.h:75
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 replaceTerminalPin
static TOOL_ACTION togglePinAltIcons
static TOOL_ACTION toggleERCExclusions
static TOOL_ACTION updateNetHighlighting
static TOOL_ACTION renameVariant
static TOOL_ACTION createNetChainBetweenPins
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
static TOOL_ACTION importNonKicadSchematic
static TOOL_ACTION nameNetChain
SCH_RENDER_SETTINGS * GetRenderSettings()
SCH_DRAW_PANEL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
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.
Commit for the schematic and symbol editors.
Definition sch_commit.h:54
void Revert() override
Revert the commit by restoring the modified items state.
void Push(const wxString &aMessage=wxEmptyString, int aCommitFlags=0) override
Execute the changes.
Each graphical item can have a SCH_CONNECTION describing its logical connection (to a bus or net).
One UI operation's hierarchy index.
void CollectNetItems(const wxString &aName, const SCH_SHEET_PATH &aSheet, std::unordered_set< SCH_ITEM * > &aItems, bool aIncludeBusParents=false, bool aIncludeBusMembers=false) const
bool ReplaceNetChainTerminalPin(const TERMINAL_CHANGE &aChange)
static wxString NetKeyForItem(const SCH_ITEM &aItem, const SCH_SHEET_PATH &aPath)
bool NetChainsBuilt() const
Returns true once RebuildNetChains() has completed at least once on this graph.
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)
Highlight net under the cursor.
int ClearHighlight(const TOOL_EVENT &aEvent)
Remove any net highlighting.
int FindNetInInspector(const TOOL_EVENT &aEvent)
int EditSymbolFields(const TOOL_EVENT &aEvent)
int GenerateBOMLegacy(const TOOL_EVENT &aEvent)
int RemoveFromNetChain(const TOOL_EVENT &aEvent)
int HighlightNetCursor(const TOOL_EVENT &aEvent)
Launch a tool to highlight nets.
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)
Notifies pcbnew about the selected item.
void SetHighlightBusMembers(bool aHighlightBusMembers)
int CopyVariant(const TOOL_EVENT &aEvent)
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)
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 EditVariantDescription(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 ReplaceTerminalPin(const TOOL_EVENT &aEvent)
Replace one of a net chain's terminal pins.
int SimTune(const TOOL_EVENT &aEvent)
int EditSymbolLibraryLinks(const TOOL_EVENT &aEvent)
int New(const TOOL_EVENT &aEvent)
int ImportNonKicadSchematic(const TOOL_EVENT &aEvent)
int ShowCreateNetChain(const TOOL_EVENT &aEvent)
std::map< wxString, SCH_SCREEN * > m_supplementaryClipboard
int ExplicitCrossProbeToPcb(const TOOL_EVENT &aEvent)
Equivalent to the above, but initiated by the user.
int ToggleOPCurrents(const TOOL_EVENT &aEvent)
int ShowPcbNew(const TOOL_EVENT &aEvent)
int UpdateNetHighlighting(const TOOL_EVENT &aEvent)
Update net highlighting after an edit.
int ToggleERCErrors(const TOOL_EVENT &aEvent)
int ShowHierarchy(const TOOL_EVENT &aEvent)
int OnAngleSnapModeChanged(const TOOL_EVENT &aEvent)
void setTransitions() override
Set up handlers for various events.
static const LIB_SYMBOL * ChoosePasteLibSymbol(const SCH_SCREEN *aClipboardScreen, const SCH_SCREEN *aDestScreen, const wxString &aLibSymbolName)
Choose which cached library symbol a pasted instance should adopt.
int ShowNetNavigator(const TOOL_EVENT &aEvent)
int NameNetChain(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 HighlightNetChain(const TOOL_EVENT &aEvent)
Highlight net chain under the cursor.
int ToggleLibraryTree(const TOOL_EVENT &aEvent)
int RenameVariant(const TOOL_EVENT &aEvent)
std::set< SCH_SYMBOL * > m_pastedSymbols
void prunePastedSymbolInstances()
Reconcile every pasted symbol's instances against the current project.
int Cut(const TOOL_EVENT &aEvent)
Clipboard support.
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)
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 CreateNetChainBetweenPins(const TOOL_EVENT &aEvent)
int Print(const TOOL_EVENT &aEvent)
int Revert(const TOOL_EVENT &aEvent)
int GenerateBOM(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 OnModify() override
Must be called after a schematic change in order to set the "modify" flag and update other data struc...
void ToggleLibraryTree() override
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
bool RecalculateConnections(SCH_COMMIT *aCommit, SCH_CLEANUP_FLAGS aCleanupFlags, PROGRESS_REPORTER *aProgressReporter=nullptr, bool aCleanupDone=false)
Generate the connection data for the entire schematic hierarchy.
void SendCrossProbeClearHighlight()
Tell Pcbnew to clear the existing highlighted net, if one exists.
SCH_SHEET_PATH & GetCurrentSheet() const
const SCH_ITEM * GetSelectedNetNavigatorItem() const
SCHEMATIC & Schematic() const
void ToggleSearch()
Toggle the show/hide state of Search pane.
wxString GetFullScreenDesc() const override
const wxString & GetHighlightedNetChain() const
void ToggleSchematicHierarchy()
Toggle the show/hide state of the left side schematic navigation panel.
void SetHighlightedConnection(const wxString &aConnection, const NET_NAVIGATOR_ITEM_DATA *aSelection=nullptr, bool aForceNetNavigatorRefresh=false)
void SetHighlightedNetChain(const wxString &aNetChain)
void SetCrossProbeConnection(const wxString &aName)
Send a connection (net or bus) to Pcbnew for highlighting.
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)
virtual const wxString & GetText() const override
Return the string associated with the text object.
Definition sch_field.h:139
void SetText(const wxString &aText) override
A set of SCH_ITEMs (i.e., without duplicates).
Definition sch_group.h:48
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 file type from the corresponding plugin type name: "kicad", "legacy", etc.
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:170
virtual bool IsConnectable() const
Definition sch_item.h:545
void SetLocked(bool aLocked) override
Definition sch_item.h:262
const SYMBOL * GetParentSymbol() const
Definition sch_item.cpp:350
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition sch_item.cpp:302
virtual void SetLastResolvedState(const SCH_ITEM *aItem)
Definition sch_item.h:666
int GetBodyStyle() const
Definition sch_item.h:253
int GetUnit() const
Definition sch_item.h:243
void SetConnectivityDirty(bool aDirty=true)
Set the dirty flag.
Definition sch_item.cpp:314
bool IsConnectivityDirty() const
Definition sch_item.h:630
std::optional< wxString > GetConnectionName(const SCH_SHEET_PATH *aSheet=nullptr, bool aLocal=false, bool aIgnoreSheet=false) const
Return the active connection name; absent for missing or stale published rows.
Definition sch_item.cpp:629
virtual void SetUnit(int aUnit)
Definition sch_item.h:242
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:580
bool HasBusConnection(const SCH_SHEET_PATH *aSheet=nullptr) const
Definition sch_item.cpp:720
virtual std::vector< VECTOR2I > GetConnectionPoints() const
Add all the connection points for this item to aPoints.
Definition sch_item.h:558
bool IsType(const std::vector< KICAD_T > &aScanTypes) const override
Check whether the item is one of the listed types.
Definition sch_item.h:185
Segment description base class to describe items which have 2 end points (track, wire,...
Definition sch_line.h:39
A net chain is a collection of nets that are connected together through passive components.
const std::set< wxString > & GetNets() const
const wxString & GetName() const
static bool IsValidName(const wxString &aName)
SCH_PIN * GetLibPin() const
Definition sch_pin.h:109
const wxString & GetNumber() const
Definition sch_pin.h:144
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition sch_pin.h:280
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).
wxString GetRef() const
bool IsSplitNeeded() const
Determine if this reference needs to be split or if it likely already has been.
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:818
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:144
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
void Clear(bool aFree=true)
Delete all draw items and clears the project settings.
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:557
EE_RTREE & Items()
Get the full RTree, usually for iterating.
Definition sch_screen.h:122
const wxString & GetFileName() const
Definition sch_screen.h:157
void UpdateSymbolLinks(REPORTER *aReporter=nullptr, LEGACY_SYMBOL_LIBS *aLegacyLibs=nullptr, SYMBOL_LIBRARY_ADAPTER *aLibraries=nullptr)
Initialize the LIB_SYMBOL reference for each SCH_SYMBOL found in this schematic from the project LIBR...
SCHEMATIC * Schematic() const
TITLE_BLOCK & GetTitleBlock()
Definition sch_screen.h:168
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)
Clear current selection event handler.
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:94
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.
int GetLastVirtualPageNumber() const
bool PageNumberExists(const wxString &aPageNumber) const
bool ContainsSheet(const SCH_SHEET *aSheet) const
bool HasPath(const KIID_PATH &aPath) const
void GetSymbols(SCH_REFERENCE_LIST &aReferences, SYMBOL_FILTER aSymbolFilter, bool aForceIncludeOrphanSymbols=false) const
Add a SCH_REFERENCE object to aReferences for each symbol in the list of sheets.
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...
bool IsSharedPath() const
Determine if this sheet path is shared in a complex hierarchy.
void GetSymbols(SCH_REFERENCE_LIST &aReferences, SYMBOL_FILTER aSymbolFilter, 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:386
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:243
const std::vector< SCH_SHEET_INSTANCE > & GetInstances() const
Definition sch_sheet.h:521
Schematic symbol object.
Definition sch_symbol.h:73
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:133
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:163
std::vector< SCH_PIN * > GetGraphicalPins(int aUnit, int aBodyStyle) const override
void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction, RECURSE_MODE aMode) override
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition sch_symbol.h:182
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)
A null aItem is ignored; the selection never holds null members.
Definition selection.cpp:38
const std::deque< EDA_ITEM * > GetItems() const
Definition selection.h:125
virtual unsigned int GetSize() const override
Return the number of stored items.
Definition selection.h:104
EDA_ITEM * Front() const
Definition selection.h:176
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, std::span< const wxString > aPins, REPORTER &aReporter)
void SetFilesStack(std::vector< EMBEDDED_FILES * > aFilesStack)
Definition sim_lib_mgr.h:45
Implement an OUTPUTFORMATTER to a memory buffer.
Definition richio.h:430
const std::string & GetString()
Definition richio.h:453
Is a LINE_READER that reads from a multiline 8 bit wide std::string.
Definition richio.h:225
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.
virtual const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const =0
SCH_EDIT_FRAME * getEditFrame() const
Definition tool_base.h:182
KIGFX::VIEW_CONTROLS * getViewControls() const
Definition tool_base.cpp:40
KIGFX::VIEW * getView() const
Definition tool_base.cpp:34
Generic, UI-independent tool event.
Definition tool_event.h:167
bool DisableGridSnapping() const
Definition tool_event.h:367
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:484
void Go(int(SCH_EDIT_FRAME::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Master controller class:
T * GetTool()
Return the tool of given type or nullptr if there is no such tool registered.
TOOLS_HOLDER * GetToolHolder() const
A wrapper for reporting to a wxString object.
Definition reporter.h:242
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:32
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:848
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition confirm.cpp:274
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition confirm.cpp:245
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition confirm.cpp:217
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
Definition confirm.cpp:192
This file is part of the common library.
@ VOLTAGE_PROBE
Definition cursors.h:56
@ CURRENT_PROBE
Definition cursors.h:58
@ BULLSEYE
Definition cursors.h:54
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:51
@ NO_RECURSE
Definition eda_item.h:52
#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:57
@ LINE_MODE_90
@ LINE_MODE_45
@ LINE_MODE_FREE
@ LINE_MODE_COUNT
@ FRAME_SCH_SYMBOL_EDITOR
Definition frame_type.h:31
@ FRAME_SCH_VIEWER
Definition frame_type.h:32
@ FRAME_SIMULATOR
Definition frame_type.h:34
bool m_ConnectivityEngine
Use the schematic connectivity engine instead of CONNECTION_GRAPH.
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
static const std::string KiCadSchematicFileExtension
static wxString KiCadSchematicFileWildcard()
static const wxChar traceSchPaste[]
Flag to enable schematic paste debugging output.
std::string source
static wxString From_UTF8(const char *cstring)
Convert a UTF8 encoded C string to a wxString for all wxWidgets build modes.
Definition idf_helpers.h:44
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition idf_helpers.h:37
#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
bool LoadFileToMemory(const wxString &aFileName, wxMemoryBuffer &aBuffer)
Load the contents of a file into a memory buffer.
#define KICTL_REVERT
reverting to a previously-saved (KiCad) file.
@ LAYER_DRAWINGSHEET
Sheet frame and title block.
Definition layer_ids.h:274
@ LAYER_ERC_WARN
Definition layer_ids.h:501
@ LAYER_ERC_ERR
Definition layer_ids.h:502
@ LAYER_SCHEMATIC_DRAWINGSHEET
Definition layer_ids.h:518
@ LAYER_OP_CURRENTS
Definition layer_ids.h:524
@ LAYER_SCHEMATIC_PAGE_LIMITS
Definition layer_ids.h:519
@ LAYER_OP_VOLTAGES
Definition layer_ids.h:523
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:54
@ GEOMETRY
Position or shape has changed.
Definition view_item.h:51
@ TARGET_NONCACHED
Auxiliary rendering target (noncached)
Definition definitions.h:34
void AllowNetworkFileSystems(wxDialog *aDialog)
Configure a file dialog to show network and virtual file systems.
Definition wxgtk/ui.cpp:533
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:32
PGM_BASE & Pgm()
The global program "get" accessor.
see class PGM_BASE
Plotting engines similar to ps (PostScript, Gerber, svg)
static bool setNetHighlight(SCH_ITEM *aItem, bool aHighlight)
#define HITTEST_THRESHOLD_PIXELS
static void recalculateIfStale(SCH_EDIT_FRAME *aFrame, SCH_ITEM *aItem)
static VECTOR2D CLEAR
static bool highlightNet(TOOL_MANAGER *aToolMgr, const SCH_SHEET_PATH &aSheetPath, const VECTOR2D &aPosition)
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.
@ SYMBOL_FILTER_NON_POWER
@ SYMBOL_FILTER_ALL
wxString UniqueGroupName(SCH_SCREEN *aScreen, const wxString &aBaseName)
Return aBaseName, or aBaseName + smallest free integer if a group with that name already exists on aS...
wxString GetSelectedItemsAsText(const SELECTION &aSel)
void PrunePastedSymbolInstances(SCH_SYMBOL *aSymbol, const SCHEMATIC &aSchematic)
Discard the instance data a paste dragged in from somewhere else, keyed by path rather than project n...
std::vector< SCH_ITEM * > FlattenGroups(const EDA_ITEMS &aItems)
Return the given items with the members of any group added, recursively.
constexpr double SCH_WORLD_UNIT(1e-7/0.0254)
@ LOCAL_CLEANUP
Definition schematic.h:94
@ NO_CLEANUP
Definition schematic.h:93
@ GLOBAL_CLEANUP
Definition schematic.h:95
const int scale
std::vector< FAB_LAYER_COLOR > dummy
wxString UnescapeString(const wxString &aSource)
Optional context derived from the user selection that opened the dialog.
wxString toRef
Second selected symbol reference, if any.
wxString fromRef
Selected symbol reference (or first of two)
wxString netName
Net name from a selected pin or wire/bus.
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:71
std::string refName
#define ALL_UNITS
Definition symbol.h:150
#define ALL_BODY_STYLES
Definition symbol.h:151
@ REFERENCE
Field Reference of part, i.e. "IC21".
@ VALUE
Field Value of part, i.e. "3.3K".
std::string path
IbisParser parser & reporter
KIBIS_MODEL * model
KIBIS_PIN * pin
KIBIS_PIN * pinA
const SHAPE_LINE_CHAIN chain
wxString result
Test unit parsing edge cases and error handling.
@ AS_GLOBAL
Global action (toolbar/main menu event, global shortcut)
Definition tool_action.h:45
@ TA_UNDO_REDO_PRE
This event is sent before undo/redo command is performed.
Definition tool_event.h:102
@ TC_MESSAGE
Definition tool_event.h:54
@ SCH_GROUP_T
Definition typeinfo.h:169
@ SCH_TABLE_T
Definition typeinfo.h:161
@ SCH_LINE_T
Definition typeinfo.h:159
@ SCH_SYMBOL_T
Definition typeinfo.h:168
@ SCH_TABLECELL_T
Definition typeinfo.h:162
@ SCH_ITEM_LOCATE_WIRE_T
Definition typeinfo.h:182
@ SCH_FIELD_T
Definition typeinfo.h:146
@ SCH_LABEL_T
Definition typeinfo.h:163
@ SCH_SHEET_T
Definition typeinfo.h:171
@ SCH_MARKER_T
Definition typeinfo.h:154
@ SCH_SHAPE_T
Definition typeinfo.h:145
@ SCH_HIER_LABEL_T
Definition typeinfo.h:165
@ SCH_SHEET_PIN_T
Definition typeinfo.h:170
@ SCH_GLOBAL_LABEL_T
Definition typeinfo.h:164
@ SCH_JUNCTION_T
Definition typeinfo.h:155
@ SCH_PIN_T
Definition typeinfo.h:149
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:708
VECTOR2< double > VECTOR2D
Definition vector2d.h:707
Definition of file extensions used in Kicad.
#define FN_NORMALIZE_FLAGS
Default flags to pass to wxFileName::Normalize().
Definition wx_filename.h:35
#define ZOOM_MIN_LIMIT_EESCHEMA
#define ZOOM_MAX_LIMIT_EESCHEMA