Higlighting one row in editor

SyntaxEditor for WPF Forum

Posted 9 years ago by Steve Montgomery
Avatar
I have modified the alternating row quckstart example so that it only highlights one row. Within the AlternatingRowsAdornmentManager class, I added a public property called HighlightRow.

My plan was to retrieve the instance of this class using
AlternatingRowsAdornmentManager adornment = (AlternatingRowsAdornmentManager)editor.Document.Language.GetService(typeof(AlternatingRowsAdornmentManager))
Then, I would set the row using adornment.HighlightRow.

The problem is that GetService is returning a null.

I used GetAllServices to create a list of registered services, and I can see AlternatingRowsAdornmentManager in there, but GetService is not finding it.

Can someone help me with this?

- Steve

Comments (8)

Posted 9 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi Steve,

What type do you register your service with? Make sure you register it with the same type that you retrieve it with.


Actipro Software Support

Posted 9 years ago by Steve Montgomery
Avatar
I am using AlternatingRowsAdornmentManager for both registration and retrieval. I am registering using the exact code from the quickstart and retrieving using the code I put in the last post.

Has anyone successfully used the GetService function? If so, can you post your code to register the service and to retrieve it using GetService? Are there any examples ActiPro provides that show how to do this?

Thanks
Posted 9 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
I think the IntelliPromptQuickInfo sample shows it. However I think your problem might be you have the typeof(...) that you are passing into GetService. Remove that and just leave the type name only. That's most likely the issue.


Actipro Software Support

Posted 9 years ago by Steve Montgomery
Avatar
OK, so if I write it like this:
AlternatingRowsAdornmentManager adornment = (AlternatingRowsAdornmentManager)editor.Document.Language.GetService(AlternatingRowsAdornmentManager)
it wont compile. Can you re-write my example code so that it will work? I think I am not understanding what you are saying. I will look at the intellisense sample in the meantime.
Posted 9 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
In our sample we do this:
IQuickInfoProvider provider = editor.Document.Language.GetService<CustomQuickInfoProvider>();


Actipro Software Support

Posted 9 years ago by Steve Montgomery
Avatar
I got it working. It is actually more complicated because you don't register an adornment manager directly, you do it indirectly through AdornmentManagerProvider. Here is the code that works:
AdornmentManagerProvider<AlternatingRowsAdornmentManager> adornmentProvider = lang.GetService<AdornmentManagerProvider<AlternatingRowsAdornmentManager>>();
AlternatingRowsAdornmentManager adornmentManager = (AlternatingRowsAdornmentManager)adornmentProvider.GetAdornmentManager(editor.syntaxEditor1.ActiveView);
Using this, I can set adornmentManager.HighlightRow and it works, sort of.

The highlighted line doesn't change automatically. It stays where it was before I changed HighlightRow. However, if I scroll the highlighted row off of the screen and then scroll back to the row that was supposed to be highlighted, the correct row is hightlighted. It is almost like I need to force the adornment to re-render after I change my variable. I tried using UpdateLayout on the editor itself, but to no effect. What do I need to do to get the adornment to re-render once I change HighlightRow?
Posted 9 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Steve,

If you are using AdornmentManagerProvider, make sure you pass a singletonKey to its constructor (one overload takes it). If you do that, then you can just call:
editor.ActiveView.Properties.TryGetValue(singletonKey, out adornmentManager)
That will give you the adornment manager that gets installed by the provider. It's effectively what your GetAdornmentManager call does if you set a singletonKey. If you didn set a singletonKey, then a new manager is being created with each call, which is bad.

If you have a single element in your adornment manager and want to re-render it, just change the location of the adornment to whatever is appropriate for your HighlightRow. You can do this with Canvas.SetLeft/SetTop methods. Or change properties on the element itselve to re-render it.


Actipro Software Support

Posted 9 years ago by Mick George - Software Engineer, CNC Software, Inc.
Avatar
I did not realize you could do that with a Syntax Editor's Properties so I created a highlight line class for my MDI project using the quick start project as a guide. I have my highlight line mimicking VS2010 and seems to work as expected. For those interested my code is below.

/// <summary>
    /// Represents an adornment manager for a view that renders a line.
    /// </summary>
    public class HighlightLineAdornmentManager : AdornmentManagerBase<IEditorView>
    {
        /// <summary>
        /// Layer definition for this adornment layer.
        /// </summary>
        private static AdornmentLayerDefinition layerDefinition =
        new AdornmentLayerDefinition("SelectedLine", new Ordering(AdornmentLayerDefinitions.TextBackground.Key, OrderPlacement.After));

        /// <summary>
        /// Initializes a new instance of the HighlightLineAdornmentManager class.
        /// </summary>
        /// <param name="view">The view to which this manager is attached.</param>
        public HighlightLineAdornmentManager(IEditorView view)
            : base(view, layerDefinition, false)
        {
            // Attach to events
            view.TextAreaLayout += new EventHandler<TextViewTextAreaLayoutEventArgs>(this.OnViewTextAreaLayout);
            view.SelectionChanged += new EventHandler<EditorViewSelectionEventArgs>(this.OnViewSelectionChanged);
            view.HasFocusChanged += new RoutedEventHandler(this.OnViewHasFocusChanged);
        }

        /// <summary>
        /// Occurs when the manager is closed and detached from the view.
        /// </summary>
        /// <remarks>
        /// The default implementation of this method does nothing.
        /// Overrides should release any event handlers set up in the manager's constructor.
        /// </remarks>
        protected override void OnClosed()
        {
            // Detach from events
            this.View.TextAreaLayout -= new EventHandler<TextViewTextAreaLayoutEventArgs>(this.OnViewTextAreaLayout);
            this.View.SelectionChanged -= new EventHandler<EditorViewSelectionEventArgs>(this.OnViewSelectionChanged);
            this.View.HasFocusChanged -= new RoutedEventHandler(this.OnViewHasFocusChanged);

            // Remove any remaining adornments
            this.AdornmentLayer.RemoveAllAdornments();
        }

        /// <summary>
        /// Adds an adornment to the <see cref="AdornmentLayer"/>.
        /// </summary>
        /// <param name="viewLine">The current <see cref="ITextViewLine"/> being examined.</param>
        private void AddAdornment(ITextViewLine viewLine)
        {
            // Create a brush
            SolidColorBrush brush = new SolidColorBrush(Color.FromRgb(0xF0, 0xF0, 0xF0));
            brush.Freeze();

            // Create the adornment
            Rectangle element = new Rectangle();
            element.Width = 1000000;
            element.Height = viewLine.Bounds.Height;
            element.Fill = brush;

            // Add the adornment to the layer
            this.AdornmentLayer.AddAdornment(element, new Point(0, viewLine.Bounds.Top), viewLine, null);
        }

        /// <summary>
        /// Occurs when a view text area layout (scroll for example) occurs.
        /// </summary>
        /// <param name="sender">The sender of the event.</param>
        /// <param name="e">A <see cref="TextViewTextAreaLayoutEventArgs"/> that contains the event data.</param>
        private void OnViewTextAreaLayout(object sender, TextViewTextAreaLayoutEventArgs e)
        {
            IEditorView view = sender as IEditorView;

            // Get the line the caret appears on within this view
            IEditorViewLine line = view.CurrentViewLine;

            // Remove all previous (should be one) adornments
            this.AdornmentLayer.RemoveAllAdornments();

            if (line.Visibility != TextViewLineVisibility.Hidden)
            {
                // Add a new adorment on the current line
                this.AddAdornment(line);
            }
        }

        /// <summary>
        /// Occurs when a view selection change occurs.
        /// </summary>
        /// <param name="sender">The sender of the event.</param>
        /// <param name="e">A <see cref="EditorViewSelectionEventArgs"/> that contains the event data.</param>
        private void OnViewSelectionChanged(object sender, EditorViewSelectionEventArgs e)
        {
            IEditorView view = sender as IEditorView;

            // Get the line the caret appears on within this view
            IEditorViewLine line = view.CurrentViewLine;

            // Remove all previous (should be one) adornments
            this.AdornmentLayer.RemoveAllAdornments();

            // Add a new adorment on the current line
            this.AddAdornment(line);
        }

        /// <summary>
        /// Occurs when a view focus hanged occurs.
        /// </summary>
        /// <param name="sender">The sender of the event.</param>
        /// <param name="e">A <see cref="TextViewTextAreaLayoutEventArgs"/> that contains the event data.</param>
        private void OnViewHasFocusChanged(object sender, RoutedEventArgs e)
        {
            this.AdornmentLayer.RemoveAllAdornments();
        }      
    } 

 this.RegisterService(new AdornmentManagerProvider<HighlightLineAdornmentManager>(typeof(HighlightLineAdornmentManager)));
 
The latest build of this product (v2019.1 build 0683) was released 1 month ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.