// Remove the specified (or second) window from the view // Doesn't actually delete the window. bool wxSplitterWindow::Unsplit(wxWindow *toRemove) { if ( ! IsSplit() ) return false; wxWindow *win; if ( toRemove == NULL || toRemove == m_windowTwo) { win = m_windowTwo ; m_windowTwo = NULL; } else if ( toRemove == m_windowOne ) { win = m_windowOne ; m_windowOne = m_windowTwo; m_windowTwo = NULL; } else { wxFAIL_MSG(wxT("splitter: attempt to remove a non-existent window")); return false; } OnUnsplit(win); DoSetSashPosition(0); SizeWindows(); return true; }
// Associates the given window with window 2, drawing the appropriate sash // and changing the split mode. // Does nothing and returns false if the window is already split. bool wxSplitterWindow::DoSplit(wxSplitMode mode, wxWindow *window1, wxWindow *window2, int sashPosition) { if ( IsSplit() ) return false; wxCHECK_MSG( window1 && window2, false, _T("can not split with NULL window(s)") ); wxCHECK_MSG( window1->GetParent() == this && window2->GetParent() == this, false, _T("windows in the splitter should have it as parent!") ); if (! window1->IsShown()) window1->Show(); if (! window2->IsShown()) window2->Show(); m_splitMode = mode; m_windowOne = window1; m_windowTwo = window2; // remember the sash position we want to set for later if we can't set it // right now (e.g. because the window is too small) m_requestedSashPosition = sashPosition; m_checkRequestedSashPosition = false; DoSetSashPosition(ConvertSashPosition(sashPosition)); SizeWindows(); return true; }
// Remove the specified (or second) window from the view // Doesn't actually delete the window. bool wxSplitWindow::Unsplit(wxWindow *toRemove) { if (!IsSplit() || toRemove == NULL) return false; if (toRemove == m_windowOne) { DoSetSashPosition (0); }else if (toRemove == m_windowTwo) { DoSetSashPosition (GetWindowSize()); }else{ wxFAIL_MSG(wxT("splitter: attempt to remove a non-existent window")); return false; } OnUnsplit (toRemove); SizeWindows(); return true; }
void wxSplitWindow::SetSashPosition (int position, bool redraw) { // remember the sash position we want to set for later if we can't set it // right now (e.g. because the window is too small) m_requestedSashPosition = position; m_checkRequestedSashPosition = false; DoSetSashPosition (ConvertSashPosition (position)); if (redraw) SizeWindows(); }
// Set pane for unsplit window void wxSplitterWindow::Initialize(wxWindow *window) { wxASSERT_MSG( (!window || window->GetParent() == this), wxT("windows in the splitter should have it as parent!") ); if (window && !window->IsShown()) window->Show(); m_windowOne = window; m_windowTwo = NULL; DoSetSashPosition(0); }
void wxSplitterWindow::SetSashPositionAndNotify(int sashPos) { // we must reset the request here, otherwise the sash would be stuck at // old position if the user attempted to move the sash after invalid // (e.g. smaller than minsize) sash position was requested using // SetSashPosition(): m_requestedSashPosition = INT_MAX; // note that we must send the event in any case, i.e. even if the sash // position hasn't changed and DoSetSashPosition() returns false because we // must generate a CHANGED event at the end of resizing DoSetSashPosition(sashPos); wxSplitterEvent event(wxEVT_SPLITTER_SASH_POS_CHANGED, this); event.m_data.pos = m_sashPosition; (void)DoSendEvent(event); }
// Position and size subwindows. // Note that the border size applies to each subwindow, not // including the edges next to the sash. void wxSplitterWindow::SizeWindows() { // check if we have delayed setting the real sash position if ( m_requestedSashPosition != INT_MAX ) { int newSashPosition = ConvertSashPosition(m_requestedSashPosition); if ( newSashPosition != m_sashPosition ) { DoSetSashPosition(newSashPosition); } if ( newSashPosition <= m_sashPosition && newSashPosition >= m_sashPosition - GetBorderSize() ) { // don't update it any more m_requestedSashPosition = INT_MAX; } } int w, h; GetClientSize(&w, &h); if ( GetWindow1() && !GetWindow2() ) { GetWindow1()->SetSize(GetBorderSize(), GetBorderSize(), w - 2*GetBorderSize(), h - 2*GetBorderSize()); } else if ( GetWindow1() && GetWindow2() ) { const int border = GetBorderSize(), sash = GetSashSize(); int size1 = GetSashPosition() - border, size2 = GetSashPosition() + sash; int x2, y2, w1, h1, w2, h2; if ( GetSplitMode() == wxSPLIT_VERTICAL ) { w1 = size1; w2 = w - 2*border - sash - w1; if (w2 < 0) w2 = 0; h2 = h - 2*border; if (h2 < 0) h2 = 0; h1 = h2; x2 = size2; y2 = border; } else // horz splitter { w2 = w - 2*border; if (w2 < 0) w2 = 0; w1 = w2; h1 = size1; h2 = h - 2*border - sash - h1; if (h2 < 0) h2 = 0; x2 = border; y2 = size2; } GetWindow2()->SetSize(x2, y2, w2, h2); GetWindow1()->SetSize(border, border, w1, h1); } wxClientDC dc(this); DrawSash(dc); }
void wxSplitterWindow::OnMouseEvent(wxMouseEvent& event) { int x = (int)event.GetX(), y = (int)event.GetY(); if ( GetWindowStyle() & wxSP_NOSASH ) { event.Skip(); return; } bool isLive = IsLive(this); if (event.LeftDown()) { if ( SashHitTest(x, y) ) { // Start the drag now m_dragMode = wxSPLIT_DRAG_DRAGGING; // Capture mouse and set the cursor CaptureMouse(); SetResizeCursor(); if ( !isLive ) { // remember the initial sash position and draw the initial // shadow sash m_sashPositionCurrent = m_sashPosition; m_oldX = (m_splitMode == wxSPLIT_VERTICAL ? m_sashPositionCurrent : x); m_oldY = (m_splitMode != wxSPLIT_VERTICAL ? m_sashPositionCurrent : y); DrawSashTracker(m_oldX, m_oldY); } m_ptStart = wxPoint(x,y); m_sashStart = m_sashPosition; return; } } else if (event.LeftUp() && m_dragMode == wxSPLIT_DRAG_DRAGGING) { // We can stop dragging now and see what we've got. m_dragMode = wxSPLIT_DRAG_NONE; // Release mouse and unset the cursor ReleaseMouse(); SetCursor(* wxSTANDARD_CURSOR); // exit if unsplit after doubleclick if ( !IsSplit() ) { return; } // Erase old tracker if ( !isLive ) { DrawSashTracker(m_oldX, m_oldY); } // the position of the click doesn't exactly correspond to // m_sashPosition, rather it changes it by the distance by which the // mouse has moved int diff = m_splitMode == wxSPLIT_VERTICAL ? x - m_ptStart.x : y - m_ptStart.y; int posSashNew = OnSashPositionChanging(m_sashStart + diff); if ( posSashNew == -1 ) { // change not allowed return; } if ( m_permitUnsplitAlways || m_minimumPaneSize == 0 ) { // Deal with possible unsplit scenarios if ( posSashNew == 0 ) { // We remove the first window from the view wxWindow *removedWindow = m_windowOne; m_windowOne = m_windowTwo; m_windowTwo = NULL; OnUnsplit(removedWindow); wxSplitterEvent eventUnsplit(wxEVT_SPLITTER_UNSPLIT, this); eventUnsplit.m_data.win = removedWindow; (void)DoSendEvent(eventUnsplit); SetSashPositionAndNotify(0); } else if ( posSashNew == GetWindowSize() ) { // We remove the second window from the view wxWindow *removedWindow = m_windowTwo; m_windowTwo = NULL; OnUnsplit(removedWindow); wxSplitterEvent eventUnsplit(wxEVT_SPLITTER_UNSPLIT, this); eventUnsplit.m_data.win = removedWindow; (void)DoSendEvent(eventUnsplit); SetSashPositionAndNotify(0); } else { SetSashPositionAndNotify(posSashNew); } } else { SetSashPositionAndNotify(posSashNew); } SizeWindows(); } // left up && dragging else if ((event.Moving() || event.Leaving() || event.Entering()) && (m_dragMode == wxSPLIT_DRAG_NONE)) { if ( event.Leaving() || !SashHitTest(x, y) ) OnLeaveSash(); else OnEnterSash(); } else if (event.Dragging() && (m_dragMode == wxSPLIT_DRAG_DRAGGING)) { int diff = m_splitMode == wxSPLIT_VERTICAL ? x - m_ptStart.x : y - m_ptStart.y; int posSashNew = OnSashPositionChanging(m_sashStart + diff); if ( posSashNew == -1 ) { // change not allowed return; } if ( !isLive ) { if ( posSashNew == m_sashPositionCurrent ) return; m_sashPositionCurrent = posSashNew; // Erase old tracker DrawSashTracker(m_oldX, m_oldY); m_oldX = (m_splitMode == wxSPLIT_VERTICAL ? m_sashPositionCurrent : x); m_oldY = (m_splitMode != wxSPLIT_VERTICAL ? m_sashPositionCurrent : y); #ifdef __WXMSW__ // As we captured the mouse, we may get the mouse events from outside // our window - for example, negative values in x, y. This has a weird // consequence under MSW where we use unsigned values sometimes and // signed ones other times: the coordinates turn as big positive // numbers and so the sash is drawn on the *right* side of the window // instead of the left (or bottom instead of top). Correct this. if ( (short)m_oldX < 0 ) m_oldX = 0; if ( (short)m_oldY < 0 ) m_oldY = 0; #endif // __WXMSW__ // Draw new one DrawSashTracker(m_oldX, m_oldY); } else { if ( posSashNew == m_sashPosition ) return; DoSetSashPosition(posSashNew); // in live mode, the new position is the actual sash position, clear requested position! m_requestedSashPosition = INT_MAX; m_needUpdating = true; } } else if ( event.LeftDClick() && m_windowTwo ) { OnDoubleClickSash(x, y); } else { event.Skip(); } }
void wxSplitterWindow::OnMouseEvent(wxMouseEvent& event) { int x = (int)event.GetX(), y = (int)event.GetY(); if (GetWindowStyle() & wxSP_NOSASH) return; // with wxSP_LIVE_UPDATE style the splitter windows are always resized // following the mouse movement while it drags the sash, without it we only // draw the sash at the new position but only resize the windows when the // dragging is finished #if defined( __WXMAC__ ) && TARGET_API_MAC_OSX == 1 bool isLive = true ; #else bool isLive = (GetWindowStyleFlag() & wxSP_LIVE_UPDATE) != 0; #endif if (event.LeftDown()) { if ( SashHitTest(x, y) ) { // Start the drag now m_dragMode = wxSPLIT_DRAG_DRAGGING; // Capture mouse and set the cursor CaptureMouse(); SetResizeCursor(); if ( !isLive ) { // remember the initial sash position and draw the initial // shadow sash m_sashPositionCurrent = m_sashPosition; DrawSashTracker(x, y); } m_oldX = x; m_oldY = y; SetResizeCursor(); return; } } else if (event.LeftUp() && m_dragMode == wxSPLIT_DRAG_DRAGGING) { // We can stop dragging now and see what we've got. m_dragMode = wxSPLIT_DRAG_NONE; // Release mouse and unset the cursor ReleaseMouse(); SetCursor(* wxSTANDARD_CURSOR); // exit if unsplit after doubleclick if ( !IsSplit() ) { return; } // Erase old tracker if ( !isLive ) { DrawSashTracker(m_oldX, m_oldY); } // the position of the click doesn't exactly correspond to // m_sashPosition, rather it changes it by the distance by which the // mouse has moved int diff = m_splitMode == wxSPLIT_VERTICAL ? x - m_oldX : y - m_oldY; int posSashOld = isLive ? m_sashPosition : m_sashPositionCurrent; int posSashNew = OnSashPositionChanging(posSashOld + diff); if ( posSashNew == -1 ) { // change not allowed return; } if ( m_permitUnsplitAlways || m_minimumPaneSize == 0 ) { // Deal with possible unsplit scenarios if ( posSashNew == 0 ) { // We remove the first window from the view wxWindow *removedWindow = m_windowOne; m_windowOne = m_windowTwo; m_windowTwo = (wxWindow *) NULL; OnUnsplit(removedWindow); wxSplitterEvent event(wxEVT_COMMAND_SPLITTER_UNSPLIT, this); event.m_data.win = removedWindow; (void)DoSendEvent(event); SetSashPositionAndNotify(0); } else if ( posSashNew == GetWindowSize() ) { // We remove the second window from the view wxWindow *removedWindow = m_windowTwo; m_windowTwo = (wxWindow *) NULL; OnUnsplit(removedWindow); wxSplitterEvent event(wxEVT_COMMAND_SPLITTER_UNSPLIT, this); event.m_data.win = removedWindow; (void)DoSendEvent(event); SetSashPositionAndNotify(0); } else { SetSashPositionAndNotify(posSashNew); } } else { SetSashPositionAndNotify(posSashNew); } SizeWindows(); } // left up && dragging else if ((event.Moving() || event.Leaving() || event.Entering()) && (m_dragMode == wxSPLIT_DRAG_NONE)) { if ( event.Leaving() || !SashHitTest(x, y) ) OnLeaveSash(); else OnEnterSash(); } else if (event.Dragging() && (m_dragMode == wxSPLIT_DRAG_DRAGGING)) { int diff = m_splitMode == wxSPLIT_VERTICAL ? x - m_oldX : y - m_oldY; if ( !diff ) { // nothing to do, mouse didn't really move far enough return; } int posSashOld = isLive ? m_sashPosition : m_sashPositionCurrent; int posSashNew = OnSashPositionChanging(posSashOld + diff); if ( posSashNew == -1 ) { // change not allowed return; } if ( posSashNew == m_sashPosition ) return; // Erase old tracker if ( !isLive ) { DrawSashTracker(m_oldX, m_oldY); } if (m_splitMode == wxSPLIT_VERTICAL) x = posSashNew; else y = posSashNew; // Remember old positions m_oldX = x; m_oldY = y; #ifdef __WXMSW__ // As we captured the mouse, we may get the mouse events from outside // our window - for example, negative values in x, y. This has a weird // consequence under MSW where we use unsigned values sometimes and // signed ones other times: the coordinates turn as big positive // numbers and so the sash is drawn on the *right* side of the window // instead of the left (or bottom instead of top). Correct this. if ( (short)m_oldX < 0 ) m_oldX = 0; if ( (short)m_oldY < 0 ) m_oldY = 0; #endif // __WXMSW__ // Draw new one if ( !isLive ) { m_sashPositionCurrent = posSashNew; DrawSashTracker(m_oldX, m_oldY); } else { DoSetSashPosition(posSashNew); m_needUpdating = true; } } else if ( event.LeftDClick() && m_windowTwo ) { OnDoubleClickSash(x, y); } }
// Position and size subwindows. // Note that the border size applies to each subwindow, not // including the edges next to the sash. void wxSplitWindow::SizeWindows() { // check if we have delayed setting the real sash position if (m_checkRequestedSashPosition && m_requestedSashPosition != INT_MAX) { int newSashPosition = ConvertSashPosition (m_requestedSashPosition); if (newSashPosition != m_sashPosition) DoSetSashPosition (newSashPosition); if (newSashPosition <= m_sashPosition && newSashPosition >= m_sashPosition - GetBorderSize()) { // don't update it any more m_requestedSashPosition = INT_MAX; } } int w, h; GetClientSize(&w, &h); const int border = GetBorderSize(); const int sash = GetSashSize(); if (m_windowOne && m_windowTwo) { int size = GetWindowSize(); int size1; int size2; if (m_sashPosition == 0) { size1 = 0; size2 = size - 2*border; }else if (m_sashPosition > 0 && m_sashPosition < size) { size1 = m_sashPosition - border; size2 = size - m_sashPosition - sash - border; }else{ size1 = size; size2 = 0 - 2*border; } int x2, y2, w1, h1, w2, h2; if (m_splitMode == wxSPLIT_VERTICAL) { w1 = size1; w2 = size2; h1 = h - 2*border; h2 = h1; x2 = size - (size2 - border); y2 = border; } else // horz splitwindow { w1 = w - 2*border; w2 = w1; h1 = size1; h2 = size2; x2 = border; y2 = size - (size2 - border); } m_windowOne->SetSize (border, border, w1, h1); m_windowTwo->SetSize (x2, y2, w2, h2); } wxClientDC dc(this); DrawSash(dc); SetNeedUpdating (false); }