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>
72#include <view/view_controls.h>
74#include <widgets/wx_infobar.h>
80#include <widgets/lib_tree.h>
85#include <panel_sym_lib_table.h>
86#include <string_utils.h>
88#include <wx/msgdlg.h>
89#include <wx/combobox.h>
90#include <wx/log.h>
91#include <trace_helpers.h>
92
93
95
96
97BEGIN_EVENT_TABLE( SYMBOL_EDIT_FRAME, SCH_BASE_FRAME )
100
101 // menubar commands
104
105 // Update user interface elements.
108
111
112 // Drop files event
113 EVT_DROP_FILES( SYMBOL_EDIT_FRAME::OnDropFiles )
114
115END_EVENT_TABLE()
116
117
118SYMBOL_EDIT_FRAME::SYMBOL_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
119 SCH_BASE_FRAME( aKiway, aParent, FRAME_SCH_SYMBOL_EDITOR, _( "Library Editor" ),
120 wxDefaultPosition, wxDefaultSize, KICAD_DEFAULT_DRAWFRAME_STYLE,
122 m_unitSelectBox( nullptr ),
123 m_bodyStyleSelectBox( nullptr ),
126{
127 m_SyncPinEdit = false;
128
129 m_symbol = nullptr;
130 m_treePane = nullptr;
131 m_libMgr = nullptr;
132 m_unit = 1;
133 m_bodyStyle = 1;
135 m_aboutTitle = _HKI( "KiCad Symbol Editor" );
136
137 wxIcon icon;
138 wxIconBundle icon_bundle;
139
140 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_libedit, 48 ) );
141 icon_bundle.AddIcon( icon );
142 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_libedit, 256 ) );
143 icon_bundle.AddIcon( icon );
144 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_libedit, 128 ) );
145 icon_bundle.AddIcon( icon );
146 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_libedit_32 ) );
147 icon_bundle.AddIcon( icon );
148 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_libedit_16 ) );
149 icon_bundle.AddIcon( icon );
150
151 SetIcons( icon_bundle );
152
155
157
158 m_treePane = new SYMBOL_TREE_PANE( this, m_libMgr );
159 m_treePane->GetLibTree()->SetSortMode( (LIB_TREE_MODEL_ADAPTER::SORT_MODE) m_settings->m_LibrarySortMode );
160
163
164 // Ensure axis are always drawn
166 gal_opts.m_axesEnabled = true;
167
170 GetScreen()->m_Center = true;
171
172 GetCanvas()->GetViewControls()->SetCrossHairCursorPosition( VECTOR2D( 0, 0 ), false );
173
174 GetRenderSettings()->LoadColors( GetColorSettings() );
175 GetRenderSettings()->m_IsSymbolEditor = true;
176 GetCanvas()->GetGAL()->SetAxesColor( m_colorSettings->GetColor( LAYER_SCHEMATIC_GRID_AXES ) );
177
178 setupTools();
180
182
186
187 UpdateTitle();
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
238 const bool modified = ctx ? ctx->IsModified() : entries[aIdx].modified;
239
240 return ResolveTabVisualState( entries[aIdx].preview, modified );
241 };
242
243 m_auimgr.AddPane( m_tabsPanel, wxAuiPaneInfo().Name( "DrawFrame" )
244 .CentrePane() );
245
246 // Columns; layers 1 - 3
247 m_auimgr.AddPane( m_treePane, EDA_PANE().Palette().Name( "LibraryTree" )
248 .Left().Layer( 3 )
249 .TopDockable( false ).BottomDockable( false )
250 .Caption( _( "Libraries" ) )
251 // Don't use -1 for don't-change-height on a growable panel; it has side-effects.
252 .MinSize( FromDIP( 250 ), FromDIP( 80 ) )
253 .BestSize( FromDIP( 250 ), -1 ) );
254
257
258 // Can be called only when all panes are created, because (at least on Windows) when items
259 // managed by m_auimgr are not the same as those existing when saved by Perspective()
260 // in config, broken settings can happen.
262
263 // Protect against broken saved Perspective() due to bugs in previous version
264 // This is currently a workaround.
265 m_auimgr.GetPane( "TopMainToolbar" ).Top().Layer( 6 ).Position(0).Show( true );
266 m_auimgr.GetPane( "LeftToolbar" ).Position(0).Show( true );
267 m_auimgr.GetPane( "RightToolbar" ).Show( true );
268
269 // Show or hide m_propertiesPanel depending on current settings:
270 wxAuiPaneInfo& propertiesPaneInfo = m_auimgr.GetPane( PropertiesPaneName() );
271 wxAuiPaneInfo& selectionFilterPane = m_auimgr.GetPane( wxS( "SelectionFilter" ) );
272 // The selection filter doesn't need to grow in the vertical direction when docked
273 selectionFilterPane.dock_proportion = 0;
274
275 propertiesPaneInfo.Show( m_settings->m_AuiPanels.show_properties );
277
279
280 // Can't put this in LoadSettings, because it has to be called before setupTools :/
282 selTool->GetFilter() = GetSettings()->m_SelectionFilter;
283 m_selectionFilterPanel->SetCheckboxesFromFilter( selTool->GetFilter() );
284
285 if( m_settings->m_LibWidth > 0 )
286 SetAuiPaneSize( m_auimgr, m_auimgr.GetPane( "LibraryTree" ), m_settings->m_LibWidth, -1 );
287
288 Raise();
289 Show( true );
290
291 SyncView();
292 GetCanvas()->GetView()->UseDrawPriority( true );
293 GetCanvas()->GetGAL()->SetAxesEnabled( true );
294
296
297 // Set the working/draw area size to display a symbol to a reasonable value:
298 // A 600mm x 600mm with a origin at the area center looks like a large working area
299 double max_size_x = schIUScale.mmToIU( 600 );
300 double max_size_y = schIUScale.mmToIU( 600 );
301 BOX2D bbox;
302 bbox.SetOrigin( -max_size_x /2, -max_size_y/2 );
303 bbox.SetSize( max_size_x, max_size_y );
304 GetCanvas()->GetView()->SetBoundary( bbox );
305
307
309 DragAcceptFiles( true );
310
311 KIPLATFORM::APP::SetShutdownBlockReason( this, _( "Library changes are unsaved" ) );
312
313 // Catch unhandled accelerator command characters that were no handled by the library tree
314 // panel.
316 Bind( wxEVT_CHAR_HOOK, &TOOL_DISPATCHER::DispatchWxEvent, m_toolDispatcher );
317
318 // GTK rejects WXK_TAB as an accelerator so cycle tabs from the char hook ahead of the dispatcher.
319 Bind( wxEVT_CHAR_HOOK, &SYMBOL_EDIT_FRAME::OnTabCharHook, this );
320
321 // Ensure the window is on top
322 Raise();
323
324 // run SyncLibraries with progress reporter enabled. The progress reporter is useful
325 // in debug mode because the loading time of ecah library can be really noticeable
326 SyncLibraries( true );
327
328 // Must follow SyncLibraries so persisted tabs can resolve against the loaded libraries.
330}
331
332
334{
335 // Hand the borrowed canvas back before the base destructor frees it, else the panel reparents
336 // freed memory on its own teardown.
337 if( m_tabsPanel )
338 m_tabsPanel->ReleaseSharedCanvas();
339
340 // Shutdown all running tools
341 if( m_toolManager )
342 m_toolManager->ShutdownAllTools();
343
344 setSymWatcher( nullptr );
345
346 if( m_activeTab )
347 {
348 // Hand the working objects back so the context deletes them exactly once below; raw deleting
349 // here would double-free with the context dtor and leak the swapped-in undo list. Covers an
350 // active instance tab too, whose m_isSymbolFromSchematic mirror is only frame state.
352 m_activeTab->AdoptWorkingObjects( m_symbol, static_cast<SCH_SCREEN*>( GetScreen() ) );
353 m_activeTab = nullptr;
354 m_symbol = nullptr;
356 }
357 else
358 {
359 // No active tab owns the current screen, so let EDA_DRAW_FRAME free it.
361 }
362
363 // Free each detached context's undo/redo with the frame on the dummy screen to avoid double-frees.
364 for( const std::unique_ptr<SYMBOL_EDITOR_TAB_CONTEXT>& ctx : m_tabContexts )
366
367 m_tabContexts.clear();
368
370 Pgm().GetSettingsManager().Save( cfg );
371
372 delete m_libMgr;
373}
374
375
377{
378 wxCHECK_RET( m_settings, "Call to SYMBOL_EDIT_FRAME::LoadSettings with null m_settings" );
379
381
382 GetRenderSettings()->m_ShowPinsElectricalType = m_settings->m_ShowPinElectricalType;
383 GetRenderSettings()->m_ShowHiddenPins = m_settings->m_ShowHiddenPins;
384 GetRenderSettings()->m_ShowHiddenFields = m_settings->m_ShowHiddenFields;
385 GetRenderSettings()->m_ShowPinAltIcons = m_settings->m_ShowPinAltIcons;
386 GetRenderSettings()->SetDefaultFont( wxEmptyString );
387}
388
389
391{
392 wxCHECK_RET( m_settings, "Call to SYMBOL_EDIT_FRAME:SaveSettings with null m_settings" );
393
395
396 // The library tree is hidden while editing a symbol from the schematic. Force it visible in the
397 // serialized AUI layout so the user's preference survives a restart, but only touch the pane
398 // metadata (not ToggleLibraryTree) to avoid a mid-session repaint/flicker and a spurious tree
399 // width capture below.
400 wxAuiPaneInfo& treePane = m_auimgr.GetPane( m_treePane );
401 wxAuiPaneInfo& filterPane = m_auimgr.GetPane( wxS( "SelectionFilter" ) );
402
403 const bool treeShown = treePane.IsShown();
404 const bool filterShown = filterPane.IsShown();
405
406 // Gate on the pending-restore flag alone, not the active-tab schematic state, which is cleared
407 // when a schematic tab closes while the tree stays auto-hidden.
408 const bool forceTreeShown = m_libTreeAutoHiddenForSchematicEdit && !treeShown;
409
410 if( forceTreeShown )
411 {
412 treePane.Show( true );
414 }
415
417
418 if( forceTreeShown )
419 {
420 treePane.Show( treeShown );
421 filterPane.Show( filterShown );
422 }
423
424 m_settings->m_ShowPinElectricalType = GetRenderSettings()->m_ShowPinsElectricalType;
425 m_settings->m_ShowHiddenPins = GetRenderSettings()->m_ShowHiddenPins;
426 m_settings->m_ShowHiddenFields = GetRenderSettings()->m_ShowHiddenFields;
427 m_settings->m_ShowPinAltIcons = GetRenderSettings()->m_ShowPinAltIcons;
428
429 m_settings->m_LibWidth = m_treePane->GetSize().x;
430
431 m_settings->m_LibrarySortMode = GetLibTree()->GetSortMode();
432
433 m_settings->m_AuiPanels.properties_splitter = m_propertiesPanel->SplitterProportion();
434 bool prop_shown = m_auimgr.GetPane( PropertiesPaneName() ).IsShown();
435 m_settings->m_AuiPanels.show_properties = prop_shown;
436
437 if( TOOL_MANAGER* toolMgr = GetToolManager() )
438 {
439 if( SCH_SELECTION_TOOL* selTool = toolMgr->GetTool<SCH_SELECTION_TOOL>() )
440 m_settings->m_SelectionFilter = selTool->GetFilter();
441 }
442
444}
445
446
448{
449 return static_cast<APP_SETTINGS_BASE*>( GetSettings() );
450}
451
452
454{
456
457 if( cfg && static_cast<SYMBOL_EDITOR_SETTINGS*>( cfg )->m_UseEeschemaColorSettings )
458 cfg = GetAppSettings<EESCHEMA_SETTINGS>( "eeschema" );
459
460 return ::GetColorSettings( cfg ? cfg->m_ColorTheme : DEFAULT_THEME );
461}
462
463
465{
466 // Create the manager and dispatcher & route draw panel events to the dispatcher
468 m_toolManager->SetEnvironment( GetScreen(), GetCanvas()->GetView(),
469 GetCanvas()->GetViewControls(), GetSettings(), this );
470 m_actions = new SCH_ACTIONS();
472
473 // Register tools
474 m_toolManager->RegisterTool( new COMMON_CONTROL );
475 m_toolManager->RegisterTool( new COMMON_TOOLS );
476 m_toolManager->RegisterTool( new ZOOM_TOOL );
477 m_toolManager->RegisterTool( new SCH_SELECTION_TOOL );
478 m_toolManager->RegisterTool( new PICKER_TOOL );
479 m_toolManager->RegisterTool( new SCH_INSPECTION_TOOL );
480 m_toolManager->RegisterTool( new SYMBOL_EDITOR_PIN_TOOL );
481 m_toolManager->RegisterTool( new SYMBOL_EDITOR_DRAWING_TOOLS );
482 m_toolManager->RegisterTool( new SCH_POINT_EDITOR );
483 m_toolManager->RegisterTool( new SCH_FIND_REPLACE_TOOL );
484 m_toolManager->RegisterTool( new SYMBOL_EDITOR_MOVE_TOOL );
485 m_toolManager->RegisterTool( new SYMBOL_EDITOR_EDIT_TOOL );
486 m_toolManager->RegisterTool( new LIBRARY_EDITOR_CONTROL );
487 m_toolManager->RegisterTool( new SYMBOL_EDITOR_CONTROL );
488 m_toolManager->RegisterTool( new PROPERTIES_TOOL );
489 m_toolManager->RegisterTool( new EMBED_TOOL );
490 m_toolManager->InitTools();
491
492 // Run the selection tool, it is supposed to be always active
493 m_toolManager->InvokeTool( "common.InteractiveSelection" );
494
496}
497
498
500{
502
503 ACTION_MANAGER* mgr = m_toolManager->GetActionManager();
504 EDITOR_CONDITIONS cond( this );
505
506 wxASSERT( mgr );
507
508#define ENABLE( x ) ACTION_CONDITIONS().Enable( x )
509#define CHECK( x ) ACTION_CONDITIONS().Check( x )
510
511 auto haveSymbolCond =
512 [this]( const SELECTION& )
513 {
514 return m_symbol;
515 };
516
517 auto isEditableCond =
518 [this]( const SELECTION& )
519 {
520 // Only root symbols from the new s-expression libraries or the schematic
521 // are editable.
522 return IsSymbolEditable() && !IsSymbolAlias();
523 };
524
525 auto isEditableInAliasCond =
526 [this]( const SELECTION& )
527 {
528 // Less restrictive than isEditableCond
529 // Symbols fields (root symbols and aliases) from the new s-expression libraries
530 // or in the schematic are editable.
531 return IsSymbolEditable();
532 };
533
534 auto symbolModifiedCondition =
535 [this]( const SELECTION& sel )
536 {
537 return m_libMgr && m_libMgr->IsSymbolModified( GetTargetLibId().GetLibItemName(),
538 GetTargetLibId().GetLibNickname() );
539 };
540
541 auto libSelectedCondition =
542 [this]( const SELECTION& sel )
543 {
544 return !GetTargetLibId().GetLibNickname().empty();
545 };
546
547 auto canEditProperties =
548 [this]( const SELECTION& sel )
549 {
551 };
552
553 auto symbolSelectedInTreeCondition =
554 [this]( const SELECTION& sel )
555 {
556 LIB_ID targetLibId = GetTargetLibId();
557 return !targetLibId.GetLibNickname().empty() && !targetLibId.GetLibItemName().empty();
558 };
559
560 auto saveSymbolAsCondition =
561 [this]( const SELECTION& aSel )
562 {
563 return getTargetSymbol() != nullptr;
564 };
565
566 const auto isSymbolFromSchematicCond =
567 [this]( const SELECTION& )
568 {
569 return IsSymbolFromSchematic();
570 };
571
572 // clang-format off
575 mgr->SetConditions( SCH_ACTIONS::saveLibraryAs, ENABLE( libSelectedCondition ) );
576 mgr->SetConditions( SCH_ACTIONS::saveSymbolAs, ENABLE( saveSymbolAsCondition ) );
577 mgr->SetConditions( SCH_ACTIONS::saveSymbolCopyAs, ENABLE( saveSymbolAsCondition ) );
580 mgr->SetConditions( SCH_ACTIONS::editLibSymbolWithLibEdit, ENABLE( isSymbolFromSchematicCond ) );
581
582 mgr->SetConditions( ACTIONS::undo, ENABLE( haveSymbolCond && cond.UndoAvailable() ) );
583 mgr->SetConditions( ACTIONS::redo, ENABLE( haveSymbolCond && cond.RedoAvailable() ) );
584 mgr->SetConditions( ACTIONS::revert, ENABLE( symbolModifiedCondition ) );
585
588
589 mgr->SetConditions( ACTIONS::cut, ENABLE( isEditableCond ) );
590 mgr->SetConditions( ACTIONS::copy, ENABLE( haveSymbolCond ) );
591 mgr->SetConditions( ACTIONS::copyAsText, ENABLE( haveSymbolCond ) );
592 mgr->SetConditions( ACTIONS::paste, ENABLE( isEditableCond &&
594 mgr->SetConditions( ACTIONS::doDelete, ENABLE( isEditableCond ) );
595 mgr->SetConditions( ACTIONS::duplicate, ENABLE( isEditableCond ) );
596 mgr->SetConditions( ACTIONS::selectAll, ENABLE( haveSymbolCond ) );
597 mgr->SetConditions( ACTIONS::unselectAll, ENABLE( haveSymbolCond ) );
598
599 // These actions in symbol editor when editing alias field rotations are allowed.
601 ENABLE( SELECTION_CONDITIONS::NotEmpty && isEditableInAliasCond )
602 .HotkeyEnable( isEditableInAliasCond ) );
604 ENABLE( SELECTION_CONDITIONS::NotEmpty && isEditableInAliasCond )
605 .HotkeyEnable( isEditableInAliasCond ) );
606
608 ENABLE( SELECTION_CONDITIONS::NotEmpty && isEditableCond )
609 .HotkeyEnable( isEditableCond ) );
611 ENABLE( SELECTION_CONDITIONS::NotEmpty && isEditableCond )
612 .HotkeyEnable( isEditableCond ) );
613
616 // clang-format on
617
618 auto pinTypeCond =
619 [this]( const SELECTION& )
620 {
622 };
623
624 auto hiddenPinCond =
625 [this]( const SELECTION& )
626 {
628 };
629
630 auto hiddenFieldCond =
631 [this]( const SELECTION& )
632 {
634 };
635
636 auto showPinAltIconsCond =
637 [this]( const SELECTION& )
638 {
640 };
641
642 auto showLibraryTreeCond =
643 [this]( const SELECTION& )
644 {
645 return IsLibraryTreeShown();
646 };
647
648 auto propertiesCond =
649 [this] ( const SELECTION& )
650 {
651 return m_auimgr.GetPane( PropertiesPaneName() ).IsShown();
652 };
653
656 mgr->SetConditions( ACTIONS::showLibraryTree, CHECK( showLibraryTreeCond ) );
657 mgr->SetConditions( ACTIONS::showProperties, CHECK( propertiesCond ) );
658 mgr->SetConditions( SCH_ACTIONS::showHiddenPins, CHECK( hiddenPinCond ) );
659 mgr->SetConditions( SCH_ACTIONS::showHiddenFields, CHECK( hiddenFieldCond ) );
660 mgr->SetConditions( SCH_ACTIONS::togglePinAltIcons, CHECK( showPinAltIconsCond ) );
661
662 auto multiUnitModeCond =
663 [this]( const SELECTION& )
664 {
665 return m_symbol && m_symbol->IsMultiUnit() && !m_symbol->UnitsLocked();
666 };
667
668 auto multiBodyStyleModeCond =
669 [this]( const SELECTION& )
670 {
671 return m_symbol && m_symbol->IsMultiBodyStyle();
672 };
673
674 auto syncedPinsModeCond =
675 [this]( const SELECTION& )
676 {
677 return m_SyncPinEdit;
678 };
679
680 auto haveDatasheetCond =
681 [this]( const SELECTION& )
682 {
683 return m_symbol && !m_symbol->GetDatasheetField().GetText().IsEmpty();
684 };
685
686 mgr->SetConditions( ACTIONS::showDatasheet, ENABLE( haveDatasheetCond ) );
687 mgr->SetConditions( SCH_ACTIONS::symbolProperties, ENABLE( symbolSelectedInTreeCondition || ( canEditProperties && haveSymbolCond ) ) );
688 mgr->SetConditions( SCH_ACTIONS::runERC, ENABLE( haveSymbolCond ) );
689 mgr->SetConditions( SCH_ACTIONS::pinTable, ENABLE( isEditableCond && haveSymbolCond ) );
690 mgr->SetConditions( SCH_ACTIONS::editSymbolPinMaps, ENABLE( isEditableCond && haveSymbolCond ) );
691 mgr->SetConditions( SCH_ACTIONS::updateSymbolFields, ENABLE( isEditableCond && haveSymbolCond ) );
692 mgr->SetConditions( SCH_ACTIONS::cycleBodyStyle, ENABLE( multiBodyStyleModeCond ) );
693
694 mgr->SetConditions( SCH_ACTIONS::toggleSyncedPinsMode, ACTION_CONDITIONS().Enable( multiUnitModeCond ).Check( syncedPinsModeCond ) );
695
696// Only enable a tool if the symbol is edtable
697#define EDIT_TOOL( tool ) ACTION_CONDITIONS().Enable( isEditableCond ).Check( cond.CurrentTool( tool ) )
698
713
714#undef CHECK
715#undef ENABLE
716#undef EDIT_TOOL
717}
718
719
721{
722 if( IsContentModified() )
723 {
724 SCH_EDIT_FRAME* schframe = (SCH_EDIT_FRAME*) Kiway().Player( FRAME_SCH, false );
725 wxString msg = _( "Save changes to '%s' before closing?" );
726
727 switch( UnsavedChangesDialog( this, wxString::Format( msg, m_reference ), nullptr ) )
728 {
729 case wxID_YES:
730 if( schframe && GetCurSymbol() ) // Should be always the case
732
733 break;
734
735 case wxID_NO:
736 break;
737
738 default:
739 case wxID_CANCEL:
740 return false;
741 }
742 }
743
744 if( doClose )
745 {
746 SetCurSymbol( nullptr, false );
747 UpdateTitle();
748 }
749
750 return true;
751}
752
753
754bool SYMBOL_EDIT_FRAME::canCloseWindow( wxCloseEvent& aEvent )
755{
756 // Shutdown blocks must be determined and vetoed as early as possible, before any modal prompt.
757 // IsContentModified only sees the active tab, so also account for dirty inactive instance tabs.
759 && aEvent.GetId() == wxEVT_QUERY_END_SESSION
761 {
762 return false;
763 }
764
766 return false;
767
768 // Prompt for any dirty inactive instance tabs, which the active-tab checks above miss.
770 return false;
771
772 if( !saveAllLibraries( true ) )
773 return false;
774
775 // Save symbol tree column widths
776 m_libMgr->GetAdapter()->SaveSettings();
777
778 return true;
779}
780
781
783{
785
786 if( GetLibTree() )
788
789 delete m_toolManager;
790 m_toolManager = nullptr;
791
792 Destroy();
793}
794
795
797{
798 if( m_unitSelectBox )
799 {
800 if( m_unitSelectBox->GetCount() != 0 )
801 m_unitSelectBox->Clear();
802
803 if( !m_symbol || m_symbol->GetUnitCount() <= 1 )
804 {
805 m_unit = 1;
806 m_unitSelectBox->Append( wxEmptyString );
807 }
808 else
809 {
810 for( int i = 0; i < m_symbol->GetUnitCount(); i++ )
811 m_unitSelectBox->Append( m_symbol->GetUnitDisplayName( i + 1, true ) );
812 }
813
814 // Ensure the selected unit is compatible with the number of units of the current symbol:
815 if( m_symbol && m_symbol->GetUnitCount() < m_unit )
816 m_unit = 1;
817
818 m_unitSelectBox->SetSelection( ( m_unit > 0 ) ? m_unit - 1 : 0 );
819 }
820
822 {
823 if( m_bodyStyleSelectBox->GetCount() != 0 )
824 m_bodyStyleSelectBox->Clear();
825
826 if( !m_symbol || !m_symbol->IsMultiBodyStyle() )
827 {
828 m_bodyStyle = 1;
829 m_bodyStyleSelectBox->Append( wxEmptyString );
830 }
831 else if( m_symbol && m_symbol->HasDeMorganBodyStyles() )
832 {
833 m_bodyStyleSelectBox->Append( wxGetTranslation( DEMORGAN_STD ) );
834 m_bodyStyleSelectBox->Append( wxGetTranslation( DEMORGAN_ALT ) );
835 }
836 else
837 {
838 for( int i = 0; i < m_symbol->GetBodyStyleCount(); i++ )
839 m_bodyStyleSelectBox->Append( m_symbol->GetBodyStyleNames()[i] );
840 }
841
842 // Ensure the selected body style is compatible with the number of body styles of the current symbol:
843 if( m_symbol && m_symbol->GetBodyStyleCount() < m_bodyStyle )
844 m_bodyStyle = 1;
845
846 m_bodyStyleSelectBox->SetSelection( ( m_bodyStyle > 0 ) ? m_bodyStyle - 1 : 0 );
847 }
848}
849
850
852{
853 if( !m_propertiesPanel )
854 return;
855
856 bool show = !m_propertiesPanel->IsShownOnScreen();
857
858 wxAuiPaneInfo& propertiesPaneInfo = m_auimgr.GetPane( PropertiesPaneName() );
859 propertiesPaneInfo.Show( show );
861
862 if( show )
863 {
864 SetAuiPaneSize( m_auimgr, propertiesPaneInfo,
865 m_settings->m_AuiPanels.properties_panel_width, -1 );
866 }
867 else
868 {
869 m_settings->m_AuiPanels.properties_panel_width = m_propertiesPanel->GetSize().x;
870 }
871
872 m_auimgr.Update();
873 Refresh();
874}
875
876
878{
879 // An explicit toggle makes the live visibility authoritative, so drop any pending restore that
880 // LoadSymbolFromSchematic's auto-hide left behind.
882
883 wxAuiPaneInfo& treePane = m_auimgr.GetPane( m_treePane );
884 treePane.Show( !IsLibraryTreeShown() );
886 m_auimgr.Update();
887 Refresh();
888}
889
890
892{
893 return const_cast<wxAuiManager&>( m_auimgr ).GetPane( m_treePane ).IsShown();
894}
895
896
901
902
904{
905 m_treePane->Freeze();
906 m_libMgr->GetAdapter()->Freeze();
907}
908
909
911{
912 m_libMgr->GetAdapter()->Thaw();
913 m_treePane->Thaw();
914}
915
916
917void SYMBOL_EDIT_FRAME::OnExitKiCad( wxCommandEvent& event )
918{
919 Kiway().OnKiCadExit();
920}
921
922
923void SYMBOL_EDIT_FRAME::OnUpdateUnitNumber( wxUpdateUIEvent& event )
924{
925 event.Enable( m_symbol && m_symbol->GetUnitCount() > 1 );
926}
927
928
929void SYMBOL_EDIT_FRAME::OnSelectUnit( wxCommandEvent& event )
930{
931 if( event.GetSelection() == wxNOT_FOUND )
932 return;
933
934 SetUnit( event.GetSelection() + 1 );
935}
936
937
938void SYMBOL_EDIT_FRAME::OnUpdateBodyStyle( wxUpdateUIEvent& event )
939{
940 event.Enable( m_symbol && m_symbol->GetBodyStyleCount() > 1 );
941}
942
943
944void SYMBOL_EDIT_FRAME::OnSelectBodyStyle( wxCommandEvent& event )
945{
946 if( event.GetSelection() == wxNOT_FOUND )
947 return;
948
949 SetBodyStyle( event.GetSelection() + 1 );
950}
951
952
954{
955 if( m_symbol )
956 {
958
959 if( auto row = adapter->GetRow( m_symbol->GetLibNickname() ); row.has_value() )
960 {
961 if( ( *row )->Type() == SCH_IO_MGR::ShowType( SCH_IO_MGR::SCH_LEGACY ) )
962 return true;
963 }
964 }
965
966 return false;
967}
968
969
971{
972 wxString libNickname = Prj().GetRString( PROJECT::SCH_LIBEDIT_CUR_LIB );
973
974 if( !libNickname.empty() )
975 {
976 if( !PROJECT_SCH::SymbolLibAdapter( &Prj() )->HasLibrary( libNickname ) )
977 {
978 Prj().SetRString( PROJECT::SCH_LIBEDIT_CUR_LIB, wxEmptyString );
979 libNickname = wxEmptyString;
980 }
981 }
982
983 return libNickname;
984}
985
986
987wxString SYMBOL_EDIT_FRAME::SetCurLib( const wxString& aLibNickname )
988{
989 wxString old = GetCurLib();
990
991 if( aLibNickname.empty() || !PROJECT_SCH::SymbolLibAdapter( &Prj() )->HasLibrary( aLibNickname ) )
992 Prj().SetRString( PROJECT::SCH_LIBEDIT_CUR_LIB, wxEmptyString );
993 else
995
996 return old;
997}
998
999
1000void SYMBOL_EDIT_FRAME::SetCurSymbol( LIB_SYMBOL* aSymbol, bool aUpdateZoom )
1001{
1002 wxCHECK( m_toolManager, /* void */ );
1003
1005 GetCanvas()->GetView()->Clear();
1006
1007 // Install the replacement and refresh the active context before freeing the old symbol, so the
1008 // context never observes a freed pointer.
1009 LIB_SYMBOL* oldSymbol = m_symbol;
1010
1011 m_symbol = aSymbol;
1012
1013 if( m_activeTab )
1014 m_activeTab->RefreshFrameOwnedObjects( m_symbol, static_cast<SCH_SCREEN*>( GetScreen() ) );
1015
1016 delete oldSymbol;
1017
1018 // select the current symbol in the tree widget
1020 GetLibTree()->SelectLibId( m_symbol->GetLibId() );
1021 else
1022 GetLibTree()->Unselect();
1023
1024 wxString symbolName;
1025 wxString libName;
1026
1027 if( m_symbol )
1028 {
1029 symbolName = m_symbol->GetName();
1030 libName = UnescapeString( m_symbol->GetLibId().GetLibNickname() );
1031 }
1032
1033 // retain in case this wxFrame is re-opened later on the same PROJECT
1035
1036 // Ensure synchronized pin edit can be enabled only symbols with interchangeable units
1037 m_SyncPinEdit = aSymbol && aSymbol->IsRoot() && aSymbol->IsMultiUnit() && !aSymbol->UnitsLocked();
1038
1040
1048
1049 if( aUpdateZoom )
1051
1052 GetCanvas()->Refresh();
1053 m_propertiesPanel->UpdateData();
1054
1055 WX_INFOBAR& infobar = *GetInfoBar();
1056 infobar.RemoveAllButtons();
1057
1058 wxArrayString msgs;
1059 int infobarFlags = wxICON_INFORMATION;
1060
1061 if( IsSymbolFromSchematic() )
1062 {
1063 msgs.push_back( wxString::Format( _( "Editing symbol %s from schematic. Saving will "
1064 "update the schematic only." ),
1065 m_reference ) );
1066
1067 wxString link = wxString::Format( _( "Open symbol from library %s" ), libName );
1068 wxHyperlinkCtrl* button = new wxHyperlinkCtrl( &infobar, wxID_ANY, link, wxEmptyString );
1069
1070 button->Bind( wxEVT_COMMAND_HYPERLINK, std::function<void( wxHyperlinkEvent& aEvent )>(
1071 [this, symbolName, libName]( wxHyperlinkEvent& aEvent )
1072 {
1074 } ) );
1075
1076 infobar.AddButton( button );
1077 }
1078 else if( IsSymbolFromLegacyLibrary() )
1079 {
1080 msgs.push_back( _( "Symbols in legacy libraries are not editable. Use Manage Symbol "
1081 "Libraries to migrate to current format." ) );
1082
1083 wxString link = _( "Manage symbol libraries" );
1084 wxHyperlinkCtrl* button = new wxHyperlinkCtrl( &infobar, wxID_ANY, link, wxEmptyString );
1085
1086 button->Bind( wxEVT_COMMAND_HYPERLINK, std::function<void( wxHyperlinkEvent& aEvent )>(
1087 [this]( wxHyperlinkEvent& aEvent )
1088 {
1090 } ) );
1091
1092 infobar.AddButton( button );
1093 }
1094 else if( IsSymbolAlias() )
1095 {
1096 msgs.push_back( wxString::Format( _( "Symbol %s is a derived symbol. Symbol graphics will "
1097 "not be editable." ),
1098 UnescapeString( symbolName ) ) );
1099
1100 // Don't assume the parent symbol shared pointer is still valid.
1101 if( std::shared_ptr<LIB_SYMBOL> rootSymbol = m_symbol->GetRootSymbol() )
1102 {
1103 int unit = GetUnit();
1104 int bodyStyle = GetBodyStyle();
1105 wxString rootSymbolName = rootSymbol->GetName();
1106 wxString link = wxString::Format( _( "Open %s" ), UnescapeString( rootSymbolName ) );
1107
1108 wxHyperlinkCtrl* button = new wxHyperlinkCtrl( &infobar, wxID_ANY, link,
1109 wxEmptyString );
1110
1111 button->Bind( wxEVT_COMMAND_HYPERLINK, std::function<void( wxHyperlinkEvent& aEvent )>(
1112 [this, rootSymbolName, unit, bodyStyle]( wxHyperlinkEvent& aEvent )
1113 {
1114 LoadSymbolFromCurrentLib( rootSymbolName, unit, bodyStyle );
1115 } ) );
1116
1117 infobar.AddButton( button );
1118 }
1119 }
1120
1121 if( m_symbol
1123 && m_libMgr->IsLibraryReadOnly( m_symbol->GetLibId().GetFullLibraryName() ) )
1124 {
1125 msgs.push_back( _( "Library is read-only. Changes cannot be saved to this library." ) );
1126
1127 wxString link = wxString::Format( _( "Create an editable copy" ) );
1128 wxHyperlinkCtrl* button = new wxHyperlinkCtrl( &infobar, wxID_ANY, link, wxEmptyString );
1129
1130 button->Bind( wxEVT_COMMAND_HYPERLINK, std::function<void( wxHyperlinkEvent& aEvent )>(
1131 [this, symbolName, libName]( wxHyperlinkEvent& aEvent )
1132 {
1133 wxString msg = wxString::Format( _( "Create an editable copy of the symbol or "
1134 "the entire library (%s)?" ),
1135 libName );
1136
1137 KIDIALOG errorDlg( this, msg, _( "Select type of item to save" ),
1138 wxYES_NO | wxCANCEL | wxICON_QUESTION );
1139 // These buttons are in a weird order(?)
1140 errorDlg.SetYesNoCancelLabels( _( "Copy symbol" ), _( "Cancel" ),
1141 _( "Copy library" ) );
1142
1143 int choice = errorDlg.ShowModal();
1144
1145 switch( choice )
1146 {
1147 case wxID_YES:
1148 SaveSymbolCopyAs( true );
1149 break;
1150 case wxID_CANCEL:
1151 SaveLibraryAs();
1152 break;
1153 default:
1154 // Do nothing
1155 break;
1156 }
1157 } ) );
1158
1159 infobar.AddButton( button );
1160 }
1161
1162 if( msgs.empty() )
1163 {
1164 infobar.Dismiss();
1165 }
1166 else
1167 {
1168 wxString msg = wxJoin( msgs, '\n', '\0' );
1169 infobar.ShowMessage( msg, infobarFlags );
1170 }
1171}
1172
1173
1179
1180
1182{
1184
1186
1187 if( !IsSymbolFromSchematic() )
1189
1190 if( m_isClosing )
1191 return;
1192
1193 // Clear preview so a later library-open gets its own tab instead of replacing this edited one.
1194 if( m_tabsPanel && m_activeTab )
1195 {
1196 m_activeTab->SetPreview( false );
1197
1198 if( int idx = m_tabsPanel->FindTab( m_activeTab->GetTabKey() ); idx >= 0 )
1199 m_tabsPanel->MarkModified( idx, true );
1200 }
1201
1203
1204 if( !GetTitle().StartsWith( "*" ) )
1205 UpdateTitle();
1206}
1207
1208
1210{
1211 wxCHECK( aUnit > 0 && aUnit <= GetCurSymbol()->GetUnitCount(), /* void*/ );
1212
1213 if( m_unit == aUnit )
1214 return;
1215
1218
1219 m_unit = aUnit;
1220
1221 if( m_unitSelectBox->GetSelection() != ( m_unit - 1 ) )
1222 m_unitSelectBox->SetSelection( m_unit - 1 );
1223
1225 RebuildView();
1227}
1228
1229
1231{
1232 wxCHECK( aBodyStyle > 0 && aBodyStyle <= GetCurSymbol()->GetBodyStyleCount(), /* void */ );
1233
1234 if( m_bodyStyle == aBodyStyle )
1235 return;
1236
1239
1240 m_bodyStyle = aBodyStyle;
1241
1242 if( m_bodyStyleSelectBox->GetSelection() != ( m_bodyStyle - 1 ) )
1243 m_bodyStyleSelectBox->SetSelection( m_bodyStyle - 1 );
1244
1245
1247 RebuildView();
1249}
1250
1251
1253{
1254 return m_SyncPinEdit && m_symbol && m_symbol->IsMultiUnit() && !m_symbol->UnitsLocked();
1255}
1256
1257
1258wxString SYMBOL_EDIT_FRAME::AddLibraryFile( bool aCreateNew )
1259{
1260 wxFileName fn = m_libMgr->GetUniqueLibraryName();
1261 bool useGlobalTable = true;
1262 FILEDLG_HOOK_NEW_LIBRARY tableChooser( useGlobalTable );
1263
1264 if( !LibraryFileBrowser( aCreateNew ? _( "New Symbol Library" ) : _( "Add Symbol Library" ),
1265 !aCreateNew, fn, FILEEXT::KiCadSymbolLibFileWildcard(),
1267 Pgm().GetSettingsManager().IsProjectOpenNotDummy() ? &tableChooser : nullptr ) )
1268 {
1269 return wxEmptyString;
1270 }
1271
1274
1275 LIBRARY_MANAGER& manager = Pgm().GetLibraryManager();
1276 std::optional<LIBRARY_TABLE*> optTable = manager.Table( LIBRARY_TABLE_TYPE::SYMBOL, scope );
1277
1278 wxCHECK( optTable.has_value(), wxEmptyString );
1279 LIBRARY_TABLE* table = optTable.value();
1280
1281 wxString libName = fn.GetName();
1282
1283 if( libName.IsEmpty() )
1284 return wxEmptyString;
1285
1287
1288 if( adapter->HasLibrary( libName ) )
1289 {
1290 DisplayError( this, wxString::Format( _( "Library '%s' already exists." ), libName ) );
1291 return wxEmptyString;
1292 }
1293
1294 if( aCreateNew )
1295 {
1296 // The file browser already asked to overwrite, so drop the old file here.
1297 // CreateLibrary fails on an existing path.
1298 if( fn.FileExists() && !wxRemoveFile( fn.GetFullPath() ) )
1299 {
1300 DisplayError( this, wxString::Format( _( "Could not overwrite the library file '%s'.\n"
1301 "Make sure you have write permissions and try again." ),
1302 fn.GetFullPath() ) );
1303 return wxEmptyString;
1304 }
1305
1306 if( !m_libMgr->CreateLibrary( fn.GetFullPath(), scope ) )
1307 {
1308 DisplayError( this, wxString::Format( _( "Could not create the library file '%s'.\n"
1309 "Make sure you have write permissions and try again." ),
1310 fn.GetFullPath() ) );
1311 return wxEmptyString;
1312 }
1313 }
1314 else
1315 {
1316 if( !m_libMgr->AddLibrary( fn.GetFullPath(), scope ) )
1317 {
1318 DisplayError( this, _( "Could not open the library file." ) );
1319 return wxEmptyString;
1320 }
1321 }
1322
1323 bool success = true;
1324
1325 // Tables are reinitialized by m_libMgr->AddLibrary(). So reinit table reference.
1326 optTable = manager.Table( LIBRARY_TABLE_TYPE::SYMBOL, scope );
1327 wxCHECK( optTable.has_value(), wxEmptyString );
1328 table = optTable.value();
1329
1330 table->Save().map_error(
1331 [&]( const LIBRARY_ERROR& aError )
1332 {
1333 KICAD_MESSAGE_DIALOG dlg( this, _( "Error saving library table." ), _( "File Save Error" ),
1334 wxOK | wxICON_ERROR );
1335 dlg.SetExtendedMessage( aError.message );
1336 dlg.ShowModal();
1337
1338 success = false;
1339 } );
1340
1341 if( success )
1342 adapter->LoadOne( fn.GetName() );
1343
1344 SyncLibraries( false );
1345 SetCurLib( fn.GetName() );
1346
1347 if( m_treePane )
1348 {
1349 LIB_ID libId( fn.GetName(), wxEmptyString );
1350 GetLibTree()->SelectLibId( libId );
1351 GetLibTree()->CenterLibId( libId );
1352 }
1353
1354 return fn.GetFullPath();
1355}
1356
1357
1358void SYMBOL_EDIT_FRAME::DdAddLibrary( wxString aLibFile )
1359{
1360 wxFileName fn = wxFileName( aLibFile );
1361 wxString libName = fn.GetName();
1362
1363 if( libName.IsEmpty() )
1364 return;
1365
1366 LIBRARY_MANAGER& manager = Pgm().GetLibraryManager();
1368
1369 if( adapter->HasLibrary( libName ) )
1370 {
1371 DisplayError( this, wxString::Format( _( "Library '%s' already exists." ), libName ) );
1372 return;
1373 }
1374
1375 if( !m_libMgr->AddLibrary( fn.GetFullPath(), LIBRARY_TABLE_SCOPE::PROJECT ) )
1376 {
1377 DisplayError( this, _( "Could not open the library file." ) );
1378 return;
1379 }
1380
1381 std::optional<LIBRARY_TABLE*> optTable = manager.Table( LIBRARY_TABLE_TYPE::SYMBOL, LIBRARY_TABLE_SCOPE::PROJECT );
1382 wxCHECK( optTable.has_value(), /* void */ );
1383 LIBRARY_TABLE* table = optTable.value();
1384 bool success = true;
1385
1386 table->Save().map_error(
1387 [&]( const LIBRARY_ERROR& aError )
1388 {
1389 KICAD_MESSAGE_DIALOG dlg( this, _( "Error saving library table." ), _( "File Save Error" ),
1390 wxOK | wxICON_ERROR );
1391 dlg.SetExtendedMessage( aError.message );
1392 dlg.ShowModal();
1393
1394 success = false;
1395 } );
1396
1397 if( success )
1398 adapter->LoadOne( libName );
1399
1400 std::string packet = fn.GetFullPath().ToStdString();
1403}
1404
1405
1407{
1408 return GetLibTree()->GetSelectedLibId( aUnit );
1409}
1410
1411
1416
1417int SYMBOL_EDIT_FRAME::GetTreeLIBIDs( std::vector<LIB_ID>& aSelection ) const
1418{
1419 return GetLibTree()->GetSelectedLibIds( aSelection );
1420}
1421
1422
1424{
1425 if( IsLibraryTreeShown() )
1426 {
1427 LIB_ID libId = GetTreeLIBID();
1428
1429 if( libId.IsValid() )
1430 return m_libMgr->GetSymbol( libId.GetLibItemName(), libId.GetLibNickname() );
1431 }
1432
1433 return m_symbol;
1434}
1435
1436
1438{
1439 LIB_ID id;
1440
1441 if( IsLibraryTreeShown() )
1442 id = GetTreeLIBID();
1443
1444 if( id.GetLibNickname().empty() && m_symbol )
1445 id = m_symbol->GetLibId();
1446
1447 return id;
1448}
1449
1450
1451std::vector<LIB_ID> SYMBOL_EDIT_FRAME::GetSelectedLibIds() const
1452{
1453 std::vector<LIB_ID> ids;
1454 GetTreeLIBIDs( ids );
1455 return ids;
1456}
1457
1458
1460{
1461 return GetTargetLibId().GetLibNickname();
1462}
1463
1464
1465void SYMBOL_EDIT_FRAME::SyncLibraries( bool aShowProgress, bool aPreloadCancelled,
1466 const wxString& aForceRefresh )
1467{
1468 wxLogTrace( wxT( "KICAD_TABS_DBG" ),
1469 wxT( "SYMBOL_EDIT_FRAME::SyncLibraries enter (progress=%d, forceRefresh='%s')" ),
1470 aShowProgress, aForceRefresh );
1471
1472 // Prevent re-entrant calls. The progress dialog yields the event loop during Sync(),
1473 // which can dispatch queued UI events (e.g. menu clicks queued while the app was busy
1474 // loading libraries). A re-entrant call would corrupt the library tree mid-rebuild.
1476 {
1477 wxLogTrace( wxT( "KICAD_TABS_DBG" ),
1478 wxT( "SYMBOL_EDIT_FRAME::SyncLibraries re-entrant; skipping" ) );
1479 return;
1480 }
1481
1483
1484 auto resetGuard = [this]( bool* )
1485 {
1487 };
1488
1489 std::unique_ptr<bool, decltype( resetGuard )> guard( &m_syncLibrariesInProgress, resetGuard );
1490
1491 LIB_ID selected;
1492 std::vector<LIB_ID> expanded;
1493
1494 if( m_treePane )
1495 {
1496 selected = GetLibTree()->GetSelectedLibId();
1497 expanded = GetLibTree()->GetExpandedLibraries();
1498 }
1499
1500 // Ensure any in-progress background library preloading is complete before syncing the
1501 // tree. Without this, libraries still in LOADING state get skipped by Sync(), resulting
1502 // in an incomplete tree that requires a manual refresh to fully populate.
1504 adapter->BlockUntilLoaded();
1505
1506 if( aShowProgress )
1507 {
1508 APP_PROGRESS_DIALOG progressDlg( _( "Loading Symbol Libraries" ), wxEmptyString,
1509 m_libMgr->GetAdapter()->GetLibrariesCount(), this );
1510
1511 THROTTLE progressThrottle( std::chrono::milliseconds( 350 ) );
1512 int pendingProgress = 0;
1513 bool callbackFired = false;
1514 wxString pendingLibName;
1515
1516 m_libMgr->Sync( aForceRefresh,
1517 [&]( int progress, int max, const wxString& libName )
1518 {
1519 pendingProgress = progress;
1520 pendingLibName = libName;
1521 callbackFired = true;
1522
1523 if( progressThrottle.Ready() )
1524 progressDlg.Update( progress, wxString::Format( _( "Loading library '%s'..." ), libName ) );
1525 } );
1526
1527 if( callbackFired )
1528 progressDlg.Update( pendingProgress, wxString::Format( _( "Loading library '%s'..." ), pendingLibName ) );
1529 }
1530 else if( !aPreloadCancelled )
1531 {
1532 m_libMgr->Sync( aForceRefresh, [&]( int progress, int max, const wxString& libName ) {} );
1533 }
1534
1535 if( m_treePane )
1536 {
1537 wxDataViewItem found;
1538
1539 if( selected.IsValid() )
1540 {
1541 // Check if the previously selected item is still valid,
1542 // if not - it has to be unselected to prevent crash
1543 found = m_libMgr->GetAdapter()->FindItem( selected );
1544
1545 if( !found )
1546 GetLibTree()->Unselect();
1547 }
1548
1549 wxLogTrace( wxT( "KICAD_TABS_DBG" ), wxT( "SYMBOL_EDIT_FRAME::SyncLibraries Regenerate" ) );
1550 GetLibTree()->Regenerate( true );
1551
1552 // Sync() collapsed the tree, so re-expand the libraries that were open before it.
1553 for( const LIB_ID& libId : expanded )
1554 GetLibTree()->ExpandLibId( libId );
1555
1556 // Try to select the parent library, in case the symbol is not found
1557 if( !found && selected.IsValid() )
1558 {
1559 selected.SetLibItemName( "" );
1560 found = m_libMgr->GetAdapter()->FindItem( selected );
1561
1562 if( found )
1563 GetLibTree()->SelectLibId( selected );
1564 }
1565
1566 // If no selection, see if there's a current symbol to centre
1567 if( !selected.IsValid() && m_symbol )
1568 {
1569 LIB_ID current( GetCurLib(), m_symbol->GetName() );
1570 GetLibTree()->CenterLibId( current );
1571 }
1572 }
1573
1574 wxLogTrace( wxT( "KICAD_TABS_DBG" ), wxT( "SYMBOL_EDIT_FRAME::SyncLibraries exit" ) );
1575}
1576
1577
1582
1583
1585{
1586 GetLibTree()->SelectLibId( aLibID );
1587}
1588
1589
1590void SYMBOL_EDIT_FRAME::UpdateLibraryTree( const wxDataViewItem& aTreeItem, LIB_SYMBOL* aSymbol )
1591{
1592 if( aTreeItem.IsOk() ) // Can be not found in tree if the current footprint is imported
1593 // from file therefore not yet in tree.
1594 {
1595 static_cast<LIB_TREE_NODE_ITEM*>( aTreeItem.GetID() )->Update( aSymbol );
1597 }
1598}
1599
1600
1601bool SYMBOL_EDIT_FRAME::backupFile( const wxFileName& aOriginalFile, const wxString& aBackupExt )
1602{
1603 if( aOriginalFile.FileExists() )
1604 {
1605 wxFileName backupFileName( aOriginalFile );
1606 backupFileName.SetExt( aBackupExt );
1607
1608 if( backupFileName.FileExists() )
1609 wxRemoveFile( backupFileName.GetFullPath() );
1610
1611 if( !wxCopyFile( aOriginalFile.GetFullPath(), backupFileName.GetFullPath() ) )
1612 {
1613 DisplayError( this, wxString::Format( _( "Failed to save backup to '%s'." ),
1614 backupFileName.GetFullPath() ) );
1615 return false;
1616 }
1617 }
1618
1619 return true;
1620}
1621
1622
1624{
1625 if( m_symbol && !GetCurLib().IsEmpty() && GetScreen()->IsContentModified() )
1626 m_libMgr->UpdateSymbol( m_symbol, GetCurLib() ); // UpdateSymbol() makes a copy
1627}
1628
1629
1631{
1632 // This will return the root symbol of any alias
1633 LIB_SYMBOL* symbol = m_libMgr->GetBufferedSymbol( aLibId.GetLibItemName(), aLibId.GetLibNickname() );
1634
1635 // Now we can compare the libId of the current symbol and the root symbol
1636 return ( symbol && m_symbol && symbol->GetLibId() == m_symbol->GetLibId() );
1637}
1638
1639
1641{
1642 GetLibTree()->Unselect();
1643 SetCurLib( wxEmptyString );
1644
1645 // Tear down every tab first so no context observes the about-to-be-deleted working symbol.
1647
1648 SetCurSymbol( nullptr, false );
1652 Refresh();
1653}
1654
1655
1657{
1659
1661 {
1662 GetRenderSettings()->m_ShowPinsElectricalType = cfg->m_ShowPinElectricalType;
1663 GetRenderSettings()->m_ShowHiddenPins = cfg->m_ShowHiddenPins;
1664 GetRenderSettings()->m_ShowHiddenFields = cfg->m_ShowHiddenFields;
1665 GetRenderSettings()->m_ShowPinAltIcons = cfg->m_ShowPinAltIcons;
1666
1667 GetGalDisplayOptions().ReadWindowSettings( cfg->m_Window );
1668 }
1669
1670 if( m_symbol )
1671 m_symbol->ClearCaches();
1672
1674
1676 GetCanvas()->Refresh();
1677
1679
1680 if( aFlags & ENVVARS_CHANGED )
1681 SyncLibraries( true );
1682
1683 Layout();
1684 SendSizeEvent();
1685}
1686
1687
1689{
1690 // call my base class
1692
1693 // tooltips in toolbars
1695
1696 // For some obscure reason, the AUI manager hides the first modified pane.
1697 // So force show panes
1698 wxAuiPaneInfo& tree_pane_info = m_auimgr.GetPane( m_treePane );
1699 bool tree_shown = tree_pane_info.IsShown();
1700 tree_pane_info.Caption( _( "Libraries" ) );
1701 tree_pane_info.Show( tree_shown );
1702 m_auimgr.Update();
1703
1705
1706 // status bar
1708
1709 if( GetRenderSettings()->m_ShowPinsElectricalType )
1710 {
1712 GetCanvas()->Refresh();
1713 }
1714
1715 UpdateTitle();
1716}
1717
1718
1720{
1721 SCH_BASE_FRAME::SetScreen( aScreen );
1722
1723 if( m_toolManager )
1724 {
1725 m_toolManager->SetEnvironment( aScreen, GetCanvas()->GetView(), GetCanvas()->GetViewControls(), GetSettings(),
1726 this );
1728 }
1729}
1730
1731
1749
1750
1752{
1753 SyncLibraries( true );
1754
1755 if( m_symbol )
1756 {
1757 SCH_SELECTION_TOOL* selectionTool = m_toolManager->GetTool<SCH_SELECTION_TOOL>();
1758 SCH_SELECTION& selection = selectionTool->GetSelection();
1759
1760 for( SCH_ITEM& item : m_symbol->GetDrawItems() )
1761 {
1762 if( !alg::contains( selection, &item ) )
1763 item.ClearSelected();
1764 else
1765 item.SetSelected();
1766 }
1767
1768 m_symbol->ClearCaches();
1769 }
1770
1771 RebuildView();
1772}
1773
1774
1775const BOX2I SYMBOL_EDIT_FRAME::GetDocumentExtents( bool aIncludeAllVisible ) const
1776{
1777 if( !m_symbol )
1778 {
1779 // Gives a reasonable drawing area size
1780 int width = schIUScale.mmToIU( 50 );
1781 int height = schIUScale.mmToIU( 30 );
1782
1783 return BOX2I( VECTOR2I( -width/2, -height/2 ), VECTOR2I( width, height ) );
1784 }
1785 else
1786 {
1787 return m_symbol->Flatten()->GetUnitBoundingBox( m_unit, m_bodyStyle );
1788 }
1789}
1790
1791
1792void SYMBOL_EDIT_FRAME::FocusOnItem( EDA_ITEM* aItem, bool aAllowScroll )
1793{
1794 static KIID lastBrightenedItemID( niluuid );
1795
1796 SCH_ITEM* lastItem = nullptr;
1797
1798 // nullptr will clear the current focus
1799 if( aItem != nullptr && !aItem->IsSCH_ITEM() )
1800 return;
1801
1802 if( m_symbol )
1803 {
1804 for( SCH_PIN* pin : m_symbol->GetGraphicalPins( 0, 0 ) )
1805 {
1806 if( pin->m_Uuid == lastBrightenedItemID )
1807 lastItem = pin;
1808 }
1809
1810 std::vector<SCH_FIELD*> fields;
1811 m_symbol->GetFields( fields );
1812
1813 for( SCH_FIELD* field : fields )
1814 {
1815 if( field->m_Uuid == lastBrightenedItemID )
1816 lastItem = field;
1817 }
1818 }
1819
1820 if( lastItem && lastItem != aItem )
1821 {
1822 lastItem->ClearBrightened();
1823
1824 UpdateItem( lastItem );
1825 lastBrightenedItemID = niluuid;
1826 }
1827
1828 if( aItem )
1829 {
1830 if( aItem->IsSCH_ITEM() )
1831 {
1832 SCH_ITEM* item = static_cast<SCH_ITEM*>( aItem );
1833
1834 if( int unit = item->GetUnit() )
1835 SetUnit( unit );
1836
1837 if( int bodyStyle = item->GetBodyStyle() )
1838 SetBodyStyle( bodyStyle );
1839 }
1840
1841 if( !aItem->IsBrightened() )
1842 {
1843 aItem->SetBrightened();
1844
1845 UpdateItem( aItem );
1846 lastBrightenedItemID = aItem->m_Uuid;
1847 }
1848
1849 FocusOnLocation( VECTOR2I( aItem->GetFocusPosition().x, aItem->GetFocusPosition().y ), aAllowScroll );
1850 }
1851}
1852
1853
1855{
1856 const std::string& payload = mail.GetPayload();
1857
1858 wxLogTrace( wxT( "KICAD_TABS_DBG" ), wxT( "SYMBOL_EDIT_FRAME::KiwayMailIn cmd=%d" ),
1859 (int) mail.Command() );
1860
1861 switch( mail.Command() )
1862 {
1863 case MAIL_LIB_EDIT:
1864 if( !payload.empty() )
1865 {
1866 wxString uri( payload );
1867 wxString libNickname;
1868 wxString msg;
1869
1871 std::optional<const LIBRARY_TABLE_ROW*> libTableRow = adapter->FindRowByURI( uri );
1872
1873 if( !libTableRow )
1874 {
1875 msg.Printf( _( "The current configuration does not include the symbol library '%s'." ),
1876 uri );
1877 msg += wxS( "\n" ) + _( "Use Manage Symbol Libraries to edit the configuration." );
1878 DisplayErrorMessage( this, _( "Library not found in symbol library table." ), msg );
1879 break;
1880 }
1881
1882 libNickname = ( *libTableRow )->Nickname();
1883
1884 if( !adapter->HasLibrary( libNickname, true ) )
1885 {
1886 msg.Printf( _( "The symbol library '%s' is not enabled in the current configuration." ),
1887 UnescapeString( libNickname ) );
1888 msg += wxS( "\n" ) + _( "Use Manage Symbol Libraries to edit the configuration." );
1889 DisplayErrorMessage( this, _( "Symbol library not enabled." ), msg );
1890 break;
1891 }
1892
1893 SetCurLib( libNickname );
1894
1895 if( m_treePane )
1896 {
1897 LIB_ID id( libNickname, wxEmptyString );
1898 GetLibTree()->SelectLibId( id );
1899 GetLibTree()->ExpandLibId( id );
1900 GetLibTree()->CenterLibId( id );
1901 }
1902 }
1903
1904 break;
1905
1906 case MAIL_RELOAD_LIB:
1907 {
1908 wxLogTrace( wxT( "KICAD_TABS_DBG" ),
1909 wxT( "SYMBOL_EDIT_FRAME::KiwayMailIn MAIL_RELOAD_LIB -> SyncLibraries" ) );
1910
1911 wxString currentLib = GetCurLib();
1912
1914
1915 // Check if the currently selected symbol library been removed or disabled.
1916 if( !currentLib.empty()
1917 && !PROJECT_SCH::SymbolLibAdapter( &Prj() )->HasLibrary( currentLib, true ) )
1918 {
1919 SetCurLib( wxEmptyString );
1920 emptyScreen();
1921 }
1922
1923 // Suppress the progress dialog for this background reload. It would steal focus from the
1924 // editor that broadcast the reload, and the tree is already frozen around the sync.
1925 SyncLibraries( false );
1928
1929 break;
1930 }
1931
1933 {
1935 LIB_SYMBOL* symbol = GetCurSymbol();
1936
1937 wxLogTrace( traceLibWatch, "Received refresh symbol request for %s", payload );
1938
1939 if( !symbol )
1940 break;
1941
1942 // Capture the name now. UpdateLibraryBuffer() recreates the buffer, so reading it from the
1943 // buffer copy afterwards would be a use-after-free.
1944 const wxString refreshSymbolName = symbol->GetName();
1945
1946 // If the frame is disabled then a modal/quasi-modal dialog (such as the symbol properties dialog) is
1947 // editing the current LIB_SYMBOL. Refreshing it here would delete the symbol out from under the dialog
1948 // and crash on dismissal. The file watcher timer will retry the reload once the dialog has closed.
1949 if( !IsEnabled() )
1950 {
1951 wxLogTrace( traceLibWatch, "Deferring symbol refresh; dialog is open on the symbol editor." );
1952 break;
1953 }
1954 // Defensive backstop for refresh mail that did not originate from this frame's debounce
1955 // timer (which already defers while a tool is active). An interactive tool holds
1956 // references into the current symbol, so replacing it here would crash; drop this refresh
1957 // and let the originating watcher retry.
1958 else if( !ToolStackIsEmpty() )
1959 {
1960 wxLogTrace( traceLibWatch, "Deferring symbol refresh; an interactive tool is active." );
1961 break;
1962 }
1963
1964 wxString libName = symbol->GetLibId().GetLibNickname();
1965 std::optional<const LIBRARY_TABLE_ROW*> row = adapter->GetRow( libName );
1966
1967 if( !row )
1968 return;
1969
1970 wxFileName libfullname( LIBRARY_MANAGER::GetFullURI( *row, true ) );
1971
1972 wxFileName changedLib( mail.GetPayload() );
1973
1974 wxLogTrace( traceLibWatch, "Received refresh symbol request for %s, current symbols is %s",
1975 changedLib.GetFullPath(), libfullname.GetFullPath() );
1976
1977 if( changedLib == libfullname )
1978 {
1979 wxLogTrace( traceLibWatch, "Refreshing symbol %s", refreshSymbolName );
1980
1981 m_libMgr->UpdateLibraryBuffer( libName );
1982
1983 if( LIB_SYMBOL* lib_symbol = m_libMgr->GetBufferedSymbol( refreshSymbolName, libName ) )
1984 {
1985 SetCurSymbol( new LIB_SYMBOL( *lib_symbol ), false );
1987
1988 if( m_toolManager )
1990 }
1991 }
1992
1993 break;
1994 }
1995
1996 default:
1997 break;
1998 }
1999}
2000
2001
2002std::unique_ptr<GRID_HELPER> SYMBOL_EDIT_FRAME::MakeGridHelper()
2003{
2004 return std::make_unique<EE_GRID_HELPER>( m_toolManager );
2005}
2006
2007
2009{
2010 // switches currently used canvas ( Cairo / OpenGL):
2011 SCH_BASE_FRAME::SwitchCanvas( aCanvasType );
2012
2013 // Set options specific to symbol editor (axies are always enabled):
2014 GetCanvas()->GetGAL()->SetAxesEnabled( true );
2016}
2017
2018
2020{
2021 wxCHECK( m_libMgr, false );
2022
2023 return m_libMgr->HasModifications();
2024}
2025
2026
2028{
2029 wxCHECK( m_libMgr, false );
2030
2031 // Test if the currently edited symbol is modified
2033 return true;
2034
2035 // Test if any library has been modified
2036 for( const wxString& libName : m_libMgr->GetLibraryNames() )
2037 {
2038 if( m_libMgr->IsLibraryModified( libName ) && !m_libMgr->IsLibraryReadOnly( libName ) )
2039 return true;
2040 }
2041
2042 return false;
2043}
2044
2045
2047{
2048 if( aItemCount == 0 )
2049 return;
2050
2051 UNDO_REDO_CONTAINER& list = ( whichList == UNDO_LIST ) ? m_undoList : m_redoList;
2052
2053 // UR_TRANSIENT is flagged on the picked item, not the wrapper, so the shared deleters miss it.
2054 // Free the items carrying UR_TRANSIENT. m_symbol never carries it, so the live copy is safe.
2055 if( aItemCount < 0 )
2056 {
2058 }
2059 else
2060 {
2061 for( int ii = 0; ii < aItemCount; ii++ )
2062 {
2063 if( list.m_CommandsList.size() == 0 )
2064 break;
2065
2066 PICKED_ITEMS_LIST* curr_cmd = list.m_CommandsList[0];
2067 list.m_CommandsList.erase( list.m_CommandsList.begin() );
2068
2069 for( unsigned jj = 0; jj < curr_cmd->GetCount(); ++jj )
2070 {
2071 EDA_ITEM* item = curr_cmd->GetPickedItem( jj );
2072
2073 if( item && item->HasFlag( UR_TRANSIENT ) && item != m_symbol )
2074 delete item;
2075 }
2076
2077 curr_cmd->ClearItemsList();
2078 delete curr_cmd; // Delete command
2079 }
2080 }
2081}
2082
2083
2085{
2086 return m_toolManager->GetTool<SCH_SELECTION_TOOL>()->GetSelection();
2087}
2088
2089
2091 bool aRestorePending, bool aTreeShownNow )
2092{
2093 // Auto-hiding a visible tree schedules its restore. A chained schematic edit finds the tree
2094 // already auto-hidden, so keep the pending restore rather than dropping it. An explicit user
2095 // toggle clears the flag elsewhere, so a tree hidden without a pending restore stays that way.
2096 if( aTreeShownNow )
2097 return true;
2098
2099 return aWasFromSchematic && aRestorePending;
2100}
2101
2102
2104{
2105 std::unique_ptr<LIB_SYMBOL> symbol = aSymbol->GetLibSymbolRef()->Flatten();
2106 wxCHECK( symbol, /* void */ );
2107
2108 symbol->SetLibId( aSymbol->GetLibId() );
2109
2110 // Take in account the symbol orientation and mirroring. to calculate the field
2111 // positions in symbol editor (i.e. no rotation, no mirroring)
2112 int orientation = aSymbol->GetOrientation() & ~( SYM_MIRROR_X | SYM_MIRROR_Y );
2113 int mirror = aSymbol->GetOrientation() & ( SYM_MIRROR_X | SYM_MIRROR_Y );
2114
2115 std::vector<SCH_FIELD> fullSetOfFields;
2116
2117 for( const SCH_FIELD& field : aSymbol->GetFields() )
2118 {
2119 VECTOR2I pos = field.GetPosition() - aSymbol->GetPosition();
2120 SCH_FIELD libField( symbol.get(), field.GetId() );
2121
2122 libField = field;
2123
2124 // The inverse transform is mirroring before, rotate after
2125 switch( mirror )
2126 {
2127 case SYM_MIRROR_X: pos.y = -pos.y; break;
2128 case SYM_MIRROR_Y: pos.x = -pos.x; break;
2129 default: break;
2130 }
2131
2132 switch( orientation )
2133 {
2134 case SYM_ORIENT_90:
2135 std::swap( pos.x, pos.y );
2136 pos.x = - pos.x;
2137 break;
2138 case SYM_ORIENT_270:
2139 std::swap( pos.x, pos.y );
2140 pos.y = - pos.y;
2141 break;
2142 case SYM_ORIENT_180:
2143 pos.x = - pos.x;
2144 pos.y = - pos.y;
2145 break;
2146 default:
2147 break;
2148 }
2149
2150 libField.SetPosition( pos );
2151
2152 fullSetOfFields.emplace_back( std::move( libField ) );
2153 }
2154
2155 symbol->SetFields( fullSetOfFields );
2156
2157 const wxString reference = symbol->GetReferenceField().GetText();
2158 const int unit = std::max( 1, aSymbol->GetUnit() );
2159 const int bodyStyle = std::max( 1, aSymbol->GetBodyStyle() );
2160
2161 // Optimize default edit options for this symbol
2162 // Usually if units are locked, graphic items are specific to each unit
2163 // and if units are interchangeable, graphic items are common to units
2165 tools->SetDrawSpecificUnit( symbol->UnitsLocked() );
2166
2167 // Hand the transient working symbol/screen to a session-only instance tab, whose activation
2168 // restores the frame's schematic-source state so the save path routes back to the schematic.
2169 SCH_SCREEN* tmpScreen = new SCH_SCREEN();
2170
2171 setSymWatcher( nullptr );
2172
2173 SYMBOL_EDITOR_TAB_CONTEXT* ctx = findOrCreateSymbolInstanceTab( symbol.release(), tmpScreen,
2174 aSymbol->m_Uuid, reference, unit,
2175 bodyStyle );
2176 wxCHECK( ctx, /* void */ );
2177
2180
2181 // Auto-hide the tree while editing a schematic symbol, remembering to restore it in SaveSettings
2182 // so the user's preference survives a restart. Hide via the pane directly, not ToggleLibraryTree,
2183 // which would treat this as a user toggle and drop the pending restore.
2186
2187 if( IsLibraryTreeShown() )
2188 {
2189 m_auimgr.GetPane( m_treePane ).Show( false );
2191 m_auimgr.Update();
2192 Refresh();
2193 }
2194
2195 UpdateTitle();
2198
2199 // Let tools add things to the view if necessary
2200 if( m_toolManager )
2202
2204 GetCanvas()->Refresh();
2205}
2206
2207
2208bool SYMBOL_EDIT_FRAME::addLibTableEntry( const wxString& aLibFile, LIBRARY_TABLE_SCOPE aScope )
2209{
2210 wxFileName fn = aLibFile;
2211 wxFileName libTableFileName( Prj().GetProjectPath(), FILEEXT::SymbolLibraryTableFileName );
2212 wxString libNickname = fn.GetName();
2214 LIBRARY_MANAGER& manager = Pgm().GetLibraryManager();
2215 const ENV_VAR_MAP& envVars = Pgm().GetLocalEnvVariables();
2216
2217 if( adapter->HasLibrary( libNickname ) )
2218 {
2219 wxString tmp;
2220 int suffix = 1;
2221
2222 while( adapter->HasLibrary( libNickname ) )
2223 {
2224 tmp.Printf( "%s%d", fn.GetName(), suffix );
2225 libNickname = tmp;
2226 suffix += 1;
2227 }
2228 }
2229
2230 std::optional<LIBRARY_TABLE*> optTable = manager.Table( LIBRARY_TABLE_TYPE::SYMBOL, aScope );
2231 wxCHECK( optTable.has_value(), false );
2232 LIBRARY_TABLE* table = optTable.value();
2233
2234 LIBRARY_TABLE_ROW* row = &table->InsertRow();
2235
2236 row->SetNickname( libNickname );
2237
2238 // We cannot normalize against the current project path when saving to global table.
2239 wxString normalizedPath = NormalizePath( aLibFile, &envVars,
2240 aScope == LIBRARY_TABLE_SCOPE::PROJECT ? Prj().GetProjectPath()
2241 : wxString( wxEmptyString ) );
2242
2243 row->SetURI( normalizedPath );
2245
2246 bool success = true;
2247
2248 table->Save().map_error(
2249 [&]( const LIBRARY_ERROR& aError )
2250 {
2251 KICAD_MESSAGE_DIALOG dlg( this, _( "Error saving library table." ), _( "File Save Error" ),
2252 wxOK | wxICON_ERROR );
2253 dlg.SetExtendedMessage( aError.message );
2254 dlg.ShowModal();
2255
2256 success = false;
2257 } );
2258
2259 if( success )
2260 {
2261 manager.ReloadTables( aScope, { LIBRARY_TABLE_TYPE::SYMBOL } );
2262 adapter->LoadOne( libNickname );
2263 }
2264
2265 return success;
2266}
2267
2268
2269bool SYMBOL_EDIT_FRAME::replaceLibTableEntry( const wxString& aLibNickname, const wxString& aLibFile )
2270{
2272 LIBRARY_MANAGER& manager = Pgm().GetLibraryManager();
2273 LIBRARY_TABLE* table = nullptr;
2275
2276 // Check the global library table first because checking the project library table
2277 // checks the global library table as well due to library chaining.
2278 if( adapter->GetRow( aLibNickname, scope ) )
2279 {
2280 std::optional<LIBRARY_TABLE*> optTable = manager.Table( LIBRARY_TABLE_TYPE::SYMBOL, scope );
2281 wxCHECK( optTable.has_value(), false );
2282 table = optTable.value();
2283 }
2284 else
2285 {
2287
2288 if( adapter->GetRow( aLibNickname, scope ) )
2289 {
2290 std::optional<LIBRARY_TABLE*> optTable = manager.Table( LIBRARY_TABLE_TYPE::SYMBOL, scope );
2291
2292 if( optTable.has_value() )
2293 table = optTable.value();
2294 }
2295 }
2296
2297 wxCHECK( table, false );
2298
2299 std::optional<LIBRARY_TABLE_ROW*> optRow = adapter->GetRow( aLibNickname, scope );
2300 wxCHECK( optRow.has_value(), false );
2301 LIBRARY_TABLE_ROW* row = optRow.value();
2302
2303 const ENV_VAR_MAP& envVars = Pgm().GetLocalEnvVariables();
2304
2305 wxString projectPath;
2306
2307 if( scope == LIBRARY_TABLE_SCOPE::PROJECT )
2308 projectPath = Prj().GetProjectPath();
2309
2310 wxString normalizedPath = NormalizePath( aLibFile, &envVars, projectPath );
2311
2312 row->SetURI( normalizedPath );
2313 row->SetType( "KiCad" );
2314
2315 bool success = true;
2316
2317 table->Save().map_error(
2318 [&]( const LIBRARY_ERROR& aError )
2319 {
2320 KICAD_MESSAGE_DIALOG dlg( this, _( "Error saving library table." ), _( "File Save Error" ),
2321 wxOK | wxICON_ERROR );
2322 dlg.SetExtendedMessage( aError.message );
2323 dlg.ShowModal();
2324
2325 success = false;
2326 } );
2327
2328 if( success )
2329 {
2330 manager.ReloadTables( scope, { LIBRARY_TABLE_TYPE::SYMBOL } );
2331 adapter->LoadOne( aLibNickname );
2332 }
2333
2334 return success;
2335}
2336
2337
2339{
2340 return m_symbol && !m_symbol->IsRoot();
2341}
2342
2343
2348
2349
2350void SYMBOL_EDIT_FRAME::UpdateItem( EDA_ITEM* aItem, bool isAddOrDelete, bool aUpdateRtree )
2351{
2352 SCH_BASE_FRAME::UpdateItem( aItem, isAddOrDelete, aUpdateRtree );
2353
2354 if( EDA_TEXT* eda_text = dynamic_cast<EDA_TEXT*>( aItem ) )
2355 {
2356 eda_text->ClearBoundingBoxCache();
2357 eda_text->ClearRenderCache();
2358 }
2359}
2360
2361
2363{
2364 wxAuiPaneInfo& treePane = m_auimgr.GetPane( m_treePane );
2365 wxAuiPaneInfo& propertiesPane = m_auimgr.GetPane( PropertiesPaneName() );
2366 wxAuiPaneInfo& selectionFilterPane = m_auimgr.GetPane( wxS( "SelectionFilter" ) );
2367
2368 // Don't give the selection filter its own visibility controls; instead show it if
2369 // anything else is visible
2370 bool showFilter = ( treePane.IsShown() && treePane.IsDocked() )
2371 || ( propertiesPane.IsShown() && propertiesPane.IsDocked() );
2372
2373 selectionFilterPane.Show( showFilter );
2374}
2375
2376
2378{
2379 // Returns the current render option for invisible fields
2381}
2382
2383
2385{
2386 // Returns the current render option for invisible pins
2388}
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.
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:44
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:796
virtual KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=nullptr)
Return the KIWAY_PLAYER* given a FRAME_T.
Definition kiway.cpp:398
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:496
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:80
const LIB_ID & GetLibId() const override
Definition lib_symbol.h:149
bool UnitsLocked() const
Check whether symbol units are interchangeable.
Definition lib_symbol.h:332
bool IsRoot() const override
For symbols derived from other symbols, IsRoot() indicates no derivation.
Definition lib_symbol.h:196
wxString GetName() const override
Definition lib_symbol.h:142
bool IsMultiUnit() const override
Definition lib_symbol.h:817
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:799
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.
@ SCH_LIBEDIT_CUR_LIB
Definition project.h:218
@ SCH_LIBEDIT_CUR_SYMBOL
Definition project.h:219
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition project.cpp:183
virtual void SetRString(RSTRING_T aStringId, const wxString &aString)
Store a "retained string", which is any session and project specific string identified in enum RSTRIN...
Definition project.cpp:355
virtual const wxString & GetRString(RSTRING_T aStringId)
Return a "retained string", which is any session and project specific string identified in enum RSTRI...
Definition project.cpp:366
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 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:913
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.
bool IsModified() const override
True when the working screen carries unsaved edits.
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.
void storeCurrentSymbol()
Rename LIB_SYMBOL aliases to avoid conflicts before adding a symbol to a library.
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 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
wxString GetCurLib() const
The nickname of the current library being edited and empty string if none.
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)
int m_bodyStyle
Flag if the symbol being edited was loaded directly from a schematic.
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
wxString SetCurLib(const wxString &aLibNickname)
Set the current library nickname and returns the old library nickname.
void UpdateTitle()
Update the main window title bar with the current library name and read only status of the library.
bool LoadSymbolFromCurrentLib(const wxString &aSymbolName, int aUnit=0, int aBodyStyle=0)
Load a symbol from the current active library, optionally setting the selected unit and convert.
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 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 wxString KiCadSymbolLibFileWildcard()
const wxChar *const traceLibWatch
Flag to enable debug output for library file watch refreshes.
@ ID_ON_GRID_SELECT
Definition id.h:112
@ ID_ON_ZOOM_SELECT
Definition id.h:111
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:485
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
std::vector< std::vector< std::string > > table
#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.