diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Document.cxx | 28 | ||||
| -rw-r--r-- | src/Document.h | 2 | ||||
| -rw-r--r-- | src/Editor.cxx | 80 | ||||
| -rw-r--r-- | src/Editor.h | 6 | 
4 files changed, 111 insertions, 5 deletions
| diff --git a/src/Document.cxx b/src/Document.cxx index 9201e162f..65c63c138 100644 --- a/src/Document.cxx +++ b/src/Document.cxx @@ -109,6 +109,7 @@ Document::Document() {  	useTabs = true;  	tabIndents = true;  	backspaceUnindents = false; +	durationStyleOneLine = 0.00001;  	matchesValid = false;  	regex = 0; @@ -1892,6 +1893,33 @@ void Document::EnsureStyledTo(int pos) {  	}  } +void Document::StyleToAdjustingLineDuration(int 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_Position lineFirst = LineFromPosition(GetEndStyled()); +	ElapsedTime etStyling; +	EnsureStyledTo(pos); +	const double durationStyling = etStyling.Duration(); +	const Sci_Position lineLast = LineFromPosition(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; +		} +	} +} +  void Document::LexerChanged() {  	// Tell the watchers the lexer has changed.  	for (std::vector<WatcherWithUserData>::iterator it = watchers.begin(); it != watchers.end(); ++it) { diff --git a/src/Document.h b/src/Document.h index ea8ddfbed..71a45879e 100644 --- a/src/Document.h +++ b/src/Document.h @@ -246,6 +246,7 @@ public:  	bool useTabs;  	bool tabIndents;  	bool backspaceUnindents; +	double durationStyleOneLine;  	DecorationList decorations; @@ -400,6 +401,7 @@ public:  	bool SCI_METHOD SetStyles(Sci_Position length, const char *styles);  	int GetEndStyled() const { return endStyled; }  	void EnsureStyledTo(int pos); +	void StyleToAdjustingLineDuration(int pos);  	void LexerChanged();  	int GetStyleClock() const { return styleClock; }  	void IncrementStyleClock(); 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))) { diff --git a/src/Editor.h b/src/Editor.h index 7b88cbab0..0d788b5a8 100644 --- a/src/Editor.h +++ b/src/Editor.h @@ -234,6 +234,8 @@ protected:	// ScintillaBase subclass needs access to much of Editor  	bool paintingAllText;  	bool willRedrawAll;  	WorkNeeded workNeeded; +	int idleStyling; +	bool needIdleStyling;  	int modEventMask; @@ -525,6 +527,10 @@ protected:	// ScintillaBase subclass needs access to much of Editor  	int PositionAfterArea(PRectangle rcArea) const;  	void StyleToPositionInView(Position pos); +	int PositionAfterMaxStyling(int posMax, bool scrolling) const; +	void StartIdleStyling(bool truncatedLastStyling); +	void StyleAreaBounded(PRectangle rcArea, bool scrolling); +	void IdleStyling();  	virtual void IdleWork();  	virtual void QueueIdleWork(WorkNeeded::workItems items, int upTo=0); | 
