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