SixPairs

July 6, 2014

Simplest Editor TextAdornment

Filed under: VS Editor — Ceyhun Ciper @ 10:31

Add a border around each line.

namespace Microsoft.VisualStudio.Text.Editor
{
  using Microsoft.VisualStudio.Text.Formatting;
  using Microsoft.VisualStudio.Utilities;
  using System.ComponentModel.Composition;
  using System.Windows;
  using System.Windows.Controls;
  using System.Windows.Media;

  [Export(typeof(IWpfTextViewCreationListener))]
  [ContentType("text")]
  [TextViewRole(PredefinedTextViewRoles.Document)]
  internal sealed class TextAdornment1Factory : IWpfTextViewCreationListener
  {
    [Export(typeof(AdornmentLayerDefinition))]
    [Name("TextAdornment1")]
    [Order(After = PredefinedAdornmentLayers.Selection, Before = PredefinedAdornmentLayers.Text)]
    public AdornmentLayerDefinition editorAdornmentLayer = null;

    public void TextViewCreated(IWpfTextView textView)
    {
      new TextAdornment1(textView);
    }
  }

  public class TextAdornment1
  {
    IAdornmentLayer layer;
    IWpfTextView view;

    public TextAdornment1(IWpfTextView view)
    {
      this.view = view;
      layer = view.GetAdornmentLayer("TextAdornment1");

      this.view.LayoutChanged += OnLayoutChanged;
    }

    private void OnLayoutChanged(object sender, TextViewLayoutChangedEventArgs e)
    {
      foreach (ITextViewLine line in e.NewOrReformattedLines)
      {
        this.CreateVisuals(line);
      }
    }

    private void CreateVisuals(ITextViewLine line)
    {
      IWpfTextViewLineCollection textViewLines = view.TextViewLines;

      Geometry g = textViewLines.GetMarkerGeometry(line.Extent);
      if (g != null)
      {
        var border = new Border
        {
          Width = g.Bounds.Width,
          Height = g.Bounds.Height,
          BorderBrush = Brushes.Violet,
          BorderThickness = new Thickness(0.8),
        };

        Canvas.SetLeft(border, g.Bounds.Left);
        Canvas.SetTop(border, g.Bounds.Top);

        layer.AddAdornment(AdornmentPositioningBehavior.TextRelative, line.Extent, null, border, null);
      }
    }
  }
}

Exercises

  1. Add a border around each line, bypassing initial spaces.

    namespace Microsoft.VisualStudio.Text.Editor
    {
      using Microsoft.VisualStudio.Text.Formatting;
      using Microsoft.VisualStudio.Utilities;
      using System.ComponentModel.Composition;
      using System.Text.RegularExpressions;
      using System.Windows;
      using System.Windows.Controls;
      using System.Windows.Media;
    
      [Export(typeof(IWpfTextViewCreationListener))]
      [ContentType("text")]
      [TextViewRole(PredefinedTextViewRoles.Document)]
      internal sealed class TextAdornment1Factory : IWpfTextViewCreationListener
      {
        [Export(typeof(AdornmentLayerDefinition))]
        [Name("TextAdornment1")]
        [Order(After = PredefinedAdornmentLayers.Selection, Before = PredefinedAdornmentLayers.Text)]
        public AdornmentLayerDefinition editorAdornmentLayer = null;
    
        public void TextViewCreated(IWpfTextView textView)
        {
          new TextAdornment1(textView);
        }
      }
    
      public class TextAdornment1
      {
        IAdornmentLayer layer;
        IWpfTextView view;
    
        public TextAdornment1(IWpfTextView view)
        {
          this.view = view;
          layer = view.GetAdornmentLayer("TextAdornment1");
    
          this.view.LayoutChanged += OnLayoutChanged;
        }
    
        private void OnLayoutChanged(object sender, TextViewLayoutChangedEventArgs e)
        {
          foreach (ITextViewLine line in e.NewOrReformattedLines)
          {
            this.CreateVisuals(line);
          }
        }
    
        private void CreateVisuals(ITextViewLine line)
        {
          IWpfTextViewLineCollection textViewLines = view.TextViewLines;
          int start = line.Start;
    
          var m = new Regex(@"\S").Match(line.Extent.GetText());
          if (m.Success) start += m.Index;
          
          var span = new SnapshotSpan(line.Snapshot, Span.FromBounds(start, line.End));
    
          Geometry g = textViewLines.GetMarkerGeometry(span);
          if (g != null)
          {
            var border = new Border
            {
              Width = g.Bounds.Width,
              Height = g.Bounds.Height,
              BorderBrush = Brushes.Violet,
              BorderThickness = new Thickness(0.8),
            };
    
            Canvas.SetLeft(border, g.Bounds.Left);
            Canvas.SetTop(border, g.Bounds.Top);
    
            layer.AddAdornment(AdornmentPositioningBehavior.TextRelative, span, null, border, null);
          }
        }
      }
    }
        
  2. Highlight spaces.

    namespace Microsoft.VisualStudio.Text.Editor
    {
      using Microsoft.VisualStudio.Text.Formatting;
      using Microsoft.VisualStudio.Utilities;
      using System.ComponentModel.Composition;
      using System.Text.RegularExpressions;
      using System.Windows;
      using System.Windows.Controls;
      using System.Windows.Media;
    
      [Export(typeof(IWpfTextViewCreationListener))]
      [ContentType("text")]
      [TextViewRole(PredefinedTextViewRoles.Document)]
      internal sealed class TextAdornment1Factory : IWpfTextViewCreationListener
      {
        [Export(typeof(AdornmentLayerDefinition))]
        [Name("TextAdornment1")]
        [Order(After = PredefinedAdornmentLayers.Selection, Before = PredefinedAdornmentLayers.Text)]
        public AdornmentLayerDefinition editorAdornmentLayer = null;
    
        public void TextViewCreated(IWpfTextView textView)
        {
          new TextAdornment1(textView);
        }
      }
    
      public class TextAdornment1
      {
        IAdornmentLayer layer;
        IWpfTextView view;
    
        public TextAdornment1(IWpfTextView view)
        {
          this.view = view;
          layer = view.GetAdornmentLayer("TextAdornment1");
    
          this.view.LayoutChanged += OnLayoutChanged;
        }
    
        private void OnLayoutChanged(object sender, TextViewLayoutChangedEventArgs e)
        {
          foreach (ITextViewLine line in e.NewOrReformattedLines)
          {
            this.CreateVisuals(line);
          }
        }
    
        private void CreateVisuals(ITextViewLine line)
        {
          IWpfTextViewLineCollection textViewLines = view.TextViewLines;
          int start = line.Start;
          int end = line.End;
    
          for (int i = start; i < end; i++)
          {
            if (line.Snapshot[i] == ' ')
            {
              var span = new SnapshotSpan(line.Snapshot, Span.FromBounds(i, i + 1));
    
              Geometry g = textViewLines.GetMarkerGeometry(span);
              if (g != null)
              {
                var border = new Border
                {
                  Width = g.Bounds.Width,
                  Height = g.Bounds.Height / 8,
                  BorderBrush = Brushes.Black,
                  BorderThickness = new Thickness(0.8, 0, 0.8, 0.8),
                };
    
                Canvas.SetLeft(border, g.Bounds.Left);
                Canvas.SetTop(border, g.Bounds.Bottom - g.Bounds.Height / 8);
    
                layer.AddAdornment(AdornmentPositioningBehavior.TextRelative, span, null, border, null);
              }
            }
          }
        }
      }
    }
        
  3. TBD

        
  4. TBD

        

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a comment

Create a free website or blog at WordPress.com.