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>
23#include <wx/hyperlink.h>
24#include <base_screen.h>
25#include <confirm.h>
26#include <core/kicad_algo.h>
27#include <core/throttle.h>
28#include <eeschema_id.h>
29#include <eeschema_settings.h>
30#include <env_paths.h>
32#include <kidialog.h>
33#include <kiface_base.h>
34#include <kiplatform/app.h>
35#include <kiway_mail.h>
36#include <symbol_edit_frame.h>
40#include <paths.h>
41#include <pgm_base.h>
42#include <project_sch.h>
43#include <sch_painter.h>
44#include <sch_view.h>
48#include <tool/action_manager.h>
49#include <tool/action_toolbar.h>
50#include <tool/common_control.h>
51#include <tool/common_tools.h>
53#include <tool/embed_tool.h>
55#include <tool/picker_tool.h>
57#include <tool/selection.h>
59#include <tool/tool_manager.h>
60#include <tool/zoom_tool.h>
61#include <tools/sch_actions.h>
73#include <view/view_controls.h>
75#include <widgets/wx_infobar.h>
81#include <widgets/lib_tree.h>
86#include <panel_sym_lib_table.h>
87#include <string_utils.h>
89#include <wx/msgdlg.h>
90#include <wx/combobox.h>
91#include <wx/log.h>
92#include <trace_helpers.h>
93
94
96
97
98BEGIN_EVENT_TABLE( SYMBOL_EDIT_FRAME, SCH_BASE_FRAME )
101
102 // menubar commands
105
106 // Update user interface elements.
109
112
113 // Drop files event
114 EVT_DROP_FILES( SYMBOL_EDIT_FRAME::OnDropFiles )
115
116END_EVENT_TABLE()
117
118
119SYMBOL_EDIT_FRAME::SYMBOL_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
120 SCH_BASE_FRAME( aKiway, aParent, FRAME_SCH_SYMBOL_EDITOR, _( "Symbol Editor" ),
121 wxDefaultPosition, wxDefaultSize, KICAD_DEFAULT_DRAWFRAME_STYLE,
123 m_unitSelectBox( nullptr ),
124 m_bodyStyleSelectBox( nullptr ),
127{
128 m_SyncPinEdit = false;
129
130 m_symbol = nullptr;
131 m_treePane = nullptr;
132 m_libMgr = nullptr;
133 m_unit = 1;
134 m_bodyStyle = 1;
136 m_aboutTitle = _HKI( "KiCad Symbol Editor" );
137
138 wxIcon icon;
139 wxIconBundle icon_bundle;
140
141 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_libedit, 48 ) );
142 icon_bundle.AddIcon( icon );
143 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_libedit, 256 ) );
144 icon_bundle.AddIcon( icon );
145 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_libedit, 128 ) );
146 icon_bundle.AddIcon( icon );
147 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_libedit_32 ) );
148 icon_bundle.AddIcon( icon );
149 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_libedit_16 ) );
150 icon_bundle.AddIcon( icon );
151
152 SetIcons( icon_bundle );
153
156
158
159 m_treePane = new SYMBOL_TREE_PANE( this, m_libMgr );
160 m_treePane->GetLibTree()->SetSortMode( (LIB_TREE_MODEL_ADAPTER::SORT_MODE) m_settings->m_LibrarySortMode );
161
164
165 // Ensure axis are always drawn
167 gal_opts.m_axesEnabled = true;
168
171 GetScreen()->m_Center = true;
172
173 GetCanvas()->GetViewControls()->SetCrossHairCursorPosition( VECTOR2D( 0, 0 ), false );
174
175 GetRenderSettings()->LoadColors( GetColorSettings() );
176 GetRenderSettings()->m_IsSymbolEditor = true;
177 GetCanvas()->GetGAL()->SetAxesColor( m_colorSettings->GetColor( LAYER_SCHEMATIC_GRID_AXES ) );
178
179 setupTools();
181
183
187
190
191 m_propertiesPanel = new SCH_PROPERTIES_PANEL( this, this );
192 m_propertiesPanel->SetSplitterProportion( m_settings->m_AuiPanels.properties_splitter );
193
195
196 m_auimgr.SetManagedWindow( this );
197
199
200 // Rows; layers 4 - 6
201 m_auimgr.AddPane( m_tbTopMain, EDA_PANE().HToolbar().Name( "TopMainToolbar" )
202 .Top().Layer( 6 ) );
203
204 m_auimgr.AddPane( m_messagePanel, EDA_PANE().Messages().Name( "MsgPanel" )
205 .Bottom().Layer( 6 ) );
206
207 m_auimgr.AddPane( m_tbLeft, EDA_PANE().VToolbar().Name( "LeftToolbar" )
208 .Left().Layer( 2 ) );
209
210 m_auimgr.AddPane( m_tbRight, EDA_PANE().VToolbar().Name( "RightToolbar" )
211 .Right().Layer( 2 ) );
212
213 m_tabsPanel = new EDITOR_TABS_PANEL( this, GetCanvas() );
214
215 m_tabsPanel->onActivateTab =
216 [this]( int aIdx )
217 {
219 activateSymbolTab( ctx );
220 };
221
222 m_tabsPanel->onCloseTabRequested =
223 [this]( int aIdx ) -> bool
224 {
225 return promptAndCloseSymbolTab( aIdx );
226 };
227
228 m_tabsPanel->onQueryVisualState =
229 [this]( int aIdx ) -> TAB_VISUAL_STATE
230 {
231 // The panel model owns preview. Read modified from the live context.
232 const std::vector<EDITOR_TABS_MODEL::ENTRY>& entries = m_tabsPanel->Model().Entries();
233
234 if( aIdx < 0 || aIdx >= static_cast<int>( entries.size() ) )
235 return TAB_VISUAL_STATE{};
236
237 bool modified = entries[aIdx].modified;
238
240 modified = ctx->IsModified();
241
242 return ResolveTabVisualState( entries[aIdx].preview, modified );
243 };
244
245 m_auimgr.AddPane( m_tabsPanel, wxAuiPaneInfo().Name( "DrawFrame" )
246 .CentrePane() );
247
248 // Columns; layers 1 - 3
249 m_auimgr.AddPane( m_treePane, EDA_PANE().Palette().Name( "LibraryTree" )
250 .Left().Layer( 3 )
251 .TopDockable( false ).BottomDockable( false )
252 .Caption( _( "Libraries" ) )
253 // Don't use -1 for don't-change-height on a growable panel; it has side-effects.
254 .MinSize( FromDIP( 250 ), FromDIP( 80 ) )
255 .BestSize( FromDIP( 250 ), -1 ) );
256
259
260 // Can be called only when all panes are created, because (at least on Windows) when items
261 // managed by m_auimgr are not the same as those existing when saved by Perspective()
262 // in config, broken settings can happen.
264
265 // Protect against broken saved Perspective() due to bugs in previous version
266 // This is currently a workaround.
267 m_auimgr.GetPane( "TopMainToolbar" ).Top().Layer( 6 ).Position(0).Show( true );
268 m_auimgr.GetPane( "LeftToolbar" ).Position(0).Show( true );
269 m_auimgr.GetPane( "RightToolbar" ).Show( true );
270
271 // Show or hide m_propertiesPanel depending on current settings:
272 wxAuiPaneInfo& propertiesPaneInfo = m_auimgr.GetPane( PropertiesPaneName() );
273 wxAuiPaneInfo& selectionFilterPane = m_auimgr.GetPane( wxS( "SelectionFilter" ) );
274 // The selection filter doesn't need to grow in the vertical direction when docked
275 selectionFilterPane.dock_proportion = 0;
276
277 propertiesPaneInfo.Show( m_settings->m_AuiPanels.show_properties );
279
281
282 // Can't put this in LoadSettings, because it has to be called before setupTools :/
284 selTool->GetFilter() = GetSettings()->m_SelectionFilter;
285 m_selectionFilterPanel->SetCheckboxesFromFilter( selTool->GetFilter() );
286
287 if( m_settings->m_LibWidth > 0 )
288 SetAuiPaneSize( m_auimgr, m_auimgr.GetPane( "LibraryTree" ), m_settings->m_LibWidth, -1 );
289
290 Raise();
291 Show( true );
292
293 SyncView();
294 GetCanvas()->GetView()->UseDrawPriority( true );
295 GetCanvas()->GetGAL()->SetAxesEnabled( true );
296
298
299 // Set the working/draw area size to display a symbol to a reasonable value:
300 // A 600mm x 600mm with a origin at the area center looks like a large working area
301 double max_size_x = schIUScale.mmToIU( 600 );
302 double max_size_y = schIUScale.mmToIU( 600 );
303 BOX2D bbox;
304 bbox.SetOrigin( -max_size_x /2, -max_size_y/2 );
305 bbox.SetSize( max_size_x, max_size_y );
306 GetCanvas()->GetView()->SetBoundary( bbox );
307
309
311 m_acceptedExts.emplace( wxS( "dxf" ), &SCH_ACTIONS::ddImportGraphics );
313 DragAcceptFiles( true );
314
315 KIPLATFORM::APP::SetShutdownBlockReason( this, _( "Library changes are unsaved" ) );
316
317 // Catch unhandled accelerator command characters that were no handled by the library tree
318 // panel.
320 Bind( wxEVT_CHAR_HOOK, &TOOL_DISPATCHER::DispatchWxEvent, m_toolDispatcher );
321
322 // GTK rejects WXK_TAB as an accelerator so cycle tabs from the char hook ahead of the dispatcher.
323 Bind( wxEVT_CHAR_HOOK, &SYMBOL_EDIT_FRAME::OnTabCharHook, this );
324
325 // Ensure the window is on top
326 Raise();
327
328 // run SyncLibraries with progress reporter enabled. The progress reporter is useful
329 // in debug mode because the loading time of ecah library can be really noticeable
330 SyncLibraries( true );
331
332 // Must follow SyncLibraries so persisted tabs can resolve against the loaded libraries.
334}
335
336
338{
339 // Hand the borrowed canvas back before the base destructor frees it, else the panel reparents
340 // freed memory on its own teardown.
341 if( m_tabsPanel )
342 m_tabsPanel->ReleaseSharedCanvas();
343
344 // Shutdown all running tools
345 if( m_toolManager )
346 m_toolManager->ShutdownAllTools();
347
348 setSymWatcher( nullptr );
349
350 if( m_activeTab )
351 {
352 // Hand the working objects back so the context deletes them exactly once below; raw deleting
353 // here would double-free with the context dtor and leak the swapped-in undo list. Covers an
354 // active instance tab too, whose m_isSymbolFromSchematic mirror is only frame state.
356 m_activeTab->AdoptWorkingObjects( m_symbol, static_cast<SCH_SCREEN*>( GetScreen() ) );
357 m_activeTab = nullptr;
358 m_symbol = nullptr;
360 }
361 else
362 {
363 // No active tab owns the current screen, so let EDA_DRAW_FRAME free it.
365 }
366
367 // Free each detached context's undo/redo with the frame on the dummy screen to avoid double-frees.
368 for( const std::unique_ptr<SYMBOL_EDITOR_TAB_CONTEXT>& ctx : m_tabContexts )
370
371 m_tabContexts.clear();
372
374 Pgm().GetSettingsManager().Save( cfg );
375
376 delete m_libMgr;
377}
378
379
381{
382 wxCHECK_RET( m_settings, "Call to SYMBOL_EDIT_FRAME::LoadSettings with null m_settings" );
383
385
386 GetRenderSettings()->m_ShowPinsElectricalType = m_settings->m_ShowPinElectricalType;
387 GetRenderSettings()->m_ShowHiddenPins = m_settings->m_ShowHiddenPins;
388 GetRenderSettings()->m_ShowHiddenFields = m_settings->m_ShowHiddenFields;
389 GetRenderSettings()->m_ShowPinAltIcons = m_settings->m_ShowPinAltIcons;
390 GetRenderSettings()->SetDefaultFont( wxEmptyString );
391}
392
393
395{
396 wxCHECK_RET( m_settings, "Call to SYMBOL_EDIT_FRAME:SaveSettings with null m_settings" );
397
399
400 // The library tree is hidden while editing a symbol from the schematic. Force it visible in the
401 // serialized AUI layout so the user's preference survives a restart, but only touch the pane
402 // metadata (not ToggleLibraryTree) to avoid a mid-session repaint/flicker and a spurious tree
403 // width capture below.
404 wxAuiPaneInfo& treePane = m_auimgr.GetPane( m_treePane );
405 wxAuiPaneInfo& filterPane = m_auimgr.GetPane( wxS( "SelectionFilter" ) );
406
407 const bool treeShown = treePane.IsShown();
408 const bool filterShown = filterPane.IsShown();
409
410 // Gate on the pending-restore flag alone, not the active-tab schematic state, which is cleared
411 // when a schematic tab closes while the tree stays auto-hidden.
412 const bool forceTreeShown = m_libTreeAutoHiddenForSchematicEdit && !treeShown;
413
414 if( forceTreeShown )
415 {
416 treePane.Show( true );
418 }
419
421
422 if( forceTreeShown )
423 {
424 treePane.Show( treeShown );
425 filterPane.Show( filterShown );
426 }
427
428 m_settings->m_ShowPinElectricalType = GetRenderSettings()->m_ShowPinsElectricalType;
429 m_settings->m_ShowHiddenPins = GetRenderSettings()->m_ShowHiddenPins;
430 m_settings->m_ShowHiddenFields = GetRenderSettings()->m_ShowHiddenFields;
431 m_settings->m_ShowPinAltIcons = GetRenderSettings()->m_ShowPinAltIcons;
432
433 m_settings->m_LibWidth = m_treePane->GetSize().x;
434
435 m_settings->m_LibrarySortMode = GetLibTree()->GetSortMode();
436
437 m_settings->m_AuiPanels.properties_splitter = m_propertiesPanel->SplitterProportion();
438 bool prop_shown = m_auimgr.GetPane( PropertiesPaneName() ).IsShown();
439 m_settings->m_AuiPanels.show_properties = prop_shown;
440
441 if( TOOL_MANAGER* toolMgr = GetToolManager() )
442 {
443 if( SCH_SELECTION_TOOL* selTool = toolMgr->GetTool<SCH_SELECTION_TOOL>() )
444 m_settings->m_SelectionFilter = selTool->GetFilter();
445 }
446
448}
449
450
452{
453 return static_cast<APP_SETTINGS_BASE*>( GetSettings() );
454}
455
456
458{
460
461 if( cfg && static_cast<SYMBOL_EDITOR_SETTINGS*>( cfg )->m_UseEeschemaColorSettings )
462 cfg = GetAppSettings<EESCHEMA_SETTINGS>( "eeschema" );
463
464 return ::GetColorSettings( cfg ? cfg->m_ColorTheme : DEFAULT_THEME );
465}
466
467
469{
470 // Create the manager and dispatcher & route draw panel events to the dispatcher
472 m_toolManager->SetEnvironment( GetScreen(), GetCanvas()->GetView(),
473 GetCanvas()->GetViewControls(), GetSettings(), this );
474 m_actions = new SCH_ACTIONS();
476
477 // Register tools
478 m_toolManager->RegisterTool( new COMMON_CONTROL );
479 m_toolManager->RegisterTool( new COMMON_TOOLS );
480 m_toolManager->RegisterTool( new ZOOM_TOOL );
481 m_toolManager->RegisterTool( new SCH_SELECTION_TOOL );
482 m_toolManager->RegisterTool( new PICKER_TOOL );
483 m_toolManager->RegisterTool( new SCH_INSPECTION_TOOL );
484 m_toolManager->RegisterTool( new SYMBOL_EDITOR_PIN_TOOL );
485 m_toolManager->RegisterTool( new SYMBOL_EDITOR_DRAWING_TOOLS );
486 m_toolManager->RegisterTool( new EE_GRAPHIC_TOOL );
487 m_toolManager->RegisterTool( new SCH_POINT_EDITOR );
488 m_toolManager->RegisterTool( new SCH_FIND_REPLACE_TOOL );
489 m_toolManager->RegisterTool( new SYMBOL_EDITOR_MOVE_TOOL );
490 m_toolManager->RegisterTool( new SYMBOL_EDITOR_EDIT_TOOL );
491 m_toolManager->RegisterTool( new LIBRARY_EDITOR_CONTROL );
492 m_toolManager->RegisterTool( new SYMBOL_EDITOR_CONTROL );
493 m_toolManager->RegisterTool( new PROPERTIES_TOOL );
494 m_toolManager->RegisterTool( new EMBED_TOOL );
495 m_toolManager->InitTools();
496
497 // Run the selection tool, it is supposed to be always active
498 m_toolManager->InvokeTool( "common.InteractiveSelection" );
499
501}
502
503
505{
507
508 ACTION_MANAGER* mgr = m_toolManager->GetActionManager();
509 EDITOR_CONDITIONS cond( this );
510
511 wxASSERT( mgr );
512
513#define ENABLE( x ) ACTION_CONDITIONS().Enable( x )
514#define CHECK( x ) ACTION_CONDITIONS().Check( x )
515
516 auto haveSymbolCond =
517 [this]( const SELECTION& )
518 {
519 return m_symbol;
520 };
521
522 auto isEditableCond =
523 [this]( const SELECTION& )
524 {
525 // Only root symbols from the new s-expression libraries or the schematic
526 // are editable.
527 return IsSymbolEditable() && !IsSymbolAlias();
528 };
529
530 auto isEditableInAliasCond =
531 [this]( const SELECTION& )
532 {
533 // Less restrictive than isEditableCond
534 // Symbols fields (root symbols and aliases) from the new s-expression libraries
535 // or in the schematic are editable.
536 return IsSymbolEditable();
537 };
538
539 auto canUpdateFieldsCond =
540 [this]( const SELECTION& )
541 {
542 return IsSymbolEditable() && m_symbol && m_symbol->CanUpdateFieldsFromParent();
543 };
544
545 auto symbolModifiedCondition =
546 [this]( const SELECTION& sel )
547 {
548 return m_libMgr && m_libMgr->IsSymbolModified( GetTargetLibId().GetLibItemName(),
549 GetTargetLibId().GetLibNickname() );
550 };
551
552 auto libSelectedCondition =
553 [this]( const SELECTION& sel )
554 {
555 return !GetTargetLibId().GetLibNickname().empty();
556 };
557
558 auto canEditProperties =
559 [this]( const SELECTION& sel )
560 {
562 };
563
564 auto symbolSelectedInTreeCondition =
565 [this]( const SELECTION& sel )
566 {
567 LIB_ID targetLibId = GetTargetLibId();
568 return !targetLibId.GetLibNickname().empty() && !targetLibId.GetLibItemName().empty();
569 };
570
571 auto saveSymbolAsCondition =
572 [this]( const SELECTION& aSel )
573 {
574 return getTargetSymbol() != nullptr;
575 };
576
577 const auto isSymbolFromSchematicCond =
578 [this]( const SELECTION& )
579 {
580 return IsSymbolFromSchematic();
581 };
582
583 // clang-format off
586 mgr->SetConditions( SCH_ACTIONS::saveLibraryAs, ENABLE( libSelectedCondition ) );
587 mgr->SetConditions( SCH_ACTIONS::saveSymbolAs, ENABLE( saveSymbolAsCondition ) );
588 mgr->SetConditions( SCH_ACTIONS::saveSymbolCopyAs, ENABLE( saveSymbolAsCondition ) );
591 mgr->SetConditions( SCH_ACTIONS::editLibSymbolWithLibEdit, ENABLE( isSymbolFromSchematicCond ) );
592
593 mgr->SetConditions( ACTIONS::undo, ENABLE( haveSymbolCond && cond.UndoAvailable() ) );
594 mgr->SetConditions( ACTIONS::redo, ENABLE( haveSymbolCond && cond.RedoAvailable() ) );
595 mgr->SetConditions( ACTIONS::revert, ENABLE( symbolModifiedCondition ) );
596
599
600 mgr->SetConditions( ACTIONS::cut, ENABLE( isEditableCond ) );
601 mgr->SetConditions( ACTIONS::copy, ENABLE( haveSymbolCond ) );
602 mgr->SetConditions( ACTIONS::copyAsText, ENABLE( haveSymbolCond ) );
603 mgr->SetConditions( ACTIONS::paste, ENABLE( isEditableCond &&
605 mgr->SetConditions( ACTIONS::doDelete, ENABLE( isEditableCond ) );
606 mgr->SetConditions( ACTIONS::duplicate, ENABLE( isEditableCond ) );
607 mgr->SetConditions( ACTIONS::selectAll, ENABLE( haveSymbolCond ) );
608 mgr->SetConditions( ACTIONS::unselectAll, ENABLE( haveSymbolCond ) );
609
610 // These actions in symbol editor when editing alias field rotations are allowed.
612 ENABLE( SELECTION_CONDITIONS::NotEmpty && isEditableInAliasCond )
613 .HotkeyEnable( isEditableInAliasCond ) );
615 ENABLE( SELECTION_CONDITIONS::NotEmpty && isEditableInAliasCond )
616 .HotkeyEnable( isEditableInAliasCond ) );
617
619 ENABLE( SELECTION_CONDITIONS::NotEmpty && isEditableCond )
620 .HotkeyEnable( isEditableCond ) );
622 ENABLE( SELECTION_CONDITIONS::NotEmpty && isEditableCond )
623 .HotkeyEnable( isEditableCond ) );
624
627 // clang-format on
628
629 auto pinTypeCond =
630 [this]( const SELECTION& )
631 {
633 };
634
635 auto hiddenPinCond =
636 [this]( const SELECTION& )
637 {
639 };
640
641 auto hiddenFieldCond =
642 [this]( const SELECTION& )
643 {
645 };
646
647 auto showPinAltIconsCond =
648 [this]( const SELECTION& )
649 {
651 };
652
653 auto showLibraryTreeCond =
654 [this]( const SELECTION& )
655 {
656 return IsLibraryTreeShown();
657 };
658
659 auto propertiesCond =
660 [this] ( const SELECTION& )
661 {
662 return m_auimgr.GetPane( PropertiesPaneName() ).IsShown();
663 };
664
667 mgr->SetConditions( ACTIONS::showLibraryTree, CHECK( showLibraryTreeCond ) );
668 mgr->SetConditions( ACTIONS::showProperties, CHECK( propertiesCond ) );
669 mgr->SetConditions( SCH_ACTIONS::showHiddenPins, CHECK( hiddenPinCond ) );
670 mgr->SetConditions( SCH_ACTIONS::showHiddenFields, CHECK( hiddenFieldCond ) );
671 mgr->SetConditions( SCH_ACTIONS::togglePinAltIcons, CHECK( showPinAltIconsCond ) );
672
673 auto multiUnitModeCond =
674 [this]( const SELECTION& )
675 {
676 return m_symbol && m_symbol->IsMultiUnit() && !m_symbol->UnitsLocked();
677 };
678
679 auto multiBodyStyleModeCond =
680 [this]( const SELECTION& )
681 {
682 return m_symbol && m_symbol->IsMultiBodyStyle();
683 };
684
685 auto syncedPinsModeCond =
686 [this]( const SELECTION& )
687 {
688 return m_SyncPinEdit;
689 };
690
691 auto haveDatasheetCond =
692 [this]( const SELECTION& )
693 {
694 return m_symbol && !m_symbol->GetDatasheetField().GetText().IsEmpty();
695 };
696
697 mgr->SetConditions( ACTIONS::showDatasheet, ENABLE( haveDatasheetCond ) );
698 mgr->SetConditions( SCH_ACTIONS::symbolProperties, ENABLE( symbolSelectedInTreeCondition || ( canEditProperties && haveSymbolCond ) ) );
699 mgr->SetConditions( SCH_ACTIONS::runERC, ENABLE( haveSymbolCond ) );
700 mgr->SetConditions( SCH_ACTIONS::pinTable, ENABLE( isEditableCond && haveSymbolCond ) );
701 mgr->SetConditions( SCH_ACTIONS::editSymbolPinMaps, ENABLE( isEditableCond && haveSymbolCond ) );
702 mgr->SetConditions( SCH_ACTIONS::updateSymbolFields, ENABLE( canUpdateFieldsCond ) );
703 mgr->SetConditions( SCH_ACTIONS::cycleBodyStyle, ENABLE( multiBodyStyleModeCond ) );
704
705 mgr->SetConditions( SCH_ACTIONS::toggleSyncedPinsMode, ACTION_CONDITIONS().Enable( multiUnitModeCond ).Check( syncedPinsModeCond ) );
706
707// Only enable a tool if the symbol is edtable
708#define EDIT_TOOL( tool ) ACTION_CONDITIONS().Enable( isEditableCond ).Check( cond.CurrentTool( tool ) )
709
724
725#undef CHECK
726#undef ENABLE
727#undef EDIT_TOOL
728}
729
730
732{
733 if( IsContentModified() )
734 {
735 SCH_EDIT_FRAME* schframe = (SCH_EDIT_FRAME*) Kiway().Player( FRAME_SCH, false );
736 wxString msg = _( "Save changes to '%s' before closing?" );
737
738 switch( UnsavedChangesDialog( this, wxString::Format( msg, m_reference ), nullptr ) )
739 {
740 case wxID_YES:
741 if( schframe && GetCurSymbol() ) // Should be always the case
743
744 break;
745
746 case wxID_NO:
747 break;
748
749 default:
750 case wxID_CANCEL:
751 return false;
752 }
753 }
754
755 if( doClose )
756 SetCurSymbol( nullptr, false );
757
758 return true;
759}
760
761
762bool SYMBOL_EDIT_FRAME::canCloseWindow( wxCloseEvent& aEvent )
763{
764 // Shutdown blocks must be determined and vetoed as early as possible, before any modal prompt.
765 // IsContentModified only sees the active tab, so also account for dirty inactive instance tabs.
767 && aEvent.GetId() == wxEVT_QUERY_END_SESSION
769 {
770 return false;
771 }
772
774 return false;
775
776 // Prompt for any dirty inactive instance tabs, which the active-tab checks above miss.
778 return false;
779
780 if( !saveAllLibraries( true ) )
781 return false;
782
783 // Save symbol tree column widths
784 m_libMgr->GetAdapter()->SaveSettings();
785
786 return true;
787}
788
789
791{
793
794 if( GetLibTree() )
796
797 delete m_toolManager;
798 m_toolManager = nullptr;
799
800 Destroy();
801}
802
803
805{
806 if( m_unitSelectBox )
807 {
808 if( m_unitSelectBox->GetCount() != 0 )
809 m_unitSelectBox->Clear();
810
811 if( !m_symbol || m_symbol->GetUnitCount() <= 1 )
812 {
813 m_unit = 1;
814 m_unitSelectBox->Append( wxEmptyString );
815 }
816 else
817 {
818 for( int i = 0; i < m_symbol->GetUnitCount(); i++ )
819 m_unitSelectBox->Append( m_symbol->GetUnitDisplayName( i + 1, true ) );
820 }
821
822 // Ensure the selected unit is compatible with the number of units of the current symbol:
823 if( m_symbol && m_symbol->GetUnitCount() < m_unit )
824 m_unit = 1;
825
826 m_unitSelectBox->SetSelection( ( m_unit > 0 ) ? m_unit - 1 : 0 );
827 }
828
830 {
831 if( m_bodyStyleSelectBox->GetCount() != 0 )
832 m_bodyStyleSelectBox->Clear();
833
834 if( !m_symbol || !m_symbol->IsMultiBodyStyle() )
835 {
836 m_bodyStyle = 1;
837 m_bodyStyleSelectBox->Append( wxEmptyString );
838 }
839 else if( m_symbol && m_symbol->HasDeMorganBodyStyles() )
840 {
841 m_bodyStyleSelectBox->Append( wxGetTranslation( DEMORGAN_STD ) );
842 m_bodyStyleSelectBox->Append( wxGetTranslation( DEMORGAN_ALT ) );
843 }
844 else
845 {
846 for( int i = 0; i < m_symbol->GetBodyStyleCount(); i++ )
847 m_bodyStyleSelectBox->Append( m_symbol->GetBodyStyleNames()[i] );
848 }
849
850 // Ensure the selected body style is compatible with the number of body styles of the current symbol:
851 if( m_symbol && m_symbol->GetBodyStyleCount() < m_bodyStyle )
852 m_bodyStyle = 1;
853
854 m_bodyStyleSelectBox->SetSelection( ( m_bodyStyle > 0 ) ? m_bodyStyle - 1 : 0 );
855 }
856}
857
858
860{
861 if( !m_propertiesPanel )
862 return;
863
864 bool show = !m_propertiesPanel->IsShownOnScreen();
865
866 wxAuiPaneInfo& propertiesPaneInfo = m_auimgr.GetPane( PropertiesPaneName() );
867 propertiesPaneInfo.Show( show );
869
870 if( show )
871 {
872 SetAuiPaneSize( m_auimgr, propertiesPaneInfo,
873 m_settings->m_AuiPanels.properties_panel_width, -1 );
874 }
875 else
876 {
877 m_settings->m_AuiPanels.properties_panel_width = m_propertiesPanel->GetSize().x;
878 }
879
880 m_auimgr.Update();
881 Refresh();
882}
883
884
886{
887 // An explicit toggle makes the live visibility authoritative, so drop any pending restore that
888 // LoadSymbolFromSchematic's auto-hide left behind.
890
891 wxAuiPaneInfo& treePane = m_auimgr.GetPane( m_treePane );
892 treePane.Show( !IsLibraryTreeShown() );
894 m_auimgr.Update();
895 Refresh();
896}
897
898
900{
901 return const_cast<wxAuiManager&>( m_auimgr ).GetPane( m_treePane ).IsShown();
902}
903
904
909
910
912{
913 m_treePane->Freeze();
914 m_libMgr->GetAdapter()->Freeze();
915}
916
917
919{
920 m_libMgr->GetAdapter()->Thaw();
921 m_treePane->Thaw();
922}
923
924
925void SYMBOL_EDIT_FRAME::OnExitKiCad( wxCommandEvent& event )
926{
927 Kiway().OnKiCadExit();
928}
929
930
931void SYMBOL_EDIT_FRAME::OnUpdateUnitNumber( wxUpdateUIEvent& event )
932{
933 event.Enable( m_symbol && m_symbol->GetUnitCount() > 1 );
934}
935
936
937void SYMBOL_EDIT_FRAME::OnSelectUnit( wxCommandEvent& event )
938{
939 if( event.GetSelection() == wxNOT_FOUND )
940 return;
941
942 SetUnit( event.GetSelection() + 1 );
943}
944
945
946void SYMBOL_EDIT_FRAME::OnUpdateBodyStyle( wxUpdateUIEvent& event )
947{
948 event.Enable( m_symbol && m_symbol->GetBodyStyleCount() > 1 );
949}
950
951
952void SYMBOL_EDIT_FRAME::OnSelectBodyStyle( wxCommandEvent& event )
953{
954 if( event.GetSelection() == wxNOT_FOUND )
955 return;
956
957 SetBodyStyle( event.GetSelection() + 1 );
958}
959
960
962{
963 if( m_symbol )
964 {
966
967 if( auto row = adapter->GetRow( m_symbol->GetLibNickname() ); row.has_value() )
968 {
969 if( ( *row )->Type() == SCH_IO_MGR::ShowType( SCH_IO_MGR::SCH_LEGACY ) )
970 return true;
971 }
972 }
973
974 return false;
975}
976
977
978void SYMBOL_EDIT_FRAME::SetCurSymbol( LIB_SYMBOL* aSymbol, bool aUpdateZoom )
979{
980 wxCHECK( m_toolManager, /* void */ );
981
983 GetCanvas()->GetView()->Clear();
984
985 // Install the replacement and refresh the active context before freeing the old symbol, so the
986 // context never observes a freed pointer.
987 LIB_SYMBOL* oldSymbol = m_symbol;
988
989 m_symbol = aSymbol;
990
991 if( m_activeTab )
992 m_activeTab->RefreshFrameOwnedObjects( m_symbol, static_cast<SCH_SCREEN*>( GetScreen() ) );
993
994 delete oldSymbol;
995
996 // select the current symbol in the tree widget
998 GetLibTree()->SelectLibId( m_symbol->GetLibId() );
999 else
1000 GetLibTree()->Unselect();
1001
1002 wxString symbolName;
1003 wxString libName;
1004
1005 if( m_symbol )
1006 {
1007 symbolName = m_symbol->GetName();
1008 libName = UnescapeString( m_symbol->GetLibId().GetLibNickname() );
1009 }
1010
1011 // Ensure synchronized pin edit can be enabled only symbols with interchangeable units
1012 m_SyncPinEdit = aSymbol && aSymbol->IsRoot() && aSymbol->IsMultiUnit() && !aSymbol->UnitsLocked();
1013
1015
1023
1024 if( aUpdateZoom )
1026
1027 GetCanvas()->Refresh();
1028 m_propertiesPanel->UpdateData();
1029
1030 WX_INFOBAR& infobar = *GetInfoBar();
1031 infobar.RemoveAllButtons();
1032
1033 wxArrayString msgs;
1034 int infobarFlags = wxICON_INFORMATION;
1035
1036 if( IsSymbolFromSchematic() )
1037 {
1038 msgs.push_back( wxString::Format( _( "Editing symbol %s from schematic. Saving will "
1039 "update the schematic only." ),
1040 m_reference ) );
1041
1042 wxString link = wxString::Format( _( "Open symbol from library %s" ), UnescapeString( libName ) );
1043 wxHyperlinkCtrl* button = new wxHyperlinkCtrl( &infobar, wxID_ANY, link, wxEmptyString );
1044
1045 button->Bind( wxEVT_COMMAND_HYPERLINK, std::function<void( wxHyperlinkEvent& aEvent )>(
1046 [this]( wxHyperlinkEvent& aEvent )
1047 {
1049 } ) );
1050
1051 infobar.AddButton( button );
1052 }
1053 else if( IsSymbolFromLegacyLibrary() )
1054 {
1055 msgs.push_back( _( "Symbols in legacy libraries are not editable. Use Manage Symbol "
1056 "Libraries to migrate to current format." ) );
1057
1058 wxString link = _( "Manage symbol libraries" );
1059 wxHyperlinkCtrl* button = new wxHyperlinkCtrl( &infobar, wxID_ANY, link, wxEmptyString );
1060
1061 button->Bind( wxEVT_COMMAND_HYPERLINK, std::function<void( wxHyperlinkEvent& aEvent )>(
1062 [this]( wxHyperlinkEvent& aEvent )
1063 {
1065 } ) );
1066
1067 infobar.AddButton( button );
1068 }
1069 else if( IsSymbolAlias() )
1070 {
1071 msgs.push_back( wxString::Format( _( "Symbol %s is a derived symbol. Symbol graphics will "
1072 "not be editable." ),
1073 UnescapeString( symbolName ) ) );
1074
1075 // Don't assume the parent symbol shared pointer is still valid.
1076 if( std::shared_ptr<LIB_SYMBOL> rootSymbol = m_symbol->GetRootSymbol() )
1077 {
1078 int unit = GetUnit();
1079 int bodyStyle = GetBodyStyle();
1080 wxString rootSymbolName = rootSymbol->GetName();
1081 wxString link = wxString::Format( _( "Open %s" ), UnescapeString( rootSymbolName ) );
1082
1083 wxHyperlinkCtrl* button = new wxHyperlinkCtrl( &infobar, wxID_ANY, link, wxEmptyString );
1084
1085 button->Bind( wxEVT_COMMAND_HYPERLINK, std::function<void( wxHyperlinkEvent& aEvent )>(
1086 [this, libName, rootSymbolName, unit, bodyStyle]( wxHyperlinkEvent& aEvent )
1087 {
1088 LoadSymbolFromLib( libName, rootSymbolName, unit, bodyStyle );
1089 } ) );
1090
1091 infobar.AddButton( button );
1092 }
1093 }
1094
1095 if( m_symbol
1097 && m_libMgr->IsLibraryReadOnly( m_symbol->GetLibId().GetFullLibraryName() ) )
1098 {
1099 msgs.push_back( _( "Library is read-only. Changes cannot be saved to this library." ) );
1100
1101 wxString link = wxString::Format( _( "Create an editable copy" ) );
1102 wxHyperlinkCtrl* button = new wxHyperlinkCtrl( &infobar, wxID_ANY, link, wxEmptyString );
1103
1104 button->Bind( wxEVT_COMMAND_HYPERLINK, std::function<void( wxHyperlinkEvent& aEvent )>(
1105 [this, libName]( wxHyperlinkEvent& aEvent )
1106 {
1107 wxString msg = wxString::Format( _( "Create an editable copy of the symbol or "
1108 "the entire library (%s)?" ),
1109 UnescapeString( libName ) );
1110
1111 KIDIALOG errorDlg( this, msg, _( "Select type of item to save" ),
1112 wxYES_NO | wxCANCEL | wxICON_QUESTION );
1113 // These buttons are in a weird order(?)
1114 errorDlg.SetYesNoCancelLabels( _( "Copy symbol" ), _( "Cancel" ), _( "Copy library" ) );
1115
1116 int choice = errorDlg.ShowModal();
1117
1118 switch( choice )
1119 {
1120 case wxID_YES:
1121 SaveSymbolCopyAs( true );
1122 break;
1123 case wxID_CANCEL:
1124 SaveLibraryAs();
1125 break;
1126 default:
1127 // Do nothing
1128 break;
1129 }
1130 } ) );
1131
1132 infobar.AddButton( button );
1133 }
1134
1135 if( msgs.empty() )
1136 {
1137 infobar.Dismiss();
1138 }
1139 else
1140 {
1141 wxString msg = wxJoin( msgs, '\n', '\0' );
1142 infobar.ShowMessage( msg, infobarFlags );
1143 }
1144}
1145
1146
1152
1153
1155{
1157
1159
1160 if( !IsSymbolFromSchematic() )
1161 {
1163 m_libMgr->UpdateSymbol( m_symbol, m_symbol->GetLibNickname() ); // UpdateSymbol() makes a copy
1164 }
1165
1166 if( m_isClosing )
1167 return;
1168
1169 // Clear preview so a later library-open gets its own tab instead of replacing this edited one.
1170 if( m_tabsPanel && m_activeTab )
1171 {
1172 m_activeTab->SetPreview( false );
1173
1174 if( int idx = m_tabsPanel->FindTab( m_activeTab->GetTabKey() ); idx >= 0 )
1175 m_tabsPanel->MarkModified( idx, true );
1176 }
1177
1179}
1180
1181
1183{
1184 wxCHECK( aUnit > 0 && aUnit <= GetCurSymbol()->GetUnitCount(), /* void*/ );
1185
1186 if( m_unit == aUnit )
1187 return;
1188
1191
1192 m_unit = aUnit;
1193
1194 if( m_unitSelectBox->GetSelection() != ( m_unit - 1 ) )
1195 m_unitSelectBox->SetSelection( m_unit - 1 );
1196
1198 RebuildView();
1200}
1201
1202
1204{
1205 wxCHECK( aBodyStyle > 0 && aBodyStyle <= GetCurSymbol()->GetBodyStyleCount(), /* void */ );
1206
1207 if( m_bodyStyle == aBodyStyle )
1208 return;
1209
1212
1213 m_bodyStyle = aBodyStyle;
1214
1215 if( m_bodyStyleSelectBox->GetSelection() != ( m_bodyStyle - 1 ) )
1216 m_bodyStyleSelectBox->SetSelection( m_bodyStyle - 1 );
1217
1218
1220 RebuildView();
1222}
1223
1224
1226{
1227 return m_SyncPinEdit && m_symbol && m_symbol->IsMultiUnit() && !m_symbol->UnitsLocked();
1228}
1229
1230
1231wxString SYMBOL_EDIT_FRAME::AddLibraryFile( bool aCreateNew )
1232{
1233 wxFileName fn = m_libMgr->GetUniqueLibraryName();
1234 bool useGlobalTable = true;
1235 FILEDLG_HOOK_NEW_LIBRARY tableChooser( useGlobalTable );
1236
1237 if( !LibraryFileBrowser( aCreateNew ? _( "New Symbol Library" ) : _( "Add Symbol Library" ),
1238 !aCreateNew, fn, FILEEXT::KiCadSymbolLibFileWildcard(),
1240 Pgm().GetSettingsManager().IsProjectOpenNotDummy() ? &tableChooser : nullptr ) )
1241 {
1242 return wxEmptyString;
1243 }
1244
1247
1248 LIBRARY_MANAGER& manager = Pgm().GetLibraryManager();
1249 std::optional<LIBRARY_TABLE*> optTable = manager.Table( LIBRARY_TABLE_TYPE::SYMBOL, scope );
1250
1251 wxCHECK( optTable.has_value(), wxEmptyString );
1252 LIBRARY_TABLE* table = optTable.value();
1253
1254 wxString libName = fn.GetName();
1255
1256 if( libName.IsEmpty() )
1257 return wxEmptyString;
1258
1260
1261 if( adapter->HasLibrary( libName ) )
1262 {
1263 DisplayError( this, wxString::Format( _( "Library '%s' already exists." ), libName ) );
1264 return wxEmptyString;
1265 }
1266
1267 if( aCreateNew )
1268 {
1269 // The file browser already asked to overwrite, so drop the old file here.
1270 // CreateLibrary fails on an existing path.
1271 if( fn.FileExists() && !wxRemoveFile( fn.GetFullPath() ) )
1272 {
1273 DisplayError( this, wxString::Format( _( "Could not overwrite the library file '%s'.\n"
1274 "Make sure you have write permissions and try again." ),
1275 fn.GetFullPath() ) );
1276 return wxEmptyString;
1277 }
1278
1279 if( !m_libMgr->CreateLibrary( fn.GetFullPath(), scope ) )
1280 {
1281 DisplayError( this, wxString::Format( _( "Could not create the library file '%s'.\n"
1282 "Make sure you have write permissions and try again." ),
1283 fn.GetFullPath() ) );
1284 return wxEmptyString;
1285 }
1286 }
1287 else
1288 {
1289 if( !m_libMgr->AddLibrary( fn.GetFullPath(), scope ) )
1290 {
1291 DisplayError( this, _( "Could not open the library file." ) );
1292 return wxEmptyString;
1293 }
1294 }
1295
1296 bool success = true;
1297
1298 // Tables are reinitialized by m_libMgr->AddLibrary(). So reinit table reference.
1299 optTable = manager.Table( LIBRARY_TABLE_TYPE::SYMBOL, scope );
1300 wxCHECK( optTable.has_value(), wxEmptyString );
1301 table = optTable.value();
1302
1303 table->Save().map_error(
1304 [&]( const LIBRARY_ERROR& aError )
1305 {
1306 KICAD_MESSAGE_DIALOG dlg( this, _( "Error saving library table." ), _( "File Save Error" ),
1307 wxOK | wxICON_ERROR );
1308 dlg.SetExtendedMessage( aError.message );
1309 dlg.ShowModal();
1310
1311 success = false;
1312 } );
1313
1314 if( success )
1315 adapter->LoadOne( fn.GetName() );
1316
1317 SyncLibraries( false );
1318
1319 if( m_treePane )
1320 {
1321 LIB_ID libId( fn.GetName(), wxEmptyString );
1322 GetLibTree()->SelectLibId( libId );
1323 GetLibTree()->CenterLibId( libId );
1324 }
1325
1326 return fn.GetFullPath();
1327}
1328
1329
1330void SYMBOL_EDIT_FRAME::DdAddLibrary( wxString aLibFile )
1331{
1332 wxFileName fn = wxFileName( aLibFile );
1333 wxString libName = fn.GetName();
1334
1335 if( libName.IsEmpty() )
1336 return;
1337
1338 LIBRARY_MANAGER& manager = Pgm().GetLibraryManager();
1340
1341 if( adapter->HasLibrary( libName ) )
1342 {
1343 DisplayError( this, wxString::Format( _( "Library '%s' already exists." ), libName ) );
1344 return;
1345 }
1346
1347 if( !m_libMgr->AddLibrary( fn.GetFullPath(), LIBRARY_TABLE_SCOPE::PROJECT ) )
1348 {
1349 DisplayError( this, _( "Could not open the library file." ) );
1350 return;
1351 }
1352
1353 std::optional<LIBRARY_TABLE*> optTable = manager.Table( LIBRARY_TABLE_TYPE::SYMBOL, LIBRARY_TABLE_SCOPE::PROJECT );
1354 wxCHECK( optTable.has_value(), /* void */ );
1355 LIBRARY_TABLE* table = optTable.value();
1356 bool success = true;
1357
1358 table->Save().map_error(
1359 [&]( const LIBRARY_ERROR& aError )
1360 {
1361 KICAD_MESSAGE_DIALOG dlg( this, _( "Error saving library table." ), _( "File Save Error" ),
1362 wxOK | wxICON_ERROR );
1363 dlg.SetExtendedMessage( aError.message );
1364 dlg.ShowModal();
1365
1366 success = false;
1367 } );
1368
1369 if( success )
1370 adapter->LoadOne( libName );
1371
1372 std::string packet = fn.GetFullPath().ToStdString();
1375}
1376
1377
1379{
1380 return GetLibTree()->GetSelectedLibId( aUnit );
1381}
1382
1383
1388
1389int SYMBOL_EDIT_FRAME::GetTreeLIBIDs( std::vector<LIB_ID>& aSelection ) const
1390{
1391 return GetLibTree()->GetSelectedLibIds( aSelection );
1392}
1393
1394
1396{
1397 if( IsLibraryTreeShown() )
1398 {
1399 LIB_ID libId = GetTreeLIBID();
1400
1401 if( libId.IsValid() )
1402 return m_libMgr->GetSymbol( libId.GetLibItemName(), libId.GetLibNickname() );
1403 }
1404
1405 return m_symbol;
1406}
1407
1408
1410{
1411 LIB_ID id;
1412
1413 if( IsLibraryTreeShown() )
1414 id = GetTreeLIBID();
1415
1416 if( id.GetLibNickname().empty() && m_symbol )
1417 id = m_symbol->GetLibId();
1418
1419 return id;
1420}
1421
1422
1423std::vector<LIB_ID> SYMBOL_EDIT_FRAME::GetSelectedLibIds() const
1424{
1425 std::vector<LIB_ID> ids;
1426 GetTreeLIBIDs( ids );
1427 return ids;
1428}
1429
1430
1432{
1433 return GetTargetLibId().GetLibNickname();
1434}
1435
1436
1437void SYMBOL_EDIT_FRAME::SyncLibraries( bool aShowProgress, bool aPreloadCancelled,
1438 const wxString& aForceRefresh )
1439{
1440 wxLogTrace( wxT( "KICAD_TABS_DBG" ),
1441 wxT( "SYMBOL_EDIT_FRAME::SyncLibraries enter (progress=%d, forceRefresh='%s')" ),
1442 aShowProgress, aForceRefresh );
1443
1444 // Prevent re-entrant calls. The progress dialog yields the event loop during Sync(),
1445 // which can dispatch queued UI events (e.g. menu clicks queued while the app was busy
1446 // loading libraries). A re-entrant call would corrupt the library tree mid-rebuild.
1448 {
1449 wxLogTrace( wxT( "KICAD_TABS_DBG" ),
1450 wxT( "SYMBOL_EDIT_FRAME::SyncLibraries re-entrant; skipping" ) );
1451 return;
1452 }
1453
1455
1456 auto resetGuard = [this]( bool* )
1457 {
1459 };
1460
1461 std::unique_ptr<bool, decltype( resetGuard )> guard( &m_syncLibrariesInProgress, resetGuard );
1462
1463 LIB_ID selected;
1464 std::vector<LIB_ID> expanded;
1465
1466 if( m_treePane )
1467 {
1468 selected = GetLibTree()->GetSelectedLibId();
1469 expanded = GetLibTree()->GetExpandedLibraries();
1470 }
1471
1472 // Ensure any in-progress background library preloading is complete before syncing the
1473 // tree. Without this, libraries still in LOADING state get skipped by Sync(), resulting
1474 // in an incomplete tree that requires a manual refresh to fully populate.
1476 adapter->BlockUntilLoaded();
1477
1478 if( aShowProgress )
1479 {
1480 APP_PROGRESS_DIALOG progressDlg( _( "Loading Symbol Libraries" ), wxEmptyString,
1481 m_libMgr->GetAdapter()->GetLibrariesCount(), this );
1482
1483 THROTTLE progressThrottle( std::chrono::milliseconds( 350 ) );
1484 int pendingProgress = 0;
1485 bool callbackFired = false;
1486 wxString pendingLibName;
1487
1488 m_libMgr->Sync( aForceRefresh,
1489 [&]( int progress, int max, const wxString& libName )
1490 {
1491 pendingProgress = progress;
1492 pendingLibName = libName;
1493 callbackFired = true;
1494
1495 if( progressThrottle.Ready() )
1496 progressDlg.Update( progress, wxString::Format( _( "Loading library '%s'..." ), libName ) );
1497 } );
1498
1499 if( callbackFired )
1500 progressDlg.Update( pendingProgress, wxString::Format( _( "Loading library '%s'..." ), pendingLibName ) );
1501 }
1502 else if( !aPreloadCancelled )
1503 {
1504 m_libMgr->Sync( aForceRefresh, [&]( int progress, int max, const wxString& libName ) {} );
1505 }
1506
1507 if( m_treePane )
1508 {
1509 wxDataViewItem found;
1510
1511 if( selected.IsValid() )
1512 {
1513 // Check if the previously selected item is still valid,
1514 // if not - it has to be unselected to prevent crash
1515 found = m_libMgr->GetAdapter()->FindItem( selected );
1516
1517 if( !found )
1518 GetLibTree()->Unselect();
1519 }
1520
1521 wxLogTrace( wxT( "KICAD_TABS_DBG" ), wxT( "SYMBOL_EDIT_FRAME::SyncLibraries Regenerate" ) );
1522 GetLibTree()->Regenerate( true );
1523
1524 // Sync() collapsed the tree, so re-expand the libraries that were open before it.
1525 for( const LIB_ID& libId : expanded )
1526 GetLibTree()->ExpandLibId( libId );
1527
1528 // Try to select the parent library, in case the symbol is not found
1529 if( !found && selected.IsValid() )
1530 {
1531 selected.SetLibItemName( "" );
1532 found = m_libMgr->GetAdapter()->FindItem( selected );
1533
1534 if( found )
1535 GetLibTree()->SelectLibId( selected );
1536 }
1537 }
1538
1539 wxLogTrace( wxT( "KICAD_TABS_DBG" ), wxT( "SYMBOL_EDIT_FRAME::SyncLibraries exit" ) );
1540}
1541
1542
1547
1548
1550{
1551 GetLibTree()->SelectLibId( aLibID );
1552}
1553
1554
1555void SYMBOL_EDIT_FRAME::UpdateLibraryTree( const wxDataViewItem& aTreeItem, LIB_SYMBOL* aSymbol )
1556{
1557 if( aTreeItem.IsOk() ) // Can be not found in tree if the current footprint is imported
1558 // from file therefore not yet in tree.
1559 {
1560 static_cast<LIB_TREE_NODE_ITEM*>( aTreeItem.GetID() )->Update( aSymbol );
1562 }
1563}
1564
1565
1566bool SYMBOL_EDIT_FRAME::backupFile( const wxFileName& aOriginalFile, const wxString& aBackupExt )
1567{
1568 if( aOriginalFile.FileExists() )
1569 {
1570 wxFileName backupFileName( aOriginalFile );
1571 backupFileName.SetExt( aBackupExt );
1572
1573 if( backupFileName.FileExists() )
1574 wxRemoveFile( backupFileName.GetFullPath() );
1575
1576 if( !wxCopyFile( aOriginalFile.GetFullPath(), backupFileName.GetFullPath() ) )
1577 {
1578 DisplayError( this, wxString::Format( _( "Failed to save backup to '%s'." ),
1579 backupFileName.GetFullPath() ) );
1580 return false;
1581 }
1582 }
1583
1584 return true;
1585}
1586
1587
1589{
1590 // This will return the root symbol of any alias
1591 LIB_SYMBOL* symbol = m_libMgr->GetBufferedSymbol( aLibId.GetLibItemName(), aLibId.GetLibNickname() );
1592
1593 // Now we can compare the libId of the current symbol and the root symbol
1594 return ( symbol && m_symbol && symbol->GetLibId() == m_symbol->GetLibId() );
1595}
1596
1597
1599{
1600 GetLibTree()->Unselect();
1601
1602 // Tear down every tab first so no context observes the about-to-be-deleted working symbol.
1604
1605 SetCurSymbol( nullptr, false );
1609 Refresh();
1610}
1611
1612
1614{
1616
1618 {
1619 GetRenderSettings()->m_ShowPinsElectricalType = cfg->m_ShowPinElectricalType;
1620 GetRenderSettings()->m_ShowHiddenPins = cfg->m_ShowHiddenPins;
1621 GetRenderSettings()->m_ShowHiddenFields = cfg->m_ShowHiddenFields;
1622 GetRenderSettings()->m_ShowPinAltIcons = cfg->m_ShowPinAltIcons;
1623
1624 GetGalDisplayOptions().ReadWindowSettings( cfg->m_Window );
1625 }
1626
1627 if( m_symbol )
1628 m_symbol->ClearCaches();
1629
1631
1633 GetCanvas()->Refresh();
1634
1636
1637 if( aFlags & ENVVARS_CHANGED )
1638 SyncLibraries( true );
1639
1640 Layout();
1641 SendSizeEvent();
1642}
1643
1644
1646{
1647 // call my base class
1649
1650 // tooltips in toolbars
1652
1653 // For some obscure reason, the AUI manager hides the first modified pane.
1654 // So force show panes
1655 wxAuiPaneInfo& tree_pane_info = m_auimgr.GetPane( m_treePane );
1656 bool tree_shown = tree_pane_info.IsShown();
1657 tree_pane_info.Caption( _( "Libraries" ) );
1658 tree_pane_info.Show( tree_shown );
1659 m_auimgr.Update();
1660
1662
1663 // status bar
1665
1666 if( GetRenderSettings()->m_ShowPinsElectricalType )
1667 {
1669 GetCanvas()->Refresh();
1670 }
1671
1672 UpdateTitle();
1673}
1674
1675
1677{
1678 SCH_BASE_FRAME::SetScreen( aScreen );
1679
1680 if( m_toolManager )
1681 {
1682 m_toolManager->SetEnvironment( aScreen, GetCanvas()->GetView(), GetCanvas()->GetViewControls(), GetSettings(),
1683 this );
1685 }
1686}
1687
1688
1706
1707
1709{
1710 SyncLibraries( true );
1711
1712 if( m_symbol )
1713 {
1714 SCH_SELECTION_TOOL* selectionTool = m_toolManager->GetTool<SCH_SELECTION_TOOL>();
1715 SCH_SELECTION& selection = selectionTool->GetSelection();
1716
1717 for( SCH_ITEM& item : m_symbol->GetDrawItems() )
1718 {
1719 if( !alg::contains( selection, &item ) )
1720 item.ClearSelected();
1721 else
1722 item.SetSelected();
1723 }
1724
1725 m_symbol->ClearCaches();
1726 }
1727
1728 RebuildView();
1729}
1730
1731
1732const BOX2I SYMBOL_EDIT_FRAME::GetDocumentExtents( bool aIncludeAllVisible ) const
1733{
1734 if( !m_symbol )
1735 {
1736 // Gives a reasonable drawing area size
1737 int width = schIUScale.mmToIU( 50 );
1738 int height = schIUScale.mmToIU( 30 );
1739
1740 return BOX2I( VECTOR2I( -width/2, -height/2 ), VECTOR2I( width, height ) );
1741 }
1742 else
1743 {
1744 return m_symbol->Flatten()->GetUnitBoundingBox( m_unit, m_bodyStyle );
1745 }
1746}
1747
1748
1749void SYMBOL_EDIT_FRAME::FocusOnItem( EDA_ITEM* aItem, bool aAllowScroll )
1750{
1751 static KIID lastBrightenedItemID( niluuid );
1752
1753 SCH_ITEM* lastItem = nullptr;
1754
1755 // nullptr will clear the current focus
1756 if( aItem != nullptr && !aItem->IsSCH_ITEM() )
1757 return;
1758
1759 if( m_symbol )
1760 {
1761 for( SCH_PIN* pin : m_symbol->GetGraphicalPins( 0, 0 ) )
1762 {
1763 if( pin->m_Uuid == lastBrightenedItemID )
1764 lastItem = pin;
1765 }
1766
1767 std::vector<SCH_FIELD*> fields;
1768 m_symbol->GetFields( fields );
1769
1770 for( SCH_FIELD* field : fields )
1771 {
1772 if( field->m_Uuid == lastBrightenedItemID )
1773 lastItem = field;
1774 }
1775 }
1776
1777 if( lastItem && lastItem != aItem )
1778 {
1779 lastItem->ClearBrightened();
1780
1781 UpdateItem( lastItem );
1782 lastBrightenedItemID = niluuid;
1783 }
1784
1785 if( aItem )
1786 {
1787 if( aItem->IsSCH_ITEM() )
1788 {
1789 SCH_ITEM* item = static_cast<SCH_ITEM*>( aItem );
1790
1791 if( int unit = item->GetUnit() )
1792 SetUnit( unit );
1793
1794 if( int bodyStyle = item->GetBodyStyle() )
1795 SetBodyStyle( bodyStyle );
1796 }
1797
1798 if( !aItem->IsBrightened() )
1799 {
1800 aItem->SetBrightened();
1801
1802 UpdateItem( aItem );
1803 lastBrightenedItemID = aItem->m_Uuid;
1804 }
1805
1806 FocusOnLocation( VECTOR2I( aItem->GetFocusPosition().x, aItem->GetFocusPosition().y ), aAllowScroll );
1807 }
1808}
1809
1810
1812{
1813 const std::string& payload = mail.GetPayload();
1814
1815 wxLogTrace( wxT( "KICAD_TABS_DBG" ), wxT( "SYMBOL_EDIT_FRAME::KiwayMailIn cmd=%d" ),
1816 (int) mail.Command() );
1817
1818 switch( mail.Command() )
1819 {
1820 case MAIL_LIB_EDIT:
1821 if( !payload.empty() )
1822 {
1823 wxString uri( payload );
1824 wxString libNickname;
1825 wxString msg;
1826
1828 std::optional<const LIBRARY_TABLE_ROW*> libTableRow = adapter->FindRowByURI( uri );
1829
1830 if( !libTableRow )
1831 {
1832 msg.Printf( _( "The current configuration does not include the symbol library '%s'." ),
1833 uri );
1834 msg += wxS( "\n" ) + _( "Use Manage Symbol Libraries to edit the configuration." );
1835 DisplayErrorMessage( this, _( "Library not found in symbol library table." ), msg );
1836 break;
1837 }
1838
1839 libNickname = ( *libTableRow )->Nickname();
1840
1841 if( !adapter->HasLibrary( libNickname, true ) )
1842 {
1843 msg.Printf( _( "The symbol library '%s' is not enabled in the current configuration." ),
1844 UnescapeString( libNickname ) );
1845 msg += wxS( "\n" ) + _( "Use Manage Symbol Libraries to edit the configuration." );
1846 DisplayErrorMessage( this, _( "Symbol library not enabled." ), msg );
1847 break;
1848 }
1849
1850 if( m_treePane )
1851 {
1852 LIB_ID id( libNickname, wxEmptyString );
1853 GetLibTree()->SelectLibId( id );
1854 GetLibTree()->ExpandLibId( id );
1855 GetLibTree()->CenterLibId( id );
1856 }
1857 }
1858
1859 break;
1860
1861 case MAIL_RELOAD_LIB:
1862 {
1863 wxLogTrace( wxT( "KICAD_TABS_DBG" ),
1864 wxT( "SYMBOL_EDIT_FRAME::KiwayMailIn MAIL_RELOAD_LIB -> SyncLibraries" ) );
1865
1867
1868 // Suppress the progress dialog for this background reload. It would steal focus from the
1869 // editor that broadcast the reload, and the tree is already frozen around the sync.
1870 SyncLibraries( false );
1873
1874 break;
1875 }
1876
1878 {
1880 LIB_SYMBOL* symbol = GetCurSymbol();
1881
1882 wxLogTrace( traceLibWatch, "Received refresh symbol request for %s", payload );
1883
1884 if( !symbol )
1885 break;
1886
1887 // Capture the name now. UpdateLibraryBuffer() recreates the buffer, so reading it from the
1888 // buffer copy afterwards would be a use-after-free.
1889 const wxString refreshSymbolName = symbol->GetName();
1890
1891 // A modal dialog may be registered before wxGTK disables the frame. Refreshing the
1892 // symbol in either state would delete the LIB_SYMBOL being edited by the dialog.
1893 if( !IsEnabled() || Kiway().HasBlockingDialog() )
1894 {
1895 wxLogTrace( traceLibWatch, "Deferring symbol refresh; dialog is open on the symbol editor." );
1896 break;
1897 }
1898 // Defensive backstop for refresh mail that did not originate from this frame's debounce
1899 // timer (which already defers while a tool is active). An interactive tool holds
1900 // references into the current symbol, so replacing it here would crash; drop this refresh
1901 // and let the originating watcher retry.
1902 else if( !ToolStackIsEmpty() )
1903 {
1904 wxLogTrace( traceLibWatch, "Deferring symbol refresh; an interactive tool is active." );
1905 break;
1906 }
1907
1908 wxString libName = symbol->GetLibId().GetLibNickname();
1909 std::optional<const LIBRARY_TABLE_ROW*> row = adapter->GetRow( libName );
1910
1911 if( !row )
1912 return;
1913
1914 wxFileName libfullname( LIBRARY_MANAGER::GetFullURI( *row, true ) );
1915
1916 wxFileName changedLib( mail.GetPayload() );
1917
1918 wxLogTrace( traceLibWatch, "Received refresh symbol request for %s, current symbols is %s",
1919 changedLib.GetFullPath(), libfullname.GetFullPath() );
1920
1921 if( changedLib == libfullname )
1922 {
1923 wxLogTrace( traceLibWatch, "Refreshing symbol %s", refreshSymbolName );
1924
1925 m_libMgr->UpdateLibraryBuffer( libName );
1926
1927 if( LIB_SYMBOL* lib_symbol = m_libMgr->GetBufferedSymbol( refreshSymbolName, libName ) )
1928 {
1929 SetCurSymbol( new LIB_SYMBOL( *lib_symbol ), false );
1931
1932 if( m_toolManager )
1934 }
1935 }
1936
1937 break;
1938 }
1939
1940 default:
1941 break;
1942 }
1943}
1944
1945
1946std::unique_ptr<GRID_HELPER> SYMBOL_EDIT_FRAME::MakeGridHelper()
1947{
1948 return std::make_unique<EE_GRID_HELPER>( m_toolManager );
1949}
1950
1951
1953{
1954 // switches currently used canvas ( Cairo / OpenGL):
1955 SCH_BASE_FRAME::SwitchCanvas( aCanvasType );
1956
1957 // Set options specific to symbol editor (axies are always enabled):
1958 GetCanvas()->GetGAL()->SetAxesEnabled( true );
1960}
1961
1962
1964{
1965 wxCHECK( m_libMgr, false );
1966
1967 return m_libMgr->HasModifications();
1968}
1969
1970
1972{
1973 wxCHECK( m_libMgr, false );
1974
1975 // Test if the currently edited symbol is modified
1977 return true;
1978
1979 // Test if any library has been modified
1980 for( const wxString& libName : m_libMgr->GetLibraryNames() )
1981 {
1982 if( m_libMgr->IsLibraryModified( libName ) && !m_libMgr->IsLibraryReadOnly( libName ) )
1983 return true;
1984 }
1985
1986 return false;
1987}
1988
1989
1991{
1992 if( aItemCount == 0 )
1993 return;
1994
1995 UNDO_REDO_CONTAINER& list = ( whichList == UNDO_LIST ) ? m_undoList : m_redoList;
1996
1997 // UR_TRANSIENT is flagged on the picked item, not the wrapper, so the shared deleters miss it.
1998 // Free the items carrying UR_TRANSIENT. m_symbol never carries it, so the live copy is safe.
1999 if( aItemCount < 0 )
2000 {
2002 }
2003 else
2004 {
2005 for( int ii = 0; ii < aItemCount; ii++ )
2006 {
2007 if( list.m_CommandsList.size() == 0 )
2008 break;
2009
2010 PICKED_ITEMS_LIST* curr_cmd = list.m_CommandsList[0];
2011 list.m_CommandsList.erase( list.m_CommandsList.begin() );
2012
2013 for( unsigned jj = 0; jj < curr_cmd->GetCount(); ++jj )
2014 {
2015 EDA_ITEM* item = curr_cmd->GetPickedItem( jj );
2016
2017 if( item && item->HasFlag( UR_TRANSIENT ) && item != m_symbol )
2018 delete item;
2019 }
2020
2021 curr_cmd->ClearItemsList();
2022 delete curr_cmd; // Delete command
2023 }
2024 }
2025}
2026
2027
2029{
2030 return m_toolManager->GetTool<SCH_SELECTION_TOOL>()->GetSelection();
2031}
2032
2033
2035 bool aRestorePending, bool aTreeShownNow )
2036{
2037 // Auto-hiding a visible tree schedules its restore. A chained schematic edit finds the tree
2038 // already auto-hidden, so keep the pending restore rather than dropping it. An explicit user
2039 // toggle clears the flag elsewhere, so a tree hidden without a pending restore stays that way.
2040 if( aTreeShownNow )
2041 return true;
2042
2043 return aWasFromSchematic && aRestorePending;
2044}
2045
2046
2048{
2049 std::unique_ptr<LIB_SYMBOL> symbol = aSymbol->GetLibSymbolRef()->Flatten();
2050 wxCHECK( symbol, /* void */ );
2051
2052 symbol->SetLibId( aSymbol->GetLibId() );
2053
2054 // Take in account the symbol orientation and mirroring. to calculate the field
2055 // positions in symbol editor (i.e. no rotation, no mirroring)
2056 int orientation = aSymbol->GetOrientation() & ~( SYM_MIRROR_X | SYM_MIRROR_Y );
2057 int mirror = aSymbol->GetOrientation() & ( SYM_MIRROR_X | SYM_MIRROR_Y );
2058
2059 std::vector<SCH_FIELD> fullSetOfFields;
2060
2061 for( const SCH_FIELD& field : aSymbol->GetFields() )
2062 {
2063 VECTOR2I pos = field.GetPosition() - aSymbol->GetPosition();
2064 SCH_FIELD libField( symbol.get(), field.GetId() );
2065
2066 libField = field;
2067
2068 // The inverse transform is mirroring before, rotate after
2069 switch( mirror )
2070 {
2071 case SYM_MIRROR_X: pos.y = -pos.y; break;
2072 case SYM_MIRROR_Y: pos.x = -pos.x; break;
2073 default: break;
2074 }
2075
2076 switch( orientation )
2077 {
2078 case SYM_ORIENT_90:
2079 std::swap( pos.x, pos.y );
2080 pos.x = - pos.x;
2081 break;
2082 case SYM_ORIENT_270:
2083 std::swap( pos.x, pos.y );
2084 pos.y = - pos.y;
2085 break;
2086 case SYM_ORIENT_180:
2087 pos.x = - pos.x;
2088 pos.y = - pos.y;
2089 break;
2090 default:
2091 break;
2092 }
2093
2094 libField.SetPosition( pos );
2095
2096 fullSetOfFields.emplace_back( std::move( libField ) );
2097 }
2098
2099 symbol->SetFields( fullSetOfFields );
2100
2101 const wxString reference = symbol->GetReferenceField().GetText();
2102 const int unit = std::max( 1, aSymbol->GetUnit() );
2103 const int bodyStyle = std::max( 1, aSymbol->GetBodyStyle() );
2104
2105 // Optimize default edit options for this symbol
2106 // Usually if units are locked, graphic items are specific to each unit
2107 // and if units are interchangeable, graphic items are common to units
2108 SetDrawSpecificUnit( symbol->UnitsLocked() );
2109
2110 // Hand the transient working symbol/screen to a session-only instance tab, whose activation
2111 // restores the frame's schematic-source state so the save path routes back to the schematic.
2112 SCH_SCREEN* tmpScreen = new SCH_SCREEN();
2113
2114 setSymWatcher( nullptr );
2115
2116 SYMBOL_EDITOR_TAB_CONTEXT* ctx = findOrCreateSymbolInstanceTab( symbol.release(), tmpScreen,
2117 aSymbol->m_Uuid, reference, unit,
2118 bodyStyle );
2119 wxCHECK( ctx, /* void */ );
2120
2123
2124 // Auto-hide the tree while editing a schematic symbol, remembering to restore it in SaveSettings
2125 // so the user's preference survives a restart. Hide via the pane directly, not ToggleLibraryTree,
2126 // which would treat this as a user toggle and drop the pending restore.
2129
2130 if( IsLibraryTreeShown() )
2131 {
2132 m_auimgr.GetPane( m_treePane ).Show( false );
2134 m_auimgr.Update();
2135 Refresh();
2136 }
2137
2140
2141 // Let tools add things to the view if necessary
2142 if( m_toolManager )
2144
2146 GetCanvas()->Refresh();
2147}
2148
2149
2150bool SYMBOL_EDIT_FRAME::addLibTableEntry( const wxString& aLibFile, LIBRARY_TABLE_SCOPE aScope )
2151{
2152 wxFileName fn = aLibFile;
2153 wxFileName libTableFileName( Prj().GetProjectPath(), FILEEXT::SymbolLibraryTableFileName );
2154 wxString libNickname = fn.GetName();
2156 LIBRARY_MANAGER& manager = Pgm().GetLibraryManager();
2157 const ENV_VAR_MAP& envVars = Pgm().GetLocalEnvVariables();
2158
2159 if( adapter->HasLibrary( libNickname ) )
2160 {
2161 wxString tmp;
2162 int suffix = 1;
2163
2164 while( adapter->HasLibrary( libNickname ) )
2165 {
2166 tmp.Printf( "%s%d", fn.GetName(), suffix );
2167 libNickname = tmp;
2168 suffix += 1;
2169 }
2170 }
2171
2172 std::optional<LIBRARY_TABLE*> optTable = manager.Table( LIBRARY_TABLE_TYPE::SYMBOL, aScope );
2173 wxCHECK( optTable.has_value(), false );
2174 LIBRARY_TABLE* table = optTable.value();
2175
2176 LIBRARY_TABLE_ROW* row = &table->InsertRow();
2177
2178 row->SetNickname( libNickname );
2179
2180 // We cannot normalize against the current project path when saving to global table.
2181 wxString normalizedPath = NormalizePath( aLibFile, &envVars,
2182 aScope == LIBRARY_TABLE_SCOPE::PROJECT ? Prj().GetProjectPath()
2183 : wxString( wxEmptyString ) );
2184
2185 row->SetURI( normalizedPath );
2187
2188 bool success = true;
2189
2190 table->Save().map_error(
2191 [&]( const LIBRARY_ERROR& aError )
2192 {
2193 KICAD_MESSAGE_DIALOG dlg( this, _( "Error saving library table." ), _( "File Save Error" ),
2194 wxOK | wxICON_ERROR );
2195 dlg.SetExtendedMessage( aError.message );
2196 dlg.ShowModal();
2197
2198 success = false;
2199 } );
2200
2201 if( success )
2202 {
2203 manager.ReloadTables( aScope, { LIBRARY_TABLE_TYPE::SYMBOL } );
2204 adapter->LoadOne( libNickname );
2205 }
2206
2207 return success;
2208}
2209
2210
2211bool SYMBOL_EDIT_FRAME::replaceLibTableEntry( const wxString& aLibNickname, const wxString& aLibFile )
2212{
2214 LIBRARY_MANAGER& manager = Pgm().GetLibraryManager();
2215 LIBRARY_TABLE* table = nullptr;
2217
2218 // Check the global library table first because checking the project library table
2219 // checks the global library table as well due to library chaining.
2220 if( adapter->GetRow( aLibNickname, scope ) )
2221 {
2222 std::optional<LIBRARY_TABLE*> optTable = manager.Table( LIBRARY_TABLE_TYPE::SYMBOL, scope );
2223 wxCHECK( optTable.has_value(), false );
2224 table = optTable.value();
2225 }
2226 else
2227 {
2229
2230 if( adapter->GetRow( aLibNickname, scope ) )
2231 {
2232 std::optional<LIBRARY_TABLE*> optTable = manager.Table( LIBRARY_TABLE_TYPE::SYMBOL, scope );
2233
2234 if( optTable.has_value() )
2235 table = optTable.value();
2236 }
2237 }
2238
2239 wxCHECK( table, false );
2240
2241 std::optional<LIBRARY_TABLE_ROW*> optRow = adapter->GetRow( aLibNickname, scope );
2242 wxCHECK( optRow.has_value(), false );
2243 LIBRARY_TABLE_ROW* row = optRow.value();
2244
2245 const ENV_VAR_MAP& envVars = Pgm().GetLocalEnvVariables();
2246
2247 wxString projectPath;
2248
2249 if( scope == LIBRARY_TABLE_SCOPE::PROJECT )
2250 projectPath = Prj().GetProjectPath();
2251
2252 wxString normalizedPath = NormalizePath( aLibFile, &envVars, projectPath );
2253
2254 row->SetURI( normalizedPath );
2255 row->SetType( "KiCad" );
2256
2257 bool success = true;
2258
2259 table->Save().map_error(
2260 [&]( const LIBRARY_ERROR& aError )
2261 {
2262 KICAD_MESSAGE_DIALOG dlg( this, _( "Error saving library table." ), _( "File Save Error" ),
2263 wxOK | wxICON_ERROR );
2264 dlg.SetExtendedMessage( aError.message );
2265 dlg.ShowModal();
2266
2267 success = false;
2268 } );
2269
2270 if( success )
2271 {
2272 manager.ReloadTables( scope, { LIBRARY_TABLE_TYPE::SYMBOL } );
2273 adapter->LoadOne( aLibNickname );
2274 }
2275
2276 return success;
2277}
2278
2279
2281{
2282 return m_symbol && !m_symbol->IsRoot();
2283}
2284
2285
2290
2291
2292void SYMBOL_EDIT_FRAME::UpdateItem( EDA_ITEM* aItem, bool isAddOrDelete, bool aUpdateRtree )
2293{
2294 SCH_BASE_FRAME::UpdateItem( aItem, isAddOrDelete, aUpdateRtree );
2295
2296 if( EDA_TEXT* eda_text = dynamic_cast<EDA_TEXT*>( aItem ) )
2297 {
2298 eda_text->ClearBoundingBoxCache();
2299 eda_text->ClearRenderCache();
2300 }
2301}
2302
2303
2305{
2306 wxAuiPaneInfo& treePane = m_auimgr.GetPane( m_treePane );
2307 wxAuiPaneInfo& propertiesPane = m_auimgr.GetPane( PropertiesPaneName() );
2308 wxAuiPaneInfo& selectionFilterPane = m_auimgr.GetPane( wxS( "SelectionFilter" ) );
2309
2310 // Don't give the selection filter its own visibility controls; instead show it if
2311 // anything else is visible
2312 bool showFilter = ( treePane.IsShown() && treePane.IsDocked() )
2313 || ( propertiesPane.IsShown() && propertiesPane.IsDocked() );
2314
2315 selectionFilterPane.Show( showFilter );
2316}
2317
2318
2320{
2321 // Returns the current render option for invisible fields
2323}
2324
2325
2327{
2328 // Returns the current render option for invisible pins
2330}
BASE_SCREEN class implementation.
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:123
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:918
BOX2< VECTOR2D > BOX2D
Definition box2.h:919
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:233
constexpr void SetSize(const SizeVec &size)
Definition box2.h:244
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
EDA_DRAW_PANEL_GAL::GAL_TYPE m_canvasType
The current canvas type.
void OnSelectGrid(wxCommandEvent &event)
Command event handler for selecting grid sizes.
void setupUnits(APP_SETTINGS_BASE *aCfg)
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:96
virtual const VECTOR2I GetFocusPosition() const
Similar to GetPosition() but allows items to return their visual center rather than their anchor.
Definition eda_item.h:289
const KIID m_Uuid
Definition eda_item.h:531
void ClearBrightened()
Definition eda_item.h:148
void SetBrightened()
Definition eda_item.h:145
bool HasFlag(EDA_ITEM_FLAGS aFlag) const
Definition eda_item.h:156
bool IsBrightened() const
Definition eda_item.h:134
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:89
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.
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
Crosshair drawing mode.
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:1218
void UpdateAllItems(int aUpdateFlags)
Update all items in the view according to the given flags.
Definition view.cpp:1686
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:311
void OnKiCadExit()
Definition kiway.cpp:786
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:183
bool UnitsLocked() const
Check whether symbol units are interchangeable.
Definition lib_symbol.h:366
bool IsRoot() const override
For symbols derived from other symbols, IsRoot() indicates no derivation.
Definition lib_symbol.h:230
wxString GetName() const override
Definition lib_symbol.h:176
bool IsMultiUnit() const override
Definition lib_symbol.h:867
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:493
void CenterLibId(const LIB_ID &aLibId)
Ensure that an item is visible (preferably centered).
Definition lib_tree.cpp:383
int GetSelectionCount() const
Definition lib_tree.h:88
void ShutdownPreviews()
Definition lib_tree.cpp:283
void ShowChangedLanguage()
Definition lib_tree.cpp:300
void FocusSearchFieldIfExists()
Focus the search widget if it exists.
Definition lib_tree.cpp:508
std::vector< LIB_ID > GetExpandedLibraries() const
Definition lib_tree.cpp:403
void SelectLibId(const LIB_ID &aLibId)
Select an item in the tree widget.
Definition lib_tree.cpp:371
LIB_TREE_MODEL_ADAPTER::SORT_MODE GetSortMode() const
Definition lib_tree.h:154
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:330
void Unselect()
Unselect currently selected item in wxDataViewCtrl.
Definition lib_tree.cpp:389
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:310
void ExpandLibId(const LIB_ID &aLibId)
Expand and item i the tree widget.
Definition lib_tree.cpp:397
void Regenerate(bool aKeepState)
Regenerate the tree.
Definition lib_tree.cpp:475
virtual ENV_VAR_MAP & GetLocalEnvVariables() const
Definition pgm_base.cpp:808
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition pgm_base.h:124
virtual LIBRARY_MANAGER & GetLibraryManager() const
Definition pgm_base.h:126
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:36
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
Definition sch_actions.h:94
static TOOL_ACTION editLibSymbolWithLibEdit
static TOOL_ACTION drawArc
Definition sch_actions.h:95
static TOOL_ACTION pinTable
static TOOL_ACTION drawSymbolLines
static TOOL_ACTION placeSymbolPin
static TOOL_ACTION drawSymbolTextBox
static TOOL_ACTION ddImportGraphics
static TOOL_ACTION drawRectangle
Definition sch_actions.h:91
static TOOL_ACTION drawEllipse
Definition sch_actions.h:93
static TOOL_ACTION drawCircle
Definition sch_actions.h:92
static TOOL_ACTION importGraphics
static TOOL_ACTION drawBezier
Definition sch_actions.h:96
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 #VIEW instance used in the panel.
void DisplaySymbol(LIB_SYMBOL *aSymbol)
Schematic editor (Eeschema) main window.
void 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:162
int GetBodyStyle() const
Definition sch_item.h:242
int GetUnit() const
Definition sch_item.h:233
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:69
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:914
const LIB_ID & GetLibId() const override
Definition sch_symbol.h:158
int GetOrientation() const override
Get the display symbol orientation.
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition sch_symbol.h:177
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.
bool m_ShowPinAltIcons
When true, dragging an outline edge will drag pins rooted on it.
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
True while a schematic-edit auto-hide of the library tree still needs restoring on save.
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 (schematic) tab that is not the active one, since the active tab's...
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.
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
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
Restore the empty editor screen, without any symbol or library selected.
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)
bool backupFile(const wxFileName &aOriginalFile, const wxString &aBackupExt)
Return currently edited symbol.
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
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)
bool IsSymbolAlias() const
Return true if aLibId is an alias for the editor screen symbol.
void ToggleProperties() override
SYMBOL_EDITOR_SETTINGS * m_settings
void HardRedraw() override
Rebuild the GAL and redraw the screen.
bool m_SyncPinEdit
Set to true to synchronize pins at the same position when editing symbols with multiple units or mult...
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.
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_ROUTED_EVENT messages from other players.
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.
KIID m_schematicSymbolUUID
RefDes of the symbol (only valid if symbol was loaded from schematic)
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::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...
void SetBodyStyle(int aBodyStyle)
bool saveAllLibraries(bool aRequireConfirmation)
Save the current symbol.
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.
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.
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.
void SaveLibraryAs()
Save the currently selected library to a new file.
bool IsContentModified() const override
Get if any symbols or libraries have been modified but not saved.
void ToggleLibraryTree() override
LIB_SYMBOL * getTargetSymbol() const
Return either the library selected in the symbol tree, if context menu is active or the library that ...
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.
bool empty() const
Definition utf8.h:105
A modified version of the wxInfoBar class that allows us to:
Definition wx_infobar.h:77
void RemoveAllButtons()
Remove all the buttons that have been added by the user.
void AddButton(wxButton *aButton)
Add an already created button to the infobar.
void Dismiss() override
Dismisses the infobar and updates the containing layout and AUI manager (if one is provided).
void ShowMessage(const wxString &aMessage, int aFlags=wxICON_INFORMATION) override
Show the info bar with the provided message and icon.
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition confirm.cpp:217
int UnsavedChangesDialog(wxWindow *parent, const wxString &aMessage, bool *aApplyToAll)
A specialized version of HandleUnsavedChanges which handles an apply-to-all checkbox.
Definition confirm.cpp:60
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.
@ 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:728
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:493
LIBRARY_TABLE_SCOPE
@ MAIL_LIB_EDIT
Definition mail_type.h:52
@ 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
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition kicad_algo.h:96
#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:38
@ SYM_MIRROR_Y
Definition symbol.h:40
@ SYM_ORIENT_180
Definition symbol.h:37
@ SYM_MIRROR_X
Definition symbol.h:39
@ SYM_ORIENT_90
Definition symbol.h:36
#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:683
VECTOR2< double > VECTOR2D
Definition vector2d.h:682
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.