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
81 : nullptr;
82
83 if( !selTool )
84 return kiids;
85
86 for( EDA_ITEM* item : selTool->GetSelection() )
87 {
88 if( item )
89 kiids.push_back( item->m_Uuid );
90 }
91
92 return kiids;
93}
94
95
96void SYMBOL_EDIT_FRAME::restoreSymbolSelectionKiids( const std::vector<KIID>& aKiids )
97{
98 if( aKiids.empty() )
99 return;
100
103 : nullptr;
104 SCH_SCREEN* screen = GetScreen();
105
106 if( !selTool || !screen )
107 return;
108
109 for( SCH_ITEM* item : screen->Items() )
110 {
111 for( const KIID& kiid : aKiids )
112 {
113 if( item->m_Uuid == kiid )
114 {
115 selTool->AddItemToSel( item, true );
116 break;
117 }
118 }
119 }
120}
121
122
124{
125 if( !m_activeTab )
126 return;
127
128 m_activeTab->ViewSnapshot() = captureSymbolViewSnapshot();
129 m_activeTab->SavedSelection() = captureSymbolSelectionKiids();
130 m_activeTab->SetUnit( m_unit );
131 m_activeTab->SetBodyStyle( m_bodyStyle );
132
133 // m_symbol may have been replaced by undo/redo since activation.
134 m_activeTab->AdoptWorkingObjects( m_symbol, static_cast<SCH_SCREEN*>( GetScreen() ) );
135
136 m_activeTab->UndoList().m_CommandsList.swap( m_undoList.m_CommandsList );
137 m_activeTab->RedoList().m_CommandsList.swap( m_redoList.m_CommandsList );
138}
139
140
142{
143 wxCHECK( m_toolManager, /* void */ );
144
145 if( !aContext )
146 return;
147
148 if( aContext == m_activeTab )
149 {
150 // Already active, but the caller may have requested a different unit/body style; apply it.
151 m_unit = aContext->GetUnit();
152 m_bodyStyle = aContext->GetBodyStyle();
153
158
161 GetCanvas()->Refresh();
162 return;
163 }
164
166 m_activeTab = aContext;
167
168 m_undoList.m_CommandsList.swap( aContext->UndoList().m_CommandsList );
169 m_redoList.m_CommandsList.swap( aContext->RedoList().m_CommandsList );
170
172
173 aContext->ReleaseToFrame();
174
175 // Restore the frame's schematic-source state from the incoming tab so the existing save path
176 // (SaveSymbolToSchematic vs the library) keys off the active tab, not whichever tab loaded last.
179 m_reference = aContext->GetReference();
180
181 m_symbol = aContext->GetSymbol();
182 m_unit = aContext->GetUnit();
183 m_bodyStyle = aContext->GetBodyStyle();
184
185 // Install the new screen before SetScreen, whose ResetTools would otherwise deref the freed one.
186 m_toolManager->SetEnvironment( aContext->GetScreen(), GetCanvas()->GetView(),
187 GetCanvas()->GetViewControls(), GetSettings(), this );
188 SetScreen( aContext->GetScreen() );
189
190 SetCurLib( aContext->GetLibrary() );
191
192 if( m_symbol )
193 {
194 wxLogTrace( wxT( "KICAD_TABS_DBG" ),
195 wxT( "activateSymbolTab SelectLibId '%s'" ),
196 m_symbol->GetLibId().Format().wx_str() );
197 GetLibTree()->SelectLibId( m_symbol->GetLibId() );
198 }
199
200 m_SyncPinEdit = m_symbol && m_symbol->IsRoot() && m_symbol->IsMultiUnit()
201 && !m_symbol->UnitsLocked();
202
203 m_toolManager->SetEnvironment( GetScreen(), GetCanvas()->GetView(),
204 GetCanvas()->GetViewControls(), GetSettings(), this );
205
210
214
215 // MODEL_RELOAD clears the selection, so restore the saved one afterwards.
217
218 if( aContext->ViewSnapshot().valid )
219 {
221 }
222 else
223 {
224 // First time this tab is shown there is no saved view
226 }
227
229
230 UpdateTitle();
232
234 m_propertiesPanel->UpdateData();
235
237 GetCanvas()->Refresh();
238}
239
240
241void SYMBOL_EDIT_FRAME::OnTabCharHook( wxKeyEvent& aEvent )
242{
243 // Only plain Ctrl+Tab and Ctrl+Shift+Tab are ours; anything else falls through.
244 const bool isTab = aEvent.GetKeyCode() == WXK_TAB;
245 const bool ctrlOnly = aEvent.ControlDown() && !aEvent.AltDown() && !aEvent.MetaDown();
246
247 // Ctrl+W closes the active tab while tabs are open, else falls through to close-window. The
248 // keycode arrives as 'W' or the control char 0x17 depending on platform, so accept both.
249 const int keyCode = aEvent.GetKeyCode();
250 const bool isCtrlW = ctrlOnly && !aEvent.ShiftDown()
251 && ( keyCode == 'W' || keyCode == ( 'W' - '@' ) );
252
253 if( isCtrlW && m_tabsPanel && m_tabsPanel->Model().Entries().size() >= 1 )
254 {
255 // Route through CloseTab so the unsaved-changes prompt still runs.
256 m_tabsPanel->CloseTab( m_tabsPanel->GetActiveTab() );
257 return;
258 }
259
260 if( !isTab || !ctrlOnly || !m_tabsPanel )
261 {
262 aEvent.Skip();
263 return;
264 }
265
266 m_tabsPanel->AdvanceTab( !aEvent.ShiftDown() );
267
268 // Consume the event so GTK's default Tab focus-traversal does not also run.
269}
270
271
273 const LIB_SYMBOL* aLiveSymbol )
274{
275 for( PICKED_ITEMS_LIST* cmd : aList.m_CommandsList )
276 {
277 // The undo copy is the picked ITEM flagged UR_TRANSIENT, not the wrapper, so the shared
278 // deleters skip it. Free exactly the items that carry UR_TRANSIENT here.
279 for( unsigned ii = 0; ii < cmd->GetCount(); ++ii )
280 {
281 EDA_ITEM* item = cmd->GetPickedItem( ii );
282
283 if( !item || !item->HasFlag( UR_TRANSIENT ) )
284 continue;
285
286 // The live working symbol clears UR_TRANSIENT when it becomes m_symbol; guard anyway
287 // against a double-free of the live symbol.
288 wxCHECK2_MSG( item != aLiveSymbol, continue,
289 wxT( "Live working symbol flagged UR_TRANSIENT in undo/redo list" ) );
290
291 delete item;
292 }
293
294 cmd->ClearItemsList();
295 delete cmd;
296 }
297
298 aList.m_CommandsList.clear();
299}
300
301
303{
304 // The context is detached here, so no undo copy is the live working object.
305 freeTransientUndoCommands( aContext.UndoList(), nullptr );
306 freeTransientUndoCommands( aContext.RedoList(), nullptr );
307}
308
309
311 EDITOR_TABS_MODEL& aModel )
312{
313 // An active tab's screen aliases the frame's current screen, so this clears the live flag too.
314 if( SCH_SCREEN* screen = aContext.GetScreen() )
315 screen->SetContentModified( false );
316
317 aModel.MarkModified( aContext.GetTabKey(), false );
318}
319
320
322{
323 for( const std::unique_ptr<SYMBOL_EDITOR_TAB_CONTEXT>& ctx : m_tabContexts )
324 {
325 if( ctx->GetLibrary() != aLibrary )
326 continue;
327
328 if( m_tabsPanel )
329 clearTabModifiedState( *ctx, m_tabsPanel->MutableModel() );
330 else if( SCH_SCREEN* screen = ctx->GetScreen() )
331 screen->SetContentModified( false );
332 }
333
334 // The strip queries the dirty flag only on repaint, so without this the cleared asterisk lingers
335 // until the next stray paint event reaches the tab the user was on.
336 if( m_tabsPanel )
337 m_tabsPanel->RefreshTabLabels();
338}
339
340
342{
343 for( const std::unique_ptr<SYMBOL_EDITOR_TAB_CONTEXT>& ctx : m_tabContexts )
344 {
345 if( ctx->GetTabKey() == aKey )
346 return ctx.get();
347 }
348
349 return nullptr;
350}
351
352
353void SYMBOL_EDIT_FRAME::dropSymbolTabContext( const wxString& aKey )
354{
356
357 // The active context is still on screen and owned by the frame, so never drop it here; only an
358 // evicted, inactive preview reaches this path.
359 if( !ctx || ctx == m_activeTab )
360 return;
361
363
364 std::erase_if( m_tabContexts,
365 [ctx]( const std::unique_ptr<SYMBOL_EDITOR_TAB_CONTEXT>& aOwned )
366 {
367 return aOwned.get() == ctx;
368 } );
369}
370
371
373{
374 if( !m_tabsPanel )
375 return nullptr;
376
377 const std::vector<EDITOR_TABS_MODEL::ENTRY>& entries = m_tabsPanel->Model().Entries();
378
379 if( aIdx < 0 || aIdx >= static_cast<int>( entries.size() ) )
380 return nullptr;
381
382 return symbolTabContextForKey( entries[aIdx].key );
383}
384
385
387 const wxString& aName,
388 int aUnit, int aBodyStyle,
389 bool aAsPreview,
390 bool* aWasCreated )
391{
392 const wxString key = SYMBOL_EDITOR_TAB_CONTEXT::MakeTabKey( aLib, aName );
393 const int unit = aUnit > 0 ? aUnit : 1;
394 const int bodyStyle = aBodyStyle > 0 ? aBodyStyle : 1;
395
397
398 if( aWasCreated )
399 *aWasCreated = false;
400
401 if( !ctx )
402 {
403 SYMBOL_BUFFER* buffer = m_libMgr ? m_libMgr->GetBuffer( aName, aLib ) : nullptr;
404
405 if( !buffer )
406 return nullptr;
407
408 m_tabContexts.push_back(
409 std::make_unique<SYMBOL_EDITOR_TAB_CONTEXT>( aLib, aName, buffer ) );
410 ctx = m_tabContexts.back().get();
411
412 if( aWasCreated )
413 *aWasCreated = true;
414 }
415
416 ctx->SetUnit( unit );
417 ctx->SetBodyStyle( bodyStyle );
418
419 if( m_tabsPanel )
420 {
421 // A previewed open reuses the existing preview slot in the panel instead of adding a tab.
422 // The panel drops the evicted key from its model, but the matching context lingers in
423 // m_tabContexts and would be persisted as a phantom tab, so capture the evicted key and drop
424 // its context once the reuse completes.
425 wxString replacedKey;
426
427 if( aAsPreview )
428 {
429 const std::vector<EDITOR_TABS_MODEL::ENTRY>& entries = m_tabsPanel->Model().Entries();
430 const int previewIdx = m_tabsPanel->Model().PreviewIndex();
431
432 if( previewIdx >= 0 && previewIdx < static_cast<int>( entries.size() )
433 && entries[previewIdx].key != key )
434 {
435 replacedKey = entries[previewIdx].key;
436 }
437 }
438
439 m_tabsPanel->AddTab( key, aName, aAsPreview );
440
441 if( !replacedKey.empty() )
442 dropSymbolTabContext( replacedKey );
443 }
444 else
445 {
446 activateSymbolTab( ctx );
447 }
448
449 return ctx;
450}
451
452
455 const KIID& aSchematicSymbolUUID,
456 const wxString& aReference, int aUnit,
457 int aBodyStyle )
458{
459 const wxString key = SYMBOL_EDITOR_TAB_CONTEXT::MakeInstanceTabKey( aSchematicSymbolUUID );
460 const int unit = aUnit > 0 ? aUnit : 1;
461 const int bodyStyle = aBodyStyle > 0 ? aBodyStyle : 1;
462
464 {
465 // Re-editing the same placed symbol focuses the live tab, so free the redundant new objects.
466 delete aSymbol;
467 delete aScreen;
468
469 existing->SetUnit( unit );
470 existing->SetBodyStyle( bodyStyle );
471
472 if( m_tabsPanel )
473 m_tabsPanel->AddTab( key, existing->GetReference(), false );
474 else
475 activateSymbolTab( existing );
476
477 return existing;
478 }
479
480 m_tabContexts.push_back( std::make_unique<SYMBOL_EDITOR_TAB_CONTEXT>(
481 aSymbol, aScreen, aSchematicSymbolUUID, aReference ) );
482 SYMBOL_EDITOR_TAB_CONTEXT* ctx = m_tabContexts.back().get();
483
484 ctx->SetUnit( unit );
485 ctx->SetBodyStyle( bodyStyle );
486
487 if( m_tabsPanel )
488 m_tabsPanel->AddTab( key, aReference, false );
489 else
490 activateSymbolTab( ctx );
491
492 return ctx;
493}
494
495
497{
499
500 if( !ctx )
501 return true;
502
503 if( ctx->IsModified() && !m_silentSymbolTabClose )
504 {
505 wxString msg = wxString::Format( _( "Save changes to '%s' before closing?" ),
506 ctx->GetDisplayName() );
507
508 KIDIALOG dlg( this, msg, _( "Confirmation" ), wxYES_NO | wxCANCEL | wxICON_WARNING );
509 dlg.SetYesNoCancelLabels( _( "Save" ), _( "Discard Changes" ), _( "Cancel" ) );
510
511 switch( dlg.ShowModal() )
512 {
513 case wxID_YES:
514 // saveCurrentSymbol operates on the active tab, so activate this one first to save it.
515 if( ctx != m_activeTab )
516 activateSymbolTab( ctx );
517
518 if( !saveCurrentSymbol() )
519 return false;
520
521 if( IsLibraryTreeShown() )
522 m_treePane->GetLibTree()->RefreshLibTree();
523
524 UpdateTitle();
525 break;
526
527 case wxID_NO:
528 break;
529
530 default:
531 return false;
532 }
533 }
534
535 // If this is the active tab the frame holds its objects, so repoint at the dummy screen and drop
536 // m_symbol before destroying the context, then let the context free them once.
537 if( ctx == m_activeTab )
538 {
539 // Clear the frame's undo/redo so nothing references the about-to-be-deleted working symbol.
541 ctx->AdoptWorkingObjects( m_symbol, static_cast<SCH_SCREEN*>( GetScreen() ) );
542
543 m_activeTab = nullptr;
544 m_symbol = nullptr;
546
547 // Clear the mirrored schematic-source state so the frame no longer looks like it holds an
548 // instance symbol; a successor tab's activateSymbolTab restores these from its own context.
551 m_reference = wxEmptyString;
552 }
553 else
554 {
555 // An inactive tab's undo/redo still holds transient copies; free them before destroying it.
557 }
558
559 std::erase_if( m_tabContexts,
560 [ctx]( const std::unique_ptr<SYMBOL_EDITOR_TAB_CONTEXT>& aOwned )
561 {
562 return aOwned.get() == ctx;
563 } );
564
565 return true;
566}
567
568
570{
571 for( const std::unique_ptr<SYMBOL_EDITOR_TAB_CONTEXT>& ctx : m_tabContexts )
572 {
573 if( ctx.get() != m_activeTab && ctx->IsTransient() && ctx->IsModified() )
574 return true;
575 }
576
577 return false;
578}
579
580
582{
583 // Collect first; saving activates a tab, which mutates m_activeTab and m_tabContexts ordering.
584 std::vector<SYMBOL_EDITOR_TAB_CONTEXT*> dirty;
585
586 for( const std::unique_ptr<SYMBOL_EDITOR_TAB_CONTEXT>& ctx : m_tabContexts )
587 {
588 // The active tab and library tabs are handled by the existing close checks.
589 if( ctx.get() != m_activeTab && ctx->IsTransient() && ctx->IsModified() )
590 dirty.push_back( ctx.get() );
591 }
592
593 // Saving activates each dirty tab in turn; restore the tab the user was on so a vetoed close leaves
594 // the editor where it was and a successful close persists the real active tab, not a discarded one.
595 SYMBOL_EDITOR_TAB_CONTEXT* originalActive = m_activeTab;
596
597 for( SYMBOL_EDITOR_TAB_CONTEXT* ctx : dirty )
598 {
599 wxString msg = wxString::Format( _( "Save changes to '%s' before closing?" ),
600 ctx->GetDisplayName() );
601
602 KIDIALOG dlg( this, msg, _( "Confirmation" ), wxYES_NO | wxCANCEL | wxICON_WARNING );
603 dlg.SetYesNoCancelLabels( _( "Save" ), _( "Discard Changes" ), _( "Cancel" ) );
604
605 const int answer = dlg.ShowModal();
606
607 if( answer == wxID_YES )
608 {
609 // saveCurrentSymbol saves the active tab via the mirrored frame state, so activate this
610 // one first; it clears the screen's modified flag on success.
611 activateSymbolTab( ctx );
612
613 if( !saveCurrentSymbol() )
614 {
615 activateSymbolTab( originalActive );
616 return false;
617 }
618 }
619 else if( answer != wxID_NO )
620 {
621 activateSymbolTab( originalActive );
622 return false;
623 }
624 }
625
626 activateSymbolTab( originalActive );
627
628 return true;
629}
630
631
633{
634 if( m_tabContexts.empty() )
635 return;
636
638
639 if( m_tabsPanel )
640 {
641 // Remove through the panel so its widget pages and the contexts stay in sync.
642 m_tabsPanel->CloseAll();
643 }
644
645 // Repoint the frame before the active tab's objects return to its soon-deleted context.
646 if( m_activeTab )
647 {
649 m_activeTab->AdoptWorkingObjects( m_symbol, static_cast<SCH_SCREEN*>( GetScreen() ) );
650 m_activeTab = nullptr;
651 m_symbol = nullptr;
653 }
654
655 // Free undo/redo for any contexts the panel path did not already close.
656 for( const std::unique_ptr<SYMBOL_EDITOR_TAB_CONTEXT>& ctx : m_tabContexts )
658
659 m_tabContexts.clear();
660
662}
663
664
666{
667 if( !m_tabsPanel )
668 return;
669
670 const wxString key = SYMBOL_EDITOR_TAB_CONTEXT::MakeTabKey( aLibId.GetLibNickname(), aLibId.GetLibItemName() );
671
672 const int idx = m_tabsPanel->FindTab( key );
673
674 if( idx < 0 )
675 return;
676
677 // The caller already confirmed the deletion, so close without re-prompting. The panel selects a
678 // successor tab when this was the active one.
680 m_tabsPanel->CloseTab( idx );
682}
683
684
685void SYMBOL_EDIT_FRAME::RenameSymbolTab( const LIB_ID& aOldId, const LIB_ID& aNewId )
686{
687 if( !m_tabsPanel )
688 return;
689
690 const wxString oldKey = SYMBOL_EDITOR_TAB_CONTEXT::MakeTabKey( aOldId.GetLibNickname(), aOldId.GetLibItemName() );
691
693 {
694 const wxString newName = aNewId.GetLibItemName();
695 const wxString newKey = SYMBOL_EDITOR_TAB_CONTEXT::MakeTabKey( aNewId.GetLibNickname(), newName );
696
697 ctx->SetName( newName );
698 m_tabsPanel->RenameTab( oldKey, newKey, newName );
699 UpdateTitle();
700 }
701}
702
703
705{
706 wxLogTrace( wxT( "KICAD_TABS_DBG" ), wxT( "restoreSymbolTabsFromSettings enter" ) );
707
708 if( !m_tabsPanel || !m_settings )
709 return;
710
711 m_loadingSymbolTab = true;
712
713 wxString activeKey = m_settings->m_ActiveTabKey;
714 int activeIdx = -1;
715
716 for( const SYMBOL_EDITOR_SETTINGS::OPEN_TAB& tab : m_settings->m_OpenTabs )
717 {
718 if( !m_libMgr->LibraryExists( tab.lib )
719 || !m_libMgr->SymbolExists( tab.name, tab.lib ) )
720 {
721 wxLogTrace( "KICAD_TABS", "Dropping unresolved persisted symbol tab '%s:%s'.",
722 tab.lib, tab.name );
723 continue;
724 }
725
727 findOrCreateSymbolTab( tab.lib, tab.name, tab.unit, tab.bodyStyle, tab.preview );
728
729 if( !ctx )
730 {
731 wxLogTrace( "KICAD_TABS", "Dropping persisted symbol tab '%s:%s'; buffer unavailable.",
732 tab.lib, tab.name );
733 continue;
734 }
735
736 const int idx = m_tabsPanel->FindTab( ctx->GetTabKey() );
737
738 if( ctx->GetTabKey() == activeKey )
739 activeIdx = idx;
740 }
741
742 m_loadingSymbolTab = false;
743
744 if( activeIdx >= 0 )
745 m_tabsPanel->SelectTab( activeIdx );
746
747 wxLogTrace( wxT( "KICAD_TABS_DBG" ), wxT( "restoreSymbolTabsFromSettings exit (activeIdx=%d)" ),
748 activeIdx );
749}
750
751
753{
754 if( !m_settings )
755 return;
756
757 m_settings->m_OpenTabs.clear();
758 m_settings->m_ActiveTabKey.clear();
759
760 for( const std::unique_ptr<SYMBOL_EDITOR_TAB_CONTEXT>& ctx : m_tabContexts )
761 {
762 // Instance tabs are session-only and never persisted.
763 if( ctx->IsTransient() )
764 continue;
765
767 tab.lib = ctx->GetLibrary();
768 tab.name = ctx->GetName();
769 tab.unit = ctx->GetUnit();
770 tab.bodyStyle = ctx->GetBodyStyle();
771
772 if( m_tabsPanel )
773 {
774 const int idx = m_tabsPanel->FindTab( ctx->GetTabKey() );
775 const std::vector<EDITOR_TABS_MODEL::ENTRY>& entries = m_tabsPanel->Model().Entries();
776
777 if( idx >= 0 && idx < static_cast<int>( entries.size() ) )
778 tab.preview = entries[idx].preview;
779 }
780
781 m_settings->m_OpenTabs.push_back( tab );
782 }
783
784 // Never restore an instance tab as the active tab, since it is not persisted.
785 if( m_activeTab && !m_activeTab->IsTransient() )
786 m_settings->m_ActiveTabKey = m_activeTab->GetTabKey();
787}
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:96
bool HasFlag(EDA_ITEM_FLAGS aFlag) const
Definition eda_item.h:156
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:44
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:80
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:162
EE_RTREE & Items()
Get the full RTree, usually for iterating.
Definition sch_screen.h:115
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.
const wxString & GetLibrary() const
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 (schematic) tab that is not the active one, since the active tab's...
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
bool m_SyncPinEdit
Set to true to synchronize pins at the same position when editing symbols with multiple units or mult...
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.
int m_bodyStyle
Flag if the symbol being edited was loaded directly from a schematic.
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 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()
Store the currently modified symbol in the library manager buffer.
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.