diff --git a/include/wx/generic/splitter.h b/include/wx/generic/splitter.h index d45cf54eb7..4dba6c4637 100644 --- a/include/wx/generic/splitter.h +++ b/include/wx/generic/splitter.h @@ -323,9 +323,13 @@ public: { SetEventObject(splitter); if (splitter) m_id = splitter->GetId(); + + m_data.resize.oldSize = 0; + m_data.resize.newSize = 0; } wxSplitterEvent(const wxSplitterEvent& event) - : wxNotifyEvent(event), m_data(event.m_data) { } + : wxNotifyEvent(event), m_data(event.m_data) + { } // SASH_POS_CHANGED methods @@ -334,17 +338,41 @@ public: void SetSashPosition(int pos) { wxASSERT( GetEventType() == wxEVT_SPLITTER_SASH_POS_CHANGED - || GetEventType() == wxEVT_SPLITTER_SASH_POS_CHANGING); + || GetEventType() == wxEVT_SPLITTER_SASH_POS_CHANGING + || GetEventType() == wxEVT_SPLITTER_SASH_POS_RESIZE); - m_data.pos = pos; + m_data.resize.pos = pos; } int GetSashPosition() const { wxASSERT( GetEventType() == wxEVT_SPLITTER_SASH_POS_CHANGED - || GetEventType() == wxEVT_SPLITTER_SASH_POS_CHANGING); + || GetEventType() == wxEVT_SPLITTER_SASH_POS_CHANGING + || GetEventType() == wxEVT_SPLITTER_SASH_POS_RESIZE); - return m_data.pos; + return m_data.resize.pos; + } + + void SetSize(int oldSize, int newSize) + { + wxASSERT(GetEventType() == wxEVT_SPLITTER_SASH_POS_RESIZE); + + m_data.resize.oldSize = oldSize; + m_data.resize.newSize = newSize; + } + + int GetOldSize() const + { + wxASSERT(GetEventType() == wxEVT_SPLITTER_SASH_POS_RESIZE); + + return m_data.resize.oldSize; + } + + int GetNewSize() const + { + wxASSERT(GetEventType() == wxEVT_SPLITTER_SASH_POS_RESIZE); + + return m_data.resize.newSize; } // UNSPLIT event methods @@ -378,7 +406,12 @@ private: // data for the different types of event union { - int pos; // position for SASH_POS_CHANGED event + struct + { + int pos; // position for SASH_POS_* events + int oldSize; // window size for SASH_POS_UPDATE event + int newSize; // window size for SASH_POS_UPDATE event + } resize; wxWindow *win; // window being removed for UNSPLIT event struct { @@ -403,6 +436,9 @@ typedef void (wxEvtHandler::*wxSplitterEventFunction)(wxSplitterEvent&); #define EVT_SPLITTER_SASH_POS_CHANGING(id, fn) \ wx__DECLARE_SPLITTEREVT(SASH_POS_CHANGING, id, fn) +#define EVT_SPLITTER_SASH_POS_RESIZE(id, fn) \ + wx__DECLARE_SPLITTEREVT(SASH_POS_UPDATE, id, fn) + #define EVT_SPLITTER_DCLICK(id, fn) \ wx__DECLARE_SPLITTEREVT(DOUBLECLICKED, id, fn) diff --git a/include/wx/splitter.h b/include/wx/splitter.h index e1f953e9ea..62fbff9f5a 100644 --- a/include/wx/splitter.h +++ b/include/wx/splitter.h @@ -32,6 +32,7 @@ class WXDLLIMPEXP_FWD_CORE wxSplitterEvent; wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_CORE, wxEVT_SPLITTER_SASH_POS_CHANGED, wxSplitterEvent ); wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_CORE, wxEVT_SPLITTER_SASH_POS_CHANGING, wxSplitterEvent ); +wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_CORE, wxEVT_SPLITTER_SASH_POS_RESIZE, wxSplitterEvent ); wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_CORE, wxEVT_SPLITTER_DOUBLECLICKED, wxSplitterEvent ); wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_CORE, wxEVT_SPLITTER_UNSPLIT, wxSplitterEvent ); diff --git a/interface/wx/splitter.h b/interface/wx/splitter.h index bd3e5f3cac..661fac4acb 100644 --- a/interface/wx/splitter.h +++ b/interface/wx/splitter.h @@ -68,6 +68,17 @@ enum May be used to modify the position of the tracking bar to properly reflect the position that would be set if the drag were to be completed at this point. Processes a @c wxEVT_SPLITTER_SASH_POS_CHANGING event. + @event{EVT_SPLITTER_SASH_POS_RESIZE(id, func)} + The sash position is in the process of being updated. + May be used to modify the position of the tracking bar to properly + reflect the position that would be set if the update were to be completed. + This can happen e.g. when the window is resized and the sash is moved + according to the gravity setting. + This event is sent when the window is resized and allows the application to select + the desired new sash position. If it doesn't process the event, the position + is determined by the gravity setting. + Processes a @c wxEVT_SPLITTER_SASH_POS_RESIZE event and is only + available in wxWidgets 3.1.6 or newer. @event{EVT_SPLITTER_SASH_POS_CHANGED(id, func)} The sash position was changed. May be used to modify the sash position before it is set, or to prevent the change from taking place. @@ -514,7 +525,8 @@ public: Returns the new sash position. May only be called while processing - @c wxEVT_SPLITTER_SASH_POS_CHANGING and + @c wxEVT_SPLITTER_SASH_POS_CHANGING, + @c wxEVT_SPLITTER_SASH_POS_RESIZE and @c wxEVT_SPLITTER_SASH_POS_CHANGED events. */ int GetSashPosition() const; @@ -553,17 +565,62 @@ public: the event handler code to prevent repositioning. May only be called while processing - @c wxEVT_SPLITTER_SASH_POS_CHANGING and + @c wxEVT_SPLITTER_SASH_POS_CHANGING, + @c wxEVT_SPLITTER_SASH_POS_RESIZE and @c wxEVT_SPLITTER_SASH_POS_CHANGED events. @param pos New sash position. */ void SetSashPosition(int pos); + + /** + Sets the size values of the window size. This size + is adjusted to the sash orientation. + For a vertical sash it should be the width and for + a horizontal sash it's the height. + + May only be called while processing + @c wxEVT_SPLITTER_SASH_POS_CHANGING, + @c wxEVT_SPLITTER_SASH_POS_RESIZE and + @c wxEVT_SPLITTER_SASH_POS_CHANGED events. + @since 3.1.6 + */ + void SetSize(int oldSize, int newSize); + + /** + Returns the old size before the update. The size value + is already adjusted to the orientation of the sash. So + for a vertical sash it's the width and for a horizontal + sash it's the height. + + May only be called while processing + @c wxEVT_SPLITTER_SASH_POS_CHANGING, + @c wxEVT_SPLITTER_SASH_POS_RESIZE and + @c wxEVT_SPLITTER_SASH_POS_CHANGED events. + @since 3.1.6 + */ + int GetOldSize() const + + + /** + Returns the new size which is set after the update. + The size value is already adjusted to the orientation + of the sash. So for a vertical sash it's the width + and for a horizontal sash it's the height. + + May only be called while processing + @c wxEVT_SPLITTER_SASH_POS_CHANGING, + @c wxEVT_SPLITTER_SASH_POS_RESIZE and + @c wxEVT_SPLITTER_SASH_POS_CHANGED events. + @since 3.1.6 + */ + int GetNewSize() const; }; wxEventType wxEVT_SPLITTER_SASH_POS_CHANGED; wxEventType wxEVT_SPLITTER_SASH_POS_CHANGING; +wxEventType wxEVT_SPLITTER_SASH_POS_RESIZE; wxEventType wxEVT_SPLITTER_DOUBLECLICKED; wxEventType wxEVT_SPLITTER_UNSPLIT; diff --git a/src/generic/splitter.cpp b/src/generic/splitter.cpp index 077c991e04..8ebcb8a0e0 100644 --- a/src/generic/splitter.cpp +++ b/src/generic/splitter.cpp @@ -41,6 +41,7 @@ wxDEFINE_EVENT( wxEVT_SPLITTER_SASH_POS_CHANGED, wxSplitterEvent ); wxDEFINE_EVENT( wxEVT_SPLITTER_SASH_POS_CHANGING, wxSplitterEvent ); +wxDEFINE_EVENT( wxEVT_SPLITTER_SASH_POS_RESIZE, wxSplitterEvent); wxDEFINE_EVENT( wxEVT_SPLITTER_DOUBLECLICKED, wxSplitterEvent ); wxDEFINE_EVENT( wxEVT_SPLITTER_UNSPLIT, wxSplitterEvent ); @@ -471,6 +472,8 @@ void wxSplitterWindow::OnSize(wxSizeEvent& event) // Apply gravity if we use it. int delta = (int) ( (size - old_size)*m_sashGravity ); + + // If delta == 0 then sash will be set according to the windows min size. if ( delta != 0 ) { newPosition = m_sashPosition + delta; @@ -478,6 +481,28 @@ void wxSplitterWindow::OnSize(wxSizeEvent& event) newPosition = m_minimumPaneSize; } + // Send an event with the newly calculated position. The handler + // can then override the new position by setting the new position. + wxSplitterEvent update(wxEVT_SPLITTER_SASH_POS_RESIZE, this); + update.m_data.resize.pos = newPosition; + update.m_data.resize.oldSize = old_size; + update.m_data.resize.newSize = size; + + if (!DoSendEvent(update)) + { + // the event handler vetoed the change + newPosition = -1; + } + else + { + // If the user set the sashposition to -1 + // we keep the already calculated value, + // otherwise the user provided the new position. + int userPos = update.GetSashPosition(); + if (userPos != -1) + newPosition = userPos; + } + // Also check if the second window became too small. newPosition = AdjustSashPosition(newPosition == -1 ? m_sashPosition @@ -669,7 +694,7 @@ void wxSplitterWindow::SetSashPositionAndNotify(int sashPos) DoSetSashPosition(sashPos); wxSplitterEvent event(wxEVT_SPLITTER_SASH_POS_CHANGED, this); - event.m_data.pos = m_sashPosition; + event.m_data.resize.pos = m_sashPosition; (void)DoSendEvent(event); } @@ -1005,7 +1030,7 @@ int wxSplitterWindow::OnSashPositionChanging(int newSashPosition) // FIXME: shouldn't we do it before the adjustments above so as to ensure // that the sash position is always reasonable? wxSplitterEvent event(wxEVT_SPLITTER_SASH_POS_CHANGING, this); - event.m_data.pos = newSashPosition; + event.m_data.resize.pos = newSashPosition; if ( !DoSendEvent(event) ) {