mirror of
https://github.com/wxWidgets/wxWidgets.git
synced 2026-09-29 10:25:27 +08:00
Add support for saving and restoring wxAuiNotebook layout
This includes multiple tab controls and pages order and uses new wxAuiSerializer and wxAuiDeserializer notebook-specific functions. These functions are pure virtual, which may be inconvenient if the program doesn't use wxAuiNotebook at all or doesn't allow splitting or reordering their pages, as it forces to still define them in this case, but this is arguably not too burdensome and making them pure virtual helps to attract attention to the fact that they need to be implemented for saving notebook layouts. Update the sample to show how to support notebook layout serialization in the simplest possible way, by creating a separate top-level XML tag for the notebooks. It could be tidier to put information about them inside the corresponding pane tags, but doing it like this is simpler and more clear, which is important for the sample code. Closes #24950.
This commit is contained in:
@@ -26,6 +26,9 @@
|
||||
#include "wx/compositebookctrl.h"
|
||||
|
||||
|
||||
class wxAuiSerializer;
|
||||
class wxAuiDeserializer;
|
||||
|
||||
class wxAuiNotebook;
|
||||
class wxAuiTabFrame;
|
||||
|
||||
@@ -432,6 +435,11 @@ public:
|
||||
// Internal, don't use: use GetPagePosition() instead.
|
||||
bool FindTab(wxWindow* page, wxAuiTabCtrl** ctrl, int* idx) const;
|
||||
|
||||
// Serialization support: this is only used by wxAuiManager, don't use
|
||||
// directly.
|
||||
void SaveLayout(const wxString& name, wxAuiSerializer& serializer) const;
|
||||
void LoadLayout(const wxString& name, wxAuiDeserializer& deserializer);
|
||||
|
||||
protected:
|
||||
// Common part of all ctors.
|
||||
void Init();
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
// Classes used to save/load wxAuiManager layout.
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Fields common to wxAuiPaneLayoutInfo and wxAuiTabLayoutInfo containing
|
||||
// information about a docked pane or tab layout.
|
||||
struct wxAuiDockLayoutInfo
|
||||
{
|
||||
// Identifies the dock containing the pane.
|
||||
@@ -33,6 +35,15 @@ struct wxAuiDockLayoutInfo
|
||||
int dock_size = 0;
|
||||
};
|
||||
|
||||
// This struct contains information about the layout of a tab control in a
|
||||
// wxAuiNotebook, including where it is docked and the order of pages in it.
|
||||
struct wxAuiTabLayoutInfo : wxAuiDockLayoutInfo
|
||||
{
|
||||
// If this vector is empty, it means that the tab control contains all
|
||||
// notebook pages in natural order.
|
||||
std::vector<int> pages;
|
||||
};
|
||||
|
||||
// This struct contains the pane name and information about its layout that can
|
||||
// be manipulated by the user interactively.
|
||||
struct wxAuiPaneLayoutInfo : wxAuiDockLayoutInfo
|
||||
@@ -87,6 +98,25 @@ public:
|
||||
// Called after the last call to SavePane(), does nothing by default.
|
||||
virtual void AfterSavePanes() { }
|
||||
|
||||
// Called before starting to save information about the notebooks, does
|
||||
// nothing by default.
|
||||
virtual void BeforeSaveNotebooks() { }
|
||||
|
||||
// Called before starting to save information about the tabs in the
|
||||
// notebook in the AUI pane with the given name.
|
||||
virtual void BeforeSaveNotebook(const wxString& name) = 0;
|
||||
|
||||
// Called to save information about a single tab control in the given
|
||||
// notebook.
|
||||
virtual void SaveNotebookTabControl(const wxAuiTabLayoutInfo& tab) = 0;
|
||||
|
||||
// Called after saving information about all the pages of the notebook in
|
||||
// the AUI pane with the given name, does nothing by default.
|
||||
virtual void AfterSaveNotebook() { }
|
||||
|
||||
// Called after the last call to SaveNotebook(), does nothing by default.
|
||||
virtual void AfterSaveNotebooks() { }
|
||||
|
||||
// Called after saving everything, does nothing by default.
|
||||
virtual void AfterSave() { }
|
||||
};
|
||||
@@ -116,6 +146,11 @@ public:
|
||||
// Load information about all the panes previously saved with SavePane().
|
||||
virtual std::vector<wxAuiPaneLayoutInfo> LoadPanes() = 0;
|
||||
|
||||
// For a pane containing wxAuiNotebook, load information about all the tab
|
||||
// controls inside it.
|
||||
virtual std::vector<wxAuiTabLayoutInfo>
|
||||
LoadNotebookTabs(const wxString& name) = 0;
|
||||
|
||||
// Create the window to be managed by the given pane: this is called if any
|
||||
// of the panes returned by LoadPanes() doesn't exist in the existing
|
||||
// layout and allows to create windows on the fly.
|
||||
|
||||
+110
-15
@@ -8,25 +8,16 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
Description of user-modifiable pane layout information.
|
||||
Description of a docked element layout.
|
||||
|
||||
This struct is used with wxAuiSerializer and wxAuiDeserializer to store the
|
||||
pane layout. Its fields have the same meaning as the corresponding fields
|
||||
in wxAuiPaneInfo (with the exception of `is_maximized`), but it doesn't
|
||||
contain the fields that it wouldn't make sense to serialize.
|
||||
The fields in this struct are shared by wxAuiPaneLayoutInfo and
|
||||
wxAuiTabLayoutInfo and contain information about the layout of a docked
|
||||
pane or tab layout.
|
||||
|
||||
@since 3.3.0
|
||||
*/
|
||||
struct wxAuiPaneLayoutInfo
|
||||
*/
|
||||
struct wxAuiDockLayoutInfo
|
||||
{
|
||||
/**
|
||||
Ctor sets the name, which is always required.
|
||||
*/
|
||||
explicit wxAuiPaneLayoutInfo(wxString name);
|
||||
|
||||
/// Unique name of the pane.
|
||||
wxString name;
|
||||
|
||||
/// Direction of the dock containing the pane.
|
||||
int dock_direction = wxAUI_DOCK_LEFT;
|
||||
|
||||
@@ -44,7 +35,47 @@ struct wxAuiPaneLayoutInfo
|
||||
|
||||
/// Size of the containing dock.
|
||||
int dock_size = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
Contains information about the layout of a tab control in a wxAuiNotebook.
|
||||
|
||||
This includes where it is docked, via the fields inherited from
|
||||
wxAuiDockLayoutInfo, and the order of pages in it.
|
||||
|
||||
@since 3.3.0
|
||||
*/
|
||||
struct wxAuiTabLayoutInfo : wxAuiDockLayoutInfo
|
||||
{
|
||||
/**
|
||||
Indices of the pages in this tab control in their order on screen.
|
||||
|
||||
If this vector is empty, it means that the tab control contains all
|
||||
notebook pages in natural order.
|
||||
*/
|
||||
std::vector<int> pages;
|
||||
};
|
||||
|
||||
/**
|
||||
Description of user-modifiable pane layout information.
|
||||
|
||||
This struct is used with wxAuiSerializer and wxAuiDeserializer to store the
|
||||
pane layout. Its fields, including the inherited ones from
|
||||
wxAuiDockLayoutInfo, have the same meaning as the corresponding fields in
|
||||
wxAuiPaneInfo (with the exception of `is_maximized`), but it doesn't
|
||||
contain the fields that it wouldn't make sense to serialize.
|
||||
|
||||
@since 3.3.0
|
||||
*/
|
||||
struct wxAuiPaneLayoutInfo : wxAuiDockLayoutInfo
|
||||
{
|
||||
/**
|
||||
Ctor sets the name, which is always required.
|
||||
*/
|
||||
explicit wxAuiPaneLayoutInfo(wxString name);
|
||||
|
||||
/// Unique name of the pane.
|
||||
wxString name;
|
||||
|
||||
/// Position of the pane when floating, may be invalid.
|
||||
wxPoint floating_pos = wxDefaultPosition;
|
||||
@@ -126,6 +157,57 @@ public:
|
||||
*/
|
||||
virtual void AfterSavePanes();
|
||||
|
||||
/**
|
||||
Called before starting to save information about the notebooks.
|
||||
|
||||
Does nothing by default.
|
||||
|
||||
Note that this function is called after AfterSavePanes() but may not be
|
||||
called at all if there are no panes containing wxAuiNotebook.
|
||||
*/
|
||||
virtual void BeforeSaveNotebooks();
|
||||
|
||||
/**
|
||||
Called before starting to save information about the tabs in the
|
||||
notebook in the AUI pane with the given name.
|
||||
|
||||
This function needs to be overridden to keep record of the notebook for
|
||||
which SaveNotebookTabControl() will be called next. Of course, if
|
||||
saving notebook layout is unnecessary, e.g. because the program doesn't
|
||||
use wxAuiNotebook at all, the implementation can be trivial and just do
|
||||
nothing.
|
||||
|
||||
This function is called one or more times after BeforeSaveNotebooks().
|
||||
*/
|
||||
virtual void BeforeSaveNotebook(const wxString& name) = 0;
|
||||
|
||||
/**
|
||||
Called to save information about a single tab control in the given
|
||||
notebook.
|
||||
|
||||
This function will be called for all tab controls in the notebook after
|
||||
BeforeSaveNotebook().
|
||||
|
||||
As with that function, it has to be implemented, but can simply do
|
||||
nothing if saving notebook layout is not necessary.
|
||||
*/
|
||||
virtual void SaveNotebookTabControl(const wxAuiTabLayoutInfo& tab) = 0;
|
||||
|
||||
/**
|
||||
Called after saving information about all the pages of the notebook in
|
||||
the AUI pane with the given name.
|
||||
|
||||
Does nothing by default.
|
||||
*/
|
||||
virtual void AfterSaveNotebook();
|
||||
|
||||
/**
|
||||
Called after the last call to SaveNotebook().
|
||||
|
||||
Does nothing by default.
|
||||
*/
|
||||
virtual void AfterSaveNotebooks();
|
||||
|
||||
/**
|
||||
Called after saving everything.
|
||||
|
||||
@@ -190,6 +272,19 @@ public:
|
||||
*/
|
||||
virtual std::vector<wxAuiPaneInfo> LoadPanes() = 0;
|
||||
|
||||
/**
|
||||
Load information about the notebook tabs previously saved by
|
||||
wxAuiSerializer::SaveNotebookTabControl().
|
||||
|
||||
The pane with the name @a name is guaranteed to exist in the layout and
|
||||
have wxAuiNotebook as the associated window.
|
||||
|
||||
If restoring the notebook layout is not necessary, this function can
|
||||
just return an empty vector.
|
||||
*/
|
||||
virtual std::vector<wxAuiTabLayoutInfo>
|
||||
LoadNotebookTabs(const wxString& name) = 0;
|
||||
|
||||
/**
|
||||
Create the window to be managed by the given pane if necessary.
|
||||
|
||||
|
||||
+177
-34
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -25,6 +25,7 @@
|
||||
#include "wx/aui/floatpane.h"
|
||||
#include "wx/aui/tabmdi.h"
|
||||
#include "wx/aui/auibar.h"
|
||||
#include "wx/aui/auibook.h"
|
||||
#include "wx/aui/serializer.h"
|
||||
#include "wx/mdi.h"
|
||||
#include "wx/wupdlock.h"
|
||||
@@ -69,6 +70,7 @@ wxDEFINE_EVENT( wxEVT_AUI_FIND_MANAGER, wxAuiManagerEvent );
|
||||
|
||||
#include "wx/generic/private/drawresize.h"
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
wxIMPLEMENT_DYNAMIC_CLASS(wxAuiManagerEvent, wxEvent);
|
||||
@@ -1451,6 +1453,10 @@ void wxAuiManager::SaveLayout(wxAuiSerializer& serializer) const
|
||||
{
|
||||
serializer.BeforeSavePanes();
|
||||
|
||||
// Collect information about all the notebooks we may have while saving
|
||||
// the panes layout.
|
||||
std::map<wxString, wxAuiNotebook*> notebooks;
|
||||
|
||||
for ( const auto& pane : m_panes )
|
||||
{
|
||||
wxAuiPaneLayoutInfo layoutInfo{pane.name};
|
||||
@@ -1460,9 +1466,26 @@ void wxAuiManager::SaveLayout(wxAuiSerializer& serializer) const
|
||||
MakeDIP(m_frame, layoutInfo.floating_size);
|
||||
|
||||
serializer.SavePane(layoutInfo);
|
||||
|
||||
if ( auto* const nb = wxDynamicCast(pane.window, wxAuiNotebook) )
|
||||
{
|
||||
notebooks[pane.name] = nb;
|
||||
}
|
||||
}
|
||||
|
||||
serializer.AfterSavePanes();
|
||||
|
||||
if ( !notebooks.empty() )
|
||||
{
|
||||
serializer.BeforeSaveNotebooks();
|
||||
|
||||
for ( const auto& kv : notebooks )
|
||||
{
|
||||
kv.second->SaveLayout(kv.first, serializer);
|
||||
}
|
||||
|
||||
serializer.AfterSaveNotebooks();
|
||||
}
|
||||
}
|
||||
|
||||
serializer.AfterSave();
|
||||
@@ -1504,7 +1527,7 @@ void wxAuiManager::LoadLayout(wxAuiDeserializer& deserializer)
|
||||
hasMaximized = true;
|
||||
|
||||
// Find the pane with the same name in the existing layout.
|
||||
bool found = false;
|
||||
wxWindow* window = nullptr;
|
||||
for ( auto& existingPane : panes )
|
||||
{
|
||||
if ( existingPane.name == layoutInfo.name )
|
||||
@@ -1512,21 +1535,29 @@ void wxAuiManager::LoadLayout(wxAuiDeserializer& deserializer)
|
||||
// Update the existing pane with the restored layout.
|
||||
CopyLayoutTo(layoutInfo, existingPane);
|
||||
|
||||
found = true;
|
||||
window = existingPane.window;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// This pane couldn't be found in the existing layout, let deserializer
|
||||
// create a new window for it if desired, otherwise just ignore it.
|
||||
if ( !found )
|
||||
if ( !window )
|
||||
{
|
||||
wxAuiPaneInfo pane;
|
||||
pane.name = layoutInfo.name;
|
||||
CopyLayoutTo(layoutInfo, pane);
|
||||
|
||||
if ( const auto w = deserializer.CreatePaneWindow(pane) )
|
||||
newPanes.emplace_back(w, pane);
|
||||
window = deserializer.CreatePaneWindow(pane);
|
||||
if ( !window )
|
||||
continue;
|
||||
|
||||
newPanes.emplace_back(window, pane);
|
||||
}
|
||||
|
||||
if ( auto* const nb = wxDynamicCast(window, wxAuiNotebook) )
|
||||
{
|
||||
nb->LoadLayout(layoutInfo.name, deserializer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user