diff --git a/include/wx/scrolwin.h b/include/wx/scrolwin.h index 3e22eb59c2..3ea03fcc60 100644 --- a/include/wx/scrolwin.h +++ b/include/wx/scrolwin.h @@ -66,9 +66,19 @@ class WXDLLIMPEXP_CORE wxAnyScrollHelperBase public: wxEXPLICIT wxAnyScrollHelperBase(wxWindow* win); + // Override this function to draw the graphic (or just process EVT_PAINT) + virtual void OnDraw(wxDC& WXUNUSED(dc)) { } + + // change the DC origin according to the scroll position. + virtual void DoPrepareDC(wxDC& dc) = 0; + // Simple accessor for the window that is really being scrolled. wxWindow *GetTargetWindow() const { return m_targetWindow; } + + // The methods called from the window event handlers. + void HandleOnPaint(wxPaintEvent& event); + protected: // the window that receives the scroll events and the window to actually // scroll, respectively @@ -199,10 +209,6 @@ public: void SetTargetRect(const wxRect& rect) { m_rectToScroll = rect; } wxRect GetTargetRect() const { return m_rectToScroll; } - // Override this function to draw the graphic (or just process EVT_PAINT) - virtual void OnDraw(wxDC& WXUNUSED(dc)) { } - - // change the DC origin according to the scroll position. virtual void DoPrepareDC(wxDC& dc); // are we generating the autoscroll events? @@ -222,7 +228,6 @@ public: // the methods to be called from the window event handlers void HandleOnScroll(wxScrollWinEvent& event); void HandleOnSize(wxSizeEvent& event); - void HandleOnPaint(wxPaintEvent& event); void HandleOnChar(wxKeyEvent& event); void HandleOnMouseEnter(wxMouseEvent& event); void HandleOnMouseLeave(wxMouseEvent& event); diff --git a/include/wx/vscroll.h b/include/wx/vscroll.h index 51e2b0b58c..2312d78f0b 100644 --- a/include/wx/vscroll.h +++ b/include/wx/vscroll.h @@ -121,9 +121,6 @@ public: // scrollbars (spreadsheet: only cell area will move). virtual void SetTargetWindow(wxWindow *target); - // Override this function to draw the graphic (or just process EVT_PAINT) - //virtual void OnDraw(wxDC& WXUNUSED(dc)) { } - // change the DC origin according to the scroll position. To properly // forward calls to wxWindow::Layout use WX_FORWARD_TO_SCROLL_HELPER() // derived class diff --git a/src/generic/scrlwing.cpp b/src/generic/scrlwing.cpp index 1323e45060..5fb622b242 100644 --- a/src/generic/scrlwing.cpp +++ b/src/generic/scrlwing.cpp @@ -186,6 +186,9 @@ void wxAutoScrollTimer::Notify() // wxScrollHelperEvtHandler // ---------------------------------------------------------------------------- +// Notice that this method is currently duplicated in the method with the same +// name in wxVarScrollHelperEvtHandler class, until this is fixed, the other +// copy of the method needs to be modified every time this version is. bool wxScrollHelperEvtHandler::ProcessEvent(wxEvent& event) { wxEventType evType = event.GetEventType(); @@ -817,7 +820,7 @@ void wxScrollHelperBase::HandleOnSize(wxSizeEvent& WXUNUSED(event)) // This calls OnDraw, having adjusted the origin according to the current // scroll position -void wxScrollHelperBase::HandleOnPaint(wxPaintEvent& WXUNUSED(event)) +void wxAnyScrollHelperBase::HandleOnPaint(wxPaintEvent& WXUNUSED(event)) { // don't use m_targetWindow here, this is always called for ourselves wxPaintDC dc(m_win); diff --git a/src/generic/vscroll.cpp b/src/generic/vscroll.cpp index 905d7cc4d0..0048bd75b0 100644 --- a/src/generic/vscroll.cpp +++ b/src/generic/vscroll.cpp @@ -61,12 +61,20 @@ private: // wxVarScrollHelperEvtHandler implementation // ============================================================================ +// FIXME: This method totally duplicates a method with the same name in +// wxScrollHelperEvtHandler, we really should merge them by reusing the +// common parts in wxAnyScrollHelperBase. bool wxVarScrollHelperEvtHandler::ProcessEvent(wxEvent& event) { wxEventType evType = event.GetEventType(); - // pass it on to the real handler - bool processed = wxEvtHandler::ProcessEvent(event); + // Pass it on to the real handler: notice that we must not call + // ProcessEvent() on this object itself as it wouldn't pass it to the next + // handler (i.e. the real window) if we're called from a previous handler + // (as indicated by "process here only" flag being set) and we do want to + // execute the handler defined in the window we're associated with right + // now, without waiting until TryAfter() is called from wxEvtHandler. + bool processed = m_nextHandler->ProcessEvent(event); // always process the size events ourselves, even if the user code handles // them as well, as we need to AdjustScrollbars() @@ -78,18 +86,28 @@ bool wxVarScrollHelperEvtHandler::ProcessEvent(wxEvent& event) if ( evType == wxEVT_SIZE ) { m_scrollHelper->HandleOnSize((wxSizeEvent &)event); - - return !event.GetSkipped(); + return true; } - if ( processed ) + if ( processed && event.IsCommandEvent()) + return true; + + // For wxEVT_PAINT the user code can either handle this event as usual or + // override virtual OnDraw(), so if the event hasn't been handled we need + // to call this virtual function ourselves. + if ( +#ifndef __WXUNIVERSAL__ + // in wxUniversal "processed" will always be true, because + // all windows use the paint event to draw themselves. + // In this case we can't use this flag to determine if a custom + // paint event handler already drew our window and we just + // call OnDraw() anyway. + !processed && +#endif // !__WXUNIVERSAL__ + evType == wxEVT_PAINT ) { - // normally, nothing more to do here - except if we have a command - // event - if ( event.IsCommandEvent() ) - { - return true; - } + m_scrollHelper->HandleOnPaint((wxPaintEvent &)event); + return true; } // reset the skipped flag (which might have been set to true in @@ -112,7 +130,8 @@ bool wxVarScrollHelperEvtHandler::ProcessEvent(wxEvent& event) { // 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 for continuous scrolling) + // relies on our return value to stop scrolling when we are at top + // or bottom already) processed = true; wasSkipped = false; } @@ -126,6 +145,17 @@ bool wxVarScrollHelperEvtHandler::ProcessEvent(wxEvent& event) event.Skip(wasSkipped); + // We called ProcessEvent() on the next handler, meaning that we explicitly + // worked around the request to process the event in this handler only. As + // explained above, this is unfortunately really necessary but the trouble + // is that the event will continue to be post-processed by the previous + // handler resulting in duplicate calls to event handlers. Call the special + // function below to prevent this from happening, base class DoTryChain() + // will check for it and behave accordingly. + // + // And if we're not called from DoTryChain(), this won't do anything anyhow. + event.DidntHonourProcessOnlyIn(); + return processed; }