diff options
Diffstat (limited to 'src/Editor.cxx')
-rw-r--r-- | src/Editor.cxx | 80 |
1 files changed, 75 insertions, 5 deletions
diff --git a/src/Editor.cxx b/src/Editor.cxx index 6141b0628..a86f8c96e 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -173,6 +173,8 @@ Editor::Editor() { paintAbandonedByStyling = false; paintingAllText = false; willRedrawAll = false; + idleStyling = SC_IDLESTYLING_NONE; + needIdleStyling = false; modEventMask = SC_MODEVENTMASKALL; @@ -919,7 +921,7 @@ void Editor::ScrollTo(int line, bool moveThumb) { SetTopLine(topLineNew); // Optimize by styling the view as this will invalidate any needed area // which could abort the initial paint if discovered later. - StyleToPositionInView(PositionAfterArea(GetClientRectangle())); + StyleAreaBounded(GetClientRectangle(), true); #ifndef UNDER_CE // Perform redraw rather than scroll if many lines would be redrawn anyway. if (performBlit) { @@ -1692,7 +1694,7 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) { paintAbandonedByStyling = false; - StyleToPositionInView(PositionAfterArea(rcArea)); + StyleAreaBounded(rcArea, false); PRectangle rcClient = GetClientRectangle(); //Platform::DebugPrintf("Client: (%3d,%3d) ... (%3d,%3d) %d\n", @@ -4893,6 +4895,8 @@ bool Editor::Idle() { // No more wrapping if (!wrapPending.NeedsWrap()) wrappingDone = true; + } else if (needIdleStyling) { + IdleStyling(); } // Add more idle things to do here, but make sure idleDone is @@ -4900,7 +4904,7 @@ bool Editor::Idle() { // false will stop calling this idle function until SetIdle() is // called again. - idleDone = wrappingDone; // && thatDone && theOtherThingDone... + idleDone = wrappingDone && !needIdleStyling; // && thatDone && theOtherThingDone... return !idleDone; } @@ -5003,12 +5007,71 @@ void Editor::StyleToPositionInView(Position pos) { } } +int Editor::PositionAfterMaxStyling(int posMax, bool scrolling) const { + if ((idleStyling == SC_IDLESTYLING_NONE) || (idleStyling == SC_IDLESTYLING_AFTERVISIBLE)) { + // Both states do not limit styling + return posMax; + } + + // Try to keep time taken by styling reasonable so interaction remains smooth. + // When scrolling, allow less time to ensure responsive + const double secondsAllowed = scrolling ? 0.005 : 0.02; + + const int linesToStyle = Platform::Clamp(static_cast<int>(secondsAllowed / pdoc->durationStyleOneLine), + 10, 0x10000); + const int stylingMaxLine = std::min( + static_cast<int>(pdoc->LineFromPosition(pdoc->GetEndStyled()) + linesToStyle), + pdoc->LinesTotal()); + return std::min(static_cast<int>(pdoc->LineStart(stylingMaxLine)), posMax); +} + +void Editor::StartIdleStyling(bool truncatedLastStyling) { + if ((idleStyling == SC_IDLESTYLING_ALL) || (idleStyling == SC_IDLESTYLING_AFTERVISIBLE)) { + if (pdoc->GetEndStyled() < pdoc->Length()) { + // Style remainder of document in idle time + needIdleStyling = true; + } + } else if (truncatedLastStyling) { + needIdleStyling = true; + } + + if (needIdleStyling) { + SetIdle(true); + } +} + +// Style for an area but bound the amount of styling to remain responsive +void Editor::StyleAreaBounded(PRectangle rcArea, bool scrolling) { + const int posAfterArea = PositionAfterArea(rcArea); + const int posAfterMax = PositionAfterMaxStyling(posAfterArea, scrolling); + if (posAfterMax < posAfterArea) { + // Idle styling may be performed before current visible area + // Style a bit now then style further in idle time + pdoc->StyleToAdjustingLineDuration(posAfterMax); + } else { + // Can style all wanted now. + StyleToPositionInView(posAfterArea); + } + StartIdleStyling(posAfterMax < posAfterArea); +} + +void Editor::IdleStyling() { + const int posAfterArea = PositionAfterArea(GetClientRectangle()); + const int endGoal = (idleStyling >= SC_IDLESTYLING_AFTERVISIBLE) ? + pdoc->Length() : posAfterArea; + const int posAfterMax = PositionAfterMaxStyling(endGoal, false); + pdoc->StyleToAdjustingLineDuration(posAfterMax); + if (pdoc->GetEndStyled() >= endGoal) { + needIdleStyling = false; + } +} + void Editor::IdleWork() { // Style the line after the modification as this allows modifications that change just the // line of the modification to heal instead of propagating to the rest of the window. - if (workNeeded.items & WorkNeeded::workStyle) + if (workNeeded.items & WorkNeeded::workStyle) { StyleToPositionInView(pdoc->LineStart(pdoc->LineFromPosition(workNeeded.upTo) + 2)); - + } NotifyUpdateUI(); workNeeded.Reset(); } @@ -6400,6 +6463,13 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_ISRANGEWORD: return pdoc->IsWordAt(static_cast<int>(wParam), static_cast<int>(lParam)); + + case SCI_SETIDLESTYLING: + idleStyling = static_cast<int>(wParam); + break; + + case SCI_GETIDLESTYLING: + return idleStyling; case SCI_SETWRAPMODE: if (vs.SetWrapState(static_cast<int>(wParam))) { |