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