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.
*/
virtual void SetupScrollbars(bool atTop = false);
virtual void SetupScrollbars(bool atTop = false, bool fromOnPaint = false);
/**
Helper function implementing keyboard navigation.
@ -2316,6 +2316,11 @@ protected:
/// An overall scale factor
double m_scale;
/// Variables for scrollbar hysteresis detection
wxSize m_lastWindowSize;
int m_setupScrollbarsCount;
int m_setupScrollbarsCountInOnSize;
};
#if wxUSE_DRAG_AND_DROP

View File

@ -376,6 +376,10 @@ void wxRichTextCtrl::Init()
m_caretPositionForDefaultStyle = -2;
m_focusObject = & m_buffer;
m_scale = 1.0;
// Scrollbar hysteresis detection
m_setupScrollbarsCount = 0;
m_setupScrollbarsCountInOnSize = 0;
}
void wxRichTextCtrl::DoThaw()
@ -460,7 +464,7 @@ void wxRichTextCtrl::OnPaint(wxPaintEvent& WXUNUSED(event))
dc.SetUserScale(1.0, 1.0);
SetupScrollbars();
SetupScrollbars(false, true /* from OnPaint */);
}
// Paint the background
@ -2592,6 +2596,10 @@ void wxRichTextCtrl::OnSize(wxSizeEvent& event)
RecreateBuffer();
#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();
}
@ -2658,7 +2666,7 @@ void wxRichTextCtrl::OnScroll(wxScrollWinEvent& event)
}
/// Set up scrollbars, e.g. after a resize
void wxRichTextCtrl::SetupScrollbars(bool atTop)
void wxRichTextCtrl::SetupScrollbars(bool atTop, bool fromOnPaint)
{
if (IsFrozen())
return;
@ -2705,9 +2713,35 @@ void wxRichTextCtrl::SetupScrollbars(bool atTop)
if (oldPPUY != 0 && (oldVirtualSizeY*oldPPUY < clientSize.y) && (unitsY*pixelsPerUnit < clientSize.y))
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
// possible
SetScrollbars(0, pixelsPerUnit, 0, unitsY, newStartX, newStartY);
if (doSetScrollbars)
SetScrollbars(0, pixelsPerUnit, 0, unitsY, newStartX, newStartY);
}
/// Paint the background