From 84438143e629905ff798c35813e62bde46554229 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 16 Mar 2025 04:36:47 +0100 Subject: [PATCH] Save and restore the active tab control page too It can be useful to preserve the last selected page -- and if the application doesn't want to do it, it can avoid it by not saving wxAuiTabLayoutInfo::active. --- include/wx/aui/serializer.h | 3 ++ interface/wx/aui/serializer.h | 9 ++++++ samples/aui/auidemo.cpp | 5 +++ src/aui/auibook.cpp | 57 ++++++++++++++++++++++++++--------- 4 files changed, 59 insertions(+), 15 deletions(-) diff --git a/include/wx/aui/serializer.h b/include/wx/aui/serializer.h index 9004fcb160..66927bbbfc 100644 --- a/include/wx/aui/serializer.h +++ b/include/wx/aui/serializer.h @@ -55,6 +55,9 @@ struct wxAuiTabLayoutInfo : wxAuiDockLayoutInfo // them can be empty. std::vector locked; std::vector pinned; + + // Currently active page in this tab control. + int active = 0; }; // This struct contains the pane name and information about its layout that can diff --git a/interface/wx/aui/serializer.h b/interface/wx/aui/serializer.h index 99cde53997..399b701ee0 100644 --- a/interface/wx/aui/serializer.h +++ b/interface/wx/aui/serializer.h @@ -74,6 +74,15 @@ struct wxAuiTabLayoutInfo : wxAuiDockLayoutInfo This vector can be empty if there are no pinned pages. */ std::vector pinned; + + /** + Index of the currently selected page in this tab control. + + Note that the value of this field is a page index in the notebook, not + the position of the active tab in this tab control, and should be one + of the elements of the `pages` vector if it is not empty. + */ + int active = 0; }; /** diff --git a/samples/aui/auidemo.cpp b/samples/aui/auidemo.cpp index 03642afdcb..9fded94621 100644 --- a/samples/aui/auidemo.cpp +++ b/samples/aui/auidemo.cpp @@ -1693,6 +1693,7 @@ public: AddPagesList(node, "pages", tab.pages); AddPagesList(node, "pinned", tab.pinned); AddPagesList(node, "locked", tab.locked); + AddChild(node, "active", tab.active); m_book->AddChild(node); } @@ -2049,6 +2050,10 @@ private: for ( const auto& s : pageIndices ) tab.locked.push_back(GetInt(s)); } + else if ( child->GetName() == "active" ) + { + tab.active = GetInt(child->GetNodeContent()); + } else { throw std::runtime_error("Unexpected tab child node name"); diff --git a/src/aui/auibook.cpp b/src/aui/auibook.cpp index 91cdf57d02..0c3fe4c5a8 100644 --- a/src/aui/auibook.cpp +++ b/src/aui/auibook.cpp @@ -2397,10 +2397,9 @@ void wxAuiNotebook::InsertPageAt(wxAuiNotebookPage& info, page->Reparent(this); // if there are currently no tabs, the first added - // tab must be active and selected, even if "select" is false + // tab must be selected, even if "select" is false if (m_tabs.GetPageCount() == 0) { - info.active = true; select = true; } @@ -4193,8 +4192,6 @@ int wxAuiNotebook::DoModifySelection(size_t n, bool events) if ( const auto tabInfo = FindTab(wnd) ) { - m_tabs.SetActivePage(wnd); - wxAuiTabCtrl* const ctrl = tabInfo.tabCtrl; ctrl->SetActivePage(tabInfo.tabIdx); @@ -4273,6 +4270,8 @@ wxAuiNotebook::SaveLayout(const wxString& name, const wxAuiTabCtrl* const tabCtrl = static_cast(pane.window)->m_tabs; + tab.active = tabCtrl->GetActivePage(); + // As an optimization, don't bother with saving the pages order for the // main control if it hasn't been changed from the default. bool mustSavePages = false; @@ -4353,6 +4352,9 @@ wxAuiNotebook::LoadLayout(const wxString& name, // we may not have to do anything at all. bool useExistingPages = false; + // Remember the active page in the main tab control if we change it. + const wxWindow* activeInMainTab = nullptr; + // Keep track of pages we've already added to some tab control: even if the // deserialized data is somehow incorrect and duplicates the page indices, // we don't want to try to have the same page in more than one tab control. @@ -4391,7 +4393,10 @@ wxAuiNotebook::LoadLayout(const wxString& name, if ( useExistingPages ) { // All pages are in the main tab in the default order - // already, so we don't have anything to do. + // already, so we don't have anything to do except + // restoring the active page -- which is in this case the + // same as selection (tab indices == notebook indices). + SetSelection(tab.active); break; } @@ -4436,7 +4441,7 @@ wxAuiNotebook::LoadLayout(const wxString& name, } // In any case, add the pages that this tab control had before to it. - bool first = true; + const wxWindow* activeWindow = nullptr; for ( auto page : *pages ) { // We just silently ignore invalid or duplicate page indices @@ -4450,17 +4455,27 @@ wxAuiNotebook::LoadLayout(const wxString& name, auto info = m_tabs.GetPage(page); - // We don't save the last active page currently, so just make the - // first one active. - if ( first ) - { - info.active = true; - first = false; - } + if ( page == tab.active ) + activeWindow = info.window; tabCtrl->AddPage(info); } + if ( !activeWindow ) + { + // We must have some active page, so make the first one active if + // the deserialized data didn't define a valid active page. + activeWindow = tabCtrl->GetWindowFromIdx(0); + } + + tabCtrl->SetActivePage(activeWindow); + + if ( tabCtrl == tabMain ) + { + // Remember it to set the selection to it below. + activeInMainTab = activeWindow; + } + // Check if the element is present in the vector: we could convert // vectors to sets first, but considering that they should normally be // pretty small (how many pinned pages can there possibly be?), it @@ -4485,8 +4500,6 @@ wxAuiNotebook::LoadLayout(const wxString& name, SetPageKind(i, kind); } - - tabCtrl->DoUpdateActive(); } // Check if there were any existing pages not added to any tab control. @@ -4552,6 +4565,20 @@ wxAuiNotebook::LoadLayout(const wxString& name, RemoveEmptyTabFrames(); } + // Update the active pages visibility in all tab controls after adding and + // removing all the pages. + for ( auto tabCtrl : GetAllTabCtrls() ) + { + tabCtrl->DoUpdateActive(); + } + + // We don't save information about the currently focused tab control, so + // always make the main one active after loading the layout by setting the + // selected page to the page active in it (if there is no such page, it + // means we're reusing the existing pages and so don't need to do anything). + if ( activeInMainTab ) + m_curPage = m_tabs.GetIdxFromWindow(activeInMainTab); + m_mgr.Update(); }