/// <summary> /// Calculate tab offsets by going up /// </summary> private void CalculateTabOffsetUp(ITextSnapshotLine curLine, int colNumber, ColumnSizeInfo colTabOffset) { int curLineNumber = curLine.LineNumber - 1; ITextSnapshot textSnapshot = _textView.TextSnapshot; ElasticTabstopsLine elasticLine = _elasticTabstopsLinesCache[curLine.LineNumber]; bool isLastColumnInLine = elasticLine.IsLastColumnInLine(colNumber); while (curLineNumber >= 0) { ITextSnapshotLine upLine = textSnapshot.GetLineFromLineNumber(curLineNumber); ElasticTabstopsLine upElasticLine = GetElasticTabstopsLine(upLine); if (upElasticLine.IsLastColumnInLine(colNumber) != isLastColumnInLine) { break; } ElasticTabstopsColumn upColumn = upElasticLine.GetColumnOrDefault(colNumber); if (upColumn == null) { break; } upColumn.TabOffset = colTabOffset; ShrinkTabOffset(upElasticLine, colNumber); curLineNumber--; } }
/// <summary> /// Calculate tab offsets by going down /// </summary> private void CalculateTabOffsetDown(ITextSnapshotLine curLine, int colNumber, ColumnSizeInfo colTabOffset) { int curLineNumber = curLine.LineNumber + 1; ITextSnapshot textSnapshot = _textView.TextSnapshot; ElasticTabstopsLine elasticLine = _elasticTabstopsLinesCache[curLine.LineNumber]; bool isLastColumnInLine = elasticLine.IsLastColumnInLine(colNumber); while (curLineNumber < textSnapshot.LineCount) { ITextSnapshotLine downLine = textSnapshot.GetLineFromLineNumber(curLineNumber); ElasticTabstopsLine downElasticLine = GetElasticTabstopsLine(downLine); if (downElasticLine.IsLastColumnInLine(colNumber) != isLastColumnInLine) { break; } ElasticTabstopsColumn downColumn = downElasticLine.GetColumnOrDefault(colNumber); if (downColumn == null) { break; } downColumn.TabOffset = colTabOffset; ShrinkTabOffset(downElasticLine, colNumber); curLineNumber++; } }
/// <summary> /// Fix tab offset for a column if needed /// </summary> private void ShrinkTabOffset(ElasticTabstopsLine tabLine, int colNumber) { ElasticTabstopsColumn colTabOffset = tabLine.ElasticColumns[colNumber]; double width = CalculateInitialWidth(tabLine, colNumber); if (colTabOffset.TabOffset.ColumnWidth < width) { colTabOffset.TabOffset.ColumnWidth = width; colTabOffset.TabOffset.TabOffset = CalculateInitialTabOffset(tabLine, colNumber); } }
/// <summary> /// Returns true if column contains changed, false otherwise /// </summary> internal bool ChangedRegardingTo(ElasticTabstopsColumn elasticTabstopsColumn) { if (this == elasticTabstopsColumn) { return(false); } if (ColumnTextLength != elasticTabstopsColumn.ColumnTextLength) { return(true); } return(TabOffset.ChangedRegardingTo(elasticTabstopsColumn.TabOffset)); }
/// <summary> /// Calculates column width for a specific column in specific line /// </summary> private double CalculateInitialWidth(ElasticTabstopsLine elasticLine, int colNumber) { ITextSnapshot textSnapshot = _textView.TextSnapshot; ElasticTabstopsColumn column = elasticLine.ElasticColumns[colNumber]; Span span = new Span(column.Start, column.ColumnTextLength); if (span.Start > textSnapshot.Length || span.End > textSnapshot.Length) { return(0); } SnapshotSpan columnSpan = new SnapshotSpan(textSnapshot, span); double columnWidth = _textMeasureService.GetWidth(columnSpan); return(Math.Max(columnWidth, _minCellWidth)); }
/// <summary> /// Calculate tab offsets for line in a given direction /// </summary> private void CalculateTabOffsets(ITextSnapshotLine line, CalculateDirection direction, bool forceInvalidate) { //Calculates tab offset for a given line for the given direction ElasticTabstopsLine elasticLine = GetElasticTabstopsLine(line, forceInvalidate); for (int colNumber = 0; colNumber < elasticLine.ElasticColumns.Length; colNumber++) { ElasticTabstopsColumn column = elasticLine.ElasticColumns[colNumber]; //Tab offset is allready calculated during other line calculation if (!forceInvalidate && column.TabOffset != null) { continue; } //Assign the same ColumnTabOffset to all columns in the same block ColumnSizeInfo colTabOffset = new ColumnSizeInfo { TabOffset = CalculateInitialTabOffset(elasticLine, colNumber), ColumnWidth = CalculateInitialWidth(elasticLine, colNumber) }; column.TabOffset = colTabOffset; switch (direction) { case CalculateDirection.Up: CalculateTabOffsetUp(line, colNumber, colTabOffset); break; case CalculateDirection.Down: CalculateTabOffsetDown(line, colNumber, colTabOffset); break; case CalculateDirection.DownUp: CalculateTabOffsetDown(line, colNumber, colTabOffset); CalculateTabOffsetUp(line, colNumber, colTabOffset); break; default: throw new ArgumentException("direction"); } } }
/// <summary> /// Returns ElasticTabstopsLine with initialized ElasticColumns /// </summary> private ElasticTabstopsLine GetElasticTabstopsLine(ITextSnapshotLine line, bool forceInvalidateColumns = false) { ElasticTabstopsLine elasticTabstopsLine = _elasticTabstopsLinesCache[line.LineNumber]; if (elasticTabstopsLine.ElasticColumns == null || forceInvalidateColumns) { string lineText = line.GetText(); string[] tabSplits = lineText.Split('\t'); elasticTabstopsLine.ElasticColumns = new ElasticTabstopsColumn[tabSplits.Length]; int curPosInLine = line.Start.Position; for (int i = 0; i < tabSplits.Length; i++) { string ts = tabSplits[i]; ElasticTabstopsColumn column = new ElasticTabstopsColumn { ColumnTextLength = ts.Length, Start = curPosInLine }; //skeep tab curPosInLine += ts.Length + 1; elasticTabstopsLine.ElasticColumns[i] = column; } } return(elasticTabstopsLine); }