KiCad PCB EDA Suite
Loading...
Searching...
No Matches
symbol_edit_frame.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) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright (C) 2008 Wayne Stambaugh <[email protected]>
6 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
22#include <bitmaps.h>
26#include <api/api_server.h>
28#include <api/api_utils.h>
29#include <wx/hyperlink.h>
30#include <base_screen.h>
31#include <confirm.h>
32#include <core/kicad_algo.h>
33#include <core/throttle.h>
34#include <eeschema_id.h>
35#include <eeschema_settings.h>
36#include <env_paths.h>
38#include <kidialog.h>
39#include <kiface_base.h>
40#include <kiplatform/app.h>
41#include <kiplatform/io.h>
42#include <kiway_mail.h>
43#include <symbol_edit_frame.h>
44#include <sch_edit_frame.h>
48#include <paths.h>
49#include <pgm_base.h>
50#include <project_sch.h>
51#include <sch_painter.h>
52#include <sch_view.h>
56#include <tool/action_manager.h>
57#include <tool/action_toolbar.h>
58#include <tool/common_control.h>
59#include <tool/common_tools.h>
61#include <tool/embed_tool.h>
63#include <tool/picker_tool.h>
65#include <tool/selection.h>
67#include <tool/tool_manager.h>
68#include <tool/zoom_tool.h>
69#include <tools/sch_actions.h>
81#include <view/view_controls.h>
83#include <widgets/wx_infobar.h>
89#include <widgets/lib_tree.h>
94#include <panel_sym_lib_table.h>
95#include <string_utils.h>
97#include <wx/dir.h>
98#include <wx/msgdlg.h>
99#include <wx/combobox.h>
100#include <wx/log.h>
101#include <wx/wfstream.h>
102#include <wx/zipstrm.h>
103#include <trace_helpers.h>
104
105
107
108
112class UNPACKED_SYMBOL_LIBRARY_DIR_TRAVERSER : public wxDirTraverser
113{
114public:
115 UNPACKED_SYMBOL_LIBRARY_DIR_TRAVERSER( std::vector<wxString>& aFiles ) :
116 m_files( aFiles) { }
117
118 virtual wxDirTraverseResult OnFile( const wxString& aFilename ) override
119 {
120 wxFileName fn( aFilename );
122
123 if( ext.CmpNoCase( fn.GetExt() ) == 0 )
124 m_files.push_back( aFilename );
125
126 return wxDIR_CONTINUE;
127 }
128
129 virtual wxDirTraverseResult OnDir( const wxString& WXUNUSED( aDirname ) ) override
130 {
131 return wxDIR_CONTINUE;
132 }
133
134private:
135 std::vector<wxString>& m_files;
136};
137
138
139BEGIN_EVENT_TABLE( SYMBOL_EDIT_FRAME, SCH_BASE_FRAME )
142
143 // menubar commands
146
147 // Update user interface elements.
150
153
154 // Drop files event
155 EVT_DROP_FILES( SYMBOL_EDIT_FRAME::OnDropFiles )
156
157END_EVENT_TABLE()
158
159
160SYMBOL_EDIT_FRAME::SYMBOL_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
161 SCH_BASE_FRAME( aKiway, aParent, FRAME_SCH_SYMBOL_EDITOR, _( "Symbol Editor" ),
162 wxDefaultPosition, wxDefaultSize, KICAD_DEFAULT_DRAWFRAME_STYLE,
164 m_unitSelectBox( nullptr ),
165 m_bodyStyleSelectBox( nullptr ),
166 m_drawSpecificUnit( false ),
170{
171 m_symbol = nullptr;
172 m_treePane = nullptr;
173 m_libMgr = nullptr;
174 m_unit = 1;
175 m_bodyStyle = 1;
177 m_aboutTitle = _HKI( "KiCad Symbol Editor" );
178
179 wxIcon icon;
180 wxIconBundle icon_bundle;
181
182 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_libedit, 48 ) );
183 icon_bundle.AddIcon( icon );
184 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_libedit, 256 ) );
185 icon_bundle.AddIcon( icon );
186 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_libedit, 128 ) );
187 icon_bundle.AddIcon( icon );
188 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_libedit_32 ) );
189 icon_bundle.AddIcon( icon );
190 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_libedit_16 ) );
191 icon_bundle.AddIcon( icon );
192
193 SetIcons( icon_bundle );
194
197
199
200 m_treePane = new SYMBOL_TREE_PANE( this, m_libMgr );
201 m_treePane->GetLibTree()->SetSortMode( (LIB_TREE_MODEL_ADAPTER::SORT_MODE) m_settings->m_LibrarySortMode );
202
204
205 // Ensure axis are always drawn
207 gal_opts.m_axesEnabled = true;
208
211 GetScreen()->m_Center = true;
212
213 GetCanvas()->GetViewControls()->SetCrossHairCursorPosition( VECTOR2D( 0, 0 ), false );
214
215 GetRenderSettings()->LoadColors( GetColorSettings() );
216 GetRenderSettings()->m_IsSymbolEditor = true;
217 GetCanvas()->GetGAL()->SetAxesColor( m_colorSettings->GetColor( LAYER_SCHEMATIC_GRID_AXES ) );
218
219 setupTools();
221
223
226
230
233
234 m_propertiesPanel = new SCH_PROPERTIES_PANEL( this, this );
235 m_propertiesPanel->SetSplitterProportion( m_settings->m_AuiPanels.properties_splitter );
236
238
239 m_auimgr.SetManagedWindow( this );
240
242
243 // Rows; layers 4 - 6
244 m_auimgr.AddPane( m_tbTopMain, EDA_PANE().HToolbar().Name( "TopMainToolbar" )
245 .Top().Layer( 6 ) );
246
247 m_auimgr.AddPane( m_messagePanel, EDA_PANE().Messages().Name( "MsgPanel" )
248 .Bottom().Layer( 6 ) );
249
250 m_auimgr.AddPane( m_tbLeft, EDA_PANE().VToolbar().Name( "LeftToolbar" )
251 .Left().Layer( 2 ) );
252
253 m_auimgr.AddPane( m_tbRight, EDA_PANE().VToolbar().Name( "RightToolbar" )
254 .Right().Layer( 2 ) );
255
256 m_tabsPanel = new EDITOR_TABS_PANEL( this, GetCanvas() );
257
258 m_tabsPanel->onActivateTab =
259 [this]( int aIdx )
260 {
262 activateSymbolTab( ctx );
263 };
264
265 m_tabsPanel->onCloseTabRequested =
266 [this]( int aIdx ) -> bool
267 {
268 return promptAndCloseSymbolTab( aIdx );
269 };
270
271 m_tabsPanel->onQueryVisualState =
272 [this]( int aIdx ) -> TAB_VISUAL_STATE
273 {
274 // The panel model owns preview. Read modified from the live context.
275 const std::vector<EDITOR_TABS_MODEL::ENTRY>& entries = m_tabsPanel->Model().Entries();
276
277 if( aIdx < 0 || aIdx >= static_cast<int>( entries.size() ) )
278 return TAB_VISUAL_STATE{};
279
280 bool modified = entries[aIdx].modified;
281
283 modified = ctx->IsModified();
284
285 return ResolveTabVisualState( entries[aIdx].preview, modified );
286 };
287
288 m_auimgr.AddPane( m_tabsPanel, wxAuiPaneInfo().Name( "DrawFrame" )
289 .CentrePane() );
290
291 // Columns; layers 1 - 3
292 m_auimgr.AddPane( m_treePane, EDA_PANE().Palette().Name( "LibraryTree" )
293 .Left().Layer( 3 )
294 .TopDockable( false ).BottomDockable( false )
295 .Caption( _( "Libraries" ) )
296 // Don't use -1 for don't-change-height on a growable panel; it has side-effects.
297 .MinSize( FromDIP( 250 ), FromDIP( 80 ) )
298 .BestSize( FromDIP( 250 ), -1 ) );
299
302
303 // Can be called only when all panes are created, because (at least on Windows) when items
304 // managed by m_auimgr are not the same as those existing when saved by Perspective()
305 // in config, broken settings can happen.
307
308 // Protect against broken saved Perspective() due to bugs in previous version
309 // This is currently a workaround.
310 m_auimgr.GetPane( "TopMainToolbar" ).Top().Layer( 6 ).Position(0).Show( true );
311 m_auimgr.GetPane( "LeftToolbar" ).Position(0).Show( true );
312 m_auimgr.GetPane( "RightToolbar" ).Show( true );
313
314 // Show or hide m_propertiesPanel depending on current settings:
315 wxAuiPaneInfo& propertiesPaneInfo = m_auimgr.GetPane( PropertiesPaneName() );
316 wxAuiPaneInfo& selectionFilterPane = m_auimgr.GetPane( wxS( "SelectionFilter" ) );
317 // The selection filter doesn't need to grow in the vertical direction when docked
318 selectionFilterPane.dock_proportion = 0;
319
320 // wx 3.3.3 turns a -1 min height into 1, and a legacy perspective restores one
321 selectionFilterPane.min_size.y = m_selectionFilterPanel->GetBestSize().y;
322
323 propertiesPaneInfo.Show( m_settings->m_AuiPanels.show_properties );
325
327
328 // Can't put this in LoadSettings, because it has to be called before setupTools :/
330 selTool->GetFilter() = GetSettings()->m_SelectionFilter;
331 m_selectionFilterPanel->SetCheckboxesFromFilter( selTool->GetFilter() );
332
333 if( m_settings->m_LibWidth > 0 )
334 SetAuiPaneSize( m_auimgr, m_auimgr.GetPane( "LibraryTree" ), m_settings->m_LibWidth, -1 );
335
336 Raise();
337 Show( true );
338
339 SyncView();
340 GetCanvas()->GetView()->UseDrawPriority( true );
341 GetCanvas()->GetGAL()->SetAxesEnabled( true );
342
344
345 // Set the working/draw area size to display a symbol to a reasonable value:
346 // A 600mm x 600mm with a origin at the area center looks like a large working area
347 double max_size_x = schIUScale.mmToIU( 600 );
348 double max_size_y = schIUScale.mmToIU( 600 );
349 BOX2D bbox;
350 bbox.SetOrigin( -max_size_x /2, -max_size_y/2 );
351 bbox.SetSize( max_size_x, max_size_y );
352 GetCanvas()->GetView()->SetBoundary( bbox );
353
355
357 m_acceptedExts.emplace( wxS( "dxf" ), &SCH_ACTIONS::ddImportGraphics );
359 DragAcceptFiles( true );
360
361 KIPLATFORM::APP::SetShutdownBlockReason( this, _( "Library changes are unsaved" ) );
362
363 // Catch unhandled accelerator command characters that were no handled by the library tree
364 // panel.
366 Bind( wxEVT_CHAR_HOOK, &TOOL_DISPATCHER::DispatchWxEvent, m_toolDispatcher );
367
368 // GTK rejects WXK_TAB as an accelerator so cycle tabs from the char hook ahead of the dispatcher.
369 Bind( wxEVT_CHAR_HOOK, &SYMBOL_EDIT_FRAME::OnTabCharHook, this );
370
371 // Ensure the window is on top
372 Raise();
373
374 // run SyncLibraries with progress reporter enabled. The progress reporter is useful
375 // in debug mode because the loading time of ecah library can be really noticeable
376 SyncLibraries( true );
377
378 m_apiHandler = std::make_unique<API_HANDLER_SYMBOL>( this );
380
381 if( Kiface().IsSingle() )
382 {
383 m_apiHandlerCommon = std::make_unique<API_HANDLER_COMMON>();
385 m_apiLibrariesHandler = std::make_unique<API_HANDLER_LIBRARIES>(
388 }
389
390 // Must follow SyncLibraries so persisted tabs can resolve against the loaded libraries.
392}
393
394
396{
397 // Ensure that teardowns without doCloseWindow() are fully unregistered
399
400 if( Kiface().IsSingle() )
401 {
404 }
405
406 // Hand the borrowed canvas back before the base destructor frees it, else the panel reparents
407 // freed memory on its own teardown.
408 if( m_tabsPanel )
409 m_tabsPanel->ReleaseSharedCanvas();
410
411 // Shutdown all running tools
412 if( m_toolManager )
413 m_toolManager->ShutdownAllTools();
414
415 setSymWatcher( nullptr );
416
417 if( m_activeTab )
418 {
419 // Hand the working objects back so the context deletes them exactly once below; raw deleting
420 // here would double-free with the context dtor and leak the swapped-in undo list. Covers an
421 // active instance tab too, whose m_isSymbolFromSchematic mirror is only frame state.
423 m_activeTab->AdoptWorkingObjects( m_symbol, static_cast<SCH_SCREEN*>( GetScreen() ) );
424 m_activeTab = nullptr;
425 m_symbol = nullptr;
427 }
428 else
429 {
430 // No active tab owns the current screen, so let EDA_DRAW_FRAME free it.
432 }
433
434 // Free each detached context's undo/redo with the frame on the dummy screen to avoid double-frees.
435 for( const std::unique_ptr<SYMBOL_EDITOR_TAB_CONTEXT>& ctx : m_tabContexts )
437
438 m_tabContexts.clear();
439
441 Pgm().GetSettingsManager().Save( cfg );
442
443 delete m_libMgr;
444}
445
446
448{
449 wxCHECK_RET( m_settings, "Call to SYMBOL_EDIT_FRAME::LoadSettings with null m_settings" );
450
452
453 GetRenderSettings()->m_ShowPinsElectricalType = m_settings->m_ShowPinElectricalType;
454 GetRenderSettings()->m_ShowHiddenPins = m_settings->m_ShowHiddenPins;
455 GetRenderSettings()->m_ShowHiddenFields = m_settings->m_ShowHiddenFields;
456 GetRenderSettings()->m_ShowPinAltIcons = m_settings->m_ShowPinAltIcons;
457 GetRenderSettings()->SetDefaultFont( wxEmptyString );
458}
459
460
462{
463 wxCHECK_RET( m_settings, "Call to SYMBOL_EDIT_FRAME:SaveSettings with null m_settings" );
464
466
467 // The library tree is hidden while editing a symbol from the schematic. Force it visible in the
468 // serialized AUI layout so the user's preference survives a restart, but only touch the pane
469 // metadata (not ToggleLibraryTree) to avoid a mid-session repaint/flicker and a spurious tree
470 // width capture below.
471 wxAuiPaneInfo& treePane = m_auimgr.GetPane( m_treePane );
472 wxAuiPaneInfo& filterPane = m_auimgr.GetPane( wxS( "SelectionFilter" ) );
473
474 const bool treeShown = treePane.IsShown();
475 const bool filterShown = filterPane.IsShown();
476
477 // Gate on the pending-restore flag alone, not the active-tab schematic state, which is cleared
478 // when a schematic tab closes while the tree stays auto-hidden.
479 const bool forceTreeShown = m_libTreeAutoHiddenForSchematicEdit && !treeShown;
480
481 if( forceTreeShown )
482 {
483 treePane.Show( true );
485 }
486
488
489 if( forceTreeShown )
490 {
491 treePane.Show( treeShown );
492 filterPane.Show( filterShown );
493 }
494
495 m_settings->m_ShowPinElectricalType = GetRenderSettings()->m_ShowPinsElectricalType;
496 m_settings->m_ShowHiddenPins = GetRenderSettings()->m_ShowHiddenPins;
497 m_settings->m_ShowHiddenFields = GetRenderSettings()->m_ShowHiddenFields;
498 m_settings->m_ShowPinAltIcons = GetRenderSettings()->m_ShowPinAltIcons;
499
500 m_settings->m_LibWidth = m_treePane->GetSize().x;
501
502 m_settings->m_LibrarySortMode = GetLibTree()->GetSortMode();
503
504 m_settings->m_AuiPanels.properties_splitter = m_propertiesPanel->SplitterProportion();
505 bool prop_shown = m_auimgr.GetPane( PropertiesPaneName() ).IsShown();
506 m_settings->m_AuiPanels.show_properties = prop_shown;
507
508 if( TOOL_MANAGER* toolMgr = GetToolManager() )
509 {
510 if( SCH_SELECTION_TOOL* selTool = toolMgr->GetTool<SCH_SELECTION_TOOL>() )
511 m_settings->m_SelectionFilter = selTool->GetFilter();
512 }
513
515}
516
517
522
523
525{
527
528 if( cfg && static_cast<SYMBOL_EDITOR_SETTINGS*>( cfg )->m_UseEeschemaColorSettings )
529 cfg = GetAppSettings<EESCHEMA_SETTINGS>( "eeschema" );
530
531 return ::GetColorSettings( cfg ? cfg->m_ColorTheme : DEFAULT_THEME );
532}
533
534
536{
537 // Create the manager and dispatcher & route draw panel events to the dispatcher
539 m_toolManager->SetEnvironment( GetScreen(), GetCanvas()->GetView(), GetCanvas()->GetViewControls(), GetSettings(),
540 this );
541 m_actions = new SCH_ACTIONS();
543
544 // Register tools
545 m_toolManager->RegisterTool( new COMMON_CONTROL );
546 m_toolManager->RegisterTool( new COMMON_TOOLS );
547 m_toolManager->RegisterTool( new ZOOM_TOOL );
548 m_toolManager->RegisterTool( new SCH_SELECTION_TOOL );
549 m_toolManager->RegisterTool( new PICKER_TOOL );
550 m_toolManager->RegisterTool( new SCH_INSPECTION_TOOL );
551 m_toolManager->RegisterTool( new SYMBOL_EDITOR_PIN_TOOL );
552 m_toolManager->RegisterTool( new SYMBOL_EDITOR_DRAWING_TOOLS );
553 m_toolManager->RegisterTool( new EE_GRAPHIC_TOOL );
554 m_toolManager->RegisterTool( new SCH_POINT_EDITOR );
555 m_toolManager->RegisterTool( new SCH_FIND_REPLACE_TOOL );
556 m_toolManager->RegisterTool( new SYMBOL_EDITOR_MOVE_TOOL );
557 m_toolManager->RegisterTool( new SYMBOL_EDITOR_EDIT_TOOL );
558 m_toolManager->RegisterTool( new LIBRARY_EDITOR_CONTROL );
559 m_toolManager->RegisterTool( new SYMBOL_EDITOR_CONTROL );
560 m_toolManager->RegisterTool( new PROPERTIES_TOOL );
561 m_toolManager->RegisterTool( new EMBED_TOOL );
562 m_toolManager->InitTools();
563
564 // Run the selection tool, it is supposed to be always active
565 m_toolManager->InvokeTool( "common.InteractiveSelection" );
566
568}
569
570
572{
574
575 ACTION_MANAGER* mgr = m_toolManager->GetActionManager();
576 EDITOR_CONDITIONS cond( this );
577
578 wxASSERT( mgr );
579
580#define ENABLE( x ) ACTION_CONDITIONS().Enable( x )
581#define CHECK( x ) ACTION_CONDITIONS().Check( x )
582
583 auto haveSymbolCond =
584 [this]( const SELECTION& )
585 {
586 return m_symbol;
587 };
588
589 auto isGraphicallyEditableCond =
590 [this]( const SELECTION& )
591 {
593 };
594
595 auto isEditableInAliasCond =
596 [this]( const SELECTION& )
597 {
598 // Less restrictive than isGraphicallyEditableCond
599 // Symbols fields (root symbols and aliases) from the new s-expression libraries
600 // or in the schematic are editable.
601 return IsSymbolEditable();
602 };
603
604 auto canUpdateFieldsCond =
605 [this]( const SELECTION& )
606 {
607 return IsSymbolEditable() && m_symbol && m_symbol->CanUpdateFieldsFromParent();
608 };
609
610 auto symbolModifiedCondition =
611 [this]( const SELECTION& sel )
612 {
613 return m_libMgr && m_libMgr->IsSymbolModified( GetTargetLibId().GetLibItemName(),
614 GetTargetLibId().GetLibNickname() );
615 };
616
617 auto libSelectedCondition =
618 [this]( const SELECTION& sel )
619 {
620 return !GetTargetLibId().GetLibNickname().empty();
621 };
622
623 auto canEditProperties =
624 [this]( const SELECTION& sel )
625 {
627 };
628
629 auto symbolSelectedInTreeCondition =
630 [this]( const SELECTION& sel )
631 {
632 LIB_ID targetLibId = GetTargetLibId();
633 return !targetLibId.GetLibNickname().empty() && !targetLibId.GetLibItemName().empty();
634 };
635
636 auto saveSymbolAsCondition =
637 [this]( const SELECTION& aSel )
638 {
639 return getTargetSymbol() != nullptr;
640 };
641
642 const auto isSymbolFromSchematicCond =
643 [this]( const SELECTION& )
644 {
645 return IsSymbolFromSchematic();
646 };
647
648 // clang-format off
651 mgr->SetConditions( SCH_ACTIONS::saveLibraryAs, ENABLE( libSelectedCondition ) );
652 mgr->SetConditions( SCH_ACTIONS::saveSymbolAs, ENABLE( saveSymbolAsCondition ) );
653 mgr->SetConditions( SCH_ACTIONS::saveSymbolCopyAs, ENABLE( saveSymbolAsCondition ) );
656 mgr->SetConditions( SCH_ACTIONS::editLibSymbolWithLibEdit, ENABLE( isSymbolFromSchematicCond ) );
657
658 mgr->SetConditions( ACTIONS::undo, ENABLE( haveSymbolCond && cond.UndoAvailable() ) );
659 mgr->SetConditions( ACTIONS::redo, ENABLE( haveSymbolCond && cond.RedoAvailable() ) );
660 mgr->SetConditions( ACTIONS::revert, ENABLE( symbolModifiedCondition ) );
661
664
665 mgr->SetConditions( ACTIONS::cut, ENABLE( isGraphicallyEditableCond ) );
666 mgr->SetConditions( ACTIONS::copy, ENABLE( haveSymbolCond ) );
667 mgr->SetConditions( ACTIONS::copyAsText, ENABLE( haveSymbolCond ) );
668 mgr->SetConditions( ACTIONS::paste, ENABLE( isGraphicallyEditableCond && SELECTION_CONDITIONS::Idle && cond.NoActiveTool() ) );
669 mgr->SetConditions( ACTIONS::doDelete, ENABLE( isGraphicallyEditableCond ) );
670 mgr->SetConditions( ACTIONS::duplicate, ENABLE( isGraphicallyEditableCond ) );
671 mgr->SetConditions( ACTIONS::selectAll, ENABLE( haveSymbolCond ) );
672 mgr->SetConditions( ACTIONS::unselectAll, ENABLE( haveSymbolCond ) );
673
674 // These actions in symbol editor when editing alias field rotations are allowed.
676 .HotkeyEnable( isEditableInAliasCond ) );
678 .HotkeyEnable( isEditableInAliasCond ) );
679
680 mgr->SetConditions( SCH_ACTIONS::mirrorH, ENABLE( SELECTION_CONDITIONS::NotEmpty && isGraphicallyEditableCond )
681 .HotkeyEnable( isGraphicallyEditableCond ) );
682 mgr->SetConditions( SCH_ACTIONS::mirrorV, ENABLE( SELECTION_CONDITIONS::NotEmpty && isGraphicallyEditableCond )
683 .HotkeyEnable( isGraphicallyEditableCond ) );
684
687 // clang-format on
688
689 auto pinTypeCond =
690 [this]( const SELECTION& )
691 {
693 };
694
695 auto hiddenPinCond =
696 [this]( const SELECTION& )
697 {
699 };
700
701 auto hiddenFieldCond =
702 [this]( const SELECTION& )
703 {
705 };
706
707 auto showPinAltIconsCond =
708 [this]( const SELECTION& )
709 {
711 };
712
713 auto showLibraryTreeCond =
714 [this]( const SELECTION& )
715 {
716 return IsLibraryTreeShown();
717 };
718
719 auto propertiesCond =
720 [this] ( const SELECTION& )
721 {
722 return m_auimgr.GetPane( PropertiesPaneName() ).IsShown();
723 };
724
727 mgr->SetConditions( ACTIONS::showLibraryTree, CHECK( showLibraryTreeCond ) );
728 mgr->SetConditions( ACTIONS::showProperties, CHECK( propertiesCond ) );
729 mgr->SetConditions( SCH_ACTIONS::showHiddenPins, CHECK( hiddenPinCond ) );
730 mgr->SetConditions( SCH_ACTIONS::showHiddenFields, CHECK( hiddenFieldCond ) );
731 mgr->SetConditions( SCH_ACTIONS::togglePinAltIcons, CHECK( showPinAltIconsCond ) );
732
733 auto multiUnitModeCond =
734 [this]( const SELECTION& )
735 {
736 return m_symbol && m_symbol->IsMultiUnit() && !m_symbol->UnitsLocked();
737 };
738
739 auto multiBodyStyleModeCond =
740 [this]( const SELECTION& )
741 {
742 return m_symbol && m_symbol->IsMultiBodyStyle();
743 };
744
745 auto syncedPinsModeCond =
746 [this]( const SELECTION& )
747 {
748 return SynchronizePins();
749 };
750
751 auto haveDatasheetCond =
752 [this]( const SELECTION& )
753 {
754 return m_symbol && !m_symbol->GetDatasheetField().GetText().IsEmpty();
755 };
756
757 mgr->SetConditions( ACTIONS::showDatasheet, ENABLE( haveDatasheetCond ) );
758 mgr->SetConditions( SCH_ACTIONS::symbolProperties, ENABLE( symbolSelectedInTreeCondition || ( canEditProperties && haveSymbolCond ) ) );
759 mgr->SetConditions( SCH_ACTIONS::runERC, ENABLE( haveSymbolCond ) );
760 mgr->SetConditions( SCH_ACTIONS::pinTable, ENABLE( isGraphicallyEditableCond && haveSymbolCond ) );
761 mgr->SetConditions( SCH_ACTIONS::editSymbolPinMaps, ENABLE( isGraphicallyEditableCond && haveSymbolCond ) );
762 mgr->SetConditions( SCH_ACTIONS::updateSymbolFields, ENABLE( canUpdateFieldsCond ) );
763 mgr->SetConditions( SCH_ACTIONS::cycleBodyStyle, ENABLE( multiBodyStyleModeCond ) );
764
765 mgr->SetConditions( SCH_ACTIONS::toggleSyncedPinsMode, ACTION_CONDITIONS().Enable( multiUnitModeCond ).Check( syncedPinsModeCond ) );
766
767// Only enable a tool if the symbol is edtable
768#define EDIT_TOOL( tool ) ACTION_CONDITIONS().Enable( isGraphicallyEditableCond ).Check( cond.CurrentTool( tool ) )
769
779 setArcModeConditions( SCH_ACTIONS::drawArc, isGraphicallyEditableCond );
785
786#undef CHECK
787#undef ENABLE
788#undef EDIT_TOOL
789}
790
791
793{
794 wxLogTrace( traceApi, "Symbol editor frame: EDA_EVT_PLUGIN_AVAILABILITY_CHANGED" );
797 aEvt.Skip();
798}
799
800
802{
803 if( IsContentModified() )
804 {
805 wxString msg = _( "Save changes to '%s' before closing?" );
806
807 if( !HandleUnsavedChanges( this, wxString::Format( msg, m_reference ),
808 [&]() -> bool
809 {
810 SCH_EDIT_FRAME* schframe = (SCH_EDIT_FRAME*) Kiway().Player( FRAME_SCH, false );
811 LIB_SYMBOL* symbol = GetCurSymbol();
812
813 if( schframe && symbol ) // Should be always the case
814 return schframe->SaveSymbolToSchematic( *symbol, m_schematicSymbolUUID );
815
816 return false;
817 } ) )
818 {
819 return false;
820 }
821 }
822
823 if( doClose )
824 SetCurSymbol( nullptr, false );
825
826 return true;
827}
828
829
830bool SYMBOL_EDIT_FRAME::canCloseWindow( wxCloseEvent& aEvent )
831{
832 // Shutdown blocks must be determined and vetoed as early as possible, before any modal prompt.
833 // IsContentModified only sees the active tab, so also account for dirty inactive instance tabs.
835 && aEvent.GetId() == wxEVT_QUERY_END_SESSION
837 {
838 aEvent.Veto();
839 return false;
840 }
841
843 {
844 aEvent.Veto();
845 return false;
846 }
847
848 // Prompt for any dirty inactive instance (symbols from the schematic) tabs, which the active-tab
849 // checks above miss.
851 return false;
852
853 // A dirty unsaved tab has no library buffer for saveAllLibraries to prompt about, so ask here
854 if( m_activeTab && m_activeTab->IsUnsaved() && GetScreen()->IsContentModified() )
855 {
856 wxString msg = wxString::Format( _( "Save changes to '%s' before closing?" ),
857 m_activeTab->GetDisplayName( true ) );
858
859 KIDIALOG dlg( this, msg, _( "Confirmation" ), wxYES_NO | wxCANCEL | wxICON_WARNING );
860 dlg.SetYesNoCancelLabels( _( "Save" ), _( "Discard Changes" ), _( "Cancel" ) );
861
862 switch( dlg.ShowModal() )
863 {
864 case wxID_YES:
865 if( !saveCurrentSymbol() )
866 {
867 aEvent.Veto();
868 return false;
869 }
870
871 break;
872
873 case wxID_NO:
874 break;
875
876 default:
877 aEvent.Veto();
878 return false;
879 }
880 }
881
882 if( !saveAllLibraries( true ) )
883 return false;
884
885 // Save symbol tree column widths
886 m_libMgr->GetAdapter()->SaveSettings();
887
888 return true;
889}
890
891
893{
895
896 if( Pgm().ApiServerOrNull() )
897 {
899
900 if( Kiface().IsSingle() )
901 {
904 }
905 }
906
907 wxTheApp->Unbind( EDA_EVT_PLUGIN_AVAILABILITY_CHANGED,
909
910 if( GetLibTree() )
912
913 delete m_toolManager;
914 m_toolManager = nullptr;
915
916 Destroy();
917}
918
919
921{
922 if( m_unitSelectBox )
923 {
924 if( m_unitSelectBox->GetCount() != 0 )
925 m_unitSelectBox->Clear();
926
927 if( !m_symbol || m_symbol->GetUnitCount() <= 1 )
928 {
929 m_unit = 1;
930 m_unitSelectBox->Append( wxEmptyString );
931 }
932 else
933 {
934 for( int i = 0; i < m_symbol->GetUnitCount(); i++ )
935 m_unitSelectBox->Append( m_symbol->GetUnitDisplayName( i + 1, true ) );
936 }
937
938 // Ensure the selected unit is compatible with the number of units of the current symbol:
939 if( m_symbol && m_symbol->GetUnitCount() < m_unit )
940 m_unit = 1;
941
942 m_unitSelectBox->SetSelection( ( m_unit > 0 ) ? m_unit - 1 : 0 );
943 }
944
946 {
947 if( m_bodyStyleSelectBox->GetCount() != 0 )
948 m_bodyStyleSelectBox->Clear();
949
950 if( !m_symbol || !m_symbol->IsMultiBodyStyle() )
951 {
952 m_bodyStyle = 1;
953 m_bodyStyleSelectBox->Append( wxEmptyString );
954 }
955 else if( m_symbol && m_symbol->HasDeMorganBodyStyles() )
956 {
957 m_bodyStyleSelectBox->Append( wxGetTranslation( DEMORGAN_STD ) );
958 m_bodyStyleSelectBox->Append( wxGetTranslation( DEMORGAN_ALT ) );
959 }
960 else
961 {
962 for( int i = 0; i < m_symbol->GetBodyStyleCount(); i++ )
963 m_bodyStyleSelectBox->Append( m_symbol->GetBodyStyleNames()[i] );
964 }
965
966 // Ensure the selected body style is compatible with the number of body styles of the current symbol:
967 if( m_symbol && m_symbol->GetBodyStyleCount() < m_bodyStyle )
968 m_bodyStyle = 1;
969
970 m_bodyStyleSelectBox->SetSelection( ( m_bodyStyle > 0 ) ? m_bodyStyle - 1 : 0 );
971 }
972}
973
974
976{
977 if( !m_propertiesPanel )
978 return;
979
980 bool show = !m_propertiesPanel->IsShownOnScreen();
981
982 wxAuiPaneInfo& propertiesPaneInfo = m_auimgr.GetPane( PropertiesPaneName() );
983 propertiesPaneInfo.Show( show );
985
986 if( show )
987 SetAuiPaneSize( m_auimgr, propertiesPaneInfo, m_settings->m_AuiPanels.properties_panel_width, -1 );
988 else
989 m_settings->m_AuiPanels.properties_panel_width = m_propertiesPanel->GetSize().x;
990
991 m_auimgr.Update();
992 Refresh();
993}
994
995
997{
998 // An explicit toggle makes the live visibility authoritative, so drop any pending restore that
999 // LoadSymbolFromSchematic's auto-hide left behind.
1001
1002 wxAuiPaneInfo& treePane = m_auimgr.GetPane( m_treePane );
1003 treePane.Show( !IsLibraryTreeShown() );
1005 m_auimgr.Update();
1006 Refresh();
1007}
1008
1009
1011{
1012 return const_cast<wxAuiManager&>( m_auimgr ).GetPane( m_treePane ).IsShown();
1013}
1014
1015
1020
1021
1023{
1024 m_treePane->Freeze();
1025 m_libMgr->GetAdapter()->Freeze();
1026}
1027
1028
1030{
1031 m_libMgr->GetAdapter()->Thaw();
1032 m_treePane->Thaw();
1033}
1034
1035
1036void SYMBOL_EDIT_FRAME::OnExitKiCad( wxCommandEvent& event )
1037{
1038 Kiway().OnKiCadExit();
1039}
1040
1041
1042void SYMBOL_EDIT_FRAME::OnUpdateUnitNumber( wxUpdateUIEvent& event )
1043{
1044 event.Enable( m_symbol && m_symbol->GetUnitCount() > 1 );
1045}
1046
1047
1048void SYMBOL_EDIT_FRAME::OnSelectUnit( wxCommandEvent& event )
1049{
1050 if( event.GetSelection() == wxNOT_FOUND )
1051 return;
1052
1053 SetUnit( event.GetSelection() + 1 );
1054}
1055
1056
1057void SYMBOL_EDIT_FRAME::OnUpdateBodyStyle( wxUpdateUIEvent& event )
1058{
1059 event.Enable( m_symbol && m_symbol->GetBodyStyleCount() > 1 );
1060}
1061
1062
1063void SYMBOL_EDIT_FRAME::OnSelectBodyStyle( wxCommandEvent& event )
1064{
1065 if( event.GetSelection() == wxNOT_FOUND )
1066 return;
1067
1068 SetBodyStyle( event.GetSelection() + 1 );
1069}
1070
1071
1073{
1074 if( m_symbol )
1075 {
1077
1078 if( std::optional<LIBRARY_TABLE_ROW*> row = adapter->GetRow( m_symbol->GetLibNickname() ); row.has_value() )
1079 {
1080 if( ( *row )->Type() == SCH_IO_MGR::ShowType( SCH_IO_MGR::SCH_LEGACY ) )
1081 return true;
1082 }
1083 }
1084
1085 return false;
1086}
1087
1088
1090{
1091 // Use CallAfter so that we update the canvas before waiting for the infobar animation
1092 CallAfter(
1093 [this]()
1094 {
1095 WX_INFOBAR& infobar = *GetInfoBar();
1096 infobar.RemoveAllButtons();
1097
1098 wxArrayString msgs;
1099 int infobarFlags = wxICON_INFORMATION;
1100 wxString symbolName;
1101 wxString libName;
1102
1103 if( m_symbol )
1104 {
1105 symbolName = m_symbol->GetName();
1106 libName = m_symbol->GetLibId().GetLibNickname().wx_str();
1107 }
1108
1109 if( IsSymbolFromSchematic() )
1110 {
1111 msgs.push_back( wxString::Format( _( "Editing %s from schematic. Saving will update the "
1112 "schematic only." ),
1113 m_reference ) );
1114
1115 infobar.AddLink( wxString::Format( _( "Open symbol from library %s" ), UnescapeString( libName ) ),
1116 [this]( wxHyperlinkEvent& aEvent )
1117 {
1119 } );
1120 }
1121 else if( IsSymbolFromLegacyLibrary() )
1122 {
1123 msgs.push_back( _( "Symbols in legacy libraries are not editable. Use Manage Symbol "
1124 "Libraries to migrate to current format." ) );
1125
1126 infobar.AddLink( _( "Manage symbol libraries" ),
1127 [this]( wxHyperlinkEvent& aEvent )
1128 {
1130 } );
1131 }
1132 else if( IsSymbolAlias() )
1133 {
1134 msgs.push_back( wxString::Format( _( "Symbol %s is a derived symbol. Symbol graphics will "
1135 "not be editable." ),
1136 UnescapeString( symbolName ) ) );
1137
1138 // Don't assume the parent symbol shared pointer is still valid.
1139 if( std::shared_ptr<LIB_SYMBOL> rootSymbol = m_symbol->GetRootSymbol() )
1140 {
1141 int unit = GetUnit();
1142 int bodyStyle = GetBodyStyle();
1143 wxString rootSymbolName = rootSymbol->GetName();
1144
1145 infobar.AddLink( wxString::Format( _( "Open %s" ), UnescapeString( rootSymbolName ) ),
1146 [this, libName, rootSymbolName, unit, bodyStyle]( wxHyperlinkEvent& aEvent )
1147 {
1148 LoadSymbolFromLib( libName, rootSymbolName, unit, bodyStyle );
1149 } );
1150 }
1151 }
1152
1153 if( m_symbol
1155 && m_libMgr->IsLibraryReadOnly( m_symbol->GetLibId().GetFullLibraryName() ) )
1156 {
1157 msgs.push_back( _( "Library is read-only. Changes cannot be saved to this library." ) );
1158
1159 infobar.AddLink( _( "Create an editable copy" ),
1160 [this, libName]( wxHyperlinkEvent& aEvent )
1161 {
1162 wxString msg = wxString::Format( _( "Create an editable copy of the symbol or "
1163 "the entire library (%s)?" ),
1164 UnescapeString( libName ) );
1165
1166 KIDIALOG errorDlg( this, msg, _( "Select type of item to save" ),
1167 wxYES_NO | wxCANCEL | wxICON_QUESTION );
1168 // These buttons are in a weird order(?)
1169 errorDlg.SetYesNoCancelLabels( _( "Copy symbol" ), _( "Cancel" ), _( "Copy library" ) );
1170
1171 int choice = errorDlg.ShowModal();
1172
1173 switch( choice )
1174 {
1175 case wxID_YES: SaveSymbolCopyAs( true ); break;
1176 case wxID_CANCEL: SaveLibraryAs(); break;
1177 default: return;
1178 }
1179
1180 // Get rid of the save-will-update-schematic-only (or any other dismissable warning)
1181 WX_INFOBAR* local_infobar = GetInfoBar();
1182
1183 if( local_infobar->IsShownOnScreen() && local_infobar->HasCloseButton() )
1184 local_infobar->Dismiss();
1185
1187 } );
1188 }
1189
1190 if( msgs.empty() )
1191 {
1192 infobar.Dismiss();
1193 }
1194 else
1195 {
1196 wxString msg = wxJoin( msgs, '\n', '\0' );
1197 infobar.AddCloseButton();
1198 infobar.ShowMessage( msg, infobarFlags );
1199 }
1200 } );
1201}
1202
1203
1204void SYMBOL_EDIT_FRAME::SetCurSymbol( LIB_SYMBOL* aSymbol, bool aUpdateZoom )
1205{
1206 wxCHECK( m_toolManager, /* void */ );
1207
1209 GetCanvas()->GetView()->Clear();
1210
1211 // Install the replacement and refresh the active context before freeing the old symbol, so the
1212 // context never observes a freed pointer.
1213 LIB_SYMBOL* oldSymbol = m_symbol;
1214
1215 m_symbol = aSymbol;
1216
1217 if( m_activeTab )
1218 m_activeTab->RefreshFrameOwnedObjects( m_symbol, static_cast<SCH_SCREEN*>( GetScreen() ) );
1219
1220 delete oldSymbol;
1221
1222 // select the current symbol in the tree widget
1224 GetLibTree()->SelectLibId( m_symbol->GetLibId() );
1225 else
1226 GetLibTree()->Unselect();
1227
1229
1237
1238 if( aUpdateZoom )
1240
1241 GetCanvas()->Refresh();
1242 m_propertiesPanel->UpdateData();
1243 updateInfoBar();
1244}
1245
1246
1252
1253
1255{
1257
1259
1260 if( !IsSymbolFromSchematic() && !( m_activeTab && m_activeTab->IsUnsaved() ) )
1261 {
1263 m_libMgr->UpdateSymbol( m_symbol, m_symbol->GetLibNickname() ); // UpdateSymbol() makes a copy
1264 }
1265
1266 if( m_isClosing )
1267 return;
1268
1269 // Clear preview so a later library-open gets its own tab instead of replacing this edited one.
1270 if( m_tabsPanel && m_activeTab )
1271 {
1272 m_activeTab->SetPreview( false );
1273
1274 if( int idx = m_tabsPanel->FindTab( m_activeTab->GetTabKey() ); idx >= 0 )
1275 m_tabsPanel->MarkModified( idx, true );
1276 }
1277
1279}
1280
1281
1283{
1284 wxCHECK( aUnit > 0 && aUnit <= GetCurSymbol()->GetUnitCount(), /* void*/ );
1285
1286 if( m_unit == aUnit )
1287 return;
1288
1291
1292 m_unit = aUnit;
1293
1294 if( m_unitSelectBox->GetSelection() != ( m_unit - 1 ) )
1295 m_unitSelectBox->SetSelection( m_unit - 1 );
1296
1298 RebuildView();
1300}
1301
1302
1304{
1305 wxCHECK( aBodyStyle > 0 && aBodyStyle <= GetCurSymbol()->GetBodyStyleCount(), /* void */ );
1306
1307 if( m_bodyStyle == aBodyStyle )
1308 return;
1309
1312
1313 m_bodyStyle = aBodyStyle;
1314
1315 if( m_bodyStyleSelectBox->GetSelection() != ( m_bodyStyle - 1 ) )
1316 m_bodyStyleSelectBox->SetSelection( m_bodyStyle - 1 );
1317
1318
1320 RebuildView();
1322}
1323
1324
1326{
1327 return m_settings && m_settings->m_SyncPinEdit && m_symbol && m_symbol->IsMultiUnit() && !m_symbol->UnitsLocked();
1328}
1329
1330
1331wxString SYMBOL_EDIT_FRAME::AddLibraryFile( bool aCreateNew )
1332{
1333 wxFileName fn = m_libMgr->GetUniqueLibraryName();
1334 bool useGlobalTable = true;
1335 FILEDLG_HOOK_NEW_LIBRARY tableChooser( useGlobalTable );
1336
1337 if( !LibraryFileBrowser( aCreateNew ? _( "New Symbol Library" ) : _( "Add Symbol Library" ),
1338 !aCreateNew, fn, FILEEXT::KiCadSymbolLibFileWildcard(),
1340 Pgm().GetSettingsManager().IsProjectOpenNotDummy() ? &tableChooser : nullptr ) )
1341 {
1342 return wxEmptyString;
1343 }
1344
1347
1348 LIBRARY_MANAGER& manager = Pgm().GetLibraryManager();
1349 std::optional<LIBRARY_TABLE*> optTable = manager.Table( LIBRARY_TABLE_TYPE::SYMBOL, scope );
1350
1351 wxCHECK( optTable.has_value(), wxEmptyString );
1352 LIBRARY_TABLE* table = optTable.value();
1353
1354 wxString libName = fn.GetName();
1355
1356 if( libName.IsEmpty() )
1357 return wxEmptyString;
1358
1360
1361 if( adapter->HasLibrary( libName ) )
1362 {
1363 DisplayError( this, wxString::Format( _( "Library '%s' already exists." ), libName ) );
1364 return wxEmptyString;
1365 }
1366
1367 if( aCreateNew )
1368 {
1369 // The file browser already asked to overwrite, so drop the old file here.
1370 // CreateLibrary fails on an existing path.
1371 if( fn.FileExists() && !wxRemoveFile( fn.GetFullPath() ) )
1372 {
1373 DisplayError( this, wxString::Format( _( "Could not overwrite the library file '%s'.\n"
1374 "Make sure you have write permissions and try again." ),
1375 fn.GetFullPath() ) );
1376 return wxEmptyString;
1377 }
1378
1379 if( !m_libMgr->CreateLibrary( fn.GetFullPath(), scope ) )
1380 {
1381 DisplayError( this, wxString::Format( _( "Could not create the library file '%s'.\n"
1382 "Make sure you have write permissions and try again." ),
1383 fn.GetFullPath() ) );
1384 return wxEmptyString;
1385 }
1386 }
1387 else
1388 {
1389 if( !m_libMgr->AddLibrary( fn.GetFullPath(), scope ) )
1390 {
1391 DisplayError( this, _( "Could not open the library file." ) );
1392 return wxEmptyString;
1393 }
1394 }
1395
1396 bool success = true;
1397
1398 // Tables are reinitialized by m_libMgr->AddLibrary(). So reinit table reference.
1399 optTable = manager.Table( LIBRARY_TABLE_TYPE::SYMBOL, scope );
1400 wxCHECK( optTable.has_value(), wxEmptyString );
1401 table = optTable.value();
1402
1403 table->Save().map_error(
1404 [&]( const LIBRARY_ERROR& aError )
1405 {
1406 KICAD_MESSAGE_DIALOG dlg( this, _( "Error saving library table." ), _( "File Save Error" ),
1407 wxOK | wxICON_ERROR );
1408 dlg.SetExtendedMessage( aError.message );
1409 dlg.ShowModal();
1410
1411 success = false;
1412 } );
1413
1414 if( success )
1415 adapter->LoadOne( fn.GetName() );
1416
1417 SyncLibraries( false );
1418
1419 if( m_treePane )
1420 {
1421 LIB_ID libId( fn.GetName(), wxEmptyString );
1422 GetLibTree()->SelectLibId( libId );
1423 GetLibTree()->CenterLibId( libId );
1424 }
1425
1426 return fn.GetFullPath();
1427}
1428
1429
1430void SYMBOL_EDIT_FRAME::DdAddLibrary( wxString aLibFile )
1431{
1432 wxFileName fn = wxFileName( aLibFile );
1433 wxString libName = fn.GetName();
1434
1435 if( libName.IsEmpty() )
1436 return;
1437
1438 LIBRARY_MANAGER& manager = Pgm().GetLibraryManager();
1440
1441 if( adapter->HasLibrary( libName ) )
1442 {
1443 DisplayError( this, wxString::Format( _( "Library '%s' already exists." ), libName ) );
1444 return;
1445 }
1446
1447 if( !m_libMgr->AddLibrary( fn.GetFullPath(), LIBRARY_TABLE_SCOPE::PROJECT ) )
1448 {
1449 DisplayError( this, _( "Could not open the library file." ) );
1450 return;
1451 }
1452
1453 std::optional<LIBRARY_TABLE*> optTable = manager.Table( LIBRARY_TABLE_TYPE::SYMBOL, LIBRARY_TABLE_SCOPE::PROJECT );
1454 wxCHECK( optTable.has_value(), /* void */ );
1455 LIBRARY_TABLE* table = optTable.value();
1456 bool success = true;
1457
1458 table->Save().map_error(
1459 [&]( const LIBRARY_ERROR& aError )
1460 {
1461 KICAD_MESSAGE_DIALOG dlg( this, _( "Error saving library table." ), _( "File Save Error" ),
1462 wxOK | wxICON_ERROR );
1463 dlg.SetExtendedMessage( aError.message );
1464 dlg.ShowModal();
1465
1466 success = false;
1467 } );
1468
1469 if( success )
1470 adapter->LoadOne( libName );
1471
1472 std::string packet = fn.GetFullPath().ToStdString();
1475}
1476
1477
1479{
1480 return GetLibTree()->GetSelectedLibId( aUnit );
1481}
1482
1483
1488
1489int SYMBOL_EDIT_FRAME::GetTreeLIBIDs( std::vector<LIB_ID>& aSelection ) const
1490{
1491 return GetLibTree()->GetSelectedLibIds( aSelection );
1492}
1493
1494
1496{
1497 if( IsLibraryTreeShown() )
1498 {
1499 LIB_ID libId = GetTreeLIBID();
1500
1501 if( libId.IsValid() )
1502 return m_libMgr->GetSymbol( libId.GetLibItemName(), libId.GetLibNickname() );
1503 }
1504
1505 return m_symbol;
1506}
1507
1508
1510{
1511 LIB_ID id;
1512
1513 if( IsLibraryTreeShown() )
1514 id = GetTreeLIBID();
1515
1516 if( id.GetLibNickname().empty() && m_symbol )
1517 id = m_symbol->GetLibId();
1518
1519 return id;
1520}
1521
1522
1523std::vector<LIB_ID> SYMBOL_EDIT_FRAME::GetSelectedLibIds() const
1524{
1525 std::vector<LIB_ID> ids;
1526 GetTreeLIBIDs( ids );
1527 return ids;
1528}
1529
1530
1532{
1533 return GetTargetLibId().GetLibNickname();
1534}
1535
1536
1537void SYMBOL_EDIT_FRAME::SyncLibraries( bool aShowProgress, bool aPreloadCancelled, const wxString& aForceRefresh )
1538{
1539 wxLogTrace( wxT( "KICAD_TABS_DBG" ),
1540 wxT( "SYMBOL_EDIT_FRAME::SyncLibraries enter (progress=%d, forceRefresh='%s')" ),
1541 aShowProgress, aForceRefresh );
1542
1543 // Prevent re-entrant calls. The progress dialog yields the event loop during Sync(),
1544 // which can dispatch queued UI events (e.g. menu clicks queued while the app was busy
1545 // loading libraries). A re-entrant call would corrupt the library tree mid-rebuild.
1547 {
1548 wxLogTrace( wxT( "KICAD_TABS_DBG" ), wxT( "SYMBOL_EDIT_FRAME::SyncLibraries re-entrant; skipping" ) );
1549 return;
1550 }
1551
1553
1554 auto resetGuard =
1555 [this]( bool* )
1556 {
1558 };
1559
1560 std::unique_ptr<bool, decltype( resetGuard )> guard( &m_syncLibrariesInProgress, resetGuard );
1561
1562 LIB_ID selected;
1563 std::vector<LIB_ID> expanded;
1564
1565 if( m_treePane )
1566 {
1567 selected = GetLibTree()->GetSelectedLibId();
1568 expanded = GetLibTree()->GetExpandedLibraries();
1569 }
1570
1571 // Ensure any in-progress background library preloading is complete before syncing the
1572 // tree. Without this, libraries still in LOADING state get skipped by Sync(), resulting
1573 // in an incomplete tree that requires a manual refresh to fully populate.
1575 adapter->BlockUntilLoaded();
1576
1577 if( aShowProgress )
1578 {
1579 APP_PROGRESS_DIALOG progressDlg( _( "Loading Symbol Libraries" ), wxEmptyString,
1580 m_libMgr->GetAdapter()->GetLibrariesCount(), this );
1581
1582 THROTTLE progressThrottle( std::chrono::milliseconds( 350 ) );
1583 int pendingProgress = 0;
1584 bool callbackFired = false;
1585 wxString pendingLibName;
1586
1587 m_libMgr->Sync( aForceRefresh,
1588 [&]( int progress, int max, const wxString& libName )
1589 {
1590 pendingProgress = progress;
1591 pendingLibName = libName;
1592 callbackFired = true;
1593
1594 if( progressThrottle.Ready() )
1595 progressDlg.Update( progress, wxString::Format( _( "Loading library '%s'..." ), libName ) );
1596 } );
1597
1598 if( callbackFired )
1599 progressDlg.Update( pendingProgress, wxString::Format( _( "Loading library '%s'..." ), pendingLibName ) );
1600 }
1601 else if( !aPreloadCancelled )
1602 {
1603 m_libMgr->Sync( aForceRefresh, [&]( int progress, int max, const wxString& libName ) {} );
1604 }
1605
1606 if( m_treePane )
1607 {
1608 wxDataViewItem found;
1609
1610 if( selected.IsValid() )
1611 {
1612 // Check if the previously selected item is still valid,
1613 // if not - it has to be unselected to prevent crash
1614 found = m_libMgr->GetAdapter()->FindItem( selected );
1615
1616 if( !found )
1617 GetLibTree()->Unselect();
1618 }
1619
1620 wxLogTrace( wxT( "KICAD_TABS_DBG" ), wxT( "SYMBOL_EDIT_FRAME::SyncLibraries Regenerate" ) );
1621 GetLibTree()->Regenerate( true );
1622
1623 // Sync() collapsed the tree, so re-expand the libraries that were open before it.
1624 for( const LIB_ID& libId : expanded )
1625 GetLibTree()->ExpandLibId( libId );
1626
1627 // Try to select the parent library, in case the symbol is not found
1628 if( !found && selected.IsValid() )
1629 {
1630 selected.SetLibItemName( "" );
1631 found = m_libMgr->GetAdapter()->FindItem( selected );
1632
1633 if( found )
1634 GetLibTree()->SelectLibId( selected );
1635 }
1636 }
1637
1638 wxLogTrace( wxT( "KICAD_TABS_DBG" ), wxT( "SYMBOL_EDIT_FRAME::SyncLibraries exit" ) );
1639}
1640
1641
1646
1647
1649{
1650 GetLibTree()->SelectLibId( aLibID );
1651}
1652
1653
1654void SYMBOL_EDIT_FRAME::UpdateLibraryTree( const wxDataViewItem& aTreeItem, LIB_SYMBOL* aSymbol )
1655{
1656 if( aTreeItem.IsOk() ) // Can be not found in tree if the current footprint is imported
1657 // from file therefore not yet in tree.
1658 {
1659 static_cast<LIB_TREE_NODE_ITEM*>( aTreeItem.GetID() )->Update( aSymbol );
1661 }
1662}
1663
1664
1665bool SYMBOL_EDIT_FRAME::backupLibrary( const wxFileName& aOriginalFile, wxString& aErrorMsg )
1666{
1667 wxFileName backupFileName;
1668
1669 if( !aOriginalFile.IsDir() && aOriginalFile.FileExists() )
1670 {
1671 backupFileName = aOriginalFile;
1672 backupFileName.SetExt( wxT( "bak" ) );
1673
1674 if( backupFileName.FileExists() )
1675 {
1676 if( !wxRemoveFile( backupFileName.GetFullPath() ) )
1677 {
1678 aErrorMsg.Printf( _( "Failed to remove existing library backup file '%s'." ),
1679 backupFileName.GetFullPath() );
1680 return false;
1681 }
1682 }
1683
1684 if( !wxCopyFile( aOriginalFile.GetFullPath(), backupFileName.GetFullPath() ) )
1685 {
1686 aErrorMsg.Printf( _( "Failed to save backup to '%s'." ), backupFileName.GetFullPath() );
1687 return false;
1688 }
1689 }
1690 else if( aOriginalFile.IsDir() && aOriginalFile.DirExists() )
1691 {
1692 backupFileName.SetPath( aOriginalFile.GetPath() );
1693 backupFileName.SetName( backupFileName.GetDirs().Last() + wxString( "_backup" ) );
1694 backupFileName.SetExt( "zip" );
1695
1696 std::vector<wxString> libFiles;
1697 wxDir libDir( aOriginalFile.GetPath() );
1698 UNPACKED_SYMBOL_LIBRARY_DIR_TRAVERSER libTraverser( libFiles );
1699
1700 if( backupFileName.FileExists() )
1701 {
1702 if( !wxRemoveFile( backupFileName.GetFullPath() ) )
1703 {
1704 aErrorMsg.Printf( _( "Failed to remove existing library backup file '%s'." ),
1705 backupFileName.GetFullPath() );
1706 return false;
1707 }
1708 }
1709
1710 if( !libDir.IsOpened() )
1711 {
1712 aErrorMsg.Printf( _( "Error opening unpacked library directory: '%s'." ), aOriginalFile.GetPath() );
1713 return false;
1714 }
1715
1716 libDir.Traverse( libTraverser, wxEmptyString, wxDIR_FILES );
1717
1718 wxFFileOutputStream ostream( backupFileName.GetFullPath() );
1719
1720 if( !ostream.IsOk() )
1721 {
1722 aErrorMsg.Printf( _( "Failed to create library backup file '%s'." ), backupFileName.GetFullPath() );
1723 return false;
1724 }
1725
1726 // Use a large I/O buffer to improve compatibility with cloud-synced folders.
1727 if( FILE* fp = ostream.GetFile()->fp() )
1728 setvbuf( fp, nullptr, _IOFBF, KIPLATFORM::IO::CLOUD_SYNC_BUFFER_SIZE );
1729
1730 wxZipOutputStream zipstream( ostream, -1, wxConvUTF8 );
1731
1732 for( const wxString& fileName : libFiles )
1733 {
1734 wxFileName fn( fileName );
1735 wxFileSystem fsFile;
1736
1737 fn.MakeRelativeTo( aOriginalFile.GetPath() );
1738
1739 wxString relativeFn = fn.GetFullPath();
1740
1741 // Read input file and add it to the zip file:
1742 wxFSFile* infile = nullptr;
1743 wxString sysError;
1744
1745 {
1746 // Failures are reported through an error dialog, prevent wx from popping its own dialog.
1747 wxLogNull suppressSysErrorPopups;
1748 infile = fsFile.OpenFile( fileName );
1749
1750 if( !infile )
1751 {
1752 if( unsigned long code = wxSysErrorCode() )
1753 sysError = wxSysErrorMsgStr( code );
1754 }
1755 }
1756
1757 if( infile )
1758 {
1759 zipstream.PutNextEntry( relativeFn, infile->GetModificationTime() );
1760 infile->GetStream()->Read( zipstream );
1761 zipstream.CloseEntry();
1762
1763 delete infile;
1764 }
1765 else
1766 {
1767 if( sysError.IsEmpty() )
1768 aErrorMsg.Printf( _( "Failed to archive file '%s'." ), relativeFn );
1769 else
1770 aErrorMsg.Printf( _( "Failed to archive file '%s': %s" ), relativeFn, sysError );
1771
1772 zipstream.Close();
1773 return false;
1774 }
1775 }
1776
1777 if( !zipstream.Close() )
1778 {
1779 aErrorMsg.Printf( _( "Failed to create file '%s'." ), backupFileName.GetFullPath() );
1780 return false;
1781 }
1782 }
1783
1784 return true;
1785}
1786
1787
1789{
1790 // This will return the root symbol of any alias
1791 LIB_SYMBOL* symbol = m_libMgr->GetBufferedSymbol( aLibId.GetLibItemName(), aLibId.GetLibNickname() );
1792
1793 // Now we can compare the libId of the current symbol and the root symbol
1794 return ( symbol && m_symbol && symbol->GetLibId() == m_symbol->GetLibId() );
1795}
1796
1797
1799{
1800 GetLibTree()->Unselect();
1801
1802 // Tear down every tab first so no context observes the about-to-be-deleted working symbol.
1804
1805 SetCurSymbol( nullptr, false );
1809 Refresh();
1810}
1811
1812
1814{
1816
1818 {
1819 GetRenderSettings()->m_ShowPinsElectricalType = cfg->m_ShowPinElectricalType;
1820 GetRenderSettings()->m_ShowHiddenPins = cfg->m_ShowHiddenPins;
1821 GetRenderSettings()->m_ShowHiddenFields = cfg->m_ShowHiddenFields;
1822 GetRenderSettings()->m_ShowPinAltIcons = cfg->m_ShowPinAltIcons;
1823
1824 GetGalDisplayOptions().ReadWindowSettings( cfg->m_Window );
1825 }
1826
1827 if( m_symbol )
1828 m_symbol->ClearCaches();
1829
1831
1833 GetCanvas()->Refresh();
1834
1836
1837 if( aFlags & ENVVARS_CHANGED )
1838 SyncLibraries( true );
1839
1840 Layout();
1841 SendSizeEvent();
1842}
1843
1844
1846{
1847 // call my base class
1849
1850 // tooltips in toolbars
1852
1853 // For some obscure reason, the AUI manager hides the first modified pane.
1854 // So force show panes
1855 wxAuiPaneInfo& tree_pane_info = m_auimgr.GetPane( m_treePane );
1856 bool tree_shown = tree_pane_info.IsShown();
1857 tree_pane_info.Caption( _( "Libraries" ) );
1858 tree_pane_info.Show( tree_shown );
1859 m_auimgr.Update();
1860
1862
1863 // status bar
1865
1866 if( GetRenderSettings()->m_ShowPinsElectricalType )
1867 {
1869 GetCanvas()->Refresh();
1870 }
1871
1872 UpdateTitle();
1873}
1874
1875
1877{
1878 SCH_BASE_FRAME::SetScreen( aScreen );
1879
1880 if( m_toolManager )
1881 {
1882 m_toolManager->SetEnvironment( aScreen, GetCanvas()->GetView(), GetCanvas()->GetViewControls(), GetSettings(),
1883 this );
1885 }
1886}
1887
1888
1906
1907
1909{
1910 SyncLibraries( true );
1911
1912 if( m_symbol )
1913 {
1914 SCH_SELECTION_TOOL* selectionTool = m_toolManager->GetTool<SCH_SELECTION_TOOL>();
1915 SCH_SELECTION& selection = selectionTool->GetSelection();
1916
1917 for( SCH_ITEM& item : m_symbol->GetDrawItems() )
1918 {
1919 if( !alg::contains( selection, &item ) )
1920 item.ClearSelected();
1921 else
1922 item.SetSelected();
1923 }
1924
1925 m_symbol->ClearCaches();
1926 }
1927
1928 RebuildView();
1929}
1930
1931
1932const BOX2I SYMBOL_EDIT_FRAME::GetDocumentExtents( bool aIncludeAllVisible ) const
1933{
1934 if( !m_symbol )
1935 {
1936 // Gives a reasonable drawing area size
1937 int width = schIUScale.mmToIU( 50 );
1938 int height = schIUScale.mmToIU( 30 );
1939
1940 return BOX2I( VECTOR2I( -width/2, -height/2 ), VECTOR2I( width, height ) );
1941 }
1942 else
1943 {
1944 return m_symbol->Flatten()->GetUnitBoundingBox( m_unit, m_bodyStyle );
1945 }
1946}
1947
1948
1949void SYMBOL_EDIT_FRAME::FocusOnItem( EDA_ITEM* aItem, bool aAllowScroll )
1950{
1951 static KIID lastBrightenedItemID( niluuid );
1952
1953 SCH_ITEM* lastItem = nullptr;
1954
1955 // nullptr will clear the current focus
1956 if( aItem != nullptr && !aItem->IsSCH_ITEM() )
1957 return;
1958
1959 if( m_symbol )
1960 {
1961 for( SCH_PIN* pin : m_symbol->GetGraphicalPins( 0, 0 ) )
1962 {
1963 if( pin->m_Uuid == lastBrightenedItemID )
1964 lastItem = pin;
1965 }
1966
1967 std::vector<SCH_FIELD*> fields;
1968 m_symbol->GetFields( fields );
1969
1970 for( SCH_FIELD* field : fields )
1971 {
1972 if( field->m_Uuid == lastBrightenedItemID )
1973 lastItem = field;
1974 }
1975 }
1976
1977 if( lastItem && lastItem != aItem )
1978 {
1979 lastItem->ClearBrightened();
1980
1981 UpdateItem( lastItem );
1982 lastBrightenedItemID = niluuid;
1983 }
1984
1985 if( aItem )
1986 {
1987 if( aItem->IsSCH_ITEM() )
1988 {
1989 SCH_ITEM* item = static_cast<SCH_ITEM*>( aItem );
1990
1991 if( int unit = item->GetUnit() )
1992 SetUnit( unit );
1993
1994 if( int bodyStyle = item->GetBodyStyle() )
1995 SetBodyStyle( bodyStyle );
1996 }
1997
1998 if( !aItem->IsBrightened() )
1999 {
2000 aItem->SetBrightened();
2001
2002 UpdateItem( aItem );
2003 lastBrightenedItemID = aItem->m_Uuid;
2004 }
2005
2006 FocusOnLocation( VECTOR2I( aItem->GetFocusPosition().x, aItem->GetFocusPosition().y ), aAllowScroll );
2007 }
2008}
2009
2010
2012{
2013 const std::string& payload = mail.GetPayload();
2014
2015 wxLogTrace( wxT( "KICAD_TABS_DBG" ), wxT( "SYMBOL_EDIT_FRAME::KiwayMailIn cmd=%d" ), (int) mail.Command() );
2016
2017 switch( mail.Command() )
2018 {
2019 case MAIL_LIB_EDIT:
2020 if( !payload.empty() )
2021 {
2022 wxString uri( payload );
2023 wxString libNickname;
2024 wxString msg;
2025
2027 std::optional<const LIBRARY_TABLE_ROW*> libTableRow = adapter->FindRowByURI( uri );
2028
2029 if( !libTableRow )
2030 {
2031 msg.Printf( _( "The current configuration does not include the symbol library '%s'." ),
2032 uri );
2033 msg += wxS( "\n" ) + _( "Use Manage Symbol Libraries to edit the configuration." );
2034 DisplayErrorMessage( this, _( "Library not found in symbol library table." ), msg );
2035 break;
2036 }
2037
2038 libNickname = ( *libTableRow )->Nickname();
2039
2040 if( !adapter->HasLibrary( libNickname, true ) )
2041 {
2042 msg.Printf( _( "The symbol library '%s' is not enabled in the current configuration." ),
2043 UnescapeString( libNickname ) );
2044 msg += wxS( "\n" ) + _( "Use Manage Symbol Libraries to edit the configuration." );
2045 DisplayErrorMessage( this, _( "Symbol library not enabled." ), msg );
2046 break;
2047 }
2048
2049 if( m_treePane )
2050 {
2051 LIB_ID id( libNickname, wxEmptyString );
2052 GetLibTree()->SelectLibId( id );
2053 GetLibTree()->ExpandLibId( id );
2054 GetLibTree()->CenterLibId( id );
2055 }
2056 }
2057
2058 break;
2059
2060 case MAIL_RELOAD_LIB:
2061 {
2062 wxLogTrace( wxT( "KICAD_TABS_DBG" ), wxT( "SYMBOL_EDIT_FRAME::KiwayMailIn MAIL_RELOAD_LIB -> SyncLibraries" ) );
2063
2065
2066 // Suppress the progress dialog for this background reload. It would steal focus from the
2067 // editor that broadcast the reload, and the tree is already frozen around the sync.
2068 SyncLibraries( false );
2071
2072 break;
2073 }
2074
2076 {
2078 LIB_SYMBOL* symbol = GetCurSymbol();
2079
2080 wxLogTrace( traceLibWatch, "Received refresh symbol request for %s", payload );
2081
2082 if( !symbol )
2083 break;
2084
2085 // Capture the name now. UpdateLibraryBuffer() recreates the buffer, so reading it from the
2086 // buffer copy afterwards would be a use-after-free.
2087 const wxString refreshSymbolName = symbol->GetName();
2088
2089 // A modal dialog may be registered before wxGTK disables the frame. Refreshing the
2090 // symbol in either state would delete the LIB_SYMBOL being edited by the dialog.
2091 if( !IsEnabled() || Kiway().HasBlockingDialog() )
2092 {
2093 wxLogTrace( traceLibWatch, "Deferring symbol refresh; dialog is open on the symbol editor." );
2094 break;
2095 }
2096 // Defensive backstop for refresh mail that did not originate from this frame's debounce
2097 // timer (which already defers while a tool is active). An interactive tool holds
2098 // references into the current symbol, so replacing it here would crash; drop this refresh
2099 // and let the originating watcher retry.
2100 else if( !ToolStackIsEmpty() )
2101 {
2102 wxLogTrace( traceLibWatch, "Deferring symbol refresh; an interactive tool is active." );
2103 break;
2104 }
2105
2106 wxString libName = symbol->GetLibId().GetLibNickname();
2107 std::optional<const LIBRARY_TABLE_ROW*> row = adapter->GetRow( libName );
2108
2109 if( !row )
2110 return;
2111
2112 wxFileName libfullname( LIBRARY_MANAGER::GetFullURI( *row, true ) );
2113
2114 wxFileName changedLib( mail.GetPayload() );
2115
2116 wxLogTrace( traceLibWatch, "Received refresh symbol request for %s, current symbols is %s",
2117 changedLib.GetFullPath(), libfullname.GetFullPath() );
2118
2119 if( changedLib == libfullname )
2120 {
2121 wxLogTrace( traceLibWatch, "Refreshing symbol %s", refreshSymbolName );
2122
2123 m_libMgr->UpdateLibraryBuffer( libName );
2124
2125 if( LIB_SYMBOL* lib_symbol = m_libMgr->GetBufferedSymbol( refreshSymbolName, libName ) )
2126 {
2127 SetCurSymbol( new LIB_SYMBOL( *lib_symbol ), false );
2129
2130 if( m_toolManager )
2132 }
2133 }
2134
2135 break;
2136 }
2137
2138 default:
2139 break;
2140 }
2141}
2142
2143
2144std::unique_ptr<GRID_HELPER> SYMBOL_EDIT_FRAME::MakeGridHelper()
2145{
2146 return std::make_unique<EE_GRID_HELPER>( m_toolManager );
2147}
2148
2149
2151{
2152 // switches currently used canvas ( Cairo / OpenGL):
2153 SCH_BASE_FRAME::SwitchCanvas( aCanvasType );
2154
2155 // Set options specific to symbol editor (axies are always enabled):
2156 GetCanvas()->GetGAL()->SetAxesEnabled( true );
2158}
2159
2160
2162{
2163 wxCHECK( m_libMgr, false );
2164
2165 return m_libMgr->HasModifications();
2166}
2167
2168
2170{
2171 wxCHECK( m_libMgr, false );
2172
2173 // Test if the currently edited symbol is modified
2175 return true;
2176
2177 // Test if any library has been modified
2178 for( const wxString& libName : m_libMgr->GetLibraryNames() )
2179 {
2180 if( m_libMgr->IsLibraryModified( libName ) && !m_libMgr->IsLibraryReadOnly( libName ) )
2181 return true;
2182 }
2183
2184 return false;
2185}
2186
2187
2189{
2190 if( aItemCount == 0 )
2191 return;
2192
2193 UNDO_REDO_CONTAINER& list = ( whichList == UNDO_LIST ) ? m_undoList : m_redoList;
2194
2195 // UR_TRANSIENT is flagged on the picked item, not the wrapper, so the shared deleters miss it.
2196 // Free the items carrying UR_TRANSIENT. m_symbol never carries it, so the live copy is safe.
2197 if( aItemCount < 0 )
2198 {
2200 }
2201 else
2202 {
2203 for( int ii = 0; ii < aItemCount; ii++ )
2204 {
2205 if( list.m_CommandsList.size() == 0 )
2206 break;
2207
2208 PICKED_ITEMS_LIST* curr_cmd = list.m_CommandsList[0];
2209 list.m_CommandsList.erase( list.m_CommandsList.begin() );
2210
2211 for( unsigned jj = 0; jj < curr_cmd->GetCount(); ++jj )
2212 {
2213 EDA_ITEM* item = curr_cmd->GetPickedItem( jj );
2214
2215 if( item && item->HasFlag( UR_TRANSIENT ) && item != m_symbol )
2216 delete item;
2217 }
2218
2219 curr_cmd->ClearItemsList();
2220 delete curr_cmd; // Delete command
2221 }
2222 }
2223}
2224
2225
2227{
2228 return m_toolManager->GetTool<SCH_SELECTION_TOOL>()->GetSelection();
2229}
2230
2231
2233 bool aRestorePending, bool aTreeShownNow )
2234{
2235 // Auto-hiding a visible tree schedules its restore. A chained schematic edit finds the tree
2236 // already auto-hidden, so keep the pending restore rather than dropping it. An explicit user
2237 // toggle clears the flag elsewhere, so a tree hidden without a pending restore stays that way.
2238 if( aTreeShownNow )
2239 return true;
2240
2241 return aWasFromSchematic && aRestorePending;
2242}
2243
2244
2246{
2247 std::unique_ptr<LIB_SYMBOL> symbol = aSymbol->GetLibSymbolRef()->Flatten();
2248 wxCHECK( symbol, /* void */ );
2249
2250 symbol->SetLibId( aSymbol->GetLibId() );
2251
2252 // Take in account the symbol orientation and mirroring. to calculate the field
2253 // positions in symbol editor (i.e. no rotation, no mirroring)
2254 int orientation = aSymbol->GetOrientation() & ~( SYM_MIRROR_X | SYM_MIRROR_Y );
2255 int mirror = aSymbol->GetOrientation() & ( SYM_MIRROR_X | SYM_MIRROR_Y );
2256
2257 std::vector<SCH_FIELD> fullSetOfFields;
2258
2259 for( const SCH_FIELD& field : aSymbol->GetFields() )
2260 {
2261 VECTOR2I pos = field.GetPosition() - aSymbol->GetPosition();
2262 SCH_FIELD libField( symbol.get(), field.GetId() );
2263
2264 libField = field;
2265
2266 // The inverse transform is mirroring before, rotate after
2267 switch( mirror )
2268 {
2269 case SYM_MIRROR_X: pos.y = -pos.y; break;
2270 case SYM_MIRROR_Y: pos.x = -pos.x; break;
2271 default: break;
2272 }
2273
2274 switch( orientation )
2275 {
2276 case SYM_ORIENT_90:
2277 std::swap( pos.x, pos.y );
2278 pos.x = - pos.x;
2279 break;
2280 case SYM_ORIENT_270:
2281 std::swap( pos.x, pos.y );
2282 pos.y = - pos.y;
2283 break;
2284 case SYM_ORIENT_180:
2285 pos.x = - pos.x;
2286 pos.y = - pos.y;
2287 break;
2288 default:
2289 break;
2290 }
2291
2292 libField.SetPosition( pos );
2293
2294 fullSetOfFields.emplace_back( std::move( libField ) );
2295 }
2296
2297 symbol->SetFields( fullSetOfFields );
2298
2299 const wxString reference = symbol->GetReferenceField().GetText();
2300 const int unit = std::max( 1, aSymbol->GetUnit() );
2301 const int bodyStyle = std::max( 1, aSymbol->GetBodyStyle() );
2302
2303 // Optimize default edit options for this symbol
2304 // Usually if units are locked, graphic items are specific to each unit
2305 // and if units are interchangeable, graphic items are common to units
2306 SetDrawSpecificUnit( symbol->UnitsLocked() );
2307
2308 // Hand the transient working symbol/screen to a session-only instance tab, whose activation
2309 // restores the frame's schematic-source state so the save path routes back to the schematic.
2310 SCH_SCREEN* tmpScreen = new SCH_SCREEN();
2311
2312 setSymWatcher( nullptr );
2313
2314 SYMBOL_EDITOR_TAB_CONTEXT* ctx = findOrCreateSymbolInstanceTab( symbol.release(), tmpScreen,
2315 aSymbol->m_Uuid, reference, unit,
2316 bodyStyle );
2317 wxCHECK( ctx, /* void */ );
2318
2321
2322 // Auto-hide the tree while editing a schematic symbol, remembering to restore it in SaveSettings
2323 // so the user's preference survives a restart. Hide via the pane directly, not ToggleLibraryTree,
2324 // which would treat this as a user toggle and drop the pending restore.
2327
2328 if( IsLibraryTreeShown() )
2329 {
2330 m_auimgr.GetPane( m_treePane ).Show( false );
2332 m_auimgr.Update();
2333 Refresh();
2334 }
2335
2338 updateInfoBar();
2339
2340 // Let tools add things to the view if necessary
2341 if( m_toolManager )
2343
2345 GetCanvas()->Refresh();
2346}
2347
2348
2349bool SYMBOL_EDIT_FRAME::addLibTableEntry( const wxString& aLibFile, LIBRARY_TABLE_SCOPE aScope )
2350{
2351 wxFileName fn = aLibFile;
2352 wxFileName libTableFileName( Prj().GetProjectPath(), FILEEXT::SymbolLibraryTableFileName );
2353 wxString libNickname = fn.GetName();
2355 LIBRARY_MANAGER& manager = Pgm().GetLibraryManager();
2356 const ENV_VAR_MAP& envVars = Pgm().GetLocalEnvVariables();
2357
2358 if( adapter->HasLibrary( libNickname ) )
2359 {
2360 wxString tmp;
2361 int suffix = 1;
2362
2363 while( adapter->HasLibrary( libNickname ) )
2364 {
2365 tmp.Printf( "%s%d", fn.GetName(), suffix );
2366 libNickname = tmp;
2367 suffix += 1;
2368 }
2369 }
2370
2371 std::optional<LIBRARY_TABLE*> optTable = manager.Table( LIBRARY_TABLE_TYPE::SYMBOL, aScope );
2372 wxCHECK( optTable.has_value(), false );
2373 LIBRARY_TABLE* table = optTable.value();
2374
2375 LIBRARY_TABLE_ROW* row = &table->InsertRow();
2376
2377 row->SetNickname( libNickname );
2378
2379 // We cannot normalize against the current project path when saving to global table.
2380 wxString normalizedPath = NormalizePath( aLibFile, &envVars,
2381 aScope == LIBRARY_TABLE_SCOPE::PROJECT ? Prj().GetProjectPath()
2382 : wxString( wxEmptyString ) );
2383
2384 row->SetURI( normalizedPath );
2386
2387 bool success = true;
2388
2389 table->Save().map_error(
2390 [&]( const LIBRARY_ERROR& aError )
2391 {
2392 KICAD_MESSAGE_DIALOG dlg( this, _( "Error saving library table." ), _( "File Save Error" ),
2393 wxOK | wxICON_ERROR );
2394 dlg.SetExtendedMessage( aError.message );
2395 dlg.ShowModal();
2396
2397 success = false;
2398 } );
2399
2400 if( success )
2401 {
2402 manager.ReloadTables( aScope, { LIBRARY_TABLE_TYPE::SYMBOL } );
2403 adapter->LoadOne( libNickname );
2404 }
2405
2406 return success;
2407}
2408
2409
2410bool SYMBOL_EDIT_FRAME::replaceLibTableEntry( const wxString& aLibNickname, const wxString& aLibFile )
2411{
2413 LIBRARY_MANAGER& manager = Pgm().GetLibraryManager();
2414 LIBRARY_TABLE* table = nullptr;
2416
2417 // Check the global library table first because checking the project library table
2418 // checks the global library table as well due to library chaining.
2419 if( adapter->GetRow( aLibNickname, scope ) )
2420 {
2421 std::optional<LIBRARY_TABLE*> optTable = manager.Table( LIBRARY_TABLE_TYPE::SYMBOL, scope );
2422 wxCHECK( optTable.has_value(), false );
2423 table = optTable.value();
2424 }
2425 else
2426 {
2428
2429 if( adapter->GetRow( aLibNickname, scope ) )
2430 {
2431 std::optional<LIBRARY_TABLE*> optTable = manager.Table( LIBRARY_TABLE_TYPE::SYMBOL, scope );
2432
2433 if( optTable.has_value() )
2434 table = optTable.value();
2435 }
2436 }
2437
2438 wxCHECK( table, false );
2439
2440 std::optional<LIBRARY_TABLE_ROW*> optRow = adapter->GetRow( aLibNickname, scope );
2441 wxCHECK( optRow.has_value(), false );
2442 LIBRARY_TABLE_ROW* row = optRow.value();
2443
2444 const ENV_VAR_MAP& envVars = Pgm().GetLocalEnvVariables();
2445
2446 wxString projectPath;
2447
2448 if( scope == LIBRARY_TABLE_SCOPE::PROJECT )
2449 projectPath = Prj().GetProjectPath();
2450
2451 wxString normalizedPath = NormalizePath( aLibFile, &envVars, projectPath );
2452
2453 row->SetURI( normalizedPath );
2454 row->SetType( "KiCad" );
2455
2456 bool success = true;
2457
2458 table->Save().map_error(
2459 [&]( const LIBRARY_ERROR& aError )
2460 {
2461 KICAD_MESSAGE_DIALOG dlg( this, _( "Error saving library table." ), _( "File Save Error" ),
2462 wxOK | wxICON_ERROR );
2463 dlg.SetExtendedMessage( aError.message );
2464 dlg.ShowModal();
2465
2466 success = false;
2467 } );
2468
2469 if( success )
2470 {
2471 manager.ReloadTables( scope, { LIBRARY_TABLE_TYPE::SYMBOL } );
2472 adapter->LoadOne( aLibNickname );
2473 }
2474
2475 return success;
2476}
2477
2478
2480{
2481 return m_symbol && !m_symbol->IsRoot();
2482}
2483
2484
2489
2490
2492{
2493 // Cannot edit graphics of symbols from legacy libraries, or of symbol aliases
2494 // unless the symbol is from a schematic (in which case it is a working copy of the symbol).
2496}
2497
2498
2499void SYMBOL_EDIT_FRAME::UpdateItem( EDA_ITEM* aItem, bool isAddOrDelete, bool aUpdateRtree )
2500{
2501 SCH_BASE_FRAME::UpdateItem( aItem, isAddOrDelete, aUpdateRtree );
2502
2503 if( EDA_TEXT* eda_text = dynamic_cast<EDA_TEXT*>( aItem ) )
2504 {
2505 eda_text->ClearBoundingBoxCache();
2506 eda_text->ClearRenderCache();
2507 }
2508}
2509
2510
2512{
2513 wxAuiPaneInfo& treePane = m_auimgr.GetPane( m_treePane );
2514 wxAuiPaneInfo& propertiesPane = m_auimgr.GetPane( PropertiesPaneName() );
2515 wxAuiPaneInfo& selectionFilterPane = m_auimgr.GetPane( wxS( "SelectionFilter" ) );
2516
2517 // Don't give the selection filter its own visibility controls; instead show it if
2518 // anything else is visible
2519 bool showFilter = ( treePane.IsShown() && treePane.IsDocked() )
2520 || ( propertiesPane.IsShown() && propertiesPane.IsDocked() );
2521
2522 selectionFilterPane.Show( showFilter );
2523}
2524
2525
2527{
2528 // Returns the current render option for invisible fields
2530}
2531
2532
2534{
2535 // Returns the current render option for invisible pins
2537}
const KICOMMON_API wxEventTypeTag< wxCommandEvent > EDA_EVT_PLUGIN_AVAILABILITY_CHANGED
Notifies other parts of KiCad when plugin availability changes.
BASE_SCREEN class implementation.
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:130
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition bitmap.cpp:100
@ icon_libedit_32
@ icon_libedit_16
BOX2< VECTOR2I > BOX2I
Definition box2.h:914
BOX2< VECTOR2D > BOX2D
Definition box2.h:915
static TOOL_ACTION toggleGrid
Definition actions.h:194
static TOOL_ACTION paste
Definition actions.h:76
static TOOL_ACTION cancelInteractive
Definition actions.h:68
static TOOL_ACTION unselectAll
Definition actions.h:79
static TOOL_ACTION revert
Definition actions.h:58
static TOOL_ACTION showLibraryTree
Definition actions.h:160
static TOOL_ACTION copy
Definition actions.h:74
static TOOL_ACTION showDatasheet
Definition actions.h:263
static TOOL_ACTION toggleBoundingBoxes
Definition actions.h:153
static TOOL_ACTION saveAll
Definition actions.h:57
static TOOL_ACTION undo
Definition actions.h:71
static TOOL_ACTION duplicate
Definition actions.h:80
static TOOL_ACTION doDelete
Definition actions.h:81
static TOOL_ACTION selectionTool
Definition actions.h:247
static TOOL_ACTION save
Definition actions.h:54
static TOOL_ACTION zoomFitScreen
Definition actions.h:138
static TOOL_ACTION redo
Definition actions.h:72
static TOOL_ACTION deleteTool
Definition actions.h:82
static TOOL_ACTION zoomTool
Definition actions.h:142
static TOOL_ACTION selectionClear
Clear the current selection.
Definition actions.h:220
static TOOL_ACTION showProperties
Definition actions.h:262
static TOOL_ACTION cut
Definition actions.h:73
static TOOL_ACTION ddAddLibrary
Definition actions.h:63
static TOOL_ACTION copyAsText
Definition actions.h:75
static TOOL_ACTION toggleGridOverrides
Definition actions.h:195
static TOOL_ACTION selectAll
Definition actions.h:78
Manage TOOL_ACTION objects.
void SetConditions(const TOOL_ACTION &aAction, const ACTION_CONDITIONS &aConditions)
Set the conditions the UI elements for activating a specific tool action should use for determining t...
wxProgressDialog with the option to also update the application progress on the taskbar
virtual bool Update(int aValue, const wxString &aNewMsg=wxEmptyString, bool *aSkip=nullptr) override
APP_SETTINGS_BASE is a settings class that should be derived for each standalone KiCad application.
wxString m_ColorTheme
Active color theme name.
Handles how to draw a screen (a board, a schematic ...)
Definition base_screen.h:37
void SetContentModified(bool aModified=true)
Definition base_screen.h:55
constexpr void SetOrigin(const Vec &pos)
Definition box2.h:234
constexpr void SetSize(const SizeVec &size)
Definition box2.h:245
Color settings are a bit different than most of the settings objects in that there can be more than o...
Handle actions that are shared between different applications.
Handles action that are shared between different applications.
UNDO_REDO_CONTAINER m_undoList
void ShowChangedLanguage() override
Redraw the menus and what not in current language.
virtual void setupUIConditions()
Setup the UI conditions for the various actions and their controls in this frame.
virtual void ClearUndoRedoList()
Clear the undo and redo list using ClearUndoORRedoList()
SETTINGS_MANAGER * GetSettingsManager() const
UNDO_REDO_LIST
Specify whether we are interacting with the undo or redo stacks.
virtual void OnModify()
Must be called after a model change in order to set the "modify" flag and do other frame-specific pro...
ACTION_TOOLBAR * m_tbRight
TOOLBAR_SETTINGS * m_toolbarSettings
wxAuiManager m_auimgr
virtual void RecreateToolbars()
UNDO_REDO_CONTAINER m_redoList
ACTION_TOOLBAR * m_tbLeft
virtual void OnDropFiles(wxDropFilesEvent &aEvent)
Handle event fired when a file is dropped to the window.
std::map< const wxString, TOOL_ACTION * > m_acceptedExts
Associate file extensions with action to execute.
ACTION_TOOLBAR * m_tbTopMain
wxString m_aboutTitle
bool m_isClosing
Set by the close window event handler after frames are asked if they can close.
void ReCreateMenuBar()
Recreate the menu bar.
WX_INFOBAR * GetInfoBar()
COLOR_SETTINGS * m_colorSettings
void OnSelectGrid(wxCommandEvent &event)
Command event handler for selecting grid sizes.
void setupUnits(APP_SETTINGS_BASE *aCfg)
void setArcModeConditions(const TOOL_ACTION &aDrawArc, const std::function< bool(const SELECTION &)> &aEnable)
Check each arc mode's tool action while the arc tool runs in that mode.
virtual void SwitchCanvas(EDA_DRAW_PANEL_GAL::GAL_TYPE aCanvasType)
Change the current rendering backend.
virtual void OnSelectZoom(wxCommandEvent &event)
Set the zoom factor when selected by the zoom list box in the main tool bar.
GAL_DISPLAY_OPTIONS_IMPL & GetGalDisplayOptions()
Return a reference to the gal rendering options used by GAL for rendering.
virtual void resolveCanvasType()
Determine the canvas type to load (with prompt if required) and initializes m_canvasType.
static const wxString PropertiesPaneName()
EDA_MSG_PANEL * m_messagePanel
virtual void SetScreen(BASE_SCREEN *aScreen)
bool LibraryFileBrowser(const wxString &aTitle, bool doOpen, wxFileName &aFilename, const wxString &wildcard, const wxString &ext, bool isDirectory, FILEDLG_HOOK_NEW_LIBRARY *aFileDlgHook=nullptr)
void FocusOnLocation(const VECTOR2I &aPos, bool aAllowScroll=true)
Useful to focus on a particular location, in find functions.
PROPERTIES_PANEL * m_propertiesPanel
void ForceRefresh()
Force a redraw.
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
KIGFX::GAL * GetGAL() const
Return a pointer to the GAL instance used in the panel.
void SetEventDispatcher(TOOL_DISPATCHER *aEventDispatcher)
Set a dispatcher that processes events and forwards them to tools.
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:98
virtual const VECTOR2I GetFocusPosition() const
Similar to GetPosition() but allows items to return their visual center rather than their anchor.
Definition eda_item.h:355
const KIID m_Uuid
Definition eda_item.h:599
void ClearBrightened()
Definition eda_item.h:154
void SetBrightened()
Definition eda_item.h:151
bool HasFlag(EDA_ITEM_FLAGS aFlag) const
Definition eda_item.h:168
bool IsBrightened() const
Definition eda_item.h:136
Specialization of the wxAuiPaneInfo class for KiCad panels.
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition eda_text.h:94
Class that groups generic conditions for editor states.
SELECTION_CONDITION NoActiveTool()
Create a functor testing if there are no tools active in the frame.
SELECTION_CONDITION BoundingBoxes()
SELECTION_CONDITION RedoAvailable()
Create a functor that tests if there are any items in the redo queue.
SELECTION_CONDITION CurrentTool(const TOOL_ACTION &aTool)
Create a functor testing if the specified tool is the current active tool in the frame.
virtual SELECTION_CONDITION UndoAvailable()
Create a functor that tests if there are any items in the undo queue.
SELECTION_CONDITION GridVisible()
Create a functor testing if the grid is visible in a frame.
SELECTION_CONDITION GridOverrides()
Create a functor testing if the grid overrides wires is enabled in a frame.
The tab strip plus the single shared GAL canvas.
Tool responsible for drawing graphical shapes (rectangles, circles, arcs, beziers,...
void ReadWindowSettings(WINDOW_SETTINGS &aCfg)
Read GAL config options from application-level config.
void RegisterHandler(API_HANDLER *aHandler)
Adds a new request handler to the server.
void DeregisterHandler(API_HANDLER *aHandler)
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition kidialog.h:38
int ShowModal() override
Definition kidialog.cpp:89
bool m_axesEnabled
Whether or not to draw the coordinate system axes.
void SetAxesEnabled(bool aAxesEnabled)
Enable drawing the axes.
void SetAxesColor(const COLOR4D &aAxesColor)
Set the axes color.
void SetDefaultFont(const wxString &aFont)
void HideDrawingSheet()
Definition sch_view.cpp:306
void ClearHiddenFlags()
Clear the hide flag of all items in the view.
Definition sch_view.cpp:294
bool IsSCH_ITEM() const
Definition view_item.h:97
void Clear()
Remove all items from the view.
Definition view.cpp:1262
void UpdateAllItems(int aUpdateFlags)
Update all items in the view according to the given flags.
Definition view.cpp:1743
Definition kiid.h:46
Carry a payload from one KIWAY_PLAYER to another within a PROJECT.
Definition kiway_mail.h:34
std::string & GetPayload()
Return the payload, which can be any text but it typically self identifying s-expression.
Definition kiway_mail.h:52
MAIL_T Command()
Returns the MAIL_T associated with this mail.
Definition kiway_mail.h:44
bool Destroy() override
Our version of Destroy() which is virtual from wxWidgets.
A minimalistic software bus for communications between various DLLs/DSOs (DSOs) within the same KiCad...
Definition kiway.h:348
void OnKiCadExit()
Definition kiway.cpp:790
virtual KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=nullptr)
Return the KIWAY_PLAYER* given a FRAME_T.
Definition kiway.cpp:388
virtual void ExpressMail(FRAME_T aDestination, MAIL_T aCommand, std::string &aPayload, wxWindow *aSource=nullptr, bool aFromOtherThread=false)
Send aPayload to aDestination from aSource.
Definition kiway.cpp:486
Module editor specific tools.
std::optional< LIBRARY_TABLE_ROW * > FindRowByURI(const wxString &aUri, LIBRARY_TABLE_SCOPE aScope=LIBRARY_TABLE_SCOPE::BOTH) const
Like LIBRARY_MANAGER::FindRowByURI but filtered to the LIBRARY_TABLE_TYPE of this adapter.
bool HasLibrary(const wxString &aNickname, bool aCheckEnabled=false) const
Test for the existence of aNickname in the library tables.
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.
void ReloadTables(LIBRARY_TABLE_SCOPE aScope, std::initializer_list< LIBRARY_TABLE_TYPE > aTablesToLoad={})
std::optional< LIBRARY_TABLE * > Table(LIBRARY_TABLE_TYPE aType, LIBRARY_TABLE_SCOPE aScope)
Retrieves a given table; creating a new empty project table if a valid project is loaded and the give...
std::optional< wxString > GetFullURI(LIBRARY_TABLE_TYPE aType, const wxString &aNickname, bool aSubstituted=false)
Return the full location specifying URI for the LIB, either in original UI form or in environment var...
void SetNickname(const wxString &aNickname)
void SetType(const wxString &aType)
void SetURI(const wxString &aUri)
A logical library item identifier and consists of various portions much like a URI.
Definition lib_id.h:45
int SetLibItemName(const UTF8 &aLibItemName)
Override the library item name portion of the LIB_ID to aLibItemName.
Definition lib_id.cpp:124
bool IsValid() const
Check if this LID_ID is valid.
Definition lib_id.h:168
const UTF8 & GetLibItemName() const
Definition lib_id.h:98
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition lib_id.h:83
Symbol library management helper that is specific to the symbol library editor frame.
Define a library symbol object.
Definition lib_symbol.h:114
const LIB_ID & GetLibId() const override
Definition lib_symbol.h:190
wxString GetName() const override
Definition lib_symbol.h:183
std::unique_ptr< LIB_SYMBOL > Flatten() const
Return a flattened symbol inheritance to the caller.
Node type: LIB_ID.
void Update(LIB_TREE_ITEM *aItem)
Update the node using data from a LIB_ALIAS object.
void RefreshLibTree()
Refresh the tree (mainly to update highlighting and asterisking)
Definition lib_tree.cpp:492
void CenterLibId(const LIB_ID &aLibId)
Ensure that an item is visible (preferably centered).
Definition lib_tree.cpp:382
int GetSelectionCount() const
Definition lib_tree.h:85
void ShutdownPreviews()
Definition lib_tree.cpp:282
void ShowChangedLanguage()
Definition lib_tree.cpp:299
void FocusSearchFieldIfExists()
Focus the search widget if it exists.
Definition lib_tree.cpp:507
std::vector< LIB_ID > GetExpandedLibraries() const
Definition lib_tree.cpp:402
void SelectLibId(const LIB_ID &aLibId)
Select an item in the tree widget.
Definition lib_tree.cpp:370
LIB_TREE_MODEL_ADAPTER::SORT_MODE GetSortMode() const
Definition lib_tree.h:151
int GetSelectedLibIds(std::vector< LIB_ID > &aSelection, std::vector< int > *aUnit=nullptr) const
Retrieve a list of selections for trees that allow multi-selection.
Definition lib_tree.cpp:329
void Unselect()
Unselect currently selected item in wxDataViewCtrl.
Definition lib_tree.cpp:388
LIB_ID GetSelectedLibId(int *aUnit=nullptr) const
For multi-unit symbols, if the user selects the symbol itself rather than picking an individual unit,...
Definition lib_tree.cpp:309
void ExpandLibId(const LIB_ID &aLibId)
Expand and item i the tree widget.
Definition lib_tree.cpp:396
void Regenerate(bool aKeepState)
Regenerate the tree.
Definition lib_tree.cpp:474
virtual ENV_VAR_MAP & GetLocalEnvVariables() const
Definition pgm_base.cpp:792
KICAD_API_SERVER & GetApiServer()
Definition pgm_base.h:141
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition pgm_base.h:123
virtual LIBRARY_MANAGER & GetLibraryManager() const
Definition pgm_base.h:125
A holder to handle information on schematic or board items.
unsigned GetCount() const
void ClearItemsList()
Delete only the list of pickers NOT the picked data itself.
EDA_ITEM * GetPickedItem(unsigned int aIdx) const
static SYMBOL_LIBRARY_ADAPTER * SymbolLibAdapter(PROJECT *aProject)
Accessor for project symbol library manager adapter.
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition project.cpp:183
Action handler for the Properties panel.
Gather all the actions that are shared by tools.
Definition sch_actions.h:46
static TOOL_ACTION rotateCCW
static TOOL_ACTION editSymbolPinMaps
static TOOL_ACTION importSymbol
static TOOL_ACTION newSymbol
static TOOL_ACTION saveLibraryAs
static TOOL_ACTION mirrorV
static TOOL_ACTION drawEllipseArc
static TOOL_ACTION editLibSymbolWithLibEdit
static TOOL_ACTION drawArc
static TOOL_ACTION pinTable
static TOOL_ACTION drawSymbolLines
static TOOL_ACTION placeSymbolPin
static TOOL_ACTION drawSymbolTextBox
static TOOL_ACTION ddImportGraphics
static TOOL_ACTION drawRectangle
static TOOL_ACTION drawEllipse
static TOOL_ACTION drawCircle
static TOOL_ACTION importGraphics
static TOOL_ACTION drawBezier
static TOOL_ACTION saveSymbolCopyAs
static TOOL_ACTION rotateCW
static TOOL_ACTION showElectricalTypes
static TOOL_ACTION drawSymbolPolygon
static TOOL_ACTION showHiddenFields
static TOOL_ACTION placeSymbolAnchor
static TOOL_ACTION showHiddenPins
static TOOL_ACTION cycleBodyStyle
static TOOL_ACTION mirrorH
static TOOL_ACTION runERC
Inspection and Editing.
static TOOL_ACTION symbolProperties
static TOOL_ACTION placeSymbolText
static TOOL_ACTION toggleSyncedPinsMode
static TOOL_ACTION togglePinAltIcons
static TOOL_ACTION updateSymbolFields
static TOOL_ACTION saveSymbolAs
A shim class between EDA_DRAW_FRAME and several derived classes: SYMBOL_EDIT_FRAME,...
SCH_BASE_FRAME(KIWAY *aKiway, wxWindow *aParent, FRAME_T aWindowType, const wxString &aTitle, const wxPoint &aPosition, const wxSize &aSize, long aStyle, const wxString &aFrameName)
SCH_RENDER_SETTINGS * GetRenderSettings()
void doCloseWindow() override
void SaveSettings(APP_SETTINGS_BASE *aCfg) override
Save common frame parameters to a configuration data file.
void LoadSettings(APP_SETTINGS_BASE *aCfg) override
Load common frame parameters from a configuration file.
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
SYMBOL_EDITOR_SETTINGS * libeditconfig() const
SCH_DRAW_PANEL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
void CommonSettingsChanged(int aFlags) override
Notification event that some of the common (suite-wide) settings have changed.
void SyncView()
Mark all items for refresh.
PANEL_SCH_SELECTION_FILTER * m_selectionFilterPanel
virtual void UpdateItem(EDA_ITEM *aItem, bool isAddOrDelete=false, bool aUpdateRtree=false)
Mark an item for refresh.
void setSymWatcher(const LIB_ID *aSymbol)
Creates (or removes) a watcher on the specified symbol library.
KIGFX::SCH_VIEW * GetView() const override
Return a pointer to the KIGFX::VIEW instance used in the panel.
void DisplaySymbol(LIB_SYMBOL *aSymbol)
Schematic editor (Eeschema) main window.
bool SaveSymbolToSchematic(const LIB_SYMBOL &aSymbol, const KIID &aSchematicSymbolUUID)
Update a schematic symbol from a LIB_SYMBOL.
void SetPosition(const VECTOR2I &aPosition) override
Handle actions specific to the schematic editor.
static const wxString ShowType(SCH_FILE_T aFileType)
Return a brief name for a plugin, given aFileType enum.
static SCH_FILE_T GuessPluginTypeFromLibPath(const wxString &aLibPath, int aCtl=0)
Return a plugin type given a symbol library using the file extension of aLibPath.
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:170
int GetBodyStyle() const
Definition sch_item.h:253
int GetUnit() const
Definition sch_item.h:243
Tool that displays edit points allowing to modify items by dragging the points.
SCH_SELECTION & GetSelection()
SCH_SELECTION_FILTER_OPTIONS & GetFilter()
Schematic symbol object.
Definition sch_symbol.h:73
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly) const override
Populate a std::vector with SCH_FIELDs, sorted in ordinal order.
VECTOR2I GetPosition() const override
Definition sch_symbol.h:895
const LIB_ID & GetLibId() const override
Definition sch_symbol.h:163
int GetOrientation() const override
Get the display symbol orientation.
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition sch_symbol.h:182
static bool NotEmpty(const SELECTION &aSelection)
Test if there are any items selected.
static bool Idle(const SELECTION &aSelection)
Test if there no items selected or being edited.
static bool ShowAlways(const SELECTION &aSelection)
The default condition function (always returns true).
Handle actions for the various symbol editor and viewers.
One open symbol tab owning a working LIB_SYMBOL and screen lent to the frame while active.
The symbol library editor main window.
std::vector< std::unique_ptr< SYMBOL_EDITOR_TAB_CONTEXT > > m_tabContexts
bool m_isSymbolFromSchematic
Flag if the symbol being edited was loaded directly from a schematic.
void restoreSymbolTabsFromSettings()
Recreate tabs from the persisted open-tab list once the libraries have loaded.
void OnExitKiCad(wxCommandEvent &event)
void LoadSettings(APP_SETTINGS_BASE *aCfg) override
Load common frame parameters from a configuration file.
bool promptToSaveInactiveInstanceTabs()
Prompt to save each dirty instance (symbol from schematic) tab that is not the active one,...
std::unique_ptr< GRID_HELPER > MakeGridHelper() override
void UpdateItem(EDA_ITEM *aItem, bool isAddOrDelete=false, bool aUpdateRtree=false) override
Mark an item for refresh.
void setupUIConditions() override
Setup the UI conditions for the various actions and their controls in this frame.
APP_SETTINGS_BASE * config() const override
Return the settings object used in SaveSettings(), and is overloaded in KICAD_MANAGER_FRAME.
std::unique_ptr< API_HANDLER_COMMON > m_apiHandlerCommon
bool hasDirtyInactiveInstanceTabs() const
True if any non-active instance (schematic) tab has unsaved edits.
bool IsLibraryTreeShown() const override
const BOX2I GetDocumentExtents(bool aIncludeAllVisible=true) const override
Return bounding box of document with option to not include some items.
SELECTION & GetCurrentSelection() override
Get the current selection from the canvas area.
wxString getTargetLib() const
Return either the library selected in the symbol tree, if context menu is active or the library that ...
bool LoadSymbolFromLib(const wxString &aLibName, const wxString &aSymbolName, int aUnit=0, int aBodyStyle=0)
Load a symbol from a library, optionally setting the selected unit and body style.
bool IsCurrentSymbol(const LIB_ID &aLibId) const
Return true if aLibId is an alias for the editor screen symbol.
bool backupLibrary(const wxFileName &aOriginalFile, wxString &aErrorMsg)
Create a backup copy of a symbol library.
static void freeTransientUndoCommands(UNDO_REDO_CONTAINER &aList, const LIB_SYMBOL *aLiveSymbol)
Free every command in the list and the UR_TRANSIENT-flagged copies it owns, which the shared deleters...
void OnSelectBodyStyle(wxCommandEvent &event)
wxString m_reference
RefDes of the symbol (only valid if symbol was loaded from schematic)
EDITOR_TABS_PANEL * m_tabsPanel
SYMBOL_EDITOR_TAB_CONTEXT * findOrCreateSymbolInstanceTab(LIB_SYMBOL *aSymbol, SCH_SCREEN *aScreen, const KIID &aSchematicSymbolUUID, const wxString &aReference, int aUnit, int aBodyStyle)
Find or create the instance tab for a placed schematic symbol and make it active.
void RefreshLibraryTree()
Redisplay the library tree.
void updateSelectionFilterVisbility() override
Selection filter panel doesn't have a dedicated visibility control, so show it if any other AUI panel...
void CommonSettingsChanged(int aFlags) override
Called after the preferences dialog is run.
void FocusLibraryTreeInput() override
wxComboBox * m_unitSelectBox
bool m_drawSpecificBodyStyle
When editing a symbol: only apply new graphic items to the current body style.
void RebuildSymbolUnitAndBodyStyleLists()
int GetTreeLIBIDs(std::vector< LIB_ID > &aSelection) const
void OnTabCharHook(wxKeyEvent &aEvent)
Cycle symbol tabs from the char hook, since GTK cannot register WXK_TAB as an accelerator.
LIB_ID GetTreeLIBID(int *aUnit=nullptr) const
Return the LIB_ID of the library or symbol selected in the symbol tree.
LIB_SYMBOL_LIBRARY_MANAGER * m_libMgr
void FocusOnLibId(const LIB_ID &aLibID)
void SaveLibraryAs(SAVE_LIBRARY_AS aSaveType=SAVE_LIBRARY_AS::NEW)
Save the currently selected library to a new file.
void ToggleProperties() override
SYMBOL_EDITOR_SETTINGS * m_settings
void onPluginAvailabilityChanged(wxCommandEvent &aEvt)
void HardRedraw() override
Rebuild the GAL and redraw the screen.
int GetTreeSelectionCount() const
bool addLibTableEntry(const wxString &aLibFile, LIBRARY_TABLE_SCOPE aScope=LIBRARY_TABLE_SCOPE::GLOBAL)
Add aLibFile to the symbol library table defined by aScope.
void SaveSettings(APP_SETTINGS_BASE *aCfg) override
Save common frame parameters to a configuration data file.
int m_unit
The unit number to edit and show.
bool CanCloseSymbolFromSchematic(bool doClose)
bool IsSymbolFromLegacyLibrary() const
bool replaceLibTableEntry(const wxString &aLibNickname, const wxString &aLibFile)
Replace the file path of the symbol library table entry aLibNickname with aLibFile.
bool IsSymbolFromSchematic() const
void SetScreen(BASE_SCREEN *aScreen) override
void KiwayMailIn(KIWAY_MAIL_EVENT &mail) override
Receive KIWAY_MAIL_EVENT messages from other players.
void emptyScreen()
Restore the empty editor screen, without any symbol or library selected.
SYMBOL_EDITOR_TAB_CONTEXT * m_activeTab
SYMBOL_EDITOR_SETTINGS * GetSettings() const
SCH_SCREEN * m_dummyScreen
Helper screen used when no symbol is loaded.
void SetCurSymbol(LIB_SYMBOL *aSymbol, bool aUpdateZoom)
Take ownership of aSymbol and notes that it is the one currently being edited.
SYMBOL_EDIT_FRAME(KIWAY *aKiway, wxWindow *aParent)
static bool libTreeAutoHiddenForSchematicEdit(bool aWasFromSchematic, bool aRestorePending, bool aTreeShownNow)
Resolve whether the library tree's auto-hide for a schematic edit still needs restoring on save.
bool IsSymbolEditable() const
Test if a symbol is loaded and can be edited.
std::unique_ptr< API_HANDLER_SYMBOL > m_apiHandler
std::vector< LIB_ID > GetSelectedLibIds() const
void SyncLibraries(bool aShowProgress, bool aPreloadCancelled=false, const wxString &aForceRefresh=wxEmptyString)
Synchronize the library manager to the symbol library table, and then the symbol tree to the library ...
void OnSelectUnit(wxCommandEvent &event)
void storeSymbolTabsToSettings()
Write the current tab set into the editor settings for the next session.
LIB_SYMBOL * GetCurSymbol() const
Return the current symbol being edited or NULL if none selected.
void UpdateSymbolMsgPanelInfo()
Display the documentation of the selected symbol.
bool canCloseWindow(wxCloseEvent &aCloseEvent) override
LIB_ID GetTargetLibId() const override
Return either the symbol selected in the symbol tree (if context menu is active) or the symbol on the...
bool m_libTreeAutoHiddenForSchematicEdit
True while a schematic-edit auto-hide of the library tree still needs restoring on save.
void SetBodyStyle(int aBodyStyle)
int m_bodyStyle
Show the normal shape (m_bodyStyle <= 1) or the DeMorgan converted shape (m_bodyStyle > 1)
bool saveAllLibraries(bool aRequireConfirmation)
Return true when the operation has succeeded (all requested libraries have been saved or none was sel...
void UpdateMsgPanel() override
Redraw the message panel.
void ClearUndoORRedoList(UNDO_REDO_LIST whichList, int aItemCount=-1) override
Free the undo or redo list from aList element.
LIB_TREE * GetLibTree() const override
void UpdateTitle()
Update the main window title bar with the current library name and read only status of the library.
bool HasLibModifications() const
Check if any pending libraries have been modified.
std::unique_ptr< API_HANDLER_LIBRARIES > m_apiLibrariesHandler
bool promptAndCloseSymbolTab(int aIdx)
Prompt for unsaved changes on the tab and drop its context.
SYMBOL_TREE_PANE * m_treePane
void SetDrawSpecificUnit(bool aSpecific)
void LoadSymbolFromSchematic(SCH_SYMBOL *aSymbol)
Load a symbol from the schematic to edit in place.
bool m_drawSpecificUnit
When editing a symbol: only apply new graphic items to the current unit.
bool saveCurrentSymbol()
Save the current symbol.
bool IsSymbolGraphicallyEditable() const
Test if a symbol is loaded and can be edited graphically.
COLOR_SETTINGS * GetColorSettings(bool aForceRefresh=false) const override
Returns a pointer to the active color theme settings.
LIB_SYMBOL_LIBRARY_MANAGER & GetLibManager()
void OnUpdateBodyStyle(wxUpdateUIEvent &event)
void SaveSymbolCopyAs(bool aOpenCopy)
Save the currently selected symbol to a new name and/or location.
void SwitchCanvas(EDA_DRAW_PANEL_GAL::GAL_TYPE aCanvasType) override
Switch currently used canvas ( Cairo / OpenGL).
void doCloseWindow() override
SYMBOL_EDITOR_TAB_CONTEXT * symbolTabContextForIndex(int aIdx) const
Resolve the tab context for a panel tab index, or nullptr.
static void clearSymbolTabUndoRedo(SYMBOL_EDITOR_TAB_CONTEXT &aContext)
Free a detached context's undo/redo, which the frame's own teardown path never reaches.
void DdAddLibrary(wxString aLibFile)
Add a library dropped file to the symbol library table.
wxString AddLibraryFile(bool aCreateNew)
Create or add an existing library to the symbol library table.
void FocusOnItem(EDA_ITEM *aItem, bool aAllowScroll=true) override
Focus on a particular canvas item.
void configureToolbars() override
void CloseWindow(wxCommandEvent &event)
Trigger the wxCloseEvent, which is handled by the function given to EVT_CLOSE() macro:
wxComboBox * m_bodyStyleSelectBox
void activateSymbolTab(SYMBOL_EDITOR_TAB_CONTEXT *aContext)
Make aContext the active tab, borrowing its working symbol, undo/redo, view and selection,...
void UpdateLibraryTree(const wxDataViewItem &aTreeItem, LIB_SYMBOL *aSymbol)
Update a symbol node in the library tree.
void closeAllSymbolTabsSilently()
Close every tab without prompting and return the frame to the empty state.
void OnModify() override
Must be called after a schematic change in order to set the "modify" flag of the current symbol.
void ShowChangedLanguage() override
Redraw the menus and what not in current language.
bool IsContentModified() const override
Get if any symbols or libraries have been modified but not saved.
void ToggleLibraryTree() override
LIB_SYMBOL * getTargetSymbol() const
Return currently edited symbol.
void OnUpdateUnitNumber(wxUpdateUIEvent &event)
An interface to the global shared library manager that is schematic-specific and linked to one projec...
std::optional< LIB_STATUS > LoadOne(LIB_DATA *aLib) override
Loads or reloads the given library, if it exists.
Library Editor pane with symbol tree and symbol library table selector.
Rate-limiter that fires at most once per interval.
Definition throttle.h:31
bool Ready()
Definition throttle.h:44
TOOL_MANAGER * m_toolManager
TOOL_DISPATCHER * m_toolDispatcher
bool ToolStackIsEmpty()
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
ACTIONS * m_actions
@ MODEL_RELOAD
Model changes (the sheet for a schematic)
Definition tool_base.h:76
virtual void DispatchWxEvent(wxEvent &aEvent)
Process wxEvents (mostly UI events), translate them to TOOL_EVENTs, and make tools handle those.
Master controller class:
bool RunAction(const std::string &aActionName, T aParam)
Run the specified action immediately, pausing the current action to run the new one.
A holder to handle a list of undo (or redo) commands.
A wxDirTraverser to filter out symbol (.kicad_sym) files in an unpacked symbol library.
virtual wxDirTraverseResult OnFile(const wxString &aFilename) override
virtual wxDirTraverseResult OnDir(const wxString &WXUNUSED(aDirname)) override
UNPACKED_SYMBOL_LIBRARY_DIR_TRAVERSER(std::vector< wxString > &aFiles)
bool empty() const
Definition utf8.h:105
A modified version of the wxInfoBar class that allows us to:
Definition wx_infobar.h:76
void RemoveAllButtons()
Remove all the buttons that have been added by the user.
bool HasCloseButton() const
void AddLink(const wxString &aLinkText, const std::function< void(wxHyperlinkEvent &)> &aFn)
Add a hypertext link to the infobar.
void Dismiss() override
Dismisses the infobar and updates the containing layout and AUI manager (if one is provided).
void AddCloseButton(const wxString &aTooltip=_("Hide this message."))
Add the default close button to the infobar on the right side.
void ShowMessage(const wxString &aMessage, int aFlags=wxICON_INFORMATION) override
Show the info bar with the provided message and icon.
bool HandleUnsavedChanges(wxWindow *aParent, const wxString &aMessage, const std::function< bool()> &aSaveFunction)
Display a dialog with Save, Cancel and Discard Changes buttons.
Definition confirm.cpp:146
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition confirm.cpp:217
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
Definition confirm.cpp:192
This file is part of the common library.
#define KICAD_MESSAGE_DIALOG
Definition confirm.h:48
#define CHECK(x)
#define ENABLE(x)
static bool empty(const wxTextEntryBase *aCtrl)
#define _(s)
#define KICAD_DEFAULT_DRAWFRAME_STYLE
#define LIB_EDIT_FRAME_NAME
#define UR_TRANSIENT
indicates the item is owned by the undo/redo stack
@ ID_LIBEDIT_SELECT_UNIT_NUMBER
Definition eeschema_id.h:59
@ ID_LIBEDIT_SELECT_BODY_STYLE
Definition eeschema_id.h:60
const wxAuiPaneInfo & defaultSchSelectionFilterPaneInfo(wxWindow *aWindow)
const wxAuiPaneInfo & defaultPropertiesPaneInfo(wxWindow *aWindow)
wxString NormalizePath(const wxFileName &aFilePath, const ENV_VAR_MAP *aEnvVars, const wxString &aProjectPath)
Normalize a file path to an environmental variable, if possible.
Definition env_paths.cpp:73
Helper functions to substitute paths with environmental variables.
@ FRAME_SCH_SYMBOL_EDITOR
Definition frame_type.h:31
@ FRAME_SCH
Definition frame_type.h:30
static const std::string SymbolLibraryTableFileName
static const std::string KiCadSymbolLibFileExtension
static const std::string SVGFileExtension
static wxString KiCadSymbolLibFileWildcard()
const wxChar *const traceLibWatch
Flag to enable debug output for library file watch refreshes.
const wxChar *const traceApi
Flag to enable debug output related to the IPC API and its plugin system.
Definition api_utils.cpp:33
@ ID_ON_GRID_SELECT
Definition id.h:113
@ ID_ON_ZOOM_SELECT
Definition id.h:112
std::map< wxString, ENV_VAR_ITEM > ENV_VAR_MAP
PROJECT & Prj()
Definition kicad.cpp:733
EVT_MENU(ID_COMPARE_PROJECT_BRANCHES, KICAD_MANAGER_FRAME::OnCompareProjectBranches) KICAD_MANAGER_FRAME
TAB_VISUAL_STATE ResolveTabVisualState(bool aPreview, bool aModified)
Resolve a tab's decorations from its document state flags.
KIID niluuid(0)
@ LAYER_SCHEMATIC_GRID_AXES
Definition layer_ids.h:509
LIBRARY_TABLE_SCOPE
@ MAIL_LIB_EDIT
Definition mail_type.h:51
@ MAIL_REFRESH_SYMBOL
Definition mail_type.h:56
@ MAIL_RELOAD_LIB
Definition mail_type.h:54
@ ALL
All except INITIAL_ADD.
Definition view_item.h:55
void SetShutdownBlockReason(wxWindow *aWindow, const wxString &aReason)
Sets the block reason why the window/application is preventing OS shutdown.
Definition unix/app.cpp:102
bool SupportsShutdownBlockReason()
Whether or not the window supports setting a shutdown block reason.
Definition unix/app.cpp:91
static constexpr size_t CLOUD_SYNC_BUFFER_SIZE
Buffer size for file I/O operations on cloud-synced folders.
Definition io.h:169
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition kicad_algo.h:96
static std::string normalizedPath(std::string aPath)
#define _HKI(x)
Definition page_info.cpp:40
void InvokeSchEditSymbolLibTable(KIWAY *aKiway, wxWindow *aParent)
PGM_BASE & Pgm()
The global program "get" accessor.
see class PGM_BASE
#define DEFAULT_THEME
COLOR_SETTINGS * GetColorSettings(const wxString &aName)
T * GetToolbarSettings(const wxString &aFilename)
T * GetAppSettings(const char *aFilename)
KIWAY Kiway(KFCTL_STANDALONE)
wxString UnescapeString(const wxString &aSource)
Functors that can be used to figure out how the action controls should be displayed in the UI and if ...
wxString message
Visual decorations derived from document state: preview is italic, modified is bold with a leading as...
@ SYM_ORIENT_270
Definition symbol.h:39
@ SYM_MIRROR_Y
Definition symbol.h:41
@ SYM_ORIENT_180
Definition symbol.h:38
@ SYM_MIRROR_X
Definition symbol.h:40
@ SYM_ORIENT_90
Definition symbol.h:37
#define EDIT_TOOL(tool)
#define DEMORGAN_ALT
#define DEMORGAN_STD
KIBIS_PIN * pin
#define ENVVARS_CHANGED
wxLogTrace helper definitions.
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:708
VECTOR2< double > VECTOR2D
Definition vector2d.h:707
Definition of file extensions used in Kicad.
void SetAuiPaneSize(wxAuiManager &aManager, wxAuiPaneInfo &aPane, int aWidth, int aHeight)
Sets the size of an AUI pane, working around http://trac.wxwidgets.org/ticket/13180.