/// <summary> /// Get the SnapshotSpan for the ITextViewLineCollection. This can throw when the ITextView is being /// laid out so we wrap the try / catch here /// </summary> public static Result <SnapshotSpan> GetFormattedSpan(this ITextViewLineCollection collection) { try { return(collection.FormattedSpan); } catch (Exception ex) { return(Result.CreateError(ex)); } }
/// <summary> /// See <see cref="ITextView2.TryGetTextViewLines(out ITextViewLineCollection)"/>. /// </summary> public static bool TryGetTextViewLines(this ITextView textView, out ITextViewLineCollection textViewLines) { if (textView == null) { throw new ArgumentNullException(nameof(textView)); } if (textView is ITextView2 textView2) { return(textView2.TryGetTextViewLines(out textViewLines)); } else { textViewLines = null; return(false); } }
public override void PreprocessMouseMove(MouseEventArgs e) { ITextViewLineCollection textViewLines = _view.TextViewLines; if (textViewLines != null) { Point position = e.GetPosition(this._view.VisualElement); position.X += this._view.ViewportLeft; position.Y += this._view.ViewportTop; ITextViewLine textViewLineContainingYCoordinate = textViewLines.GetTextViewLineContainingYCoordinate(position.Y); if (textViewLineContainingYCoordinate != null) { MousePosition = textViewLineContainingYCoordinate.Start.Position; } } base.PreprocessMouseMove(e); }
///////////////////////////////////////////////////////////////////////////////////////////////////// // PUBLIC PROCEDURES ///////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Draws the margin and its content. /// </summary> /// <param name="context">The <see cref="TextViewDrawContext"/> to use for rendering.</param> public void Draw(TextViewDrawContext context) { Rect marginBounds = context.Bounds; // Loop through all the view lines ITextViewLineCollection visibleLines = view.VisibleViewLines; foreach (ITextViewLine viewLine in visibleLines) { // Get bounds relative to this element Rect bounds = view.TransformFromTextArea(viewLine.Bounds); // Get the number of characters on the line string characterCount = viewLine.CharacterCount.ToString(CultureInfo.CurrentCulture) + " chars"; // Get the foreground var foreground = Colors.Black; if (viewLine.CharacterCount > 60) { foreground = Colors.Red; } else if (viewLine.CharacterCount > 40) { foreground = Colors.DarkGoldenrod; } else if (viewLine.CharacterCount > 20) { foreground = Colors.DarkGreen; } // Get the line layout var firstLayoutLine = context.Canvas.CreateTextLayout(characterCount, 0, this.FontFamily.Source, (float)this.FontSize, foreground).Lines[0]; // Get x/y double x = marginBounds.Right - firstLayoutLine.Width - this.Padding.Right; double y = marginBounds.Y + viewLine.TextBounds.Y + (int)Math.Round(viewLine.Baseline - firstLayoutLine.Baseline, MidpointRounding.AwayFromZero); // Draw the text context.DrawText(new Point(x, y), firstLayoutLine); } }
public static bool TryGetClosestTextViewLine(this ITextView textView, double yCoordinate, out ITextViewLine closestLine) { if (textView == null) { throw new ArgumentNullException(nameof(textView)); } if (textView.IsClosed || textView.InLayout) { closestLine = null; return(false); } ITextViewLine textLine = null; ITextViewLineCollection textLines = textView.TextViewLines; if (textLines != null && textLines.Count > 0) { textLine = textLines.GetTextViewLineContainingYCoordinate(yCoordinate); if (textLine == null) { if (yCoordinate <= textLines.FirstVisibleLine.Bottom) { textLine = textLines.FirstVisibleLine; } else if (yCoordinate >= textLines.LastVisibleLine.Top) { textLine = textLines.LastVisibleLine; } } closestLine = textLine; return(true); } closestLine = null; return(false); }
public bool TryGetTextViewLines(out ITextViewLineCollection textViewLines) => _innerTextView.TryGetTextViewLines(out textViewLines);
private void renderColumnsForLines(GeometryGroup geometry, List <int> columns, ITextViewLineCollection lines) { double top = 0.0, bottom = _view.ViewportHeight; int lineindex = 0; bool resetTopAtNextLine = true; int leftmostcolumn = getFirstColumn(); int rightmostcolumn = getLastColumn(); foreach (var line in lines) { // Create new columns starting from this line if (resetTopAtNextLine) { top = line.Top - _view.ViewportTop; } bottom = line.Bottom - _view.ViewportTop; // If next line is not starting at a different column than this // one we need to draw this line immediately, and disregard // the current line's top for when drawing the next lines. resetTopAtNextLine = (!line.IsLastTextViewLineForSnapshotLine || !line.IsFirstTextViewLineForSnapshotLine); // We need to draw the current columns before next line if (resetTopAtNextLine) { renderColumns(geometry, columns, top, bottom, _linesOffset[lineindex], leftmostcolumn, rightmostcolumn); } lineindex++; } if (!resetTopAtNextLine && ((lineindex - 1) < _linesOffset.Count)) { renderColumns(geometry, columns, top, bottom, _linesOffset[lineindex - 1], leftmostcolumn, rightmostcolumn); } }
public override void PreprocessMouseMove(System.Windows.Input.MouseEventArgs e) { ITextViewLineCollection textLines = this.view.TextViewLines; if ((textLines != null) && (this.visibleBlocks.Count > 0)) { ITextViewLine firstVisible = textLines.FirstVisibleLine; int screenTop = (firstVisible.VisibilityState == VisibilityState.FullyVisible) ? firstVisible.Start : firstVisible.EndIncludingLineBreak; Point pt = e.GetPosition(this.view.VisualElement); pt.X += this.view.ViewportLeft; pt.Y += this.view.ViewportTop; foreach (VisibleBlock block in this.visibleBlocks) { if ((Math.Abs(pt.X - block.x) < 4.0) && (pt.Y >= block.yTop) && (pt.Y <= block.yBottom)) { SnapshotPoint?statementStart = this.view.BufferGraph.MapUpToSnapshot(block.tag.StatementStart, PointTrackingMode.Positive, PositionAffinity.Successor, this.view.TextSnapshot); if (statementStart.HasValue && (statementStart.Value < screenTop)) { if (this.tipWindow == null) { this.tipWindow = new ToolTip(); this.tipWindow.ClipToBounds = true; this.tipWindow.Placement = PlacementMode.Top; this.tipWindow.PlacementTarget = this.view.VisualElement; this.tipWindow.HorizontalAlignment = HorizontalAlignment.Left; this.tipWindow.HorizontalContentAlignment = HorizontalAlignment.Left; this.tipWindow.VerticalAlignment = VerticalAlignment.Top; this.tipWindow.VerticalContentAlignment = VerticalAlignment.Top; } this.tipWindow.PlacementRectangle = new Rect(block.x, 0.0, 0.0, 0.0); this.tipWindow.IsOpen = true; FrameworkElement context = block.tag.Context(this.blockColoring, this.view.FormattedLineSource.DefaultTextProperties.Typeface, this.view.FormattedLineSource.DefaultTextProperties.FontRenderingEmSize); //The width of the view is in zoomed coordinates so factor the zoom factor into the tip window width computation. double zoom = this.view.ZoomLevel / 100.0; this.tipWindow.MaxWidth = Math.Max(100.0, this.view.ViewportWidth * zoom * 0.5); this.tipWindow.MinHeight = this.tipWindow.MaxHeight = context.Height + 12.0; this.tipWindow.Content = context; return; } } } } if (this.tipWindow != null) { this.tipWindow.IsOpen = false; this.tipWindow = null; } }
/// <summary> /// See <see cref="ITextView2.TryGetTextViewLineContainingBufferPosition(SnapshotPoint, out Formatting.ITextViewLine)"/>. /// </summary> public static bool TryGetTextViewLineContainingBufferPosition(this ITextView textView, SnapshotPoint bufferPosition, out ITextViewLineCollection textViewLines) { if (textView == null) { throw new ArgumentNullException(nameof(textView)); } if (textView is ITextView2 textView2) { return(textView2.TryGetTextViewLineContainingBufferPosition(bufferPosition, out textViewLines)); } else { textViewLines = null; return(false); } }
public override void PreprocessMouseMove(System.Windows.Input.MouseEventArgs e) { ITextViewLineCollection textLines = _view.TextViewLines; if ((textLines != null) && (_visibleBlocks.Count > 0)) { ITextViewLine firstVisible = textLines.FirstVisibleLine; Point pt = e.GetPosition(_view.VisualElement); pt.X += _view.ViewportLeft; pt.Y += _view.ViewportTop; //Horrible hack for peek: prevent the tip from showing if the y coordinate is in the space below the bottom of a line's text //(which is where the peek adornment would be displayed). var line = textLines.GetTextViewLineContainingYCoordinate(pt.Y); if ((line != null) && (pt.Y <= line.TextBottom + 1.0)) { int screenTop = (firstVisible.VisibilityState == VisibilityState.FullyVisible) ? firstVisible.Start : firstVisible.EndIncludingLineBreak; foreach (VisibleBlock block in _visibleBlocks) { if ((Math.Abs(pt.X - block.x) < 4.0) && (pt.Y >= block.yTop) && (pt.Y <= block.yBottom)) { SnapshotPoint?statementStart = _view.BufferGraph.MapUpToSnapshot(block.tag.StatementStart, PointTrackingMode.Positive, PositionAffinity.Successor, _view.TextSnapshot); if (statementStart.HasValue && (statementStart.Value < screenTop)) { if (_tipWindow == null) { _tipWindow = new ToolTip(); _tipWindow.ClipToBounds = true; _tipWindow.Placement = PlacementMode.Top; _tipWindow.PlacementTarget = _view.VisualElement; _tipWindow.HorizontalAlignment = HorizontalAlignment.Left; _tipWindow.HorizontalContentAlignment = HorizontalAlignment.Left; _tipWindow.VerticalAlignment = VerticalAlignment.Top; _tipWindow.VerticalContentAlignment = VerticalAlignment.Top; } _tipWindow.PlacementRectangle = new Rect(block.x, 0.0, 0.0, 0.0); if (_tipWindow.IsOpen) { var existingContext = _tipWindow.Content as FrameworkElement; if ((existingContext != null) && (existingContext.Tag == block.tag)) { // No changes from the last time we opened the tip. return; } } FrameworkElement context = block.tag.Context(_coloring, _view.FormattedLineSource.DefaultTextProperties); context.Tag = block.tag; //The width of the view is in zoomed coordinates so factor the zoom factor into the tip window width computation. double zoom = _view.ZoomLevel / 100.0; _tipWindow.MaxWidth = Math.Max(100.0, _view.ViewportWidth * zoom * 0.5); _tipWindow.MinHeight = _tipWindow.MaxHeight = context.Height + 12.0; var rd = _formatMap.GetProperties("TextView Background"); if (rd.Contains(EditorFormatDefinition.BackgroundBrushId)) { _tipWindow.Background = rd[EditorFormatDefinition.BackgroundBrushId] as Brush; } _tipWindow.Content = context; _tipWindow.IsOpen = true; StructureMarginElement.LogTipOpened("VS/PPT-Structure/AdornmentTipOpened", context); return; } } } } } this.CloseTip(); }
private void renderColumnsForLines(GeometryGroup geometry, List<int> columns, ITextViewLineCollection lines) { double top = 0.0, bottom = _view.ViewportHeight; int lineindex = 0; bool resetTopAtNextLine = true; int leftmostcolumn = getFirstColumn(); int rightmostcolumn = getLastColumn(); foreach (var line in lines) { // Create new columns starting from this line if (resetTopAtNextLine) { top = line.Top - _view.ViewportTop; } bottom = line.Bottom - _view.ViewportTop; // If next line is not starting at a different column than this // one we need to draw this line immediately, and disregard // the current line's top for when drawing the next lines. resetTopAtNextLine = (!line.IsLastTextViewLineForSnapshotLine || !line.IsFirstTextViewLineForSnapshotLine); // We need to draw the current columns before next line if (resetTopAtNextLine) { renderColumns(geometry, columns, top, bottom, _linesOffset[lineindex], leftmostcolumn, rightmostcolumn); } lineindex++; } if (!resetTopAtNextLine && ((lineindex - 1) < _linesOffset.Count)) { renderColumns(geometry, columns, top, bottom, _linesOffset[lineindex - 1], leftmostcolumn, rightmostcolumn); } }
public static bool MarkerGeometrySpansMultipleLines(ITextViewLineCollection collection, SnapshotSpan bufferSpan) { ITextViewLine start = collection.GetTextViewLineContainingBufferPosition(bufferSpan.Start); return(start == null || bufferSpan.End > start.EndIncludingLineBreak); }