X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/f4621a09f06512d0fcf8f70c5e3dc88818f02316..93b7364ecd30d7788e917362cac29380c86f2555:/src/generic/splitter.cpp diff --git a/src/generic/splitter.cpp b/src/generic/splitter.cpp index 44243d300b..69ddce49e0 100644 --- a/src/generic/splitter.cpp +++ b/src/generic/splitter.cpp @@ -24,7 +24,6 @@ #include "wx/wx.h" #endif -#include #include #include "wx/string.h" @@ -33,11 +32,16 @@ #if !USE_SHARED_LIBRARY IMPLEMENT_DYNAMIC_CLASS(wxSplitterWindow, wxWindow) +IMPLEMENT_DYNAMIC_CLASS(wxSplitterEvent, wxCommandEvent) BEGIN_EVENT_TABLE(wxSplitterWindow, wxWindow) EVT_PAINT(wxSplitterWindow::OnPaint) EVT_SIZE(wxSplitterWindow::OnSize) EVT_MOUSE_EVENTS(wxSplitterWindow::OnMouseEvent) + + EVT_SPLITTER_SASH_POS_CHANGED(-1, wxSplitterWindow::OnSashPosChanged) + EVT_SPLITTER_DCLICK(-1, wxSplitterWindow::OnDoubleClick) + EVT_SPLITTER_UNSPLIT(-1, wxSplitterWindow::OnUnsplitEvent) END_EVENT_TABLE() #endif @@ -140,13 +144,29 @@ void wxSplitterWindow::OnPaint(wxPaintEvent& WXUNUSED(event)) DrawSash(dc); } + void wxSplitterWindow::OnMouseEvent(wxMouseEvent& event) { - long x, y; - event.Position(&x, &y); + long x = event.GetX(); + long y = event.GetY(); // reset the cursor +#ifdef __WXMOTIF__ + SetCursor(* wxSTANDARD_CURSOR); +#endif +#ifdef __WXMSW__ SetCursor(wxCursor()); +#endif + + // under wxGTK the method above causes the mouse + // to flicker so we set the standard cursor only + // when leaving the window and when moving over + // non-sash parts of the window. this should work + // on the other platforms as well, but who knows. +#ifdef __WXGTK__ + if (event.Leaving()) + SetCursor(* wxSTANDARD_CURSOR); +#endif if (event.LeftDown()) { @@ -171,64 +191,49 @@ void wxSplitterWindow::OnMouseEvent(wxMouseEvent& event) // Erase old tracker DrawSashTracker(m_oldX, m_oldY); + // Obtain window size. We are only interested in the dimension the sash + // splits up int w, h; GetClientSize(&w, &h); - if ( m_splitMode == wxSPLIT_VERTICAL ) + int window_size = (m_splitMode == wxSPLIT_VERTICAL ? w : h ); + int new_sash_position = + (int) ( m_splitMode == wxSPLIT_VERTICAL ? x : y ); + + wxSplitterEvent eventSplitter(wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGED, + this); + eventSplitter.m_data.pos = new_sash_position; + if ( GetEventHandler()->ProcessEvent(eventSplitter) ) { - if ( !OnSashPositionChange(x) ) - return; - - if ( x <= 4 ) + new_sash_position = eventSplitter.GetSashPosition(); + if ( new_sash_position == -1 ) { - // We remove the first window from the view - wxWindow *removedWindow = m_windowOne; - m_windowOne = m_windowTwo; - m_windowTwo = (wxWindow *) NULL; - - OnUnsplit(removedWindow); - m_sashPosition = 0; - } - else if ( x >= (w - 4) ) - { - // We remove the second window from the view - wxWindow *removedWindow = m_windowTwo; - m_windowTwo = (wxWindow *) NULL; - OnUnsplit(removedWindow); - m_sashPosition = 0; - } - else - { - m_sashPosition = x; + // change not allowed + return; } } - else // m_splitMode == wxSPLIT_VERTICAL - { - if ( !OnSashPositionChange(y) ) - return; - if ( y <= 4 ) - { - // We remove the first window from the view - wxWindow *removedWindow = m_windowOne; - m_windowOne = m_windowTwo; - m_windowTwo = (wxWindow *) NULL; + if ( new_sash_position == 0 ) + { + // We remove the first window from the view + wxWindow *removedWindow = m_windowOne; + m_windowOne = m_windowTwo; + m_windowTwo = (wxWindow *) NULL; + SendUnsplitEvent(removedWindow); + m_sashPosition = 0; + } + else if ( new_sash_position == window_size ) + { + // We remove the second window from the view + wxWindow *removedWindow = m_windowTwo; + m_windowTwo = (wxWindow *) NULL; + SendUnsplitEvent(removedWindow); + m_sashPosition = 0; + } + else + { + m_sashPosition = new_sash_position; + } - OnUnsplit(removedWindow); - m_sashPosition = 0; - } - else if ( y >= (h - 4) ) - { - // We remove the second window from the view - wxWindow *removedWindow = m_windowTwo; - m_windowTwo = (wxWindow *) NULL; - OnUnsplit(removedWindow); - m_sashPosition = 0; - } - else - { - m_sashPosition = y; - } - } // m_splitMode == wxSPLIT_VERTICAL SizeWindows(); } // left up && dragging else if (event.Moving() && !event.Dragging()) @@ -245,6 +250,13 @@ void wxSplitterWindow::OnMouseEvent(wxMouseEvent& event) SetCursor(*m_sashCursorNS); } } +#ifdef __WXGTK__ + else + { + // where else do we unset the cursor? + SetCursor(* wxSTANDARD_CURSOR); + } +#endif // __WXGTK__ } else if (event.Dragging() && (m_dragMode == wxSPLIT_DRAG_DRAGGING)) { @@ -259,7 +271,12 @@ void wxSplitterWindow::OnMouseEvent(wxMouseEvent& event) } else if ( event.LeftDClick() ) { - OnDoubleClickSash(x, y); + wxSplitterEvent eventSplitter(wxEVT_COMMAND_SPLITTER_DOUBLECLICKED, + this); + eventSplitter.m_data.pt.x = x; + eventSplitter.m_data.pt.y = y; + + (void)GetEventHandler()->ProcessEvent(eventSplitter); } } @@ -489,6 +506,9 @@ void wxSplitterWindow::SizeWindows() if ( m_windowOne && !m_windowTwo ) { m_windowOne->SetSize(m_borderSize, m_borderSize, w - 2*m_borderSize, h - 2*m_borderSize); + + if (m_windowOne->GetAutoLayout()) + m_windowOne->Layout(); } else if ( m_windowOne && m_windowTwo ) { @@ -506,6 +526,11 @@ void wxSplitterWindow::SizeWindows() m_windowOne->SetSize(x1, y1, w1, h1); m_windowTwo->SetSize(x2, y2, w2, h2); + + if (m_windowOne->GetAutoLayout()) + m_windowOne->Layout(); + if (m_windowTwo->GetAutoLayout()) + m_windowTwo->Layout(); } else { @@ -513,6 +538,11 @@ void wxSplitterWindow::SizeWindows() w - 2*m_borderSize, m_sashPosition - m_borderSize); m_windowTwo->SetSize(m_borderSize, m_sashPosition + m_sashSize, w - 2*m_borderSize, h - 2*m_borderSize - m_sashSize - (m_sashPosition - m_borderSize)); + + if (m_windowOne->GetAutoLayout()) + m_windowOne->Layout(); + if (m_windowTwo->GetAutoLayout()) + m_windowTwo->Layout(); } } wxClientDC dc(this); @@ -599,12 +629,12 @@ bool wxSplitterWindow::Unsplit(wxWindow *toRemove) } else { - wxFAIL_MSG("splitter: attempt to remove a non-existent window"); + wxFAIL_MSG(_T("splitter: attempt to remove a non-existent window")); return FALSE; } - OnUnsplit(win); + SendUnsplitEvent(win); m_sashPosition = 0; SizeWindows(); @@ -614,8 +644,8 @@ bool wxSplitterWindow::Unsplit(wxWindow *toRemove) // Replace a window with another one bool wxSplitterWindow::ReplaceWindow(wxWindow *winOld, wxWindow *winNew) { - wxCHECK_MSG( winOld, FALSE, "use one of Split() functions instead" ); - wxCHECK_MSG( winNew, FALSE, "use Unsplit() functions instead" ); + wxCHECK_MSG( winOld, FALSE, _T("use one of Split() functions instead") ); + wxCHECK_MSG( winNew, FALSE, _T("use Unsplit() functions instead") ); if ( winOld == m_windowTwo ) { @@ -627,7 +657,7 @@ bool wxSplitterWindow::ReplaceWindow(wxWindow *winOld, wxWindow *winNew) } else { - wxFAIL_MSG("splitter: attempt to replace a non-existent window"); + wxFAIL_MSG(_T("splitter: attempt to replace a non-existent window")); return FALSE; } @@ -647,42 +677,6 @@ void wxSplitterWindow::SetSashPosition(int position, bool redraw) } } -bool wxSplitterWindow::OnSashPositionChange(int newSashPosition) -{ - // is the left/upper pane too small? - if ( newSashPosition < m_minimumPaneSize ) - return NULL; - - // is the right/lower pane too small? - int w, h; - GetClientSize(&w, &h); - - if ( m_splitMode == wxSPLIT_VERTICAL ) - { - if ( w - newSashPosition < m_minimumPaneSize ) - return FALSE; - } - else // m_splitMode = wxSPLIT_HORIZONTAL - { - if ( h - newSashPosition < m_minimumPaneSize ) - return FALSE; - } - - // it's ok to move sash - return TRUE; -} - -// Called when the sash is double-clicked. -// The default behaviour is to remove the sash if the -// minimum pane size is zero. -void wxSplitterWindow::OnDoubleClickSash(int WXUNUSED(x), int WXUNUSED(y) ) -{ - if ( GetMinimumPaneSize() == 0 ) - { - Unsplit(); - } -} - // Initialize colours void wxSplitterWindow::InitColours() { @@ -720,3 +714,84 @@ void wxSplitterWindow::InitColours() #endif // Win32/!Win32 } +void wxSplitterWindow::SendUnsplitEvent(wxWindow *winRemoved) +{ + wxSplitterEvent event(wxEVT_COMMAND_SPLITTER_UNSPLIT, this); + event.m_data.win = winRemoved; + + (void)GetEventHandler()->ProcessEvent(event); +} + +// --------------------------------------------------------------------------- +// splitter event handlers +// --------------------------------------------------------------------------- + +void wxSplitterWindow::OnSashPosChanged(wxSplitterEvent& event) +{ + // If within UNSPLIT_THRESHOLD from edge, set to edge to cause closure. + const int UNSPLIT_THRESHOLD = 4; + + int newSashPosition = event.GetSashPosition(); + + // Obtain relevant window dimension for bottom / right threshold check + int w, h; + GetClientSize(&w, &h); + int window_size = (m_splitMode == wxSPLIT_VERTICAL) ? w : h ; + + if ( newSashPosition <= UNSPLIT_THRESHOLD ) + { + // threshold top / left check + newSashPosition = 0; + } + else if ( newSashPosition >= window_size - UNSPLIT_THRESHOLD ) + { + // threshold bottom/right check + newSashPosition = window_size; + } + + // If resultant pane would be too small, enlarge it. + + // Check upper / left pane + if ( newSashPosition < m_minimumPaneSize ) + newSashPosition = m_minimumPaneSize; + + // Check lower / right pane (check even if sash was just adjusted) + if ( newSashPosition > window_size - m_minimumPaneSize ) + newSashPosition = window_size - m_minimumPaneSize; + + // If the result is out of bounds it means minimum size is too big, + // so split window in half as best compromise. + if ( newSashPosition < 0 || newSashPosition > window_size ) + newSashPosition = window_size / 2; + + // for compatibility, call the virtual function + if ( !OnSashPositionChange(newSashPosition) ) + { + newSashPosition = -1; + } + + event.SetSashPosition(newSashPosition); +} + +// Called when the sash is double-clicked. The default behaviour is to remove +// the sash if the minimum pane size is zero. +void wxSplitterWindow::OnDoubleClick(wxSplitterEvent& event) +{ + // for compatibility, call the virtual function + OnDoubleClickSash(event.GetX(), event.GetY()); + + if ( GetMinimumPaneSize() == 0 ) + { + Unsplit(); + } +} + +void wxSplitterWindow::OnUnsplitEvent(wxSplitterEvent& event) +{ + wxWindow *win = event.GetWindowBeingRemoved(); + + // for compatibility, call the virtual function + OnUnsplit(win); + + win->Show(FALSE); +}