X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/ed4b0fdca60e017afe72c55940799ce0fed925f0..3cb6eaec797ebbe20a0e05e5c9ba625909845e72:/src/generic/scrlwing.cpp diff --git a/src/generic/scrlwing.cpp b/src/generic/scrlwing.cpp index 53b6270584..4d4c52bc70 100644 --- a/src/generic/scrlwing.cpp +++ b/src/generic/scrlwing.cpp @@ -18,10 +18,6 @@ // headers // ---------------------------------------------------------------------------- -#ifdef __VMS -#define XtDisplay XTDISPLAY -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -29,19 +25,26 @@ #pragma hdrstop #endif +#ifdef __VMS +#define XtDisplay XTDISPLAY +#endif + #include "wx/scrolwin.h" #ifndef WX_PRECOMP #include "wx/utils.h" #include "wx/panel.h" #include "wx/dcclient.h" + #if wxUSE_TIMER + #include "wx/timer.h" + #endif + #include "wx/sizer.h" #endif -#if wxUSE_TIMER - #include "wx/timer.h" +#ifdef __WXMAC__ +#include "wx/scrolbar.h" #endif -#include "wx/sizer.h" #include "wx/recguard.h" #ifdef __WXMSW__ @@ -232,16 +235,18 @@ bool wxScrollHelperEvtHandler::ProcessEvent(wxEvent& event) } } - // reset the skipped flag to false as it might have been set to true in - // ProcessEvent() above - event.Skip(false); - if ( evType == wxEVT_PAINT ) { m_scrollHelper->HandleOnPaint((wxPaintEvent &)event); return true; } + // reset the skipped flag (which might have been set to true in + // ProcessEvent() above) to be able to test it below + bool wasSkipped = event.GetSkipped(); + if ( wasSkipped ) + event.Skip(false); + if ( evType == wxEVT_SCROLLWIN_TOP || evType == wxEVT_SCROLLWIN_BOTTOM || evType == wxEVT_SCROLLWIN_LINEUP || @@ -251,8 +256,16 @@ bool wxScrollHelperEvtHandler::ProcessEvent(wxEvent& event) evType == wxEVT_SCROLLWIN_THUMBTRACK || evType == wxEVT_SCROLLWIN_THUMBRELEASE ) { - m_scrollHelper->HandleOnScroll((wxScrollWinEvent &)event); - return !event.GetSkipped(); + m_scrollHelper->HandleOnScroll((wxScrollWinEvent &)event); + if ( !event.GetSkipped() ) + { + // it makes sense to indicate that we processed the message as we + // did scroll the window (and also notice that wxAutoScrollTimer + // relies on our return value to stop scrolling when we are at top + // or bottom already) + processed = true; + wasSkipped = false; + } } if ( evType == wxEVT_ENTER_WINDOW ) @@ -264,18 +277,29 @@ bool wxScrollHelperEvtHandler::ProcessEvent(wxEvent& event) m_scrollHelper->HandleOnMouseLeave((wxMouseEvent &)event); } #if wxUSE_MOUSEWHEEL + // Use GTK's own scroll wheel handling in GtkScrolledWindow +#ifndef __WXGTK20__ else if ( evType == wxEVT_MOUSEWHEEL ) { m_scrollHelper->HandleOnMouseWheel((wxMouseEvent &)event); + return true; } +#endif #endif // wxUSE_MOUSEWHEEL else if ( evType == wxEVT_CHAR ) { m_scrollHelper->HandleOnChar((wxKeyEvent &)event); - return !event.GetSkipped(); + if ( !event.GetSkipped() ) + { + processed = true; + wasSkipped = false; + } } - return false; + if ( processed ) + event.Skip(wasSkipped); + + return processed; } // ---------------------------------------------------------------------------- @@ -312,6 +336,8 @@ wxScrollHelper::wxScrollHelper(wxWindow *win) m_handler = NULL; m_win = win; + + m_win->SetScrollHelper( this ); // by default, the associated window is also the target window DoSetTargetWindow(win); @@ -461,21 +487,10 @@ void wxScrollHelper::HandleOnScroll(wxScrollWinEvent& event) return; } - int orient = event.GetOrientation(); - if (orient == wxHORIZONTAL) - { - m_xScrollPosition += nScrollInc; - m_win->SetScrollPos(wxHORIZONTAL, m_xScrollPosition); - } - else - { - m_yScrollPosition += nScrollInc; - m_win->SetScrollPos(wxVERTICAL, m_yScrollPosition); - } - bool needsRefresh = false; int dx = 0, dy = 0; + int orient = event.GetOrientation(); if (orient == wxHORIZONTAL) { if ( m_xScrollingEnabled ) @@ -499,6 +514,30 @@ void wxScrollHelper::HandleOnScroll(wxScrollWinEvent& event) } } + if ( !needsRefresh ) + { + // flush all pending repaints before we change m_{x,y}ScrollPosition, as + // otherwise invalidated area could be updated incorrectly later when + // ScrollWindow() makes sure they're repainted before scrolling them +#ifdef __WXMAC__ + // wxWindowMac is taking care of making sure the update area is correctly + // set up, while not forcing an immediate redraw +#else + m_targetWindow->Update(); +#endif + } + + if (orient == wxHORIZONTAL) + { + m_xScrollPosition += nScrollInc; + m_win->SetScrollPos(wxHORIZONTAL, m_xScrollPosition); + } + else + { + m_yScrollPosition += nScrollInc; + m_win->SetScrollPos(wxVERTICAL, m_yScrollPosition); + } + if ( needsRefresh ) { m_targetWindow->Refresh(true, GetScrollRect()); @@ -562,49 +601,36 @@ int wxScrollHelper::CalcScrollInc(wxScrollWinEvent& event) if (orient == wxHORIZONTAL) { - if (m_xScrollPixelsPerLine > 0) + if ( m_xScrollPosition + nScrollInc < 0 ) { - if ( m_xScrollPosition + nScrollInc < 0 ) - { - // As -ve as we can go - nScrollInc = -m_xScrollPosition; - } - else // check for the other bound + // As -ve as we can go + nScrollInc = -m_xScrollPosition; + } + else // check for the other bound + { + const int posMax = m_xScrollLines - m_xScrollLinesPerPage; + if ( m_xScrollPosition + nScrollInc > posMax ) { - const int posMax = m_xScrollLines - m_xScrollLinesPerPage; - if ( m_xScrollPosition + nScrollInc > posMax ) - { - // As +ve as we can go - nScrollInc = posMax - m_xScrollPosition; - } + // As +ve as we can go + nScrollInc = posMax - m_xScrollPosition; } } - else - m_targetWindow->Refresh(true, GetScrollRect()); } - else + else // wxVERTICAL { - if ( m_yScrollPixelsPerLine > 0 ) + if ( m_yScrollPosition + nScrollInc < 0 ) { - if ( m_yScrollPosition + nScrollInc < 0 ) - { - // As -ve as we can go - nScrollInc = -m_yScrollPosition; - } - else // check for the other bound - { - const int posMax = m_yScrollLines - m_yScrollLinesPerPage; - if ( m_yScrollPosition + nScrollInc > posMax ) - { - // As +ve as we can go - nScrollInc = posMax - m_yScrollPosition; - } - } + // As -ve as we can go + nScrollInc = -m_yScrollPosition; } - else + else // check for the other bound { - // VZ: why do we do this? (FIXME) - m_targetWindow->Refresh(true, GetScrollRect()); + const int posMax = m_yScrollLines - m_yScrollLinesPerPage; + if ( m_yScrollPosition + nScrollInc > posMax ) + { + // As +ve as we can go + nScrollInc = posMax - m_yScrollPosition; + } } } @@ -814,8 +840,17 @@ void wxScrollHelper::AdjustScrollbars() void wxScrollHelper::DoPrepareDC(wxDC& dc) { wxPoint pt = dc.GetDeviceOrigin(); - dc.SetDeviceOrigin( pt.x - m_xScrollPosition * m_xScrollPixelsPerLine, - pt.y - m_yScrollPosition * m_yScrollPixelsPerLine ); +#ifdef __WXGTK__ + // It may actually be correct to always query + // the m_sign from the DC here, but I leve the + // #ifdef GTK for now. + if (m_win->GetLayoutDirection() == wxLayout_RightToLeft) + dc.SetDeviceOrigin( pt.x + m_xScrollPosition * m_xScrollPixelsPerLine, + pt.y - m_yScrollPosition * m_yScrollPixelsPerLine ); + else +#endif + dc.SetDeviceOrigin( pt.x - m_xScrollPosition * m_xScrollPixelsPerLine, + pt.y - m_yScrollPosition * m_yScrollPixelsPerLine ); dc.SetUserScale( m_scaleX, m_scaleY ); } @@ -845,6 +880,15 @@ void wxScrollHelper::GetScrollPixelsPerUnit (int *x_unit, int *y_unit) const *y_unit = m_yScrollPixelsPerLine; } + +int wxScrollHelper::GetScrollLines( int orient ) const +{ + if ( orient == wxHORIZONTAL ) + return m_xScrollLines; + else + return m_yScrollLines; +} + int wxScrollHelper::GetScrollPageSize(int orient) const { if ( orient == wxHORIZONTAL ) @@ -875,47 +919,64 @@ void wxScrollHelper::Scroll( int x_pos, int y_pos ) int w = 0, h = 0; GetTargetSize(&w, &h); + // compute new position: + int new_x = m_xScrollPosition; + int new_y = m_yScrollPosition; + if ((x_pos != -1) && (m_xScrollPixelsPerLine)) { - int old_x = m_xScrollPosition; - m_xScrollPosition = x_pos; + new_x = x_pos; // Calculate page size i.e. number of scroll units you get on the // current client window - int noPagePositions = (int) ( (w/(double)m_xScrollPixelsPerLine) + 0.5 ); + int noPagePositions = w/m_xScrollPixelsPerLine; if (noPagePositions < 1) noPagePositions = 1; // Correct position if greater than extent of canvas minus // the visible portion of it or if below zero - m_xScrollPosition = wxMin( m_xScrollLines-noPagePositions, m_xScrollPosition ); - m_xScrollPosition = wxMax( 0, m_xScrollPosition ); - - if (old_x != m_xScrollPosition) { - m_win->SetScrollPos( wxHORIZONTAL, m_xScrollPosition ); - m_targetWindow->ScrollWindow( (old_x-m_xScrollPosition)*m_xScrollPixelsPerLine, 0, - GetScrollRect() ); - } + new_x = wxMin( m_xScrollLines-noPagePositions, new_x ); + new_x = wxMax( 0, new_x ); } if ((y_pos != -1) && (m_yScrollPixelsPerLine)) { - int old_y = m_yScrollPosition; - m_yScrollPosition = y_pos; + new_y = y_pos; // Calculate page size i.e. number of scroll units you get on the // current client window - int noPagePositions = (int) ( (h/(double)m_yScrollPixelsPerLine) + 0.5 ); + int noPagePositions = h/m_yScrollPixelsPerLine; if (noPagePositions < 1) noPagePositions = 1; // Correct position if greater than extent of canvas minus // the visible portion of it or if below zero - m_yScrollPosition = wxMin( m_yScrollLines-noPagePositions, m_yScrollPosition ); - m_yScrollPosition = wxMax( 0, m_yScrollPosition ); + new_y = wxMin( m_yScrollLines-noPagePositions, new_y ); + new_y = wxMax( 0, new_y ); + } - if (old_y != m_yScrollPosition) { - m_win->SetScrollPos( wxVERTICAL, m_yScrollPosition ); - m_targetWindow->ScrollWindow( 0, (old_y-m_yScrollPosition)*m_yScrollPixelsPerLine, - GetScrollRect() ); - } + if ( new_x == m_xScrollPosition && new_y == m_yScrollPosition ) + return; // nothing to do, the position didn't change + + // flush all pending repaints before we change m_{x,y}ScrollPosition, as + // otherwise invalidated area could be updated incorrectly later when + // ScrollWindow() makes sure they're repainted before scrolling them + m_targetWindow->Update(); + + // update the position and scroll the window now: + if (m_xScrollPosition != new_x) + { + int old_x = m_xScrollPosition; + m_xScrollPosition = new_x; + m_win->SetScrollPos( wxHORIZONTAL, new_x ); + m_targetWindow->ScrollWindow( (old_x-new_x)*m_xScrollPixelsPerLine, 0, + GetScrollRect() ); + } + + if (m_yScrollPosition != new_y) + { + int old_y = m_yScrollPosition; + m_yScrollPosition = new_y; + m_win->SetScrollPos( wxVERTICAL, new_y ); + m_targetWindow->ScrollWindow( 0, (old_y-new_y)*m_yScrollPixelsPerLine, + GetScrollRect() ); } } @@ -1127,18 +1188,18 @@ void wxScrollHelper::HandleOnChar(wxKeyEvent& event) if ( m_xScrollPosition != xScrollOld ) { - wxScrollWinEvent event(wxEVT_SCROLLWIN_THUMBTRACK, m_xScrollPosition, + wxScrollWinEvent evt(wxEVT_SCROLLWIN_THUMBTRACK, m_xScrollPosition, wxHORIZONTAL); - event.SetEventObject(m_win); - m_win->GetEventHandler()->ProcessEvent(event); + evt.SetEventObject(m_win); + m_win->GetEventHandler()->ProcessEvent(evt); } if ( m_yScrollPosition != yScrollOld ) { - wxScrollWinEvent event(wxEVT_SCROLLWIN_THUMBTRACK, m_yScrollPosition, + wxScrollWinEvent evt(wxEVT_SCROLLWIN_THUMBTRACK, m_yScrollPosition, wxVERTICAL); - event.SetEventObject(m_win); - m_win->GetEventHandler()->ProcessEvent(event); + evt.SetEventObject(m_win); + m_win->GetEventHandler()->ProcessEvent(evt); } } @@ -1255,7 +1316,7 @@ void wxScrollHelper::HandleOnMouseWheel(wxMouseEvent& event) wxScrollWinEvent newEvent; newEvent.SetPosition(0); - newEvent.SetOrientation(wxVERTICAL); + newEvent.SetOrientation( event.GetWheelAxis() == 0 ? wxVERTICAL : wxHORIZONTAL); newEvent.SetEventObject(m_win); if (event.IsPageScroll()) @@ -1306,7 +1367,13 @@ bool wxScrolledWindow::Create(wxWindow *parent, MacSetClipChildren( true ) ; #endif - bool ok = wxPanel::Create(parent, id, pos, size, style|wxHSCROLL|wxVSCROLL, name); + // by default, we're scrollable in both directions (but if one of the + // styles is specified explicitly, we shouldn't add the other one + // automatically) + if ( !(style & (wxHSCROLL | wxVSCROLL)) ) + style |= wxHSCROLL | wxVSCROLL; + + bool ok = wxPanel::Create(parent, id, pos, size, style, name); return ok; }