diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Document.cxx | 47 | ||||
-rw-r--r-- | src/Document.h | 22 | ||||
-rw-r--r-- | src/Editor.cxx | 3 |
3 files changed, 48 insertions, 24 deletions
diff --git a/src/Document.cxx b/src/Document.cxx index 44f301e90..ab29eb423 100644 --- a/src/Document.cxx +++ b/src/Document.cxx @@ -84,8 +84,31 @@ int LexInterface::LineEndTypesSupported() { return 0; } +ActionDuration::ActionDuration(double duration_, double minDuration_, double maxDuration_) noexcept : + duration(duration_), minDuration(minDuration_), maxDuration(maxDuration_) { +} + +void ActionDuration::AddSample(size_t numberActions, double durationOfActions) noexcept { + // Only adjust for multiple actions to avoid instability + if (numberActions < 8) + return; + + // Alpha value for exponential smoothing. + // Most recent value contributes 25% to smoothed value. + const double alpha = 0.25; + + const double durationOne = durationOfActions / numberActions; + duration = std::clamp(alpha * durationOne + (1.0 - alpha) * durationOne, + minDuration, maxDuration); +} + +double ActionDuration::Duration() const noexcept { + return duration; +} + Document::Document(int options) : - cb((options & SC_DOCUMENTOPTION_STYLES_NONE) == 0, (options & SC_DOCUMENTOPTION_TEXT_LARGE) != 0) { + cb((options & SC_DOCUMENTOPTION_STYLES_NONE) == 0, (options & SC_DOCUMENTOPTION_TEXT_LARGE) != 0), + durationStyleOneLine(0.00001, 0.000001, 0.0001) { refCount = 0; #ifdef _WIN32 eolMode = SC_EOL_CRLF; @@ -106,7 +129,6 @@ Document::Document(int options) : useTabs = true; tabIndents = true; backspaceUnindents = false; - durationStyleOneLine = 0.00001; matchesValid = false; @@ -2211,30 +2233,11 @@ void Document::EnsureStyledTo(Sci::Position pos) { } void Document::StyleToAdjustingLineDuration(Sci::Position pos) { - // Place bounds on the duration used to avoid glitches spiking it - // and so causing slow styling or non-responsive scrolling - const double minDurationOneLine = 0.000001; - const double maxDurationOneLine = 0.0001; - - // Alpha value for exponential smoothing. - // Most recent value contributes 25% to smoothed value. - const double alpha = 0.25; - const Sci::Line lineFirst = SciLineFromPosition(GetEndStyled()); ElapsedPeriod epStyling; EnsureStyledTo(pos); - const double durationStyling = epStyling.Duration(); const Sci::Line lineLast = SciLineFromPosition(GetEndStyled()); - if (lineLast >= lineFirst + 8) { - // Only adjust for styling multiple lines to avoid instability - const double durationOneLine = durationStyling / (lineLast - lineFirst); - durationStyleOneLine = alpha * durationOneLine + (1.0 - alpha) * durationStyleOneLine; - if (durationStyleOneLine < minDurationOneLine) { - durationStyleOneLine = minDurationOneLine; - } else if (durationStyleOneLine > maxDurationOneLine) { - durationStyleOneLine = maxDurationOneLine; - } - } + durationStyleOneLine.AddSample(lineLast - lineFirst, epStyling.Duration()); } void Document::LexerChanged() { diff --git a/src/Document.h b/src/Document.h index 0ef967e09..19a03ad1d 100644 --- a/src/Document.h +++ b/src/Document.h @@ -190,6 +190,26 @@ struct RegexError : public std::runtime_error { }; /** + * The ActionDuration class stores the average time taken for some action such as styling or + * wrapping a line. It is used to decide how many repetitions of that action can be performed + * on idle to maximize efficiency without affecting application responsiveness. + * The duration changes if the time for the action changes. For example, if a simple lexer is + * changed to a complex lexer. Changes are damped and clamped to avoid short periods of easy + * or difficult processing moving the value too far leading to inefficiency or poor user + * experience. + */ + +class ActionDuration { + double duration; + const double minDuration; + const double maxDuration; +public: + ActionDuration(double duration_, double minDuration_, double maxDuration_) noexcept; + void AddSample(size_t numberActions, double durationOfActions) noexcept; + double Duration() const noexcept; +}; + +/** */ class Document : PerLine, public IDocument, public ILoader { @@ -259,7 +279,7 @@ public: bool useTabs; bool tabIndents; bool backspaceUnindents; - double durationStyleOneLine; + ActionDuration durationStyleOneLine; std::unique_ptr<IDecorationList> decorations; diff --git a/src/Editor.cxx b/src/Editor.cxx index 83cb6fec6..c07c0e4a9 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -5055,7 +5055,8 @@ Sci::Position Editor::PositionAfterMaxStyling(Sci::Position posMax, bool scrolli // When scrolling, allow less time to ensure responsive const double secondsAllowed = scrolling ? 0.005 : 0.02; - const Sci::Line linesToStyle = std::clamp(static_cast<int>(secondsAllowed / pdoc->durationStyleOneLine), + const Sci::Line linesToStyle = std::clamp( + static_cast<int>(secondsAllowed / pdoc->durationStyleOneLine.Duration()), 10, 0x10000); const Sci::Line stylingMaxLine = std::min( pdoc->SciLineFromPosition(pdoc->GetEndStyled()) + linesToStyle, |