KiCad PCB EDA Suite
Loading...
Searching...
No Matches
symbol_edit_frame_tabs.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 The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
26
27#include <symbol_edit_frame.h>
28
29#include <kidialog.h>
30#include <lib_symbol.h>
32#include <sch_screen.h>
33#include <sch_view.h>
36#include <tool/actions.h>
37#include <tool/selection.h>
38#include <tool/tool_manager.h>
40#include <view/view.h>
41#include <view/view_controls.h>
43#include <widgets/lib_tree.h>
45
46
48{
50
51 if( KIGFX::VIEW* view = GetCanvas() ? GetCanvas()->GetView() : nullptr )
52 {
53 snapshot.scale = view->GetScale();
54 snapshot.center = view->GetCenter();
55 snapshot.valid = true;
56 }
57
58 return snapshot;
59}
60
61
63{
64 if( !aSnapshot.valid )
65 return;
66
67 if( KIGFX::VIEW* view = GetCanvas() ? GetCanvas()->GetView() : nullptr )
68 {
69 view->SetScale( aSnapshot.scale );
70 view->SetCenter( aSnapshot.center );
71 }
72}
73
74
76{
77 std::vector<KIID> kiids;
78
80 : nullptr;
81
82 if( !selTool )
83 return kiids;
84
85 for( EDA_ITEM* item : selTool->GetSelection() )
86 {
87 if( item )
88 kiids.push_back( item->m_Uuid );
89 }
90
91 return kiids;
92}
93
94
95void SYMBOL_EDIT_FRAME::restoreSymbolSelectionKiids( const std::vector<KIID>& aKiids )
96{
97 if( aKiids.empty() )
98 return;
99
101 : nullptr;
102 SCH_SCREEN* screen = GetScreen();
103
104 if( !selTool || !screen )
105 return;
106
107 for( SCH_ITEM* item : screen->Items() )
108 {
109 for( const KIID& kiid : aKiids )
110 {
111 if( item->m_Uuid == kiid )
112 {
113 selTool->AddItemToSel( item, true );
114 break;
115 }
116 }
117 }
118}
119
120
122{
123 if( !m_activeTab )
124 return;
125
126 m_activeTab->ViewSnapshot() = captureSymbolViewSnapshot();
127 m_activeTab->SavedSelection() = captureSymbolSelectionKiids();
128 m_activeTab->SetUnit( m_unit );
129 m_activeTab->SetBodyStyle( m_bodyStyle );
130
131 // m_symbol may have been replaced by undo/redo since activation.
132 m_activeTab->AdoptWorkingObjects( m_symbol, static_cast<SCH_SCREEN*>( GetScreen() ) );
133
134 m_activeTab->UndoList().m_CommandsList.swap( m_undoList.m_CommandsList );
135 m_activeTab->RedoList().m_CommandsList.swap( m_redoList.m_CommandsList );
136}
137
138
140{
141 wxCHECK( m_toolManager, /* void */ );
142
143 if( !aContext )
144 return;
145
146 if( aContext == m_activeTab )
147 {
148 // Already active, but the caller may have requested a different unit/body style; apply it.
149 m_unit = aContext->GetUnit();
150 m_bodyStyle = aContext->GetBodyStyle();
151
156
159 GetCanvas()->Refresh();
160 return;
161 }
162
164 m_activeTab = aContext;
165
166 m_undoList.m_CommandsList.swap( aContext->UndoList().m_CommandsList );
167 m_redoList.m_CommandsList.swap( aContext->RedoList().m_CommandsList );
168
170
171 aContext->ReleaseToFrame();
172
173 // Restore the frame's schematic-source state from the incoming tab so the existing save path
174 // (SaveSymbolToSchematic vs the library) keys off the active tab, not whichever tab loaded last.
177 m_reference = aContext->GetReference();
178
179 m_symbol = aContext->GetSymbol();
180 m_unit = aContext->GetUnit();
181 m_bodyStyle = aContext->GetBodyStyle();
182
183 // Install the new screen before SetScreen, whose ResetTools would otherwise deref the freed one.
184 m_toolManager->SetEnvironment( aContext->GetScreen(), GetCanvas()->GetView(), GetCanvas()->GetViewControls(),
185 GetSettings(), this );
186 SetScreen( aContext->GetScreen() );
187
188 if( m_symbol )
189 {
190 wxLogTrace( wxT( "KICAD_TABS_DBG" ), wxT( "activateSymbolTab SelectLibId '%s'" ),
191 m_symbol->GetLibId().Format().wx_str() );
192 GetLibTree()->SelectLibId( m_symbol->GetLibId() );
193 }
194
195 m_toolManager->SetEnvironment( GetScreen(), GetCanvas()->GetView(), GetCanvas()->GetViewControls(),
196 GetSettings(), this );
197
202
206
207 // MODEL_RELOAD clears the selection, so restore the saved one afterwards.
209
210 if( aContext->ViewSnapshot().valid )
211 {
213 }
214 else
215 {
216 // First time this tab is shown there is no saved view
218 }
219
221
223
225 m_propertiesPanel->UpdateData();
226
229 GetCanvas()->Refresh();
230}
231
232
233void SYMBOL_EDIT_FRAME::OnTabCharHook( wxKeyEvent& aEvent )
234{
235 // Only plain Ctrl+Tab and Ctrl+Shift+Tab are ours; anything else falls through.
236 const bool isTab = aEvent.GetKeyCode() == WXK_TAB;
237 const bool ctrlOnly = aEvent.ControlDown() && !aEvent.AltDown() && !aEvent.MetaDown();
238
239 // Ctrl+W closes the active tab while tabs are open, else falls through to close-window. The
240 // keycode arrives as 'W' or the control char 0x17 depending on platform, so accept both.
241 const int keyCode = aEvent.GetKeyCode();
242 const bool isCtrlW = ctrlOnly && !aEvent.ShiftDown()
243 && ( keyCode == 'W' || keyCode == ( 'W' - '@' ) );
244
245 if( isCtrlW && m_tabsPanel && m_tabsPanel->Model().Entries().size() >= 1 )
246 {
247 // Route through CloseTab so the unsaved-changes prompt still runs.
248 m_tabsPanel->CloseTab( m_tabsPanel->GetActiveTab() );
249 return;
250 }
251
252 if( !isTab || !ctrlOnly || !m_tabsPanel )
253 {
254 aEvent.Skip();
255 return;
256 }
257
258 m_tabsPanel->AdvanceTab( !aEvent.ShiftDown() );
259
260 // Consume the event so GTK's default Tab focus-traversal does not also run.
261}
262
263
265 const LIB_SYMBOL* aLiveSymbol )
266{
267 for( PICKED_ITEMS_LIST* cmd : aList.m_CommandsList )
268 {
269 // The undo copy is the picked ITEM flagged UR_TRANSIENT, not the wrapper, so the shared
270 // deleters skip it. Free exactly the items that carry UR_TRANSIENT here.
271 for( unsigned ii = 0; ii < cmd->GetCount(); ++ii )
272 {
273 EDA_ITEM* item = cmd->GetPickedItem( ii );
274
275 if( !item || !item->HasFlag( UR_TRANSIENT ) )
276 continue;
277
278 // The live working symbol clears UR_TRANSIENT when it becomes m_symbol; guard anyway
279 // against a double-free of the live symbol.
280 wxCHECK2_MSG( item != aLiveSymbol, continue,
281 wxT( "Live working symbol flagged UR_TRANSIENT in undo/redo list" ) );
282
283 delete item;
284 }
285
286 cmd->ClearItemsList();
287 delete cmd;
288 }
289
290 aList.m_CommandsList.clear();
291}
292
293
295{
296 // The context is detached here, so no undo copy is the live working object.
297 freeTransientUndoCommands( aContext.UndoList(), nullptr );
298 freeTransientUndoCommands( aContext.RedoList(), nullptr );
299}
300
301
303 EDITOR_TABS_MODEL& aModel )
304{
305 // An active tab's screen aliases the frame's current screen, so this clears the live flag too.
306 if( SCH_SCREEN* screen = aContext.GetScreen() )
307 screen->SetContentModified( false );
308
309 aModel.MarkModified( aContext.GetTabKey(), false );
310}
311
312
314{
315 for( const std::unique_ptr<SYMBOL_EDITOR_TAB_CONTEXT>& ctx : m_tabContexts )
316 {
317 if( ctx->GetLibrary() != aLibrary )
318 continue;
319
320 if( m_tabsPanel )
321 clearTabModifiedState( *ctx, m_tabsPanel->MutableModel() );
322 else if( SCH_SCREEN* screen = ctx->GetScreen() )
323 screen->SetContentModified( false );
324 }
325
326 // The strip queries the dirty flag only on repaint, so without this the cleared asterisk lingers
327 // until the next stray paint event reaches the tab the user was on.
328 if( m_tabsPanel )
329 m_tabsPanel->RefreshTabLabels();
330}
331
332
334{
335 for( const std::unique_ptr<SYMBOL_EDITOR_TAB_CONTEXT>& ctx : m_tabContexts )
336 {
337 if( ctx->GetTabKey() == aKey )
338 return ctx.get();
339 }
340
341 return nullptr;
342}
343
344
345void SYMBOL_EDIT_FRAME::dropSymbolTabContext( const wxString& aKey )
346{
348
349 // The active context is still on screen and owned by the frame, so never drop it here; only an
350 // evicted, inactive preview reaches this path.
351 if( !ctx || ctx == m_activeTab )
352 return;
353
355
356 std::erase_if( m_tabContexts,
357 [ctx]( const std::unique_ptr<SYMBOL_EDITOR_TAB_CONTEXT>& aOwned )
358 {
359 return aOwned.get() == ctx;
360 } );
361}
362
363
365{
366 if( !m_tabsPanel )
367 return nullptr;
368
369 const std::vector<EDITOR_TABS_MODEL::ENTRY>& entries = m_tabsPanel->Model().Entries();
370
371 if( aIdx < 0 || aIdx >= static_cast<int>( entries.size() ) )
372 return nullptr;
373
374 return symbolTabContextForKey( entries[aIdx].key );
375}
376
377
378SYMBOL_EDITOR_TAB_CONTEXT* SYMBOL_EDIT_FRAME::findOrCreateSymbolTab( const wxString& aLib, const wxString& aName,
379 int aUnit, int aBodyStyle, bool aAsPreview,
380 bool* aWasCreated )
381{
382 const wxString key = SYMBOL_EDITOR_TAB_CONTEXT::MakeTabKey( aLib, aName );
383 const int unit = aUnit > 0 ? aUnit : 1;
384 const int bodyStyle = aBodyStyle > 0 ? aBodyStyle : 1;
385
387
388 if( aWasCreated )
389 *aWasCreated = false;
390
391 if( !ctx )
392 {
393 SYMBOL_BUFFER* buffer = m_libMgr ? m_libMgr->GetBuffer( aName, aLib ) : nullptr;
394
395 if( !buffer )
396 return nullptr;
397
398 m_tabContexts.push_back( std::make_unique<SYMBOL_EDITOR_TAB_CONTEXT>( aLib, aName, buffer ) );
399 ctx = m_tabContexts.back().get();
400
401 if( aWasCreated )
402 *aWasCreated = true;
403 }
404
405 ctx->SetUnit( unit );
406 ctx->SetBodyStyle( bodyStyle );
407
408 if( m_tabsPanel )
409 {
410 // A previewed open reuses the existing preview slot in the panel instead of adding a tab.
411 // The panel drops the evicted key from its model, but the matching context lingers in
412 // m_tabContexts and would be persisted as a phantom tab, so capture the evicted key and drop
413 // its context once the reuse completes.
414 wxString replacedKey;
415
416 if( aAsPreview )
417 {
418 const std::vector<EDITOR_TABS_MODEL::ENTRY>& entries = m_tabsPanel->Model().Entries();
419 const int previewIdx = m_tabsPanel->Model().PreviewIndex();
420
421 if( previewIdx >= 0 && previewIdx < static_cast<int>( entries.size() ) && entries[previewIdx].key != key )
422 replacedKey = entries[previewIdx].key;
423 }
424
425 m_tabsPanel->AddTab( key, aName, aAsPreview );
426
427 if( !replacedKey.empty() )
428 dropSymbolTabContext( replacedKey );
429 }
430 else
431 {
432 activateSymbolTab( ctx );
433 }
434
435 return ctx;
436}
437
438
441 const KIID& aSchematicSymbolUUID, const wxString& aReference,
442 int aUnit, int aBodyStyle )
443{
444 const wxString key = SYMBOL_EDITOR_TAB_CONTEXT::MakeInstanceTabKey( aSchematicSymbolUUID );
445 const int unit = aUnit > 0 ? aUnit : 1;
446 const int bodyStyle = aBodyStyle > 0 ? aBodyStyle : 1;
447
449 {
450 // Re-editing the same placed symbol focuses the live tab, so free the redundant new objects.
451 delete aSymbol;
452 delete aScreen;
453
454 existing->SetUnit( unit );
455 existing->SetBodyStyle( bodyStyle );
456
457 if( m_tabsPanel )
458 m_tabsPanel->AddTab( key, existing->GetReference() + wxS( " " ) + _( "[from schematic]" ), false );
459 else
460 activateSymbolTab( existing );
461
462 return existing;
463 }
464
465 m_tabContexts.push_back( std::make_unique<SYMBOL_EDITOR_TAB_CONTEXT>( aSymbol, aScreen, aSchematicSymbolUUID,
466 aReference ) );
467 SYMBOL_EDITOR_TAB_CONTEXT* ctx = m_tabContexts.back().get();
468
469 ctx->SetUnit( unit );
470 ctx->SetBodyStyle( bodyStyle );
471
472 if( m_tabsPanel )
473 m_tabsPanel->AddTab( key, aReference + wxS( " " ) + _( "[from schematic]" ), false );
474 else
475 activateSymbolTab( ctx );
476
477 return ctx;
478}
479
480
482{
484
485 if( !ctx )
486 return true;
487
488 if( ctx->IsModified() && !m_silentSymbolTabClose )
489 {
490 wxString msg = wxString::Format( _( "Save changes to '%s' before closing?" ),
491 ctx->GetDisplayName() );
492
493 KIDIALOG dlg( this, msg, _( "Confirmation" ), wxYES_NO | wxCANCEL | wxICON_WARNING );
494 dlg.SetYesNoCancelLabels( _( "Save" ), _( "Discard Changes" ), _( "Cancel" ) );
495
496 switch( dlg.ShowModal() )
497 {
498 case wxID_YES:
499 // saveCurrentSymbol operates on the active tab, so activate this one first to save it.
500 if( ctx != m_activeTab )
501 activateSymbolTab( ctx );
502
503 if( !saveCurrentSymbol() )
504 return false;
505
506 if( IsLibraryTreeShown() )
507 m_treePane->GetLibTree()->RefreshLibTree();
508
509 break;
510
511 case wxID_NO:
512 break;
513
514 default:
515 return false;
516 }
517 }
518
519 // If this is the active tab the frame holds its objects, so repoint at the dummy screen and drop
520 // m_symbol before destroying the context, then let the context free them once.
521 if( ctx == m_activeTab )
522 {
523 // Clear the frame's undo/redo so nothing references the about-to-be-deleted working symbol.
525 ctx->AdoptWorkingObjects( m_symbol, static_cast<SCH_SCREEN*>( GetScreen() ) );
526
527 m_activeTab = nullptr;
528 m_symbol = nullptr;
530
531 // Clear the mirrored schematic-source state so the frame no longer looks like it holds an
532 // instance symbol; a successor tab's activateSymbolTab restores these from its own context.
535 m_reference = wxEmptyString;
536 }
537 else
538 {
539 // An inactive tab's undo/redo still holds transient copies; free them before destroying it.
541 }
542
543 std::erase_if( m_tabContexts,
544 [ctx]( const std::unique_ptr<SYMBOL_EDITOR_TAB_CONTEXT>& aOwned )
545 {
546 return aOwned.get() == ctx;
547 } );
548
549 return true;
550}
551
552
554{
555 for( const std::unique_ptr<SYMBOL_EDITOR_TAB_CONTEXT>& ctx : m_tabContexts )
556 {
557 if( ctx.get() != m_activeTab && ctx->IsTransient() && ctx->IsModified() )
558 return true;
559 }
560
561 return false;
562}
563
564
566{
567 // Collect first; saving activates a tab, which mutates m_activeTab and m_tabContexts ordering.
568 std::vector<SYMBOL_EDITOR_TAB_CONTEXT*> dirty;
569
570 for( const std::unique_ptr<SYMBOL_EDITOR_TAB_CONTEXT>& ctx : m_tabContexts )
571 {
572 // The active tab and library tabs are handled by the existing close checks.
573 if( ctx.get() != m_activeTab && ctx->IsTransient() && ctx->IsModified() )
574 dirty.push_back( ctx.get() );
575 }
576
577 // Saving activates each dirty tab in turn; restore the tab the user was on so a vetoed close leaves
578 // the editor where it was and a successful close persists the real active tab, not a discarded one.
579 SYMBOL_EDITOR_TAB_CONTEXT* originalActive = m_activeTab;
580
581 for( SYMBOL_EDITOR_TAB_CONTEXT* ctx : dirty )
582 {
583 wxString msg = wxString::Format( _( "Save changes to '%s' before closing?" ), ctx->GetDisplayName() );
584
585 KIDIALOG dlg( this, msg, _( "Confirmation" ), wxYES_NO | wxCANCEL | wxICON_WARNING );
586 dlg.SetYesNoCancelLabels( _( "Save" ), _( "Discard Changes" ), _( "Cancel" ) );
587
588 const int answer = dlg.ShowModal();
589
590 if( answer == wxID_YES )
591 {
592 // saveCurrentSymbol saves the active tab via the mirrored frame state, so activate this
593 // one first; it clears the screen's modified flag on success.
594 activateSymbolTab( ctx );
595
596 if( !saveCurrentSymbol() )
597 {
598 activateSymbolTab( originalActive );
599 return false;
600 }
601 }
602 else if( answer != wxID_NO )
603 {
604 activateSymbolTab( originalActive );
605 return false;
606 }
607 }
608
609 activateSymbolTab( originalActive );
610
611 return true;
612}
613
614
616{
617 if( m_tabContexts.empty() )
618 return;
619
621
622 if( m_tabsPanel )
623 {
624 // Remove through the panel so its widget pages and the contexts stay in sync.
625 m_tabsPanel->CloseAll();
626 }
627
628 // Repoint the frame before the active tab's objects return to its soon-deleted context.
629 if( m_activeTab )
630 {
632 m_activeTab->AdoptWorkingObjects( m_symbol, static_cast<SCH_SCREEN*>( GetScreen() ) );
633 m_activeTab = nullptr;
634 m_symbol = nullptr;
636 }
637
638 // Free undo/redo for any contexts the panel path did not already close.
639 for( const std::unique_ptr<SYMBOL_EDITOR_TAB_CONTEXT>& ctx : m_tabContexts )
641
642 m_tabContexts.clear();
643
645}
646
647
649{
650 if( !m_tabsPanel )
651 return;
652
653 const wxString key = SYMBOL_EDITOR_TAB_CONTEXT::MakeTabKey( aLibId.GetLibNickname(), aLibId.GetLibItemName() );
654
655 const int idx = m_tabsPanel->FindTab( key );
656
657 if( idx < 0 )
658 return;
659
660 // The caller already confirmed the deletion, so close without re-prompting. The panel selects a
661 // successor tab when this was the active one.
663 m_tabsPanel->CloseTab( idx );
665}
666
667
668void SYMBOL_EDIT_FRAME::RenameSymbolTab( const LIB_ID& aOldId, const LIB_ID& aNewId )
669{
670 if( !m_tabsPanel )
671 return;
672
673 const wxString oldKey = SYMBOL_EDITOR_TAB_CONTEXT::MakeTabKey( aOldId.GetLibNickname(), aOldId.GetLibItemName() );
674
676 {
677 const wxString newName = aNewId.GetLibItemName();
678 const wxString newKey = SYMBOL_EDITOR_TAB_CONTEXT::MakeTabKey( aNewId.GetLibNickname(), newName );
679
680 ctx->SetName( newName );
681 m_tabsPanel->RenameTab( oldKey, newKey, newName );
682 }
683}
684
685
687{
688 wxLogTrace( wxT( "KICAD_TABS_DBG" ), wxT( "restoreSymbolTabsFromSettings enter" ) );
689
690 if( !m_tabsPanel || !m_settings )
691 return;
692
693 m_loadingSymbolTab = true;
694
695 wxString activeKey = m_settings->m_ActiveTabKey;
696 int activeIdx = -1;
697
698 for( const SYMBOL_EDITOR_SETTINGS::OPEN_TAB& tab : m_settings->m_OpenTabs )
699 {
700 if( !m_libMgr->LibraryExists( tab.lib ) || !m_libMgr->SymbolExists( tab.name, tab.lib ) )
701 {
702 wxLogTrace( "KICAD_TABS", "Dropping unresolved persisted symbol tab '%s:%s'.", tab.lib, tab.name );
703 continue;
704 }
705
707 findOrCreateSymbolTab( tab.lib, tab.name, tab.unit, tab.bodyStyle, tab.preview );
708
709 if( !ctx )
710 {
711 wxLogTrace( "KICAD_TABS", "Dropping persisted symbol tab '%s:%s'; buffer unavailable.", tab.lib, tab.name );
712 continue;
713 }
714
715 const int idx = m_tabsPanel->FindTab( ctx->GetTabKey() );
716
717 if( ctx->GetTabKey() == activeKey )
718 activeIdx = idx;
719 }
720
721 m_loadingSymbolTab = false;
722
723 if( activeIdx >= 0 )
724 m_tabsPanel->SelectTab( activeIdx );
725
726 wxLogTrace( wxT( "KICAD_TABS_DBG" ), wxT( "restoreSymbolTabsFromSettings exit (activeIdx=%d)" ), activeIdx );
727}
728
729
731{
732 if( !m_settings )
733 return;
734
735 m_settings->m_OpenTabs.clear();
736 m_settings->m_ActiveTabKey.clear();
737
738 for( const std::unique_ptr<SYMBOL_EDITOR_TAB_CONTEXT>& ctx : m_tabContexts )
739 {
740 // Instance tabs are session-only and never persisted.
741 if( ctx->IsTransient() )
742 continue;
743
745 tab.lib = ctx->GetLibrary();
746 tab.name = ctx->GetName();
747 tab.unit = ctx->GetUnit();
748 tab.bodyStyle = ctx->GetBodyStyle();
749
750 if( m_tabsPanel )
751 {
752 const int idx = m_tabsPanel->FindTab( ctx->GetTabKey() );
753 const std::vector<EDITOR_TABS_MODEL::ENTRY>& entries = m_tabsPanel->Model().Entries();
754
755 if( idx >= 0 && idx < static_cast<int>( entries.size() ) )
756 tab.preview = entries[idx].preview;
757 }
758
759 m_settings->m_OpenTabs.push_back( tab );
760 }
761
762 // Never restore an instance tab as the active tab, since it is not persisted.
763 if( m_activeTab && !m_activeTab->IsTransient() )
764 m_settings->m_ActiveTabKey = m_activeTab->GetTabKey();
765}
static TOOL_ACTION zoomFitScreen
Definition actions.h:138
static TOOL_ACTION selectionClear
Clear the current selection.
Definition actions.h:220
UNDO_REDO_CONTAINER m_undoList
virtual void ClearUndoRedoList()
Clear the undo and redo list using ClearUndoORRedoList()
UNDO_REDO_CONTAINER m_redoList
PROPERTIES_PANEL * m_propertiesPanel
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:98
bool HasFlag(EDA_ITEM_FLAGS aFlag) const
Definition eda_item.h:168
GUI-free preview/dirty/close state machine.
void MarkModified(const wxString &aKey, bool aModified)
Update the modified flag.
VIEW_SNAPSHOT & ViewSnapshot()
std::vector< KIID > & SavedSelection()
Selection saved as resolved KIIDs, restored after the view is rebuilt.
UNDO_REDO_CONTAINER & RedoList()
UNDO_REDO_CONTAINER & UndoList()
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
void HideDrawingSheet()
Definition sch_view.cpp:306
void ClearHiddenFlags()
Clear the hide flag of all items in the view.
Definition sch_view.cpp:294
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition view.h:63
Definition kiid.h:46
A logical library item identifier and consists of various portions much like a URI.
Definition lib_id.h:45
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
Define a library symbol object.
Definition lib_symbol.h:119
void SelectLibId(const LIB_ID &aLibId)
Select an item in the tree widget.
Definition lib_tree.cpp:371
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
SCH_RENDER_SETTINGS * GetRenderSettings()
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
SCH_DRAW_PANEL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
KIGFX::SCH_VIEW * GetView() const override
Return a pointer to the #VIEW instance used in the panel.
void DisplaySymbol(LIB_SYMBOL *aSymbol)
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:165
EE_RTREE & Items()
Get the full RTree, usually for iterating.
Definition sch_screen.h:118
SCH_SELECTION & GetSelection()
int AddItemToSel(const TOOL_EVENT &aEvent)
One open symbol tab owning a working LIB_SYMBOL and screen lent to the frame while active.
void ReleaseToFrame()
Hand the working symbol/screen to the frame as the tab becomes active.
wxString GetDisplayName() const override
Short label shown on the tab.
LIB_SYMBOL * GetSymbol() const
Observe the working symbol/screen.
const wxString & GetReference() const
static wxString MakeTabKey(const wxString &aLib, const wxString &aName)
De-duplication key for a library:symbol pair.
static wxString MakeInstanceTabKey(const KIID &aSchematicSymbolUUID)
De-duplication key for a placed schematic instance, in a namespace disjoint from library keys.
wxString GetTabKey() const override
Stable identity for persistence and de-duplication.
const KIID & GetSchematicSymbolUUID() const
bool IsModified() const override
True when the working screen carries unsaved edits.
void AdoptWorkingObjects(LIB_SYMBOL *aSymbol, SCH_SCREEN *aScreen)
Take ownership back on detach, capturing whatever the frame's symbol now points at.
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.
bool promptToSaveInactiveInstanceTabs()
Prompt to save each dirty instance (symbol from schematic) tab that is not the active one,...
bool hasDirtyInactiveInstanceTabs() const
True if any non-active instance (schematic) tab has unsaved edits.
bool IsLibraryTreeShown() const override
void RenameSymbolTab(const LIB_ID &aOldId, const LIB_ID &aNewId)
Update the open tab for aOldId, if any, to the renamed symbol aNewId so its label and key track the r...
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...
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 restoreSymbolSelectionKiids(const std::vector< KIID > &aKiids)
Reselect the items named by aKiids after a reload rebuilt the view.
static void clearTabModifiedState(SYMBOL_EDITOR_TAB_CONTEXT &aContext, EDITOR_TABS_MODEL &aModel)
Clear a tab's dirty state on both the context (read on repaint) and the strip model (read on close),...
void RebuildSymbolUnitAndBodyStyleLists()
void OnTabCharHook(wxKeyEvent &aEvent)
Cycle symbol tabs from the char hook, since GTK cannot register WXK_TAB as an accelerator.
LIB_SYMBOL_LIBRARY_MANAGER * m_libMgr
bool IsSymbolAlias() const
Return true if aLibId is an alias for the editor screen symbol.
SYMBOL_EDITOR_SETTINGS * m_settings
void dropSymbolTabContext(const wxString &aKey)
Drop the inactive context for aKey from m_tabContexts, freeing its undo/redo.
bool IsSymbolFromLegacyLibrary() const
bool IsSymbolFromSchematic() const
void SetScreen(BASE_SCREEN *aScreen) override
SYMBOL_EDITOR_TAB_CONTEXT * m_activeTab
SYMBOL_EDITOR_SETTINGS * GetSettings() const
SCH_SCREEN * m_dummyScreen
< Helper screen used when no symbol is loaded
KIID m_schematicSymbolUUID
RefDes of the symbol (only valid if symbol was loaded from schematic)
EDITOR_TAB_CONTEXT::VIEW_SNAPSHOT captureSymbolViewSnapshot() const
Capture the current view zoom/center for the active tab's snapshot.
void restoreSymbolViewSnapshot(const EDITOR_TAB_CONTEXT::VIEW_SNAPSHOT &aSnapshot)
Restore a previously captured view zoom/center.
SYMBOL_EDITOR_TAB_CONTEXT * findOrCreateSymbolTab(const wxString &aLib, const wxString &aName, int aUnit, int aBodyStyle, bool aAsPreview, bool *aWasCreated=nullptr)
Open aName from aLib in a tab, creating it when absent, and return the activated context.
SYMBOL_EDITOR_TAB_CONTEXT * symbolTabContextForKey(const wxString &aKey) const
Resolve the tab context for a tab key, or nullptr.
void storeSymbolTabsToSettings()
Write the current tab set into the editor settings for the next session.
void UpdateSymbolMsgPanelInfo()
Display the documentation of the selected symbol.
LIB_TREE * GetLibTree() const override
bool promptAndCloseSymbolTab(int aIdx)
Prompt for unsaved changes on the tab and drop its context.
SYMBOL_TREE_PANE * m_treePane
std::vector< KIID > captureSymbolSelectionKiids() const
Capture the KIIDs of the current selection for the active tab's snapshot.
void closeSymbolTab(const LIB_ID &aLibId)
Close the open tab for aLibId, if any, without prompting and leaving the other tabs open.
bool saveCurrentSymbol()
Rename LIB_SYMBOL aliases to avoid conflicts before adding a symbol to a library.
void clearSymbolTabsModifiedForLibrary(const wxString &aLibrary)
Clear the unsaved-edits flag on every tab in a saved library so its dirty indicator clears.
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 detachActiveSymbolTab()
Snapshot the active tab's view and selection into its context without deleting the document.
void activateSymbolTab(SYMBOL_EDITOR_TAB_CONTEXT *aContext)
Make aContext the active tab, borrowing its working symbol, undo/redo, view and selection,...
void closeAllSymbolTabsSilently()
Close every tab without prompting and return the frame to the empty state.
TOOL_MANAGER * m_toolManager
@ MODEL_RELOAD
Model changes (the sheet for a schematic)
Definition tool_base.h:76
A holder to handle a list of undo (or redo) commands.
std::vector< PICKED_ITEMS_LIST * > m_CommandsList
#define _(s)
#define UR_TRANSIENT
indicates the item is owned by the undo/redo stack
KIID niluuid(0)
View snapshot captured on detach, restored on activate.
One persisted open editor tab, restored on the next session.