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