protected OutlineRegionBuilder(ITextBuffer textBuffer) { CurrentRegions = new OutlineRegionCollection(0); TextBuffer = textBuffer; TextBuffer.Changed += OnTextBufferChanged; BackgroundTask = new IdleTimeAsyncTask(TaskAction, MainThreadAction); BackgroundTask.DoTaskOnIdle(300); }
public virtual object Clone() { var clone = new OutlineRegionCollection(this.TextBufferVersion); foreach (var item in this) { clone.Add(item.Clone() as OutlineRegion); } return(clone); }
protected virtual object TaskAction() { if (!IsDisposed()) { var snapshot = TextBuffer.CurrentSnapshot; var newRegions = new OutlineRegionCollection(snapshot.Version.VersionNumber); BuildRegions(newRegions); lock (_regionsLock) { var changedRange = CompareRegions(newRegions, CurrentRegions, snapshot.Length); return(new OutlineRegionsChange(changedRange, newRegions)); } } return(null); }
protected static ITextRange CompareRegions( OutlineRegionCollection newRegions, OutlineRegionCollection oldRegions, int upperBound) { TextRangeCollection <OutlineRegion> oldClone = null; TextRangeCollection <OutlineRegion> newClone = null; if (oldRegions != null) { oldClone = oldRegions.Clone() as OutlineRegionCollection; oldClone.Sort(); } newClone = newRegions.Clone() as OutlineRegionCollection; newClone.Sort(); return(newClone.RangeDifference(oldClone, 0, upperBound)); }
private void OnRegionsChanged(object sender, OutlineRegionsChangedEventArgs e) { var snapshot = this._textBuffer.CurrentSnapshot; if (e.Regions.TextBufferVersion == this._textBuffer.CurrentSnapshot.Version.VersionNumber) { if (TagsChanged != null) { var start = Math.Min(e.ChangedRange.Start, snapshot.Length); var end = Math.Min(e.ChangedRange.End, snapshot.Length); TagsChanged(this, new SnapshotSpanEventArgs( new SnapshotSpan(snapshot, Span.FromBounds(start, end)))); } this._currentRegions = e.Regions; } }
protected abstract void BuildRegions(OutlineRegionCollection newRegions);
public OutlineRegionsChangedEventArgs(OutlineRegionCollection regions, ITextRange changedRange) { this.Regions = regions; this.ChangedRange = changedRange; }
private static void BuildRegions(OutlineRegionCollection newRegions, ITextSnapshot snapshot) { // Figure out regions based on line indent if (snapshot.LineCount == 0) { return; } var regionStack = new Stack <CodeBlock>(); var lineLengths = new int[snapshot.LineCount]; var lastBlockIndent = 0; for (var i = 0; i < snapshot.LineCount; i++) { var line = snapshot.GetLineFromLineNumber(i); var lineText = line.GetText(); if (string.IsNullOrWhiteSpace(lineText)) { lineLengths[i] = 0; continue; } lineLengths[i] = line.Length; var indent = GetLineIndent(line); if (regionStack.Count > 0) { lastBlockIndent = regionStack.Peek().Indent; } else { lastBlockIndent = 0; } if (indent <= lastBlockIndent) { // We add regions optimistically since any line can // start a new region if lines below it are indented // deeper that this line. while (regionStack.Count > 0) { // If we have line with the same indent, remove previously added region // and replace it with a new one potentially starting with the current line. var prevCodeBlock = regionStack.Pop(); var startLine = snapshot.GetLineNumberFromPosition(prevCodeBlock.Start); // Trim empty lines var j = i - 1; for (; j >= 0; j--) { if (lineLengths[j] > 0) { break; } } j++; if (j > 0 && j - startLine >= _minLinesToOutline) { var prevLine = snapshot.GetLineFromLineNumber(j - 1); if (prevCodeBlock.Start < prevLine.End) { newRegions.Add(OutlineRegion.FromBounds(snapshot.TextBuffer, prevCodeBlock.Start, prevLine.End)); } } if (regionStack.Count > 0) { prevCodeBlock = regionStack.Peek(); if (prevCodeBlock.Indent < indent) { break; } } } } lastBlockIndent = indent; regionStack.Push(new CodeBlock(line.Start, indent)); } // Note that last region may be bogus since we add regions optimistically. // Remove last region if its indent is the same as the line before it if (regionStack.Count > 0) { var codeBlock = regionStack.Peek(); var lineNumber = snapshot.GetLineNumberFromPosition(codeBlock.Start); if (lineNumber > 0) { var prevLine = snapshot.GetLineFromLineNumber(lineNumber - 1); var indent = GetLineIndent(prevLine); if (indent == codeBlock.Indent) { regionStack.Pop(); } } } while (regionStack.Count > 0) { var codeBlock = regionStack.Pop(); var startLine = snapshot.GetLineNumberFromPosition(codeBlock.Start); if (snapshot.LineCount - startLine >= _minLinesToOutline) { newRegions.Add(OutlineRegion.FromBounds(snapshot.TextBuffer, codeBlock.Start, snapshot.Length)); } } }
protected override void BuildRegions(OutlineRegionCollection newRegions) { BuildRegions(newRegions, this.TextBuffer.CurrentSnapshot); }