Added scrollbar hysteresis detection to stop infinite looping when vertical scrollbar presence or absence affects the content height.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@75373 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Julian Smart
2013-12-10 15:24:35 +00:00
parent 79ec1e6c30
commit 87ba46f05e
2 changed files with 43 additions and 4 deletions

View File

@@ -1926,7 +1926,7 @@ public:
/** /**
A helper function setting up scrollbars, for example after a resize. A helper function setting up scrollbars, for example after a resize.
*/ */
virtual void SetupScrollbars(bool atTop = false); virtual void SetupScrollbars(bool atTop = false, bool fromOnPaint = false);
/** /**
Helper function implementing keyboard navigation. Helper function implementing keyboard navigation.
@@ -2316,6 +2316,11 @@ protected:
/// An overall scale factor /// An overall scale factor
double m_scale; double m_scale;
/// Variables for scrollbar hysteresis detection
wxSize m_lastWindowSize;
int m_setupScrollbarsCount;
int m_setupScrollbarsCountInOnSize;
}; };
#if wxUSE_DRAG_AND_DROP #if wxUSE_DRAG_AND_DROP

View File

@@ -376,6 +376,10 @@ void wxRichTextCtrl::Init()
m_caretPositionForDefaultStyle = -2; m_caretPositionForDefaultStyle = -2;
m_focusObject = & m_buffer; m_focusObject = & m_buffer;
m_scale = 1.0; m_scale = 1.0;
// Scrollbar hysteresis detection
m_setupScrollbarsCount = 0;
m_setupScrollbarsCountInOnSize = 0;
} }
void wxRichTextCtrl::DoThaw() void wxRichTextCtrl::DoThaw()
@@ -460,7 +464,7 @@ void wxRichTextCtrl::OnPaint(wxPaintEvent& WXUNUSED(event))
dc.SetUserScale(1.0, 1.0); dc.SetUserScale(1.0, 1.0);
SetupScrollbars(); SetupScrollbars(false, true /* from OnPaint */);
} }
// Paint the background // Paint the background
@@ -2592,6 +2596,10 @@ void wxRichTextCtrl::OnSize(wxSizeEvent& event)
RecreateBuffer(); RecreateBuffer();
#endif #endif
// Anti-hysteresis code: a way to determine whether a combination of OnPaint and
// OnSize was the source of a scrollbar change.
m_setupScrollbarsCountInOnSize = m_setupScrollbarsCount;
event.Skip(); event.Skip();
} }
@@ -2658,7 +2666,7 @@ void wxRichTextCtrl::OnScroll(wxScrollWinEvent& event)
} }
/// Set up scrollbars, e.g. after a resize /// Set up scrollbars, e.g. after a resize
void wxRichTextCtrl::SetupScrollbars(bool atTop) void wxRichTextCtrl::SetupScrollbars(bool atTop, bool fromOnPaint)
{ {
if (IsFrozen()) if (IsFrozen())
return; return;
@@ -2705,9 +2713,35 @@ void wxRichTextCtrl::SetupScrollbars(bool atTop)
if (oldPPUY != 0 && (oldVirtualSizeY*oldPPUY < clientSize.y) && (unitsY*pixelsPerUnit < clientSize.y)) if (oldPPUY != 0 && (oldVirtualSizeY*oldPPUY < clientSize.y) && (unitsY*pixelsPerUnit < clientSize.y))
return; return;
// Hysteresis detection. If an object width is relative to the window width, then there can be
// interaction between image width and total content height, causing the scrollbar to appear
// and disappear rapidly. We need to see if we're getting this looping via OnSize/OnPaint,
// and if so, keep the scrollbar shown. We use a counter to see whether the SetupScrollbars
// call is caused by OnSize, versus any other operation such as editing.
// There may still be some flickering when editing at the boundary of scrollbar/no scrollbar
// states, but looping will be avoided.
bool doSetScrollbars = true;
wxSize windowSize = GetSize();
if (fromOnPaint)
{
if ((windowSize == m_lastWindowSize) && (m_setupScrollbarsCountInOnSize == m_setupScrollbarsCount))
{
// If we will be going from scrollbar to no scrollbar, we're now probably in hysteresis.
// So don't set the scrollbars this time.
if ((oldPPUY != 0) && (oldVirtualSizeY*oldPPUY > clientSize.y) && (unitsY*pixelsPerUnit <= clientSize.y))
doSetScrollbars = false;
}
}
m_lastWindowSize = windowSize;
m_setupScrollbarsCount ++;
if (m_setupScrollbarsCount > 32000)
m_setupScrollbarsCount = 0;
// Move to previous scroll position if // Move to previous scroll position if
// possible // possible
SetScrollbars(0, pixelsPerUnit, 0, unitsY, newStartX, newStartY); if (doSetScrollbars)
SetScrollbars(0, pixelsPerUnit, 0, unitsY, newStartX, newStartY);
} }
/// Paint the background /// Paint the background