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 wxString msg;
426 msg.Printf( _( "Revert '%s' (and all sub-sheets) to last version saved?" ), m_frame->Schematic().GetFileName() );
427
428 if( !IsOK( m_frame, msg ) )
429 return 0;
430
431 m_frame->ReloadFromDisk();
432
433 return 0;
434}
435
436
438{
439 m_frame->ShowSchematicSetupDialog();
440 return 0;
441}
442
443
445{
446 PICKED_ITEMS_LIST undoCmd;
448 ITEM_PICKER wrapper( m_frame->GetScreen(), undoItem, UNDO_REDO::PAGESETTINGS );
449
450 undoCmd.PushItem( wrapper );
451 undoCmd.SetDescription( _( "Page Settings" ) );
452 m_frame->SaveCopyInUndoList( undoCmd, UNDO_REDO::PAGESETTINGS, false );
453
454 DIALOG_EESCHEMA_PAGE_SETTINGS dlg( m_frame, m_frame->Schematic().GetEmbeddedFiles(),
457
458 if( dlg.ShowModal() == wxID_OK )
459 {
460 // Update text variables
461 m_frame->GetCanvas()->GetView()->MarkDirty();
462 m_frame->GetCanvas()->GetView()->UpdateAllItems( KIGFX::REPAINT );
463 m_frame->GetCanvas()->Refresh();
464
465 m_frame->OnModify();
466 }
467 else
468 {
469 m_frame->RollbackSchematicFromUndo();
470 }
471
472 return 0;
473}
474
475
477{
478 SCH_SCREENS schematic( m_frame->Schematic().Root() );
479
480 if( schematic.HasNoFullyDefinedLibIds() )
481 RescueLegacyProject( true );
482 else
484
485 return 0;
486}
487
488
489bool SCH_EDITOR_CONTROL::RescueLegacyProject( bool aRunningOnDemand )
490{
491 LEGACY_RESCUER rescuer( m_frame->Prj(), &m_frame->Schematic(), &m_frame->GetCurrentSheet(),
492 m_frame->GetCanvas()->GetBackend() );
493
494 return rescueProject( rescuer, aRunningOnDemand );
495}
496
497
499{
500 SYMBOL_LIB_TABLE_RESCUER rescuer( m_frame->Prj(), &m_frame->Schematic(), &m_frame->GetCurrentSheet(),
501 m_frame->GetCanvas()->GetBackend() );
502
503 return rescueProject( rescuer, aRunningOnDemand );
504}
505
506
507bool SCH_EDITOR_CONTROL::rescueProject( RESCUER& aRescuer, bool aRunningOnDemand )
508{
509 if( !RESCUER::RescueProject( m_frame, aRescuer, aRunningOnDemand ) )
510 return false;
511
512 if( aRescuer.GetCandidateCount() )
513 {
514 KIWAY_PLAYER* viewer = m_frame->Kiway().Player( FRAME_SCH_VIEWER, false );
515
516 if( viewer )
517 static_cast<SYMBOL_VIEWER_FRAME*>( viewer )->ReCreateLibList();
518
519 if( aRunningOnDemand )
520 {
521 SCH_SCREENS schematic( m_frame->Schematic().Root() );
522
523 schematic.UpdateSymbolLinks();
524 m_frame->RecalculateConnections( nullptr, GLOBAL_CLEANUP );
525 }
526
527 m_frame->ClearUndoRedoList();
528 m_frame->SyncView();
529 m_frame->GetCanvas()->Refresh();
530 m_frame->OnModify();
531 }
532
533 return true;
534}
535
536
538{
539 DIALOG_SYMBOL_REMAP dlgRemap( m_frame );
540
541 dlgRemap.ShowQuasiModal();
542
543 m_frame->GetCanvas()->Refresh( true );
544
545 return 0;
546}
547
548
550{
551 DIALOG_PRINT dlg( m_frame );
552
553 dlg.ShowModal();
554
555 return 0;
556}
557
558
560{
562
563 dlg.ShowModal();
564
565 return 0;
566}
567
568
570{
571 m_frame->Schematic().OnSchSelectionChanged();
572 doCrossProbeSchToPcb( aEvent, false );
573 return 0;
574}
575
576
578{
579 doCrossProbeSchToPcb( aEvent, true );
580 return 0;
581}
582
583
584void SCH_EDITOR_CONTROL::doCrossProbeSchToPcb( const TOOL_EVENT& aEvent, bool aForce )
585{
586 // Don't get in an infinite loop SCH -> PCB -> SCH -> PCB -> SCH -> ...
587 if( m_probingPcbToSch || m_frame->IsSyncingSelection() )
588 return;
589
590 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
591 SCH_SELECTION& selection = aForce ? selTool->RequestSelection() : selTool->GetSelection();
592
593 m_frame->SendSelectItemsToPcb( selection.GetItemsSortedBySelectionOrder(), aForce );
594}
595
596
598{
599 bool savePowerSymbols = false;
600 bool map = false;
602 wxString targetLib;
603 wxString msg;
604
605 targetLib = m_frame->SelectLibrary( _( "Export Symbols" ), _( "Export symbols to library:" ),
606 { { _( "Include power symbols in export" ), &savePowerSymbols },
607 { _( "Update schematic symbols to link to exported symbols" ), &map }
608 } );
609
610 if( targetLib.empty() )
611 return 0;
612
613 SCH_SHEET_LIST sheets = m_frame->Schematic().BuildSheetListSortedByPageNumbers();
614 SCH_REFERENCE_LIST symbols;
615 sheets.GetSymbols( symbols, savePowerSymbols ? SYMBOL_FILTER_ALL : SYMBOL_FILTER_NON_POWER );
616
617 std::map<LIB_ID, LIB_SYMBOL*> libSymbols;
618 std::map<LIB_ID, std::vector<SCH_SYMBOL*>> symbolMap;
619
620 for( size_t i = 0; i < symbols.GetCount(); ++i )
621 {
622 SCH_SYMBOL* symbol = symbols[i].GetSymbol();
623 LIB_SYMBOL* libSymbol = symbol->GetLibSymbolRef().get();
624 LIB_ID id = libSymbol->GetLibId();
625
626 if( libSymbols.count( id ) )
627 {
628 wxASSERT_MSG( libSymbols[id]->Compare( *libSymbol, ~SCH_ITEM::COMPARE_FLAGS::UUID ) == 0,
629 "Two symbols have the same LIB_ID but are different!" );
630 }
631 else
632 {
633 libSymbols[id] = libSymbol;
634 }
635
636 symbolMap[id].emplace_back( symbol );
637 }
638
639 bool append = false;
640 SCH_COMMIT commit( m_frame );
642
643 auto optRow = adapter->GetRow( targetLib );
644 wxCHECK( optRow, 0 );
645 const LIBRARY_TABLE_ROW* row = *optRow;
646
647 SCH_IO_MGR::SCH_FILE_T type = SCH_IO_MGR::EnumFromStr( row->Type() );
648 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( type ) );
649
650 wxFileName dest = LIBRARY_MANAGER::GetFullURI( row );
651 dest.Normalize( FN_NORMALIZE_FLAGS | wxPATH_NORM_ENV_VARS );
652
653 for( const std::pair<const LIB_ID, LIB_SYMBOL*>& it : libSymbols )
654 {
655 LIB_SYMBOL* origSym = it.second;
656 std::unique_ptr<LIB_SYMBOL> newSym = origSym->Flatten();
657 const wxString newSymName = newSym->GetName();
658
659 try
660 {
661 pi->SaveSymbol( dest.GetFullPath(), std::move( newSym ) );
662 }
663 catch( const IO_ERROR& ioe )
664 {
665 msg.Printf( _( "Error saving symbol %s to library '%s'." ), newSymName, row->Nickname() );
666 msg += wxS( "\n\n" ) + ioe.What();
667 wxLogWarning( msg );
668 return 0;
669 }
670
671 if( map )
672 {
673 LIB_ID id = it.first;
674 id.SetLibNickname( targetLib );
675
676 for( SCH_SYMBOL* symbol : symbolMap[it.first] )
677 {
678 SCH_SCREEN* parentScreen = static_cast<SCH_SCREEN*>( symbol->GetParent() );
679
680 wxCHECK2( parentScreen, continue );
681
682 commit.Modify( symbol, parentScreen, RECURSE_MODE::NO_RECURSE );
683 symbol->SetLibId( id );
684 append = true;
685 }
686 }
687 }
688
689 if( append )
690 {
691 std::set<SCH_SCREEN*> processedScreens;
692
693 for( SCH_SHEET_PATH& sheet : sheets )
694 {
695 SCH_SCREEN* screen = sheet.LastScreen();
696
697 if( processedScreens.find( ( screen ) ) == processedScreens.end() )
698 {
699 processedScreens.insert( screen );
700 screen->UpdateSymbolLinks();
701 }
702 }
703
704 commit.Push( wxS( "Update Library Identifiers" ) );
705 }
706
707 return 0;
708}
709
710
711#define HITTEST_THRESHOLD_PIXELS 5
712
714{
715 static const std::vector<KICAD_T> voltageProbeTypes = {
718 };
719
720 PICKER_TOOL* picker = m_toolMgr->GetTool<PICKER_TOOL>();
721 KIWAY_PLAYER* sim_player = m_frame->Kiway().Player( FRAME_SIMULATOR, false );
722 SIMULATOR_FRAME* sim_Frame = static_cast<SIMULATOR_FRAME*>( sim_player );
723
724 if( !sim_Frame ) // Defensive coding; shouldn't happen.
725 return 0;
726
727 if( wxWindow* blocking_win = sim_Frame->Kiway().GetBlockingDialog() )
728 blocking_win->Close( true );
729
730 if( ADVANCED_CFG::GetCfg().m_ConnectivityEngine && !m_frame->RecalculateConnections( nullptr, NO_CLEANUP ) )
731 return 0;
732
733 // Deactivate other tools; particularly important if another PICKER is currently running
734 Activate();
735
737 picker->SetSnapping( false );
738 picker->ClearHandlers();
739
740 picker->SetClickHandler(
741 [this]( const VECTOR2D& aPosition )
742 {
743 KIWAY_PLAYER* player = m_frame->Kiway().Player( FRAME_SIMULATOR, false );
744 SIMULATOR_FRAME* simFrame = static_cast<SIMULATOR_FRAME*>( player );
745 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
746
747 // We do not really want to keep an item selected in schematic,
748 // so clear the current selection
749 selTool->ClearSelection();
750
751 EDA_ITEM* item = selTool->GetNode( aPosition );
752 SCH_SHEET_PATH& sheet = m_frame->GetCurrentSheet();
753 wxString variant = m_frame->Schematic().GetCurrentVariant();
754
755 if( !item )
756 return false;
757
758 if( item->Type() == SCH_PIN_T )
759 {
760 SCH_PIN* schPin = static_cast<SCH_PIN*>( item );
761 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( schPin->GetParentSymbol() );
762 SCH_PIN* libPin = schPin->GetLibPin();
763
764 if( !symbol || !libPin )
765 return false;
766
767 try
768 {
770 SIM_LIB_MGR mgr( &m_frame->Prj() );
771
772 std::vector<EMBEDDED_FILES*> embeddedFilesStack;
773 embeddedFilesStack.push_back( m_frame->Schematic().GetEmbeddedFiles() );
774
775 if( EMBEDDED_FILES* symbolEmbeddedFile = symbol->GetEmbeddedFiles() )
776 embeddedFilesStack.push_back( symbolEmbeddedFile );
777
778 mgr.SetFilesStack( std::move( embeddedFilesStack ) );
779
780 SIM_MODEL& model = mgr.CreateModel( &sheet, *symbol, true, 0, variant, reporter ).model;
781
782 if( reporter.HasMessage() )
783 THROW_IO_ERROR( reporter.GetMessages() );
784
785 SPICE_ITEM spiceItem;
786 spiceItem.refName = symbol->GetRef( &sheet ).ToStdString();
787 std::vector<std::string> currentNames = model.SpiceGenerator().CurrentNames( spiceItem );
788
789 if( currentNames.size() == 0 )
790 {
791 return true;
792 }
793 else if( currentNames.size() == 1 )
794 {
795 if( simFrame )
796 simFrame->AddCurrentTrace( currentNames.at( 0 ) );
797
798 return true;
799 }
800
801 int modelPinIndex = model.FindModelPinIndex( libPin->GetNumber().ToStdString() );
802
803 if( modelPinIndex != SIM_MODEL_PIN::NOT_CONNECTED )
804 {
805 wxString name = currentNames.at( modelPinIndex );
806
807 if( simFrame )
808 simFrame->AddCurrentTrace( name );
809 }
810 }
811 catch( const IO_ERROR& e )
812 {
814 }
815 }
816 else if( item->IsType( voltageProbeTypes ) )
817 {
818 const SCH_ITEM* schItem = static_cast<const SCH_ITEM*>( item );
819
820 if( schItem->HasBusConnection( &sheet ) )
821 return true;
822
823 if( const auto name = schItem->GetConnectionName( &sheet );
824 name && !name->IsEmpty() )
825 {
826 wxString spiceNet = *name;
828
829 if( simFrame )
830 simFrame->AddVoltageTrace( wxString::Format( "V(%s)", spiceNet ) );
831 }
832 }
833
834 return true;
835 } );
836
837 picker->SetMotionHandler(
838 [this]( const VECTOR2D& aPos )
839 {
840 SCH_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
841 EDA_ITEM* item = selectionTool->GetNode( aPos );
842 wxString connectionName;
843
844 if( item && item->IsType( voltageProbeTypes ) )
845 {
846 const SCH_ITEM* schItem = static_cast<const SCH_ITEM*>( item );
847 const SCH_SHEET_PATH& sheet = m_frame->GetCurrentSheet();
848 item = nullptr;
849
850 if( !schItem->HasBusConnection( &sheet ) )
851 connectionName = schItem->GetConnectionName( &sheet ).value_or( wxString() );
852 }
853 else if( item && item->Type() != SCH_PIN_T )
854 {
855 item = nullptr;
856 }
857
858 if( item && item->Type() == SCH_PIN_T )
859 m_toolMgr->GetTool<PICKER_TOOL>()->SetCursor( KICURSOR::CURRENT_PROBE );
860 else
861 m_toolMgr->GetTool<PICKER_TOOL>()->SetCursor( KICURSOR::VOLTAGE_PROBE );
862
863 if( m_pickerItem != item )
864 {
865 if( m_pickerItem )
866 selectionTool->UnbrightenItem( m_pickerItem );
867
868 m_pickerItem = item;
869
870 if( m_pickerItem )
871 selectionTool->BrightenItem( m_pickerItem );
872 }
873
874 if( m_frame->GetHighlightedConnection() != connectionName )
875 {
876 m_frame->SetHighlightedConnection( connectionName );
877
878 TOOL_EVENT dummyEvent;
879 UpdateNetHighlighting( dummyEvent );
880 }
881 } );
882
883 picker->SetFinalizeHandler(
884 [this]( const int& aFinalState )
885 {
886 if( m_pickerItem )
887 m_toolMgr->GetTool<SCH_SELECTION_TOOL>()->UnbrightenItem( m_pickerItem );
888
889 if( !m_frame->GetHighlightedConnection().IsEmpty() )
890 {
891 m_frame->SetHighlightedConnection( wxEmptyString );
892
893 TOOL_EVENT dummyEvent;
894 UpdateNetHighlighting( dummyEvent );
895 }
896
897 // Wake the selection tool after exiting to ensure the cursor gets updated
898 // and deselect previous selection from simulator to avoid any issue
899 // ( avoid crash in some cases when the SimProbe tool is deselected )
900 SCH_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
901 selectionTool->ClearSelection();
903 } );
904
905 m_toolMgr->RunAction( ACTIONS::pickerTool, &aEvent );
906
907 return 0;
908}
909
910
912{
913 PICKER_TOOL* picker = m_toolMgr->GetTool<PICKER_TOOL>();
914
915 // Deactivate other tools; particularly important if another PICKER is currently running
916 Activate();
917
918 picker->SetCursor( KICURSOR::TUNE );
919 picker->SetSnapping( false );
920 picker->ClearHandlers();
921
922 picker->SetClickHandler(
923 [this]( const VECTOR2D& aPosition )
924 {
925 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
926 EDA_ITEM* item = nullptr;
927 selTool->SelectPoint( aPosition, { SCH_SYMBOL_T, SCH_FIELD_T }, &item );
928
929 if( !item )
930 return false;
931
932 if( item->Type() != SCH_SYMBOL_T )
933 {
934 item = item->GetParent();
935
936 if( item->Type() != SCH_SYMBOL_T )
937 return false;
938 }
939
940 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
941 SCH_SHEET_PATH sheetPath = symbol->Schematic()->CurrentSheet();
942 KIWAY_PLAYER* simFrame = m_frame->Kiway().Player( FRAME_SIMULATOR, false );
943
944 if( simFrame )
945 {
946 if( wxWindow* blocking_win = simFrame->Kiway().GetBlockingDialog() )
947 blocking_win->Close( true );
948
949 static_cast<SIMULATOR_FRAME*>( simFrame )->AddTuner( sheetPath, symbol );
950 }
951
952 // We do not really want to keep a symbol selected in schematic,
953 // so clear the current selection
954 selTool->ClearSelection();
955 return true;
956 } );
957
958 picker->SetMotionHandler(
959 [this]( const VECTOR2D& aPos )
960 {
961 SCH_COLLECTOR collector;
962 collector.m_Threshold = KiROUND( getView()->ToWorld( HITTEST_THRESHOLD_PIXELS ) );
963 collector.Collect( m_frame->GetScreen(), { SCH_SYMBOL_T, SCH_FIELD_T }, aPos );
964
965 SCH_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
966 selectionTool->GuessSelectionCandidates( collector, aPos );
967
968 EDA_ITEM* item = collector.GetCount() == 1 ? collector[0] : nullptr;
969
970 if( item && item->Type() == SCH_FIELD_T )
971 item = static_cast<SCH_FIELD*>( item )->GetParentSymbol();
972
973 if( m_pickerItem != item )
974 {
975 if( m_pickerItem )
976 selectionTool->UnbrightenItem( m_pickerItem );
977
978 m_pickerItem = item;
979
980 if( m_pickerItem )
981 selectionTool->BrightenItem( m_pickerItem );
982 }
983 } );
984
985 picker->SetFinalizeHandler(
986 [this]( const int& aFinalState )
987 {
988 if( m_pickerItem )
989 m_toolMgr->GetTool<SCH_SELECTION_TOOL>()->UnbrightenItem( m_pickerItem );
990
991 // Wake the selection tool after exiting to ensure the cursor gets updated
992 // and deselect previous selection from simulator to avoid any issue
993 // ( avoid crash in some cases when the SimTune tool is deselected )
994 SCH_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
995 selectionTool->ClearSelection();
997 } );
998
999 m_toolMgr->RunAction( ACTIONS::pickerTool, &aEvent );
1000
1001 return 0;
1002}
1003
1004
1005// A singleton reference for clearing the highlight
1007
1008
1009static void recalculateIfStale( SCH_EDIT_FRAME* aFrame, SCH_ITEM* aItem )
1010{
1011 if( ( aItem && aItem->IsConnectivityDirty() ) || !aFrame->Schematic().NetChains().NetChainsBuilt() )
1012 aFrame->RecalculateConnections( nullptr, NO_CLEANUP );
1013}
1014
1015
1016static bool setNetHighlight( SCH_ITEM* aItem, bool aHighlight )
1017{
1018 if( aItem->IsNetHighlighted() == aHighlight )
1019 return false;
1020
1021 aItem->SetNetHighlighted( aHighlight );
1022 return true;
1023}
1024
1025
1026static bool highlightNet( TOOL_MANAGER* aToolMgr, const SCH_SHEET_PATH& aSheetPath, const VECTOR2D& aPosition )
1027{
1028 wxLogTrace( "KICAD_SCH_HIGHLIGHT", "highlightNet: pos=(%f,%f) clear=%d", aPosition.x, aPosition.y,
1029 ( aPosition == CLEAR ) );
1030 SCH_EDIT_FRAME* editFrame = static_cast<SCH_EDIT_FRAME*>( aToolMgr->GetToolHolder() );
1031 SCH_SELECTION_TOOL* selTool = aToolMgr->GetTool<SCH_SELECTION_TOOL>();
1032 SCH_EDITOR_CONTROL* editorControl = aToolMgr->GetTool<SCH_EDITOR_CONTROL>();
1033 std::optional<wxString> connName;
1034 SCH_ITEM* item = nullptr;
1035 bool retVal = true;
1036
1037 if( aPosition != CLEAR )
1038 {
1039 ERC_TESTER erc( &editFrame->Schematic() );
1040
1041 if( erc.TestDuplicateSheetNames( false ) > 0 )
1042 {
1043 wxMessageBox( _( "Error: duplicate sub-sheet names found in current sheet." ) );
1044 retVal = false;
1045 }
1046 else
1047 {
1048 item = static_cast<SCH_ITEM*>( selTool->GetNode( aPosition ) );
1049 wxLogTrace( "KICAD_SCH_HIGHLIGHT", "highlightNet: item=%p type=%d", (void*) item, item ? (int) item->Type()
1050 : -1 );
1051 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( item );
1052
1053 if( item )
1054 {
1055 recalculateIfStale( editFrame, item );
1056
1057 if( item->Type() == SCH_FIELD_T )
1058 symbol = dynamic_cast<SCH_SYMBOL*>( item->GetParent() );
1059
1060 if( symbol && symbol->GetLibSymbolRef() && symbol->GetLibSymbolRef()->IsPower() )
1061 {
1062 std::vector<SCH_PIN*> pins = symbol->GetPins( &aSheetPath );
1063
1064 if( pins.size() == 1 )
1065 connName = pins[0]->GetConnectionName( &editFrame->GetCurrentSheet() );
1066 }
1067 else
1068 {
1069 connName = item->GetConnectionName( &editFrame->GetCurrentSheet() );
1070 }
1071 }
1072 }
1073 }
1074
1075 if( !connName || connName->IsEmpty() )
1076 {
1077 wxLogTrace( "KICAD_SCH_HIGHLIGHT", "highlightNet: no connection under cursor" );
1078 editFrame->SetStatusText( wxT( "" ) );
1079 editFrame->SendCrossProbeClearHighlight();
1080 editFrame->SetHighlightedConnection( wxEmptyString );
1081 // Also clear any highlighted net chain so ESC or clicking empty space clears both modes
1082 editFrame->SetHighlightedNetChain( wxEmptyString );
1083 editorControl->SetHighlightBusMembers( false );
1084 }
1085 else
1086 {
1087 NET_NAVIGATOR_ITEM_DATA itemData( editFrame->GetCurrentSheet(), item );
1088
1089 if( *connName != editFrame->GetHighlightedConnection() )
1090 {
1091 wxLogTrace( "KICAD_SCH_HIGHLIGHT", "highlightNet: setting highlighted connection to %s", *connName );
1092 editorControl->SetHighlightBusMembers( false );
1093 // Clear any previous chain highlight when switching to net highlight
1094 editFrame->SetHighlightedNetChain( wxEmptyString );
1095 editFrame->SetCrossProbeConnection( *connName );
1096 editFrame->SetHighlightedConnection( *connName, &itemData );
1097 }
1098 else
1099 {
1100 auto& chains = editFrame->Schematic().NetChains();
1101
1102 if( SCH_NETCHAIN* chain = chains.GetNetChainForNet( *connName ) )
1103 {
1104 editFrame->SetHighlightedConnection( wxEmptyString );
1105 editFrame->SetHighlightedNetChain( chain->GetName() );
1106 editorControl->SetHighlightBusMembers( false );
1107 }
1108 else
1109 {
1110 editorControl->SetHighlightBusMembers( !editorControl->GetHighlightBusMembers() );
1111
1112 if( item != editFrame->GetSelectedNetNavigatorItem() )
1113 editFrame->SelectNetNavigatorItem( &itemData );
1114 }
1115 }
1116 }
1117
1118 editFrame->UpdateNetHighlightStatus();
1119
1121 editorControl->UpdateNetHighlighting( dummy );
1122 wxLogTrace( "KICAD_SCH_HIGHLIGHT", "highlightNet: done" );
1123
1124 return retVal;
1125}
1126
1127
1129{
1131 VECTOR2D cursorPos = controls->GetCursorPosition( !aEvent.DisableGridSnapping() );
1132
1133 highlightNet( m_toolMgr, m_frame->GetCurrentSheet(), cursorPos );
1134
1135 return 0;
1136}
1137
1138
1140{
1142 const VECTOR2D cursorPos = controls->GetCursorPosition( !aEvent.DisableGridSnapping() );
1143 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
1144 SCH_ITEM* item = static_cast<SCH_ITEM*>( selTool->GetNode( cursorPos ) );
1145 auto& chains = m_frame->Schematic().NetChains();
1146
1147 recalculateIfStale( m_frame, item );
1148
1149 const auto name = item ? item->GetConnectionName( &m_frame->GetCurrentSheet() ) : std::nullopt;
1150 wxString newChain;
1151 wxString newConnection;
1152
1153 if( name && !name->IsEmpty() )
1154 {
1155 if( SCH_NETCHAIN* chain = chains.GetNetChainForNet( *name ) )
1156 {
1157 newChain = chain->GetName();
1158
1159 if( !chain->GetNets().empty() )
1160 m_frame->SendCrossProbeNetName( *chain->GetNets().begin() );
1161 }
1162 else
1163 {
1164 newConnection = *name;
1165 m_frame->SetCrossProbeConnection( *name );
1166 }
1167 }
1168 else
1169 {
1170 m_frame->SendCrossProbeClearHighlight();
1171 }
1172
1173 SetHighlightBusMembers( false );
1174 m_frame->SetHighlightedNetChain( newChain );
1175 m_frame->SetHighlightedConnection( newConnection );
1176 m_frame->UpdateNetHighlightStatus();
1179 return 0;
1180}
1181
1183{
1184 SCH_EDIT_FRAME* editFrame = static_cast<SCH_EDIT_FRAME*>( m_toolMgr->GetToolHolder() );
1185 if( !editFrame )
1186 return 0;
1187
1188 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
1190 VECTOR2D cursorPos = controls->GetCursorPosition( !aEvent.DisableGridSnapping() );
1191
1192 SCH_ITEM* target = nullptr;
1193
1194 // Prefer current selection; otherwise, use item under cursor
1195 if( selTool && selTool->GetSelection().GetSize() == 1 )
1196 target = static_cast<SCH_ITEM*>( selTool->GetSelection().Front() );
1197 else if( selTool )
1198 target = static_cast<SCH_ITEM*>( selTool->GetNode( cursorPos ) );
1199
1200 if( !target )
1201 return 0;
1202
1203 auto& chains = editFrame->Schematic().NetChains();
1204 const wxString net = SCH_CONNECTIVITY::NETCHAIN_MANAGER::NetKeyForItem( *target, editFrame->GetCurrentSheet() );
1205 const SCH_NETCHAIN* chain = chains.GetNetChainForNet( net );
1206
1207 if( !chain )
1208 return 0;
1209
1210 SCH_COMMIT commit( editFrame );
1211
1212 for( const auto& [symbol, screen] : chains.GetBridgeSymbols( *chain, net ) )
1213 {
1214 commit.Modify( symbol, screen );
1215 symbol->SetPassthroughMode( SCH_SYMBOL::PASSTHROUGH_MODE::BLOCK );
1216 }
1217
1218 commit.Push( _( "Remove from Net Chain" ) );
1219
1220 return 0;
1221}
1222
1223
1225{
1226 highlightNet( m_toolMgr, m_frame->GetCurrentSheet(), CLEAR );
1227
1228 // Also clear any highlighted chain explicitly
1229 if( m_frame )
1230 m_frame->SetHighlightedNetChain( wxEmptyString );
1231
1232 return 0;
1233}
1234
1235
1237{
1238 SCH_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
1239 SCHEMATIC& schematic = m_frame->Schematic();
1240 const SCH_SHEET_PATH path = m_frame->GetCurrentSheet();
1241 SCH_SCREEN* screen = path.LastScreen();
1242 const bool usePublished = ADVANCED_CFG::GetCfg().m_ConnectivityEngine;
1243
1244 if( usePublished && !m_frame->RecalculateConnections( nullptr, NO_CLEANUP ) )
1245 return 0;
1246
1247 const auto getNetNamePattern =
1248 []( const auto& aConn ) -> std::optional<wxString>
1249 {
1250 wxString netName = aConn.Name();
1251
1252 if( aConn.IsBus() )
1253 {
1254 wxString prefix;
1255
1256 if( NET_SETTINGS::ParseBusVector( netName, &prefix, nullptr ) )
1257 return prefix + wxT( "*" );
1258 else if( NET_SETTINGS::ParseBusGroup( netName, &prefix, nullptr ) )
1259 return prefix + wxT( ".*" );
1260 }
1261 else if( !aConn.Driver() || CONNECTION_SUBGRAPH::GetDriverPriority( aConn.Driver() )
1263 {
1264 return std::nullopt;
1265 }
1266
1267 return netName;
1268 };
1269
1270 std::set<wxString> netNames;
1271
1272 for( EDA_ITEM* item : selectionTool->GetSelection() )
1273 {
1274 SCH_ITEM* schItem = static_cast<SCH_ITEM*>( item );
1275 std::optional<wxString> netNamePattern;
1276
1277 if( usePublished )
1278 {
1279 const auto connection = schematic.Connectivity().Connection( schItem->m_Uuid, path.PathRef() );
1280
1281 if( !connection )
1282 continue;
1283
1284 netNamePattern = getNetNamePattern( *connection );
1285 }
1286 else
1287 {
1288 const SCH_CONNECTION* connection = schItem->Connection( &path );
1289
1290 if( !connection )
1291 continue;
1292
1293 netNamePattern = getNetNamePattern( *connection );
1294 }
1295
1296 if( !netNamePattern )
1297 {
1298 // This is a choice, we can also allow some un-labeled nets as long as some are labeled.
1299 m_frame->ShowInfoBarError( _( "All selected nets must be labeled to assign a netclass." ) );
1300 return 0;
1301 }
1302
1303 netNames.insert( *netNamePattern );
1304 }
1305
1306 if( netNames.empty() )
1307 {
1308 m_frame->ShowInfoBarError( _( "No nets selected." ) );
1309 return 0;
1310 }
1311
1312 selectionTool->ClearSelection();
1313
1314 DIALOG_ASSIGN_NETCLASS dlg( m_frame, netNames, schematic.GetNetClassAssignmentCandidates(),
1315 [&]( const std::vector<wxString>& aNetNames )
1316 {
1317 std::unordered_set<SCH_ITEM*> highlighted;
1318 const SCH_CONNECTIVITY::NAVIGATION_QUERY query( schematic );
1319
1320 for( const wxString& name : aNetNames )
1321 query.CollectNetItems( name, path, highlighted );
1322
1323 for( SCH_ITEM* item : screen->Items() )
1324 {
1325 bool redraw = setNetHighlight( item, highlighted.contains( item ) );
1326
1327 item->RunOnChildren(
1328 [&]( SCH_ITEM* aChild )
1329 {
1330 redraw |= setNetHighlight( aChild, highlighted.contains( aChild ) );
1331 },
1332 RECURSE_MODE::NO_RECURSE );
1333
1334 if( redraw )
1335 getView()->Update( item, KIGFX::VIEW_UPDATE_FLAGS::REPAINT );
1336 }
1337
1338 m_frame->GetCanvas()->ForceRefresh();
1339 } );
1340
1341 if( dlg.ShowModal() )
1342 {
1343 getView()->UpdateAllItemsConditionally(
1344 [&]( KIGFX::VIEW_ITEM* aItem ) -> int
1345 {
1346 int flags = 0;
1347
1348 auto invalidateTextVars =
1349 [&flags]( EDA_TEXT* text )
1350 {
1351 if( text->HasTextVars() )
1352 {
1353 text->ClearRenderCache();
1354 text->ClearBoundingBoxCache();
1356 }
1357 };
1358
1359 // Netclass coloured items
1360 //
1361 if( dynamic_cast<SCH_LINE*>( aItem ) )
1362 flags |= KIGFX::REPAINT;
1363 else if( dynamic_cast<SCH_JUNCTION*>( aItem ) )
1364 flags |= KIGFX::REPAINT;
1365 else if( dynamic_cast<SCH_BUS_ENTRY_BASE*>( aItem ) )
1366 flags |= KIGFX::REPAINT;
1367
1368 // Items that might reference an item's netclass name
1369 //
1370 if( EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( aItem ) )
1371 invalidateTextVars( text );
1372
1373 if( SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( aItem ) )
1374 {
1375 item->RunOnChildren(
1376 [&invalidateTextVars]( SCH_ITEM* aChild )
1377 {
1378 if( EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( aChild ) )
1379 invalidateTextVars( text );
1380 },
1382
1383 if( flags & KIGFX::GEOMETRY )
1384 m_frame->GetScreen()->UpdateDisplayBounds( item );
1385 }
1386
1387 return flags;
1388 } );
1389 }
1390
1391 highlightNet( m_toolMgr, m_frame->GetCurrentSheet(), CLEAR );
1392 return 0;
1393}
1394
1395
1397{
1398 SCH_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
1399
1400 if( !selectionTool )
1401 return 0;
1402
1403 const SCH_SHEET_PATH path = m_frame->GetCurrentSheet();
1404 const bool usePublished = ADVANCED_CFG::GetCfg().m_ConnectivityEngine;
1405
1406 if( usePublished && !m_frame->RecalculateConnections( nullptr, NO_CLEANUP ) )
1407 return 0;
1408
1409 wxString netName;
1410
1411 for( EDA_ITEM* item : selectionTool->GetSelection() )
1412 {
1413 if( SCH_ITEM* schItem = dynamic_cast<SCH_ITEM*>( item ) )
1414 {
1415 if( usePublished )
1416 {
1417 const auto connection = m_frame->Schematic().Connectivity().Connection(
1418 schItem->m_Uuid, path.PathRef() );
1419
1420 if( connection && !connection->IsUnconnected() )
1421 netName = connection->Name();
1422 }
1423 else if( const SCH_CONNECTION* connection = schItem->Connection( &path ) )
1424 {
1425 netName = connection->GetNetName();
1426 }
1427
1428 if( !netName.IsEmpty() )
1429 break;
1430 }
1431 }
1432
1433 if( netName.IsEmpty() )
1434 netName = m_frame->GetHighlightedConnection();
1435
1436 if( netName.IsEmpty() )
1437 {
1438 m_frame->ShowInfoBarError( _( "No connected net selected." ) );
1439 return 0;
1440 }
1441
1442 m_frame->FindNetInInspector( netName );
1443
1444 return 0;
1445}
1446
1447
1449{
1450 wxCHECK( m_frame, 0 );
1451
1452 const SCH_SHEET_PATH& sheetPath = m_frame->GetCurrentSheet();
1453 SCH_SCREEN* screen = sheetPath.LastScreen();
1454 wxCHECK( screen, 0 );
1455
1456 const wxString selectedName = m_frame->GetHighlightedConnection();
1457 const wxString chainName = m_frame->GetHighlightedNetChain();
1458 SCH_NETCHAIN* chain = chainName.IsEmpty() ? nullptr
1459 : m_frame->Schematic().NetChains().GetNetChainByName( chainName );
1460 std::unordered_set<SCH_ITEM*> highlighted;
1461
1462 if( !selectedName.IsEmpty() || chain )
1463 {
1464 const SCH_CONNECTIVITY::NAVIGATION_QUERY query( m_frame->Schematic() );
1465
1466 if( !selectedName.IsEmpty() )
1467 query.CollectNetItems( selectedName, sheetPath, highlighted, true, m_highlightBusMembers );
1468
1469 if( chain )
1470 {
1471 for( const wxString& name : chain->GetNets() )
1472 query.CollectNetItems( name, sheetPath, highlighted );
1473 }
1474 }
1475
1476 bool changed = false;
1477
1478 for( SCH_ITEM* item : screen->Items() )
1479 {
1480 if( !item )
1481 continue;
1482
1483 bool redraw = setNetHighlight( item, highlighted.contains( item ) );
1484 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( item );
1485 bool powerHighlight = false;
1486
1487 if( symbol && symbol->IsPower() )
1488 {
1489 std::vector<SCH_PIN*> pins = symbol->GetPins( &sheetPath );
1490 powerHighlight = !pins.empty() && highlighted.contains( pins.front() );
1491 }
1492
1493 item->RunOnChildren(
1494 [&]( SCH_ITEM* child )
1495 {
1496 bool highlight = highlighted.contains( child );
1497
1498 if( powerHighlight && child->Type() == SCH_FIELD_T )
1499 {
1500 const auto* field = static_cast<SCH_FIELD*>( child );
1501 highlight = field->IsVisible() && ( field->GetId() == FIELD_T::REFERENCE
1502 || field->GetId() == FIELD_T::VALUE );
1503 }
1504
1505 redraw |= setNetHighlight( child, highlight );
1507
1508 if( redraw )
1509 {
1510 getView()->Update( item, KIGFX::REPAINT );
1511 changed = true;
1512 }
1513 }
1514
1515 if( changed )
1516 m_frame->GetCanvas()->Refresh();
1517
1518 return 0;
1519}
1520
1521
1523{
1524 PICKER_TOOL* picker = m_toolMgr->GetTool<PICKER_TOOL>();
1525
1526 // Deactivate other tools; particularly important if another PICKER is currently running
1527 Activate();
1528
1529 picker->SetCursor( KICURSOR::BULLSEYE );
1530 picker->SetSnapping( false );
1531 picker->ClearHandlers();
1532
1533 picker->SetClickHandler(
1534 [this]( const VECTOR2D& aPos )
1535 {
1536 return highlightNet( m_toolMgr, m_frame->GetCurrentSheet(), aPos );
1537 } );
1538
1539 m_toolMgr->RunAction( ACTIONS::pickerTool, &aEvent );
1540
1541 return 0;
1542}
1543
1544
1546{
1547 SCH_EDIT_FRAME* editFrame = static_cast<SCH_EDIT_FRAME*>( m_toolMgr->GetToolHolder() );
1549
1550 if( editFrame->Schematic().NetChains().ReplaceNetChainTerminalPin( change ) )
1551 {
1552 editFrame->OnModify();
1553 editFrame->GetCanvas()->Refresh();
1554 }
1555 else
1556 {
1557 DisplayError( editFrame, _( "Unable to replace the net chain terminal pin." ) );
1558 }
1559
1560 return 0;
1561}
1562
1563
1565{
1566 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
1567 SCH_ITEM* item = static_cast<SCH_ITEM*>( selTool->GetSelection().Front() );
1568 SCH_PIN* pin = dynamic_cast<SCH_PIN*>( item );
1569
1570 if( !pin )
1571 return 0;
1572
1573 SCH_EDIT_FRAME* editFrame = static_cast<SCH_EDIT_FRAME*>( m_toolMgr->GetToolHolder() );
1574 auto& chains = editFrame->Schematic().NetChains();
1575 const auto netName = pin->GetConnectionName( &editFrame->GetCurrentSheet() );
1576
1577 if( !netName )
1578 return 0;
1579
1580 if( SCH_NETCHAIN* sig = chains.GetNetChainForNet( *netName ) )
1581 {
1582 const wxString oldName = sig->GetName();
1583 const wxString newName = wxGetTextFromUser( _( "Net chain name:" ), _( "Name Net Chain" ), oldName );
1584
1585 if( newName.IsEmpty() || newName == oldName )
1586 return 0;
1587
1588 if( !SCH_NETCHAIN::IsValidName( newName ) )
1589 {
1590 DisplayError( editFrame, _( "Chain name cannot contain spaces, quotes, or parentheses." ) );
1591 return 0;
1592 }
1593
1594 if( !chains.RenameCommittedNetChain( oldName, newName ) )
1595 {
1596 DisplayError( editFrame, wxString::Format( _( "Unable to rename net chain '%s' to '%s'." ),
1597 oldName, newName ) );
1598 return 0;
1599 }
1600
1601 editFrame->OnModify();
1602 editFrame->SetHighlightedNetChain( newName );
1605 editFrame->UpdateNetHighlightStatus();
1606 }
1607
1608 return 0;
1609}
1610
1612{
1613 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
1614 auto& selection = selTool->GetSelection();
1615
1616 if( selection.GetSize() != 2 )
1617 return 0;
1618
1619 SCH_PIN* pinA = dynamic_cast<SCH_PIN*>( static_cast<SCH_ITEM*>( selection[0] ) );
1620 SCH_PIN* pinB = dynamic_cast<SCH_PIN*>( static_cast<SCH_ITEM*>( selection[1] ) );
1621
1622 if( !pinA || !pinB )
1623 return 0;
1624
1625 SCH_EDIT_FRAME* editFrame = static_cast<SCH_EDIT_FRAME*>( m_toolMgr->GetToolHolder() );
1626 auto& chains = editFrame->Schematic().NetChains();
1627 const SCH_SHEET_PATH& path = editFrame->GetCurrentSheet();
1628
1629 SCH_NETCHAIN* potential = chains.FindPotentialNetChainBetweenPins( pinA, path, pinB, path );
1630 if( !potential )
1631 {
1632 DisplayError( editFrame, _( "No potential net chain connects the selected pins." ) );
1633 return 0;
1634 }
1635
1636 // Potentials are rebuilt regardless of commitment and GetNetChainForNet() returns the first owner
1637 for( const wxString& net : potential->GetNets() )
1638 {
1639 if( SCH_NETCHAIN* owner = chains.GetNetChainForNet( net ) )
1640 {
1641 DisplayError( editFrame, wxString::Format( _( "The selected pins are already in net chain '%s'." ),
1642 owner->GetName() ) );
1643 return 0;
1644 }
1645 }
1646
1647 // Build default suggestion name
1648 wxString suggestion = wxString::Format( wxS( "%s_%s" ), pinA->GetParentSymbol()->GetRef( &editFrame->GetCurrentSheet() ), pinB->GetParentSymbol()->GetRef( &editFrame->GetCurrentSheet() ) );
1649
1650 // Compose display text for dialog
1651 wxString msg = wxString::Format( _( "Create Net Chain between %s:%s and %s:%s" ),
1652 pinA->GetParentSymbol()->GetRef( &editFrame->GetCurrentSheet() ), pinA->GetNumber(),
1653 pinB->GetParentSymbol()->GetRef( &editFrame->GetCurrentSheet() ), pinB->GetNumber() );
1654
1655 // Temporary highlight preview: highlight all nets in potential (reuse SetHighlightedNetChain with temp name)
1656 // We use the potential's current name as a temporary highlight identifier
1657 wxString prevHighlightedChain = editFrame->GetHighlightedNetChain();
1658 wxString prevHighlightedConn = editFrame->GetHighlightedConnection();
1659
1660 editFrame->SetHighlightedConnection( wxEmptyString );
1661 editFrame->SetHighlightedNetChain( potential->GetName() );
1664 editFrame->UpdateNetHighlightStatus();
1665
1666 // Zoom to bounding box of the two pins (union) expanded slightly
1667 BOX2I bbox = pinA->GetBoundingBox();
1668 bbox.Merge( pinB->GetBoundingBox() );
1669 // Expand by 25% for context
1670 int dx = bbox.GetWidth() / 4; if( dx < 100 ) dx = 100;
1671 int dy = bbox.GetHeight() / 4; if( dy < 100 ) dy = 100;
1672 bbox.Inflate( dx, dy );
1673 if( auto canvas = editFrame->GetCanvas() )
1674 {
1675 canvas->GetView()->SetCenter( bbox.GetCenter() );
1676 // Compute scale so bbox roughly fits viewport height
1677 auto view = canvas->GetView();
1678 if( view )
1679 {
1680 BOX2D viewBox = view->GetBoundary();
1681 double scaleX = (double) viewBox.GetWidth() / (double) bbox.GetWidth();
1682 double scaleY = (double) viewBox.GetHeight() / (double) bbox.GetHeight();
1683 double scale = std::min( scaleX, scaleY );
1684 if( scale > 0 )
1685 view->SetScale( scale );
1686 }
1687 }
1688
1689 const auto restoreHighlight =
1690 [&]()
1691 {
1692 editFrame->SetHighlightedNetChain( prevHighlightedChain );
1693 editFrame->SetHighlightedConnection( prevHighlightedConn );
1695 editFrame->UpdateNetHighlightStatus();
1696 };
1697
1698 wxString name = wxGetTextFromUser( msg, _( "Create Net Chain" ), suggestion, editFrame );
1699
1700 if( name.IsEmpty() )
1701 {
1702 restoreHighlight();
1703 return 0; // cancelled
1704 }
1705
1707 {
1708 restoreHighlight();
1709 DisplayError( editFrame, _( "Chain name cannot contain spaces, quotes, or parentheses." ) );
1710 return 0;
1711 }
1712
1713 if( chains.GetNetChainByName( name ) )
1714 {
1715 restoreHighlight();
1716 DisplayError( editFrame, wxString::Format( _( "A net chain named '%s' already exists." ), name ) );
1717 return 0;
1718 }
1719
1720 if( !chains.CreateNetChainFromPotential( potential, name ) )
1721 {
1722 restoreHighlight();
1723 DisplayError( editFrame, wxString::Format( _( "Unable to create net chain '%s'." ), name ) );
1724 return 0;
1725 }
1726
1727 editFrame->OnModify();
1728
1729 // Replace temporary highlight with new chain name
1730 editFrame->SetHighlightedNetChain( name );
1731 editFrame->SetHighlightedConnection( wxEmptyString );
1733 editFrame->UpdateNetHighlightStatus();
1734 editFrame->Refresh();
1735
1736 return 0;
1737}
1738
1739
1741{
1742 SCH_EDIT_FRAME* editFrame = static_cast<SCH_EDIT_FRAME*>( m_toolMgr->GetToolHolder() );
1743
1744 editFrame->RecalculateConnections( nullptr, NO_CLEANUP );
1745
1747
1748 if( SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>() )
1749 {
1750 const SCH_SELECTION& sel = selTool->GetSelection();
1751
1752 std::vector<SCH_SYMBOL*> symbols;
1753
1754 for( EDA_ITEM* item : sel )
1755 {
1756 if( SCH_SYMBOL* sym = dynamic_cast<SCH_SYMBOL*>( static_cast<SCH_ITEM*>( item ) ) )
1757 symbols.push_back( sym );
1758 }
1759
1760 if( symbols.size() >= 1 )
1761 hint.fromRef = symbols[0]->GetRef( &editFrame->GetCurrentSheet() );
1762
1763 if( symbols.size() >= 2 )
1764 hint.toRef = symbols[1]->GetRef( &editFrame->GetCurrentSheet() );
1765
1766 // Single pin or single wire/bus → use its connection's net name as the focus hint.
1767 if( symbols.empty() && sel.GetSize() == 1 )
1768 {
1769 SCH_ITEM* schItem = static_cast<SCH_ITEM*>( sel.Front() );
1770
1771 if( schItem && schItem->IsType( { SCH_PIN_T, SCH_ITEM_LOCATE_WIRE_T, SCH_ITEM_LOCATE_BUS_T } ) )
1772 {
1773 if( const auto name = schItem->GetConnectionName( &editFrame->GetCurrentSheet() ) )
1774 hint.netName = *name;
1775 }
1776 }
1777 }
1778
1779 DIALOG_CREATE_NET_CHAIN dlg( editFrame, hint );
1780 dlg.ShowModal();
1781
1782 return 0;
1783}
1784
1785
1787{
1788 wxCHECK( m_frame, 0 );
1789
1790 if( m_frame->GetUndoCommandCount() <= 0 )
1791 return 0;
1792
1793 // Inform tools that undo command was issued
1794 m_toolMgr->ProcessEvent( { TC_MESSAGE, TA_UNDO_REDO_PRE, AS_GLOBAL } );
1795
1796 // Get the old list
1797 PICKED_ITEMS_LIST* undo_list = m_frame->PopCommandFromUndoList();
1798
1799 wxCHECK( undo_list, 0 );
1800
1801 m_frame->PutDataInPreviousState( undo_list );
1802
1803 // Now push the old command to the RedoList
1804 undo_list->ReversePickersListOrder();
1805 m_frame->PushCommandToRedoList( undo_list );
1806
1807 m_toolMgr->GetTool<SCH_SELECTION_TOOL>()->RebuildSelection();
1808
1809 m_frame->GetCanvas()->Refresh();
1810 m_frame->OnModify();
1811
1812 return 0;
1813}
1814
1815
1817{
1818 wxCHECK( m_frame, 0 );
1819
1820 if( m_frame->GetRedoCommandCount() == 0 )
1821 return 0;
1822
1823 // Inform tools that undo command was issued
1824 m_toolMgr->ProcessEvent( { TC_MESSAGE, TA_UNDO_REDO_PRE, AS_GLOBAL } );
1825
1826 /* Get the old list */
1827 PICKED_ITEMS_LIST* list = m_frame->PopCommandFromRedoList();
1828
1829 wxCHECK( list, 0 );
1830
1831 /* Redo the command: */
1832 m_frame->PutDataInPreviousState( list );
1833
1834 /* Put the old list in UndoList */
1835 list->ReversePickersListOrder();
1836 m_frame->PushCommandToUndoList( list );
1837
1838 m_toolMgr->GetTool<SCH_SELECTION_TOOL>()->RebuildSelection();
1839
1840 m_frame->GetCanvas()->Refresh();
1841 m_frame->OnModify();
1842
1843 return 0;
1844}
1845
1846
1847bool SCH_EDITOR_CONTROL::doCopy( bool aUseDuplicateClipboard )
1848{
1849 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
1850 SCH_SELECTION& selection = selTool->RequestSelection();
1851 SCHEMATIC& schematic = m_frame->Schematic();
1852
1853 if( selection.Empty() )
1854 return false;
1855
1856 if( aUseDuplicateClipboard )
1857 m_duplicateIsHoverSelection = selection.IsHover();
1858
1859 selection.SetScreen( m_frame->GetScreen() );
1861
1862 for( EDA_ITEM* item : selection.GetItems() )
1863 {
1864 if( item->Type() == SCH_SHEET_T )
1865 {
1866 SCH_SHEET* sheet = (SCH_SHEET*) item;
1867 m_supplementaryClipboard[sheet->GetFileName()] = sheet->GetScreen();
1868 }
1869 else if( item->Type() == SCH_FIELD_T && selection.IsHover() )
1870 {
1871 // Most of the time the user is trying to duplicate the parent symbol
1872 // and the field text is in it
1873 selection.Add( item->GetParent() );
1874 }
1875 else if( item->Type() == SCH_MARKER_T )
1876 {
1877 // Don't let the markers be copied
1878 selection.Remove( item );
1879 }
1880 else if( item->Type() == SCH_GROUP_T )
1881 {
1882 // Groups need to have all their items selected
1883 static_cast<SCH_ITEM*>( item )->RunOnChildren(
1884 [&]( EDA_ITEM* aChild )
1885 {
1886 selection.Add( aChild );
1887 },
1889 }
1890 }
1891
1892 bool result = true;
1893 STRING_FORMATTER formatter;
1894 SCH_IO_KICAD_SEXPR plugin;
1895 SCH_SHEET_PATH selPath = m_frame->GetCurrentSheet();
1896
1897 plugin.Format( &selection, &selPath, schematic, &formatter, true );
1898
1899 std::string prettyData = formatter.GetString();
1900 KICAD_FORMAT::Prettify( prettyData, KICAD_FORMAT::FORMAT_MODE::COMPACT_TEXT_PROPERTIES );
1901
1902 if( !aUseDuplicateClipboard )
1903 {
1904 wxLogNull doNotLog; // disable logging of failed clipboard actions
1905
1906 result &= wxTheClipboard->Open();
1907
1908 if( result )
1909 {
1910 wxDataObjectComposite* data = new wxDataObjectComposite();
1911
1912 // Add KiCad data
1913 wxCustomDataObject* kicadObj = new wxCustomDataObject( wxDataFormat( "application/kicad" ) );
1914 kicadObj->SetData( prettyData.size(), prettyData.data() );
1915 data->Add( kicadObj );
1916
1917 BOX2I selectionBox = expandedSelectionBox( selection );
1918
1919 if( selectionBox.GetWidth() > 0 && selectionBox.GetHeight() > 0 )
1920 {
1921 // Add bitmap data (encoded once, used for both PNG clipboard and HTML)
1922 wxImage image = renderSelectionToImageForClipboard( m_frame, selection, selectionBox, true, false );
1923 wxMemoryBuffer pngBuffer;
1924
1925 if( image.IsOk() && EncodeImageToPng( image, pngBuffer ) )
1926 {
1927 AddPngToClipboardData( data, pngBuffer, &image );
1928
1929 // Add HTML with embedded base64 PNG for pasting into documents
1930 wxMemoryBuffer htmlBuffer;
1931
1932 if( generateHtmlFromPngData( pngBuffer, htmlBuffer ) )
1933 {
1934 wxCustomDataObject* htmlObj = new wxCustomDataObject( wxDF_HTML );
1935 htmlObj->SetData( htmlBuffer.GetDataLen(), htmlBuffer.GetData() );
1936 data->Add( htmlObj );
1937 }
1938 }
1939
1940 // Add SVG data
1941 wxMemoryBuffer svgBuffer;
1942
1943 if( plotSelectionToSvg( m_frame, selection, selectionBox, svgBuffer ) )
1944 {
1945 wxCustomDataObject* svgObj = new wxCustomDataObject( wxDataFormat( "image/svg+xml" ) );
1946 svgObj->SetData( svgBuffer.GetDataLen(), svgBuffer.GetData() );
1947 data->Add( svgObj );
1948 }
1949 }
1950
1951 // Finally add text data
1952 data->Add( new wxTextDataObject( wxString::FromUTF8( prettyData ) ) );
1953
1954 result &= wxTheClipboard->SetData( data );
1955 result &= wxTheClipboard->Flush(); // Allow data to be available after closing KiCad
1956 wxTheClipboard->Close();
1957 }
1958 }
1959
1960 if( selection.IsHover() )
1961 m_toolMgr->RunAction( ACTIONS::selectionClear );
1962
1963 if( aUseDuplicateClipboard )
1964 {
1965 m_duplicateClipboard = prettyData;
1966 return true;
1967 }
1968
1969 return result;
1970}
1971
1972
1973bool SCH_EDITOR_CONTROL::searchSupplementaryClipboard( const wxString& aSheetFilename, SCH_SCREEN** aScreen )
1974{
1975 if( m_supplementaryClipboard.count( aSheetFilename ) > 0 )
1976 {
1977 *aScreen = m_supplementaryClipboard[aSheetFilename];
1978 return true;
1979 }
1980
1981 return false;
1982}
1983
1984
1986{
1987 doCopy( true ); // Use the local clipboard
1988 Paste( aEvent );
1989
1990 return 0;
1991}
1992
1993
1995{
1996 wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( wxWindow::FindFocus() );
1997
1998 if( textEntry )
1999 {
2000 textEntry->Cut();
2001 return 0;
2002 }
2003
2004 if( doCopy() )
2005 m_toolMgr->RunAction( ACTIONS::doDelete );
2006
2007 return 0;
2008}
2009
2010
2012{
2013 wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( wxWindow::FindFocus() );
2014
2015 if( textEntry )
2016 {
2017 textEntry->Copy();
2018 return 0;
2019 }
2020
2021 doCopy();
2022
2023 return 0;
2024}
2025
2026
2028{
2029 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
2030 SCH_SELECTION& selection = selTool->RequestSelection();
2031
2032 if( selection.Empty() )
2033 return false;
2034
2035 wxString itemsAsText = GetSelectedItemsAsText( selection );
2036
2037 if( selection.IsHover() )
2038 m_toolMgr->RunAction( ACTIONS::selectionClear );
2039
2040 return SaveClipboard( itemsAsText.ToStdString() );
2041}
2042
2043
2045 const KIID_PATH& aClipPath, bool aForceKeepAnnotations )
2046{
2047 wxCHECK( m_frame && aSymbol, /* void */ );
2048
2049 SCH_SYMBOL_INSTANCE newInstance;
2050 bool instanceFound = false;
2051 KIID_PATH pasteLookupPath = aClipPath;
2052
2053 m_pastedSymbols.insert( aSymbol );
2054
2055 for( const SCH_SYMBOL_INSTANCE& tmp : aSymbol->GetInstances() )
2056 {
2057 if( ( tmp.m_Path.empty() && aClipPath.empty() ) || ( !aClipPath.empty() && tmp.m_Path.EndsWith( aClipPath ) ) )
2058 {
2059 newInstance = tmp;
2060 instanceFound = true;
2061
2062 wxLogTrace( traceSchPaste, wxS( "Pasting found symbol instance with reference %s, unit %d:\n"
2063 "\tClipboard path: %s\n"
2064 "\tSymbol UUID: %s." ),
2065 tmp.m_Reference,
2066 tmp.m_Unit,
2067 aClipPath.AsString(),
2068 aSymbol->m_Uuid.AsString() );
2069
2070 break;
2071 }
2072 }
2073
2074 // The pasted symbol look up paths include the symbol UUID.
2075 pasteLookupPath.push_back( aSymbol->m_Uuid );
2076
2077 if( !instanceFound )
2078 {
2079 wxLogTrace( traceSchPaste, wxS( "Clipboard symbol instance **not** found:\n\tClipboard path: %s\n"
2080 "\tSymbol UUID: %s." ),
2081 aClipPath.AsString(),
2082 aSymbol->m_Uuid.AsString() );
2083
2084 // Some legacy versions saved value fields escaped. While we still do in the symbol
2085 // editor, we don't anymore in the schematic, so be sure to unescape them.
2086 SCH_FIELD* valueField = aSymbol->GetField( FIELD_T::VALUE );
2087 valueField->SetText( UnescapeString( valueField->GetText() ) );
2088
2089 // Pasted from notepad or an older instance of eeschema. Use the values in the fields
2090 // instead.
2091 newInstance.m_Reference = aSymbol->GetField( FIELD_T::REFERENCE )->GetText();
2092 newInstance.m_Unit = aSymbol->GetUnit();
2093 }
2094
2095 newInstance.m_Path = aPastePath.Path();
2096 newInstance.m_ProjectName = m_frame->Prj().GetProjectName();
2097
2098 aSymbol->AddHierarchicalReference( newInstance );
2099
2100 if( !aForceKeepAnnotations )
2101 aSymbol->ClearAnnotation( &aPastePath, false );
2102
2103 // We might clear annotations but always leave the original unit number from the paste.
2104 aSymbol->SetUnit( newInstance.m_Unit );
2105}
2106
2107
2109 const KIID_PATH& aClipPath, bool aForceKeepAnnotations,
2110 SCH_SHEET_LIST* aPastedSheets, std::map<SCH_SHEET_PATH,
2111 SCH_REFERENCE_LIST>& aPastedSymbols )
2112{
2113 wxCHECK( aSheet && aPastedSheets, aPastePath );
2114
2115 SCH_SHEET_PATH sheetPath = aPastePath;
2116 sheetPath.push_back( aSheet );
2117
2118 aPastedSheets->push_back( sheetPath );
2119
2120 if( aSheet->GetScreen() == nullptr )
2121 return sheetPath; // We can only really set the page number but not load any items
2122
2123 bool isSharedPath = sheetPath.IsSharedPath();
2124
2125 for( SCH_ITEM* item : aSheet->GetScreen()->Items() )
2126 {
2127 if( item->IsConnectable() )
2128 item->SetConnectivityDirty();
2129
2130 if( item->Type() == SCH_SYMBOL_T )
2131 {
2132 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
2133
2134 wxCHECK2( symbol, continue );
2135
2136 // Only do this once if the symbol is shared across multiple sheets.
2137 if( !m_pastedSymbols.count( symbol ) )
2138 {
2139 if( !isSharedPath )
2140 const_cast<KIID&>( symbol->m_Uuid ) = KIID();
2141
2143 {
2144 // Only update the UUID if the symbol is not in a shared sheet.
2145 if( !isSharedPath )
2146 const_cast<KIID&>( pin->m_Uuid ) = KIID();
2147
2148 pin->SetConnectivityDirty();
2149 }
2150 }
2151
2152 updatePastedSymbol( symbol, sheetPath, aClipPath, aForceKeepAnnotations );
2153 }
2154 else if( item->Type() == SCH_SHEET_T )
2155 {
2156 SCH_SHEET* subsheet = static_cast<SCH_SHEET*>( item );
2157
2158 wxCHECK2( subsheet, continue );
2159
2160 // Make sure pins get a new UUID and set the dirty connectivity flag.
2161 if( !aPastedSheets->ContainsSheet( subsheet ) )
2162 {
2163 if( !isSharedPath )
2164 const_cast<KIID&>( subsheet->m_Uuid ) = KIID();
2165
2166 for( SCH_SHEET_PIN* pin : subsheet->GetPins() )
2167 {
2168 if( !isSharedPath )
2169 const_cast<KIID&>( pin->m_Uuid ) = KIID();
2170
2171 pin->SetConnectivityDirty();
2172 }
2173 }
2174
2175 KIID_PATH newClipPath = aClipPath;
2176 newClipPath.push_back( subsheet->m_Uuid );
2177
2178 updatePastedSheet( subsheet, sheetPath, newClipPath, aForceKeepAnnotations, aPastedSheets, aPastedSymbols );
2179 }
2180 }
2181
2182 sheetPath.GetSymbols( aPastedSymbols[aPastePath], SYMBOL_FILTER_ALL );
2183
2184 return sheetPath;
2185}
2186
2187
2189{
2190 wxCHECK( m_frame, /* void */ );
2191
2192 for( SCH_SYMBOL* symbol : m_pastedSymbols )
2193 {
2194 wxCHECK2( symbol, continue );
2195
2196 PrunePastedSymbolInstances( symbol, m_frame->Schematic() );
2197 }
2198}
2199
2200
2202 const SCH_SCREEN* aDestScreen,
2203 const wxString& aLibSymbolName )
2204{
2205 // The clipboard's cached library symbol is a matched pair with the pasted instance, so it
2206 // must win over the destination's same-named cache. Pasting from the destination cache would
2207 // silently remap the instance to a different definition and drop in-place edits such as
2208 // renumbered pins (issue 21401) or a changed power type (issue 22162). Fall back to the
2209 // destination cache only when the clipboard carries no copy.
2210 if( aClipboardScreen )
2211 {
2212 auto clipIt = aClipboardScreen->GetLibSymbols().find( aLibSymbolName );
2213
2214 if( clipIt != aClipboardScreen->GetLibSymbols().end() )
2215 return clipIt->second;
2216 }
2217
2218 if( aDestScreen )
2219 {
2220 auto destIt = aDestScreen->GetLibSymbols().find( aLibSymbolName );
2221
2222 if( destIt != aDestScreen->GetLibSymbols().end() )
2223 return destIt->second;
2224 }
2225
2226 return nullptr;
2227}
2228
2229
2231{
2232 wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( wxWindow::FindFocus() );
2233
2234 if( textEntry )
2235 {
2236 textEntry->Paste();
2237 return 0;
2238 }
2239
2240 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
2241 std::string content;
2242 VECTOR2I eventPos;
2243
2244 SCH_SHEET tempSheet;
2245
2246 // Priority for paste:
2247 // 1. application/kicad format (handled by GetClipboardUTF8 which checks this first)
2248 // 2. Text data that can be parsed as KiCad S-expressions
2249 // 3. Bitmap/image data (fallback only if no valid text content)
2250 if( aEvent.IsAction( &ACTIONS::duplicate ) )
2251 content = m_duplicateClipboard;
2252 else
2253 content = GetClipboardUTF8();
2254
2255 // Only fall back to image data if there's no text content
2256 if( content.empty() )
2257 {
2258 std::unique_ptr<wxBitmap> clipImg = GetImageFromClipboard();
2259
2260 if( clipImg )
2261 {
2262 auto bitmap = std::make_unique<SCH_BITMAP>();
2263
2264 if( bitmap->GetReferenceImage().SetImage( clipImg->ConvertToImage() ) )
2265 return m_toolMgr->RunAction( SCH_ACTIONS::placeImage, bitmap.release() );
2266 }
2267
2268 return 0;
2269 }
2270
2271 if( aEvent.IsAction( &ACTIONS::duplicate ) )
2272 eventPos = getViewControls()->GetCursorPosition( false );
2273
2274 STRING_LINE_READER reader( content, "Clipboard" );
2275 SCH_IO_KICAD_SEXPR plugin;
2276
2277 // Screen object on heap is owned by the sheet.
2278 SCH_SCREEN* tempScreen = new SCH_SCREEN( &m_frame->Schematic() );
2279 tempSheet.SetScreen( tempScreen );
2280
2281 try
2282 {
2283 plugin.LoadContent( reader, &tempSheet );
2284 }
2285 catch( IO_ERROR& )
2286 {
2287 // If it wasn't schematic content, paste as a text object
2288 {
2289 if( content.size() > static_cast<size_t>( ADVANCED_CFG::GetCfg().m_MaxPastedTextLength ) )
2290 {
2291 int result = IsOK( m_frame, _( "Pasting a long text text string may be very slow. "
2292 "Do you want to continue?" ) );
2293 if( !result )
2294 return 0;
2295 }
2296
2297 SCH_TEXT* text_item = new SCH_TEXT( VECTOR2I( 0, 0 ), content );
2298 tempScreen->Append( text_item );
2299 }
2300 }
2301
2302 SELECTION& currentSelection = selTool->GetSelection();
2303
2304 bool hasTableCells = false;
2305
2306 for( EDA_ITEM* item : currentSelection )
2307 {
2308 if( item->Type() == SCH_TABLECELL_T )
2309 {
2310 hasTableCells = true;
2311 break;
2312 }
2313 }
2314
2315 if( hasTableCells )
2316 {
2317 SCH_TABLE* clipboardTable = nullptr;
2318
2319 for( SCH_ITEM* item : tempScreen->Items() )
2320 {
2321 if( item->Type() == SCH_TABLE_T )
2322 {
2323 clipboardTable = static_cast<SCH_TABLE*>( item );
2324 break;
2325 }
2326 }
2327
2328 if( clipboardTable )
2329 {
2330 SCH_EDIT_TABLE_TOOL* tableEditTool = m_toolMgr->GetTool<SCH_EDIT_TABLE_TOOL>();
2331
2332 if( tableEditTool )
2333 {
2334 wxString errorMsg;
2335
2336 if( !tableEditTool->validatePasteIntoSelection( currentSelection, errorMsg ) )
2337 {
2338 DisplayError( m_frame, errorMsg );
2339 return 0;
2340 }
2341
2342 SCH_COMMIT commit( m_toolMgr );
2343
2344 if( tableEditTool->pasteCellsIntoSelection( currentSelection, clipboardTable, commit ) )
2345 {
2346 commit.Push( _( "Paste Cells" ) );
2347 return 0;
2348 }
2349 else
2350 {
2351 DisplayError( m_frame, _( "Failed to paste cells" ) );
2352 return 0;
2353 }
2354 }
2355 }
2356 }
2357
2358 m_pastedSymbols.clear();
2359
2360 tempScreen->MigrateSimModels();
2361
2362 bool annotateAutomatic = m_frame->eeconfig()->m_AnnotatePanel.automatic;
2363 SCHEMATIC_SETTINGS& schematicSettings = m_frame->Schematic().Settings();
2364 int annotateStartNum = schematicSettings.m_AnnotateStartNum;
2365
2367 bool forceRemoveAnnotations = false;
2368
2369 if( aEvent.IsAction( &ACTIONS::pasteSpecial ) )
2370 {
2371 PASTE_MODE defaultPasteMode = pasteMode;
2372 DIALOG_PASTE_SPECIAL dlg( m_frame, &pasteMode );
2373
2374 if( dlg.ShowModal() == wxID_CANCEL )
2375 return 0;
2376
2377 // We have to distinguish if removing was explicit
2378 forceRemoveAnnotations = pasteMode == PASTE_MODE::REMOVE_ANNOTATIONS && pasteMode != defaultPasteMode;
2379 }
2380
2381 bool forceKeepAnnotations = pasteMode != PASTE_MODE::REMOVE_ANNOTATIONS;
2382
2383 // SCH_SEXP_PLUGIN added the items to the paste screen, but not to the view or anything
2384 // else. Pull them back out to start with.
2385 SCH_COMMIT commit( m_toolMgr );
2386 EDA_ITEMS loadedItems;
2387 std::vector<SCH_ITEM*> sortedLoadedItems;
2388 bool sheetsPasted = false;
2389 SCH_SHEET_LIST hierarchy = m_frame->Schematic().Hierarchy();
2390 SCH_SHEET_PATH& pasteRoot = m_frame->GetCurrentSheet();
2391 wxFileName destFn = pasteRoot.Last()->GetFileName();
2392
2393 if( destFn.IsRelative() )
2394 destFn.MakeAbsolute( m_frame->Prj().GetProjectPath() );
2395
2396 // List of paths in the hierarchy that refer to the destination sheet of the paste
2397 SCH_SHEET_LIST sheetPathsForScreen = hierarchy.FindAllSheetsForScreen( pasteRoot.LastScreen() );
2398 sheetPathsForScreen.SortByPageNumbers();
2399
2400 // Build a list of screens from the current design (to avoid loading sheets that already exist)
2401 std::map<wxString, SCH_SCREEN*> loadedScreens;
2402
2403 for( const SCH_SHEET_PATH& item : hierarchy )
2404 {
2405 if( item.LastScreen() )
2406 loadedScreens[item.Last()->GetFileName()] = item.LastScreen();
2407 }
2408
2409 // Get set of sheet names in the current schematic to prevent duplicate sheet names on paste.
2410 std::set<wxString> existingSheetNames = pasteRoot.LastScreen()->GetSheetNames();
2411
2412 // Build symbol list for reannotation of duplicates
2413 SCH_REFERENCE_LIST existingRefs;
2414 hierarchy.GetSymbols( existingRefs, SYMBOL_FILTER_ALL );
2415 existingRefs.SortByReferenceOnly();
2416
2417 std::set<wxString> existingRefsSet;
2418
2419 for( const SCH_REFERENCE& ref : existingRefs )
2420 existingRefsSet.insert( ref.GetRef() );
2421
2422 // Build UUID map for fetching last-resolved-properties
2423 std::unordered_map<KIID, EDA_ITEM*> itemMap;
2424 hierarchy.FillItemMap( itemMap );
2425
2426 // Keep track of pasted sheets and symbols for the different paths to the hierarchy.
2427 std::map<SCH_SHEET_PATH, SCH_REFERENCE_LIST> pastedSymbols;
2428 std::map<SCH_SHEET_PATH, SCH_SHEET_LIST> pastedSheets;
2429
2430 for( SCH_ITEM* item : tempScreen->Items() )
2431 {
2432 if( item->Type() == SCH_SHEET_T )
2433 sortedLoadedItems.push_back( item );
2434 else
2435 loadedItems.push_back( item );
2436 }
2437
2438 sort( sortedLoadedItems.begin(), sortedLoadedItems.end(),
2439 []( SCH_ITEM* firstItem, SCH_ITEM* secondItem )
2440 {
2441 SCH_SHEET* firstSheet = static_cast<SCH_SHEET*>( firstItem );
2442 SCH_SHEET* secondSheet = static_cast<SCH_SHEET*>( secondItem );
2443 return StrNumCmp( firstSheet->GetName(), secondSheet->GetName(), false ) < 0;
2444 } );
2445
2446
2447 for( SCH_ITEM* item : sortedLoadedItems )
2448 {
2449 loadedItems.push_back( item );
2450
2451 if( item->Type() == SCH_SHEET_T )
2452 {
2453 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
2454 wxFileName srcFn = sheet->GetFileName();
2455
2456 if( srcFn.IsRelative() )
2457 srcFn.MakeAbsolute( m_frame->Prj().GetProjectPath() );
2458
2459 SCH_SHEET_LIST sheetHierarchy( sheet );
2460
2461 if( hierarchy.TestForRecursion( sheetHierarchy, destFn.GetFullPath( wxPATH_UNIX ) ) )
2462 {
2463 auto msg = wxString::Format( _( "The pasted sheet '%s'\n"
2464 "was dropped because the destination already has "
2465 "the sheet or one of its subsheets as a parent." ),
2466 sheet->GetFileName() );
2467 DisplayError( m_frame, msg );
2468 loadedItems.pop_back();
2469 }
2470 }
2471 }
2472
2473 // Remove the references from our temporary screen to prevent freeing on the DTOR
2474 tempScreen->Clear( false );
2475
2476 for( EDA_ITEM* item : loadedItems )
2477 {
2478 KIID_PATH clipPath( wxT( "/" ) ); // clipboard is at root
2479
2480 SCH_ITEM* schItem = static_cast<SCH_ITEM*>( item );
2481
2482 wxCHECK2( schItem, continue );
2483
2484 if( schItem->IsConnectable() )
2485 schItem->SetConnectivityDirty();
2486
2487 // Clear lock state on paste to match PCB editor behavior
2488 schItem->SetLocked( false );
2489
2490 if( item->Type() == SCH_SYMBOL_T )
2491 {
2492 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
2493
2494 SCH_SCREEN* currentScreen = m_frame->GetScreen();
2495
2496 wxCHECK2( currentScreen, continue );
2497
2498 const LIB_SYMBOL* source = ChoosePasteLibSymbol( tempScreen, currentScreen,
2499 symbol->GetSchSymbolLibraryName() );
2500
2501 if( source )
2502 symbol->SetLibSymbol( new LIB_SYMBOL( *source ) );
2503
2504 for( const LIB_ID& alternate : symbol->GetVariantSymbolOverrides() )
2505 {
2506 wxString key = alternate.Format().wx_str();
2507 auto it = tempScreen->GetLibSymbols().find( key );
2508
2509 if( it != tempScreen->GetLibSymbols().end() && it->second
2510 && !currentScreen->GetLibSymbols().contains( key ) )
2511 currentScreen->AddLibSymbol( key, it->second->Flatten() );
2512 }
2513
2514 // If the symbol is already in the schematic we have to always keep the annotations. The exception
2515 // is if the user has chosen to remove them.
2516 for( const SCH_SYMBOL_INSTANCE& instance : symbol->GetInstances() )
2517 {
2518 if( !existingRefsSet.contains( instance.m_Reference ) )
2519 {
2520 forceKeepAnnotations = !forceRemoveAnnotations;
2521 break;
2522 }
2523 }
2524
2525 for( SCH_SHEET_PATH& sheetPath : sheetPathsForScreen )
2526 updatePastedSymbol( symbol, sheetPath, clipPath, forceKeepAnnotations );
2527
2528 // Most modes will need new KIIDs for the symbol and its pins. However, if we are pasting
2529 // unique annotations, we need to check if the symbol is not already in the hierarchy. If we
2530 // don't already have a copy of the symbol, we just keep the existing KIID data as it is likely
2531 // the same symbol being moved around the schematic.
2532 bool needsNewKiid = ( pasteMode == PASTE_MODE::UNIQUE_ANNOTATIONS );
2533
2534 for( const SCH_SYMBOL_INSTANCE& instance : symbol->GetInstances() )
2535 {
2536 if( existingRefsSet.contains( instance.m_Reference ) )
2537 {
2538 needsNewKiid = true;
2539 break;
2540 }
2541 }
2542
2543 if( needsNewKiid )
2544 {
2545 // Assign a new KIID
2546 const_cast<KIID&>( item->m_Uuid ) = KIID();
2547
2548 // Make sure pins get a new UUID
2550 {
2551 const_cast<KIID&>( pin->m_Uuid ) = KIID();
2552 pin->SetConnectivityDirty();
2553 }
2554
2555 for( SCH_SHEET_PATH& sheetPath : sheetPathsForScreen )
2556 {
2557 // Ignore symbols from a non-existant library.
2558 if( source )
2559 {
2560 SCH_REFERENCE schReference( symbol, sheetPath );
2561 schReference.SetSheetNumber( sheetPath.GetPageNumberAsInt() );
2562 pastedSymbols[sheetPath].AddItem( schReference );
2563 }
2564 }
2565 }
2566 }
2567 else if( item->Type() == SCH_SHEET_T )
2568 {
2569 SCH_SHEET* sheet = (SCH_SHEET*) item;
2570 SCH_FIELD* nameField = sheet->GetField( FIELD_T::SHEET_NAME );
2571 wxString baseName = nameField->GetText();
2572 wxString candidateName = baseName;
2573 wxString number;
2574
2575 while( !baseName.IsEmpty() && wxIsdigit( baseName.Last() ) )
2576 {
2577 number = baseName.Last() + number;
2578 baseName.RemoveLast();
2579 }
2580
2581 // Update hierarchy to include any other sheets we already added, avoiding
2582 // duplicate sheet names
2583 hierarchy = m_frame->Schematic().Hierarchy();
2584
2585 int uniquifier = std::max( 0, wxAtoi( number ) ) + 1;
2586
2587 while( existingSheetNames.count( candidateName ) )
2588 candidateName = wxString::Format( wxT( "%s%d" ), baseName, uniquifier++ );
2589
2590 nameField->SetText( candidateName );
2591 existingSheetNames.emplace( candidateName );
2592
2593 wxFileName fn = sheet->GetFileName();
2594 SCH_SCREEN* existingScreen = nullptr;
2595
2596 sheet->SetParent( pasteRoot.Last() );
2597 sheet->SetScreen( nullptr );
2598
2599 if( !fn.IsAbsolute() )
2600 {
2601 wxFileName currentSheetFileName = pasteRoot.LastScreen()->GetFileName();
2602 fn.Normalize( FN_NORMALIZE_FLAGS | wxPATH_NORM_ENV_VARS, currentSheetFileName.GetPath() );
2603 }
2604
2605 // Try to find the screen for the pasted sheet by several means
2606 if( !m_frame->Schematic().Root().SearchHierarchy( fn.GetFullPath( wxPATH_UNIX ), &existingScreen ) )
2607 {
2608 if( loadedScreens.count( sheet->GetFileName() ) > 0 )
2609 existingScreen = loadedScreens.at( sheet->GetFileName() );
2610 else
2611 searchSupplementaryClipboard( sheet->GetFileName(), &existingScreen );
2612 }
2613
2614 if( existingScreen )
2615 {
2616 sheet->SetScreen( existingScreen );
2617 }
2618 else
2619 {
2620 if( !m_frame->LoadSheetFromFile( sheet, &pasteRoot, fn.GetFullPath() ) )
2621 m_frame->InitSheet( sheet, sheet->GetFileName() );
2622 }
2623
2624 sheetsPasted = true;
2625
2626 // Push it to the clipboard path while it still has its old KIID
2627 clipPath.push_back( sheet->m_Uuid );
2628
2629 // Assign a new KIID to the pasted sheet
2630 const_cast<KIID&>( sheet->m_Uuid ) = KIID();
2631
2632 // Make sure pins get a new UUID
2633 for( SCH_SHEET_PIN* pin : sheet->GetPins() )
2634 {
2635 const_cast<KIID&>( pin->m_Uuid ) = KIID();
2636 pin->SetConnectivityDirty();
2637 }
2638
2639 // Once we have our new KIID we can update all pasted instances. This will either
2640 // reset the annotations or copy "kept" annotations from the supplementary clipboard.
2641 for( SCH_SHEET_PATH& sheetPath : sheetPathsForScreen )
2642 {
2643 SCH_SHEET_PATH subPath = updatePastedSheet( sheet, sheetPath, clipPath,
2644 ( forceKeepAnnotations && annotateAutomatic ),
2645 &pastedSheets[sheetPath], pastedSymbols );
2646 }
2647 }
2648 else
2649 {
2650 SCH_ITEM* srcItem = dynamic_cast<SCH_ITEM*>( itemMap[item->m_Uuid] );
2651 SCH_ITEM* destItem = dynamic_cast<SCH_ITEM*>( item );
2652
2653 // Everything gets a new KIID
2654 const_cast<KIID&>( item->m_Uuid ) = KIID();
2655
2656 if( srcItem && destItem )
2657 {
2658 destItem->SetConnectivityDirty( true );
2659 destItem->SetLastResolvedState( srcItem );
2660 }
2661
2662 // Pasted named groups need a unique name, the multichannel tool matches groups by name.
2663 if( item->Type() == SCH_GROUP_T )
2664 {
2665 SCH_GROUP* group = static_cast<SCH_GROUP*>( item );
2666
2667 if( !group->GetName().IsEmpty() )
2668 group->SetName( UniqueGroupName( m_frame->GetScreen(), group->GetName() ) );
2669 }
2670 }
2671
2672 // Lines need both ends selected for a move after paste so the whole line moves.
2673 if( item->Type() == SCH_LINE_T )
2674 item->SetFlags( STARTPOINT | ENDPOINT );
2675
2676 item->SetFlags( IS_NEW | IS_PASTED | IS_MOVING );
2677
2678 if( !m_frame->GetScreen()->CheckIfOnDrawList( (SCH_ITEM*) item ) ) // don't want a loop!
2679 m_frame->AddToScreen( item, m_frame->GetScreen() );
2680
2681 commit.Added( (SCH_ITEM*) item, m_frame->GetScreen() );
2682
2683 // Start out hidden so the pasted items aren't "ghosted" in their original location
2684 // before being moved to the current location.
2685 getView()->Hide( item, true );
2686 }
2687
2688 if( sheetsPasted )
2689 {
2690 // The full schematic hierarchy need to be update before assigning new annotation and page numbers.
2691 m_frame->Schematic().RefreshHierarchy();
2692
2693 // Update sheet instance page and virtual page numbers to ensure annotation works correctly.
2694 for( SCH_SHEET_PATH& sheetPath : sheetPathsForScreen )
2695 {
2696 for( SCH_SHEET_PATH& pastedSheet : pastedSheets[sheetPath] )
2697 {
2698 // Find next free string page number for the sheet instance.
2699 int page = 1;
2700 wxString pageNum = wxString::Format( "%d", page );
2701
2702 while( hierarchy.PageNumberExists( pageNum ) )
2703 pageNum = wxString::Format( "%d", ++page );
2704
2705 int virtualPageNumber = page;
2706
2707 // The virtual page and sheet instance page numbers do not necessarily track. Increment by one
2708 // to ensure the annotation sheet paths all have unique virtual page numbers.
2709 if( page == hierarchy.GetLastVirtualPageNumber() )
2710 virtualPageNumber = hierarchy.GetLastVirtualPageNumber() + 1;
2711
2712 pastedSheet.SetVirtualPageNumber( virtualPageNumber );
2713
2714 SCH_SHEET_INSTANCE sheetInstance;
2715
2716 sheetInstance.m_Path = pastedSheet.Path();
2717
2718 // Don't include the actual sheet in the instance path.
2719 sheetInstance.m_Path.pop_back();
2720 sheetInstance.m_PageNumber = pageNum;
2721 sheetInstance.m_ProjectName = m_frame->Prj().GetProjectName();
2722
2723 SCH_SHEET* sheet = pastedSheet.Last();
2724
2725 wxCHECK2( sheet, continue );
2726
2727 sheet->AddInstance( sheetInstance );
2728 hierarchy.push_back( pastedSheet );
2729
2730 // Remove all pasted sheet instance data that is not part of the current project.
2731 std::vector<KIID_PATH> instancesToRemove;
2732
2733 for( const SCH_SHEET_INSTANCE& instance : sheet->GetInstances() )
2734 {
2735 if( !hierarchy.HasPath( instance.m_Path ) )
2736 instancesToRemove.push_back( instance.m_Path );
2737 }
2738
2739 for( const KIID_PATH& instancePath : instancesToRemove )
2740 sheet->RemoveInstance( instancePath );
2741
2742 // The sheet paths for the annotation code where copied in updatePastedSheets() when the virtual
2743 // page number was still 1. Set the virtual page number in the copied sheet paths.
2744 for( auto&[path, refs] : pastedSymbols )
2745 {
2746 for( SCH_REFERENCE& ref : refs )
2747 {
2748 if( ref.GetSheetPath() == pastedSheet )
2749 {
2750 ref.GetSheetPath().SetVirtualPageNumber( virtualPageNumber );
2751 ref.SetSheetNumber( virtualPageNumber );
2752 }
2753 }
2754 }
2755 }
2756 }
2757
2758 m_frame->SetSheetNumberAndCount();
2759
2760 // Get a version with correct sheet numbers since we've pasted sheets,
2761 // we'll need this when annotating next
2762 hierarchy = m_frame->Schematic().Hierarchy();
2763 }
2764
2765 std::map<SCH_SHEET_PATH, SCH_REFERENCE_LIST> annotatedSymbols;
2766
2767 // Update the list of symbol instances that satisfy the annotation criteria.
2768 for( const SCH_SHEET_PATH& sheetPath : sheetPathsForScreen )
2769 {
2770 for( size_t i = 0; i < pastedSymbols[sheetPath].GetCount(); i++ )
2771 {
2772 if( pasteMode == PASTE_MODE::UNIQUE_ANNOTATIONS || pastedSymbols[sheetPath][i].AlwaysAnnotate() )
2773 annotatedSymbols[sheetPath].AddItem( pastedSymbols[sheetPath][i] );
2774 }
2775
2776 for( const SCH_SHEET_PATH& pastedSheetPath : pastedSheets[sheetPath] )
2777 {
2778 for( size_t i = 0; i < pastedSymbols[pastedSheetPath].GetCount(); i++ )
2779 {
2780 if( pasteMode == PASTE_MODE::UNIQUE_ANNOTATIONS || pastedSymbols[pastedSheetPath][i].AlwaysAnnotate() )
2781 annotatedSymbols[pastedSheetPath].AddItem( pastedSymbols[pastedSheetPath][i] );
2782 }
2783 }
2784 }
2785
2786 if( !annotatedSymbols.empty() )
2787 {
2788 ANNOTATE_ORDER_T annotateOrder = static_cast<ANNOTATE_ORDER_T>( schematicSettings.m_AnnotateSortOrder );
2789 ANNOTATE_ALGO_T annotateAlgo = static_cast<ANNOTATE_ALGO_T>( schematicSettings.m_AnnotateMethod );
2790
2791 for( SCH_SHEET_PATH& path : sheetPathsForScreen )
2792 {
2793 annotatedSymbols[path].SortByReferenceOnly();
2794 annotatedSymbols[path].SetRefDesTracker( schematicSettings.m_refDesTracker );
2795
2796 if( pasteMode == PASTE_MODE::UNIQUE_ANNOTATIONS )
2797 {
2798 annotatedSymbols[path].ReannotateDuplicates( existingRefs, annotateAlgo );
2799 }
2800 else
2801 {
2802 annotatedSymbols[path].ReannotateByOptions( annotateOrder, annotateAlgo, annotateStartNum,
2803 existingRefs, false, &hierarchy );
2804 }
2805
2806 annotatedSymbols[path].UpdateAnnotation();
2807
2808 // Update existing refs for next iteration
2809 for( size_t i = 0; i < annotatedSymbols[path].GetCount(); i++ )
2810 existingRefs.AddItem( annotatedSymbols[path][i] );
2811
2812 for( const SCH_SHEET_PATH& pastedSheetPath : pastedSheets[path] )
2813 {
2814 annotatedSymbols[pastedSheetPath].SortByReferenceOnly();
2815 annotatedSymbols[pastedSheetPath].SetRefDesTracker( schematicSettings.m_refDesTracker );
2816
2817 if( pasteMode == PASTE_MODE::UNIQUE_ANNOTATIONS )
2818 {
2819 annotatedSymbols[pastedSheetPath].ReannotateDuplicates( existingRefs, annotateAlgo );
2820 }
2821 else
2822 {
2823 annotatedSymbols[pastedSheetPath].ReannotateByOptions( annotateOrder, annotateAlgo,
2824 annotateStartNum, existingRefs,
2825 false, &hierarchy );
2826 }
2827
2828 annotatedSymbols[pastedSheetPath].UpdateAnnotation();
2829
2830 // Update existing refs for next iteration
2831 for( size_t i = 0; i < annotatedSymbols[pastedSheetPath].GetCount(); i++ )
2832 existingRefs.AddItem( annotatedSymbols[pastedSheetPath][i] );
2833 }
2834 }
2835 }
2836
2837 m_frame->GetCurrentSheet().UpdateAllScreenReferences();
2838
2839 // The copy operation creates instance paths that are not valid for the current project or
2840 // saved as part of another project. Prune them now so they do not accumulate in the saved
2841 // schematic file.
2843
2844 SCH_SHEET_LIST sheets = m_frame->Schematic().Hierarchy();
2845 SCH_SCREENS allScreens( m_frame->Schematic().Root() );
2846
2847 allScreens.PruneOrphanedSymbolInstances( m_frame->Prj().GetProjectName(), sheets );
2848 allScreens.PruneOrphanedSheetInstances( m_frame->Prj().GetProjectName(), sheets );
2849
2850 // Now clear the previous selection, select the pasted items, and fire up the "move" tool.
2851 m_toolMgr->RunAction( ACTIONS::selectionClear );
2852
2853 // If the item has a parent group, it will be part of the loadedItems, and will handle
2854 // the move action. Iterate backwards to avoid invalidating the iterator.
2855 for( int i = loadedItems.size() - 1; i >= 0; i-- )
2856 {
2857 EDA_ITEM* item = loadedItems[i];
2858
2859 if( item->GetParentGroup() )
2860 {
2861 loadedItems.erase( loadedItems.begin() + i );
2862 // These were hidden before because they would be added to the move preview,
2863 // but now they need to be shown as a preview so they appear to move when
2864 // the group moves.
2865 getView()->SetVisible( item );
2866 getView()->AddToPreview( item, false );
2867 }
2868 }
2869
2870 m_toolMgr->RunAction<EDA_ITEMS*>( ACTIONS::selectItems, &loadedItems );
2871
2872 SCH_SELECTION& selection = selTool->GetSelection();
2873
2874 if( !selection.Empty() )
2875 {
2876 if( aEvent.IsAction( &ACTIONS::duplicate ) )
2877 {
2878 int closest_dist = INT_MAX;
2879
2880 auto processPt =
2881 [&]( const VECTOR2I& pt )
2882 {
2883 int dist = ( eventPos - pt ).EuclideanNorm();
2884
2885 if( dist < closest_dist )
2886 {
2887 selection.SetReferencePoint( pt );
2888 closest_dist = dist;
2889 }
2890 };
2891
2892 std::vector<SCH_ITEM*> anchorCandidates = FlattenGroups( selection.Items() );
2893
2894 // Prefer connection points (which should remain on grid)
2895 for( EDA_ITEM* item : anchorCandidates )
2896 {
2897 SCH_ITEM* sch_item = dynamic_cast<SCH_ITEM*>( item );
2898 SCH_PIN* pin = dynamic_cast<SCH_PIN*>( item );
2899
2900 if( sch_item && sch_item->IsConnectable() )
2901 {
2902 for( const VECTOR2I& pt : sch_item->GetConnectionPoints() )
2903 processPt( pt );
2904 }
2905 else if( pin )
2906 {
2907 processPt( pin->GetPosition() );
2908 }
2909
2910 // Symbols need to have their center point added since often users are trying to
2911 // move parts from their center.
2912 if( dynamic_cast<SCH_SYMBOL*>( item ) )
2913 processPt( item->GetPosition() );
2914 }
2915
2916 // Only process other points if we didn't find any connection points
2917 if( closest_dist == INT_MAX )
2918 {
2919 for( EDA_ITEM* item : anchorCandidates )
2920 {
2921 switch( item->Type() )
2922 {
2923 // A group's position is its bounding box centre, which is off grid
2924 case SCH_GROUP_T: break;
2925
2926 case SCH_LINE_T:
2927 processPt( static_cast<SCH_LINE*>( item )->GetStartPoint() );
2928 processPt( static_cast<SCH_LINE*>( item )->GetEndPoint() );
2929 break;
2930
2931 case SCH_SHAPE_T:
2932 {
2933 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( item );
2934
2935 switch( shape->GetShape() )
2936 {
2937 case SHAPE_T::RECTANGLE:
2938 for( const VECTOR2I& pt : shape->GetRectCorners() )
2939 processPt( pt );
2940
2941 break;
2942
2943 case SHAPE_T::CIRCLE:
2944 processPt( shape->GetCenter() );
2945 break;
2946
2947 case SHAPE_T::POLY:
2948 for( int ii = 0; ii < shape->GetPolyShape().TotalVertices(); ++ii )
2949 processPt( shape->GetPolyShape().CVertex( ii ) );
2950
2951 break;
2952
2953 default:
2954 processPt( shape->GetStart() );
2955 processPt( shape->GetEnd() );
2956 break;
2957 }
2958
2959 break;
2960 }
2961
2962 default:
2963 processPt( item->GetPosition() );
2964 break;
2965 }
2966 }
2967 }
2968
2969 selection.SetIsHover( m_duplicateIsHoverSelection );
2970 }
2971 // We want to the first non-group item in the selection to be the reference point.
2972 else if( selection.GetTopLeftItem()->Type() == SCH_GROUP_T )
2973 {
2974 SCH_GROUP* group = static_cast<SCH_GROUP*>( selection.GetTopLeftItem() );
2975
2976 bool found = false;
2977 SCH_ITEM* item = nullptr;
2978
2979 group->RunOnChildren(
2980 [&]( SCH_ITEM* schItem )
2981 {
2982 if( !found && schItem->Type() != SCH_GROUP_T )
2983 {
2984 item = schItem;
2985 found = true;
2986 }
2987 },
2989
2990 if( found )
2991 selection.SetReferencePoint( item->GetPosition() );
2992 else
2993 selection.SetReferencePoint( group->GetPosition() );
2994 }
2995 else
2996 {
2997 SCH_ITEM* item = static_cast<SCH_ITEM*>( selection.GetTopLeftItem() );
2998
2999 selection.SetReferencePoint( item->GetPosition() );
3000 }
3001
3002 if( m_toolMgr->RunSynchronousAction( SCH_ACTIONS::move, &commit ) )
3003 {
3004 // Pushing the commit will update the connectivity.
3005 commit.Push( _( "Paste" ) );
3006
3007 if( !sheetsPasted && !ADVANCED_CFG::GetCfg().m_ConnectivityEngine )
3008 m_frame->RefreshNetNavigator();
3009 }
3010 else
3011 {
3012 commit.Revert();
3013 }
3014
3015 getView()->ClearPreview();
3016 }
3017
3018 return 0;
3019}
3020
3021
3023{
3024 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
3025 SCH_SELECTION& selection = selTool->RequestSelection( { SCH_SYMBOL_T } );
3026 SCH_SYMBOL* symbol = nullptr;
3027 SYMBOL_EDIT_FRAME* symbolEditor;
3028
3029 if( selection.GetSize() >= 1 )
3030 symbol = (SCH_SYMBOL*) selection.Front();
3031
3032 if( selection.IsHover() )
3033 m_toolMgr->RunAction( ACTIONS::selectionClear );
3034
3035 if( !symbol )
3036 {
3037 // Giant hack: by default we assign Edit Table to the same hotkey, so give the table
3038 // tool a chance to handle it if we can't.
3039 if( SCH_EDIT_TABLE_TOOL* tableTool = m_toolMgr->GetTool<SCH_EDIT_TABLE_TOOL>() )
3040 tableTool->EditTable( aEvent );
3041
3042 return 0;
3043 }
3044
3045 if( symbol->GetEditFlags() != 0 )
3046 return 0;
3047
3048 if( symbol->IsMissingLibSymbol() )
3049 {
3050 m_frame->ShowInfoBarError( _( "Symbols with broken library symbol links cannot be edited." ) );
3051 return 0;
3052 }
3053
3055 symbolEditor = (SYMBOL_EDIT_FRAME*) m_frame->Kiway().Player( FRAME_SCH_SYMBOL_EDITOR, false );
3056
3057 if( symbolEditor )
3058 {
3059 if( wxWindow* blocking_win = symbolEditor->Kiway().GetBlockingDialog() )
3060 blocking_win->Close( true );
3061
3062 if( aEvent.IsAction( &SCH_ACTIONS::editWithLibEdit ) )
3063 {
3064 symbolEditor->LoadSymbolFromSchematic( symbol );
3065 }
3067 {
3068 symbolEditor->LoadSymbol( symbol->GetLibId(), symbol->GetUnit(), symbol->GetBodyStyle() );
3069
3070 if( !symbolEditor->IsLibraryTreeShown() )
3071 symbolEditor->ToggleLibraryTree();
3072 }
3073 }
3074
3075 return 0;
3076}
3077
3078
3080{
3081 m_frame->OnAnnotate();
3082 return 0;
3083}
3084
3085
3087{
3089 dlg.m_FirstRefDes->SetValidator( wxTextValidator( wxFILTER_EMPTY ) );
3090
3091 dlg.SetInitialFocus( dlg.m_FirstRefDes );
3092
3093 if( dlg.ShowModal() == wxID_OK )
3094 {
3095 SCH_REFERENCE startRef;
3096 startRef.SetRef( dlg.m_FirstRefDes->GetValue() );
3097
3098 if( startRef.IsSplitNeeded() )
3099 startRef.Split();
3100 else
3101 return 0;
3102
3103 int startNum = atoi( startRef.GetRefNumber().utf8_string().c_str() );
3104
3105 SCH_COMMIT commit( m_frame );
3106 SCHEMATIC* schematic = m_frame->m_schematic;
3107 SCH_REFERENCE_LIST references;
3108
3109 if( dlg.m_AllSheets->GetValue() )
3110 schematic->Hierarchy().GetSymbols( references, SYMBOL_FILTER_ALL );
3111 else
3112 schematic->CurrentSheet().GetSymbols( references, SYMBOL_FILTER_ALL );
3113
3114 references.SplitReferences();
3115
3116 for( SCH_REFERENCE& ref : references )
3117 {
3118 if( ref.GetRef() == startRef.GetRef() )
3119 {
3120 int num = atoi( ref.GetRefNumber().utf8_string().c_str() );
3121
3122 if( num >= startNum )
3123 {
3124 const SCH_SHEET_PATH& sheet = ref.GetSheetPath();
3125 wxString fullRef = ref.GetRef();
3126
3127 num += dlg.m_Increment->GetValue();
3128 fullRef << num;
3129
3130 commit.Modify( ref.GetSymbol(), sheet.LastScreen(), RECURSE_MODE::NO_RECURSE );
3131 ref.GetSymbol()->SetRef( &sheet, From_UTF8( fullRef.c_str() ) );
3132 }
3133 }
3134 }
3135
3136 if( !commit.Empty() )
3137 commit.Push( _( "Increment Annotations" ) );
3138 }
3139
3140 return 0;
3141}
3142
3143
3145{
3146 m_frame->OnOpenCvpcb();
3147 return 0;
3148}
3149
3150
3152{
3153 m_frame->OnImportProject();
3154 return 0;
3155}
3156
3157
3159{
3160 DIALOG_SYMBOL_FIELDS_TABLE* dlg = m_frame->GetSymbolFieldsTableDialog();
3161
3162 if( !dlg )
3163 return 0;
3164
3165 // Needed at least on Windows. Raise() is not enough
3166 dlg->Show( true );
3167
3168 // Bring it to the top if already open. Dual monitor users need this.
3169 dlg->Raise();
3170
3171 dlg->ShowEditTab();
3172
3173 return 0;
3174}
3175
3176
3178{
3179 if( !m_frame->Schematic().GetCurrentVariant().IsEmpty() )
3180 {
3182 _( "Bulk Edit Symbol Library Links is not available when a design variant is "
3183 "active. Switch to the default variant first." ) );
3184 return 0;
3185 }
3186
3188 m_frame->HardRedraw();
3189
3190 return 0;
3191}
3192
3193
3195{
3196 m_frame->OnOpenPcbnew();
3197 return 0;
3198}
3199
3200
3202{
3203 m_frame->OnUpdatePCB();
3204 return 0;
3205}
3206
3207
3209{
3211 dlg.ShowModal();
3212 return 0;
3213}
3214
3215
3217{
3219
3220 // If a plugin is removed or added, rebuild and reopen the new dialog
3221 while( result == NET_PLUGIN_CHANGE )
3223
3224 return 0;
3225}
3226
3227
3229{
3230 DIALOG_SYMBOL_FIELDS_TABLE* dlg = m_frame->GetSymbolFieldsTableDialog();
3231
3232 if( !dlg )
3233 return 0;
3234
3235 // Needed at least on Windows. Raise() is not enough
3236 dlg->Show( true );
3237
3238 // Bring it to the top if already open. Dual monitor users need this.
3239 dlg->Raise();
3240
3241 dlg->ShowExportTab();
3242
3243 return 0;
3244}
3245
3246
3248{
3250 return 0;
3251}
3252
3253
3255{
3256 m_frame->RecalculateConnections( nullptr, LOCAL_CLEANUP );
3257
3258 // Create a selection with all items from the current sheet
3259 SCH_SELECTION sheetSelection;
3260 SCH_SCREEN* screen = m_frame->GetScreen();
3261
3262 for( SCH_ITEM* item : screen->Items() )
3263 {
3264 sheetSelection.Add( item );
3265 }
3266
3267 // Get the full page bounding box for rendering the complete sheet
3268 BOX2I pageBBox( VECTOR2I( 0, 0 ), m_frame->GetPageSizeIU() );
3269
3270 // Render the full sheet selection including the worksheet
3271 wxImage image = renderSelectionToImageForClipboard( m_frame, sheetSelection, pageBBox, true, true );
3272
3273 if( image.IsOk() )
3274 {
3275 wxLogNull doNotLog; // disable logging of failed clipboard actions
3276
3277 if( wxTheClipboard->Open() )
3278 {
3279 wxDataObjectComposite* data = new wxDataObjectComposite();
3280
3282
3283 wxTheClipboard->SetData( data );
3284 wxTheClipboard->Flush(); // Allow data to be available after closing KiCad
3285 wxTheClipboard->Close();
3286 }
3287 }
3288 else
3289 {
3290 wxLogMessage( _( "Cannot create the schematic image" ) );
3291 }
3292
3293 return 0;
3294}
3295
3296
3298{
3300 return 0;
3301}
3302
3303
3309
3310
3316
3317
3323
3324
3330
3331
3337
3338
3344
3345
3347{
3348 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3350
3352 m_frame->GetCanvas()->Refresh();
3353
3354 return 0;
3355}
3356
3357
3359{
3360 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3362
3363 m_frame->GetRenderSettings()->m_ShowHiddenFields = cfg->m_Appearance.show_hidden_fields;
3364
3366 m_frame->GetCanvas()->Refresh();
3367
3368 return 0;
3369}
3370
3371
3373{
3374 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3376
3378 m_frame->GetCanvas()->Refresh();
3379
3380 return 0;
3381}
3382
3383
3385{
3386 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3388
3390 m_frame->GetCanvas()->Refresh();
3391
3392 return 0;
3393}
3394
3395
3397{
3398 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3400
3402 m_frame->GetCanvas()->Refresh();
3403
3404 return 0;
3405}
3406
3407
3409{
3410 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3412
3413 m_frame->GetCanvas()->Refresh();
3414
3415 return 0;
3416}
3417
3418
3420{
3421 SCH_SHEET_PATH* sheetPath = &m_frame->GetCurrentSheet();
3422 wxString variant = m_frame->Schematic().GetCurrentVariant();
3423 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3425
3426 m_frame->GetCanvas()->GetView()->UpdateAllItemsConditionally(
3427 [&]( KIGFX::VIEW_ITEM* aItem ) -> int
3428 {
3429 int flags = 0;
3430
3431 auto invalidateTextVars =
3432 [&flags]( EDA_TEXT* text )
3433 {
3434 if( text->HasTextVars() )
3435 {
3436 text->ClearRenderCache();
3437 text->ClearBoundingBoxCache();
3439 }
3440 };
3441
3442 if( SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( aItem ) )
3443 {
3444 item->RunOnChildren(
3445 [&invalidateTextVars]( SCH_ITEM* aChild )
3446 {
3447 if( EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( aChild ) )
3448 invalidateTextVars( text );
3449 },
3451
3452 if( item->GetExcludedFromSim( sheetPath, variant ) )
3454 }
3455
3456 if( EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( aItem ) )
3457 invalidateTextVars( text );
3458
3459 return flags;
3460 } );
3461
3462 m_frame->GetCanvas()->Refresh();
3463
3464 return 0;
3465}
3466
3467
3469{
3470 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3472
3474 m_frame->RefreshOperatingPointDisplay();
3475 m_frame->GetCanvas()->Refresh();
3476
3477 return 0;
3478}
3479
3480
3482{
3483 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3485
3487 m_frame->RefreshOperatingPointDisplay();
3488 m_frame->GetCanvas()->Refresh();
3489
3490 return 0;
3491}
3492
3493
3495{
3496 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3498
3499 m_frame->GetRenderSettings()->m_ShowPinAltIcons = cfg->m_Appearance.show_pin_alt_icons;
3500
3502 m_frame->GetCanvas()->Refresh();
3503
3504 return 0;
3505}
3506
3507
3509{
3510 m_frame->eeconfig()->m_Drawing.line_mode = aEvent.Parameter<LINE_MODE>();
3511 m_toolMgr->PostAction( ACTIONS::refreshPreview );
3512 // Notify toolbar to update selection
3514 return 0;
3515}
3516
3517
3519{
3520 m_frame->eeconfig()->m_Drawing.line_mode++;
3521 m_frame->eeconfig()->m_Drawing.line_mode %= LINE_MODE::LINE_MODE_COUNT;
3522 m_toolMgr->PostAction( ACTIONS::refreshPreview );
3523 // Notify toolbar to update selection
3525 return 0;
3526}
3527
3528
3530{
3531 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3533 return 0;
3534}
3535
3536
3538{
3539 // Update the left toolbar Line modes group icon to match current mode
3540 switch( static_cast<LINE_MODE>( m_frame->eeconfig()->m_Drawing.line_mode ) )
3541 {
3542 case LINE_MODE::LINE_MODE_FREE: m_frame->SelectToolbarAction( SCH_ACTIONS::lineModeFree ); break;
3543 case LINE_MODE::LINE_MODE_90: m_frame->SelectToolbarAction( SCH_ACTIONS::lineMode90 ); break;
3544 default:
3545 case LINE_MODE::LINE_MODE_45: m_frame->SelectToolbarAction( SCH_ACTIONS::lineMode45 ); break;
3546 }
3547
3548 return 0;
3549}
3550
3551
3553{
3554 if( !Pgm().GetCommonSettings()->m_Input.hotkey_feedback )
3555 return 0;
3556
3557 GRID_SETTINGS& gridSettings = m_toolMgr->GetSettings()->m_Window.grid;
3558 int currentIdx = m_toolMgr->GetSettings()->m_Window.grid.last_size_idx;
3559
3560 wxArrayString gridsLabels;
3561
3562 for( const GRID& grid : gridSettings.grids )
3563 gridsLabels.Add( grid.UserUnitsMessageText( m_frame ) );
3564
3565 if( !m_frame->GetHotkeyPopup() )
3566 m_frame->CreateHotkeyPopup();
3567
3568 HOTKEY_CYCLE_POPUP* popup = m_frame->GetHotkeyPopup();
3569
3570 if( popup )
3571 popup->Popup( _( "Grid" ), gridsLabels, currentIdx );
3572
3573 return 0;
3574}
3575
3576
3578{
3579 SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
3580
3581 if( !editFrame )
3582 return 1;
3583
3584 // Need to have a group selected and it needs to have a linked design block
3585 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
3586 SCH_SELECTION selection = selTool->GetSelection();
3587
3588 if( selection.Size() != 1 || selection[0]->Type() != SCH_GROUP_T )
3589 return 1;
3590
3591 SCH_GROUP* group = static_cast<SCH_GROUP*>( selection[0] );
3592
3593 if( !group->HasDesignBlockLink() )
3594 return 1;
3595
3596 // Get the associated design block
3597 DESIGN_BLOCK_PANE* designBlockPane = editFrame->GetDesignBlockPane();
3598 std::unique_ptr<DESIGN_BLOCK> designBlock( designBlockPane->GetDesignBlock( group->GetDesignBlockLibId(),
3599 true, true ) );
3600
3601 if( !designBlock )
3602 return 1;
3603
3604 if( designBlock->GetSchematicFile().IsEmpty() )
3605 {
3606 wxString msg;
3607 msg.Printf( _( "Design block %s does not have a schematic file." ),
3608 group->GetDesignBlockLibId().GetUniStringLibId() );
3609 m_frame->GetInfoBar()->ShowMessageFor( msg, 5000, wxICON_WARNING );
3610 return 1;
3611 }
3612
3613 editFrame->GetDesignBlockPane()->SelectLibId( group->GetDesignBlockLibId() );
3614
3615 return m_toolMgr->RunAction( SCH_ACTIONS::placeDesignBlock, designBlock.release() );
3616}
3617
3618
3620{
3621 SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
3622
3623 if( !editFrame )
3624 return 1;
3625
3626 // Need to have a group selected and it needs to have a linked design block
3627 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
3628 SCH_SELECTION selection = selTool->GetSelection();
3629
3630 if( selection.Size() != 1 || selection[0]->Type() != SCH_GROUP_T )
3631 return 1;
3632
3633 SCH_GROUP* group = static_cast<SCH_GROUP*>( selection[0] );
3634
3635 if( !group->HasDesignBlockLink() )
3636 return 1;
3637
3638 // Get the associated design block
3639 DESIGN_BLOCK_PANE* designBlockPane = editFrame->GetDesignBlockPane();
3640 std::unique_ptr<DESIGN_BLOCK> designBlock( designBlockPane->GetDesignBlock( group->GetDesignBlockLibId(),
3641 true, true ) );
3642
3643 if( !designBlock )
3644 return 1;
3645
3646 editFrame->GetDesignBlockPane()->SelectLibId( group->GetDesignBlockLibId() );
3647
3648 return m_toolMgr->RunAction( SCH_ACTIONS::updateDesignBlockFromSelection ) ? 1 : 0;
3649}
3650
3651
3653{
3654 SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
3655
3656 if( !editFrame )
3657 return 1;
3658
3659 editFrame->AddVariant();
3660
3661 return 0;
3662}
3663
3664
3666{
3667 SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
3668
3669 if( !editFrame )
3670 return 1;
3671
3672 editFrame->RemoveVariant();
3673 return 0;
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 editFrame->EditVariantDescription();
3685 return 0;
3686}
3687
3688
3690{
3691 SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
3692
3693 if( !editFrame )
3694 return 1;
3695
3696 editFrame->RenameVariant();
3697 return 0;
3698}
3699
3700
3702{
3703 SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
3704
3705 if( !editFrame )
3706 return 1;
3707
3708 editFrame->CopyVariant();
3709 return 0;
3710}
3711
3712
3714{
3715 Go( &SCH_EDITOR_CONTROL::New, ACTIONS::doNew.MakeEvent() );
3716 Go( &SCH_EDITOR_CONTROL::Open, ACTIONS::open.MakeEvent() );
3717 Go( &SCH_EDITOR_CONTROL::Save, ACTIONS::save.MakeEvent() );
3724 Go( &SCH_EDITOR_CONTROL::Plot, ACTIONS::plot.MakeEvent() );
3725
3728
3734
3737
3749
3752
3753 Go( &SCH_EDITOR_CONTROL::Undo, ACTIONS::undo.MakeEvent() );
3754 Go( &SCH_EDITOR_CONTROL::Redo, ACTIONS::redo.MakeEvent() );
3755 Go( &SCH_EDITOR_CONTROL::Cut, ACTIONS::cut.MakeEvent() );
3756 Go( &SCH_EDITOR_CONTROL::Copy, ACTIONS::copy.MakeEvent() );
3761
3763
3780
3789
3806
3808
3811
3817}
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 showGitCommitPane
Definition actions.h:263
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
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:177
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition eda_shape.h:333
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Definition eda_shape.h:283
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:348
static const TOOL_EVENT GridChangedByKeyEvent
Used for hotkey feedback.
Definition actions.h:366
static const TOOL_EVENT SelectedEvent
Definition actions.h:346
static const TOOL_EVENT SelectedItemsModified
Selected item had a property changed (except movement)
Definition actions.h:353
static const TOOL_EVENT PointSelectedEvent
Definition actions.h:345
static const TOOL_EVENT UnselectedEvent
Definition actions.h:347
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:2631
void SetLayerVisible(int aLayer, bool aVisible=true)
Control the visibility of a particular layer.
Definition view.h:431
void ClearPreview()
Definition view.cpp:2719
static constexpr int VIEW_MAX_LAYERS
Maximum number of layers that may be shown.
Definition view.h:899
void UpdateAllItems(int aUpdateFlags)
Update all items in the view according to the given flags.
Definition view.cpp:2475
void Hide(VIEW_ITEM *aItem, bool aHide=true, bool aHideOverlay=false)
Temporarily hide the item in the view (e.g.
Definition view.cpp:2576
void AddToPreview(VIEW_ITEM *aItem, bool aTakeOwnership=true)
Definition view.cpp:2741
void SetVisible(VIEW_ITEM *aItem, bool aIsVisible=true)
Set the item visibility.
Definition view.cpp:2552
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:693
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:325
wxString GetVariantDescription(const wxString &aVariantName) const
Return the description for a variant.
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_PATH & CurrentSheet() const
Definition schematic.h:312
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 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)
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 ToggleGitCommitPane(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)
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:550
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:671
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:635
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:563
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:826
void UpdateSymbolLinks(REPORTER *aReporter=nullptr)
Initialize the LIB_SYMBOL reference for each SCH_SYMBOL found in the full schematic.
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 AddLibSymbol(LIB_SYMBOL *aLibSymbol)
Add aLibSymbol to the library symbol map.
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:565
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:96
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
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
void FillItemMap(std::unordered_map< KIID, EDA_ITEM * > &aMap) const
Fill an item cache for temporary use when many items need to be fetched.
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:392
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:151
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:249
const std::vector< SCH_SHEET_INSTANCE > & GetInstances() const
Definition sch_sheet.h:527
Schematic symbol object.
Definition sch_symbol.h:75
EMBEDDED_FILES * GetEmbeddedFiles() override
SCH_SYMBOLs don't currently support embedded files, but their LIB_SYMBOL counterparts do.
const std::vector< SCH_SYMBOL_INSTANCE > & GetInstances() const
Definition sch_symbol.h:135
std::vector< LIB_ID > GetVariantSymbolOverrides() const
wxString GetSchSymbolLibraryName() const
std::vector< const SCH_PIN * > GetPins(const SCH_SHEET_PATH *aSheet) const
Retrieve a list of the SCH_PINs for the given sheet path.
void ClearAnnotation(const SCH_SHEET_PATH *aSheetPath, bool aResetPrefix)
Clear exiting symbol annotation.
void AddHierarchicalReference(const KIID_PATH &aPath, const wxString &aRef, int aUnit)
Add a full hierarchical reference to this symbol.
bool IsMissingLibSymbol() const
Check to see if the library symbol is set to the dummy library symbol.
const LIB_ID & GetLibId() const override
Definition sch_symbol.h:165
std::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:184
void SetLibSymbol(LIB_SYMBOL *aLibSymbol)
Set this schematic symbol library symbol reference to aLibSymbol.
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const override
bool IsPower() const override
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this symbol.
void BrightenItem(EDA_ITEM *aItem)
void UnbrightenItem(EDA_ITEM *aItem)
virtual void Add(EDA_ITEM *aItem)
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:880
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:57
@ CURRENT_PROBE
Definition cursors.h:59
@ BULLSEYE
Definition cursors.h:55
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.
@ LAYER_DRAWINGSHEET
Sheet frame and title block.
Definition layer_ids.h:274
@ LAYER_ERC_WARN
Definition layer_ids.h:507
@ LAYER_ERC_ERR
Definition layer_ids.h:508
@ LAYER_SCHEMATIC_DRAWINGSHEET
Definition layer_ids.h:524
@ LAYER_OP_CURRENTS
Definition layer_ids.h:530
@ LAYER_SCHEMATIC_PAGE_LIMITS
Definition layer_ids.h:525
@ LAYER_OP_VOLTAGES
Definition layer_ids.h:529
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
@ LAYERS
Layers have changed.
Definition view_item.h:52
@ 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:640
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