void wxSplitWindow::OnInternalIdle() { wxWindow::OnInternalIdle(); // if this is the first idle time after a sash position has potentially // been set, allow SizeWindows to check for a requested size. if (!m_checkRequestedSashPosition) { m_checkRequestedSashPosition = true; SizeWindows(); return; // it won't needUpdating in this case } if (m_needUpdating) SizeWindows(); }
// 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; }
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(); }
void wxSplitterWindow::OnSize(wxSizeEvent& event) { // only process this message if we're not iconized - otherwise iconizing // and restoring a window containing the splitter has a funny side effect // of changing the splitter position! wxWindow *parent = wxGetTopLevelParent(this); bool iconized; wxTopLevelWindow *winTop = wxDynamicCast(parent, wxTopLevelWindow); if ( winTop ) { iconized = winTop->IsIconized(); } else { wxFAIL_MSG(wxT("should have a top level parent!")); iconized = false; } if ( iconized ) { m_lastSize = wxSize(0,0); event.Skip(); return; } if ( m_windowTwo ) { int w, h; GetClientSize(&w, &h); int size = m_splitMode == wxSPLIT_VERTICAL ? w : h; int old_size = m_splitMode == wxSPLIT_VERTICAL ? m_lastSize.x : m_lastSize.y; if ( old_size != 0 ) { int delta = (int) ( (size - old_size)*m_sashGravity ); if ( delta != 0 ) { int newPosition = m_sashPosition + delta; if( newPosition < m_minimumPaneSize ) newPosition = m_minimumPaneSize; SetSashPositionAndNotify(newPosition); } } if ( m_sashPosition >= size - 5 ) SetSashPositionAndNotify(wxMax(10, size - 40)); m_lastSize = wxSize(w,h); } SizeWindows(); }
void wxSplitterWindow::OnInternalIdle() { wxWindow::OnInternalIdle(); // We may need to update the children sizes if we're in the middle of // a live update as indicated by m_needUpdating. The other possible case, // when we have a requested but not yet set sash position (as indicated // by m_requestedSashPosition having a valid value) is handled by OnSize. if ( m_needUpdating ) { m_needUpdating = false; SizeWindows(); } }
// 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 wxSplitterWindow::OnInternalIdle() { wxWindow::OnInternalIdle(); // We may need to update the children sizes in two cases: either because // we're in the middle of a live update as indicated by m_needUpdating or // because we have a requested but not yet set sash position as indicated // by m_requestedSashPosition having a valid value. if ( m_needUpdating ) { m_needUpdating = false; } else if ( m_requestedSashPosition == INT_MAX ) { // We don't need to resize the children. return; } SizeWindows(); }
// Replace a window with another one bool wxSplitterWindow::ReplaceWindow(wxWindow *winOld, wxWindow *winNew) { wxCHECK_MSG( winOld, false, wxT("use one of Split() functions instead") ); wxCHECK_MSG( winNew, false, wxT("use Unsplit() functions instead") ); if ( winOld == m_windowTwo ) { m_windowTwo = winNew; } else if ( winOld == m_windowOne ) { m_windowOne = winNew; } else { wxFAIL_MSG(wxT("splitter: attempt to replace a non-existent window")); return false; } SizeWindows(); return true; }
// Make sure the child window sizes are updated. This is useful // for reducing flicker by updating the sizes before a // window is shown, if you know the overall size is correct. void wxSplitterWindow::UpdateSize() { SizeWindows(); }
void wxSplitterWindow::OnSize(wxSizeEvent& event) { // only process this message if we're not iconized - otherwise iconizing // and restoring a window containing the splitter has a funny side effect // of changing the splitter position! wxWindow *parent = wxGetTopLevelParent(this); bool iconized; wxTopLevelWindow *winTop = wxDynamicCast(parent, wxTopLevelWindow); if ( winTop ) { iconized = winTop->IsIconized(); } else { wxFAIL_MSG(wxT("should have a top level parent!")); iconized = false; } if ( iconized ) { m_lastSize = wxSize(0,0); event.Skip(); return; } const wxSize curSize = event.GetSize(); // Update the sash position if needed. // // Notice that we shouldn't do this if the sash position requested by user // couldn't be set yet as it would never be taken into account at all if we // modified it before this happens. if ( m_windowTwo && m_requestedSashPosition == INT_MAX ) { int size = m_splitMode == wxSPLIT_VERTICAL ? curSize.x : curSize.y; int old_size = m_splitMode == wxSPLIT_VERTICAL ? m_lastSize.x : m_lastSize.y; // Don't do anything if the size didn't really change. if ( size != old_size ) { int newPosition = -1; // Apply gravity if we use it. int delta = (int) ( (size - old_size)*m_sashGravity ); if ( delta != 0 ) { newPosition = m_sashPosition + delta; if( newPosition < m_minimumPaneSize ) newPosition = m_minimumPaneSize; } // Also check if the second window became too small. newPosition = AdjustSashPosition(newPosition == -1 ? m_sashPosition : newPosition); if ( newPosition != m_sashPosition ) SetSashPositionAndNotify(newPosition); } } m_lastSize = curSize; SizeWindows(); }
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(); } }
// Make sure the child window sizes are updated. This is useful // for reducing flicker by updating the sizes before a // window is shown, if you know the overall size is correct. void wxSplitterWindow::UpdateSize() { m_checkRequestedSashPosition = true; SizeWindows(); m_checkRequestedSashPosition = false; }
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); } }
void wxSashWindow::OnSize(wxSizeEvent& WXUNUSED(event)) { SizeWindows(); }