From f24b3d54833a1c15ae3bba87dead83bf9a90c41d Mon Sep 17 00:00:00 2001 From: Doukas Dergiades Date: Mon, 12 Feb 2024 04:17:53 +0200 Subject: [PATCH] Save last wxSplitterWindow position before it was unsplit Use this position when the window is split again and also save and restore it from persistent storage in wxPersistentSplitter. Closes #24329. --- include/wx/generic/splitter.h | 10 ++++++++++ include/wx/persist/splitter.h | 19 +++++++++++++++++++ interface/wx/splitter.h | 30 ++++++++++++++++++++++++++++++ src/generic/splitter.cpp | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 91 insertions(+) diff --git a/include/wx/generic/splitter.h b/include/wx/generic/splitter.h index 2d632993ac..26a41dc6b9 100644 --- a/include/wx/generic/splitter.h +++ b/include/wx/generic/splitter.h @@ -226,6 +226,15 @@ public: // all any more. wxDEPRECATED_INLINE( void SetSashSize(int WXUNUSED(width)), return; ) + // Get the sash position that was last used before Unsplit() was called. + // Horizontal and vertical components correspond to the split in the + // corresponding direction, and are 0 if the splitter hadn't been split in + // this direction at all. + wxPoint GetLastSplitPosition() const; + + // Set the default initial sash position to use when the splitter is split. + void SetLastSplitPosition(const wxPoint& pos); + protected: // event handlers #if defined(__WXMSW__) || defined(__WXMAC__) @@ -289,6 +298,7 @@ protected: wxPoint m_ptStart; // mouse position when dragging started int m_sashStart; // sash position when dragging started int m_minimumPaneSize; + wxPoint m_lastSplitPosition; wxCursor m_sashCursorWE; wxCursor m_sashCursorNS; wxOverlay m_overlay; diff --git a/include/wx/persist/splitter.h b/include/wx/persist/splitter.h index e1b452fdcf..fa66d5990c 100644 --- a/include/wx/persist/splitter.h +++ b/include/wx/persist/splitter.h @@ -23,6 +23,9 @@ // Special position value of -1 means the splitter is not split at all. #define wxPERSIST_SPLITTER_POSITION wxASCII_STR("Position") +#define wxPERSIST_SPLITTER_DEFAULT_HORIZONTAL wxASCII_STR("LastHorz") +#define wxPERSIST_SPLITTER_DEFAULT_VERTICAL wxASCII_STR("LastVert") + // ---------------------------------------------------------------------------- // wxPersistentSplitter: supports saving/restoring splitter position // ---------------------------------------------------------------------------- @@ -41,6 +44,14 @@ public: int pos = splitter->IsSplit() ? splitter->GetSashPosition() : -1; SaveValue(wxPERSIST_SPLITTER_POSITION, pos); + + // Save the previously used position too if we have them. + const wxPoint lastSplitPos = splitter->GetLastSplitPosition(); + if ( lastSplitPos.x || lastSplitPos.y ) + { + SaveValue(wxPERSIST_SPLITTER_DEFAULT_HORIZONTAL, lastSplitPos.y); + SaveValue(wxPERSIST_SPLITTER_DEFAULT_VERTICAL, lastSplitPos.x); + } } virtual bool Restore() override @@ -54,6 +65,14 @@ public: else Get()->SetSashPosition(pos); + // Note that it's possible that default position was not stored, in + // which case lastSplitPos will just remain as (0, 0) and that's ok. + wxPoint lastSplitPos; + RestoreValue(wxPERSIST_SPLITTER_DEFAULT_HORIZONTAL, &lastSplitPos.x); + RestoreValue(wxPERSIST_SPLITTER_DEFAULT_VERTICAL, &lastSplitPos.y); + + Get()->SetLastSplitPosition(lastSplitPos); + return true; } diff --git a/interface/wx/splitter.h b/interface/wx/splitter.h index 4ff835b2ee..18cdd6d20a 100644 --- a/interface/wx/splitter.h +++ b/interface/wx/splitter.h @@ -477,6 +477,36 @@ public: before showing the top-level window. */ void UpdateSize(); + + /** + Get the last sash position before the splitter was unsplit. + + The last sash position gets updated each time the window is unsplit. It + is kept internally to allow restoring the sash in its previous position + when if it is split again. + + @return Point whose x/y component corresponds to the position of the + vertical/horizontal sash before the last unsplit or 0 if the + splitter was never split in the corresponding direction. + + @since 3.3.0 + */ + const wxPoint& GetLastSplitPosition() const; + + /** + Sets the last sash position. + + This does not affect the actual sash position while the window is split + but determines the initial position of the sash when the window gets + split in the future. + + @param pos + Point containing the default positions for wxSPLIT_VERTICAL and + wxSPLIT_HORIZONTAL modes respectively in its x and y components. + + @since 3.3.0 + */ + void SetLastSplitPosition(const wxPoint& pos); }; diff --git a/src/generic/splitter.cpp b/src/generic/splitter.cpp index c163993446..c25555be0d 100644 --- a/src/generic/splitter.cpp +++ b/src/generic/splitter.cpp @@ -840,6 +840,18 @@ int wxSplitterWindow::ConvertSashPosition(int sashPosition) const } else // sashPosition == 0 { + // Use last split position if we have it. + if ( m_splitMode == wxSPLIT_VERTICAL ) + { + if ( m_lastSplitPosition.x ) + return m_lastSplitPosition.x; + } + else if ( m_splitMode == wxSPLIT_HORIZONTAL ) + { + if ( m_lastSplitPosition.y ) + return m_lastSplitPosition.y; + } + // default, put it in the centre return GetWindowSize() / 2; } @@ -871,6 +883,15 @@ bool wxSplitterWindow::Unsplit(wxWindow *toRemove) return false; } + if (m_splitMode == wxSPLIT_VERTICAL) + { + m_lastSplitPosition.x = m_sashPosition; + } + else if (m_splitMode == wxSPLIT_HORIZONTAL) + { + m_lastSplitPosition.y = m_sashPosition; + } + OnUnsplit(win); DoSetSashPosition(0); SizeWindows(); @@ -1086,6 +1107,17 @@ void wxSplitterWindow::OnUnsplit(wxWindow *winRemoved) winRemoved->Show(false); } +wxPoint wxSplitterWindow::GetLastSplitPosition() const +{ + return m_lastSplitPosition; +} + +void wxSplitterWindow::SetLastSplitPosition(const wxPoint& pos) +{ + m_lastSplitPosition = pos; +} + + #if defined( __WXMSW__ ) || defined( __WXMAC__) // this is currently called (and needed) under MSW only...