New to Telerik UI for WinFormsStart a free 30-day trial

How to Achieve Multiple Highlight Rules in SyntaxEditor

Updated over 6 months ago

Environment

Product VersionProductAuthor
2022.1.222RadSyntaxEditor for WinFormsDesislava Yordanova

Description

By default, RadSyntaxEditor offers default highlight style for the Find and Replace functionality. This article demonstrates how to highlight in a different way another portion of text matches.

Default Highlight Style

customize-highlight-style-for-found-results-in-syntaxeditor 001

Solution

RadSyntaxEditor is purposed to offer one common highlight style for the found search results. Hence, multiple HighlightAllMatches rules are not supported. If you need to highlight specific portion of text in a different color (different than the standard search format style), it would be necessary to create a custom tagger to classify the desired words and mark these words as specific. Then, add a custom UI layer to paint the desired format style. As a result, you will have different styles for the different words to be classified.

In the below code snippet, there are two words "this" and "editor" that are classified as different:

Multiple Highlight Styles

multiple-highlight-rules 001

C#
public RadForm1()
{
    InitializeComponent();

    this.radSyntaxEditor1.SyntaxEditorElement.UILayersBuilder = new CustomUILayersBuilder();
    this.radSyntaxEditor1.TextFormatDefinitions.AddLast(MyTextSearchHighlightTagger.TelerikClassificationType,
    new TextFormatDefinition(new SolidBrush(System.Drawing.Color.Black), new SolidBrush(System.Drawing.Color.Red),
                         null,
                         new Telerik.WinForms.Controls.SyntaxEditor.UI.Pen(new SolidBrush(System.Drawing.Color.Green), 2)));

    MyTextSearchHighlightTagger highlightTagger = new MyTextSearchHighlightTagger(this.radSyntaxEditor1.SyntaxEditorElement);
    this.radSyntaxEditor1.TaggersRegistry.RegisterTagger(highlightTagger);
}
public class MyTextSearchHighlightTagger : WordTaggerBase
{
    public static readonly ClassificationType TelerikClassificationType = new ClassificationType("Telerik");
    public static readonly Dictionary<string, ClassificationType> WordsToClassificationType = new Dictionary<string, ClassificationType>();
    private StringComparison comparison = StringComparison.OrdinalIgnoreCase; 
    public MyTextSearchHighlightTagger(RadSyntaxEditorElement editor)
       : base(editor)
    { 
        WordsToClassificationType.Add("this", TelerikClassificationType);
        WordsToClassificationType.Add("editor", TelerikClassificationType);
    }

    protected override Dictionary<string, ClassificationType> GetWordsToClassificationTypes()
    {
        return MyTextSearchHighlightTagger.WordsToClassificationType;
    }

    public override IEnumerable<TagSpan<ClassificationTag>> GetTags(NormalizedSnapshotSpanCollection spans)
    {

        if (WordsToClassificationType.Count == 0)
        {
            yield break;
        }

        TextSnapshot snapshot = this.Document.CurrentSnapshot;
        foreach (TextSnapshotSpan snapshotSpan in spans)
        {
            string lineString = snapshotSpan.GetText();
            foreach (KeyValuePair<string, ClassificationType> searchWord in WordsToClassificationType)
            {

                int index = lineString.IndexOf(searchWord.Key, comparison);
                while (index != -1)
                {
                    TextSnapshotSpan tempSnapshotSpan = new TextSnapshotSpan(snapshot,
                        new Telerik.WinForms.SyntaxEditor.Core.Text.Span(snapshotSpan.Start + index, searchWord.Key.Length));

                    yield return new TagSpan<ClassificationTag>(tempSnapshotSpan, new ClassificationTag(TelerikClassificationType));

                    index = lineString.IndexOf(searchWord.Key, index + searchWord.Key.Length);
                }
            }
        }
    }
}

public class CustomUILayersBuilder : Telerik.WinForms.Controls.SyntaxEditor.UI.Layers.UILayersBuilder
{
    public override void BuildUILayers(UILayerStack uiLayers)
    { 
        uiLayers.AddLast(new MyTextUnderlineUILayer());
        base.BuildUILayers(uiLayers);
       
    }
}
public class MyTextUnderlineUILayer : LineBasedUILayer<ClassificationTag>
{
    public override string Name => "MyTextUnderlineUILayer";

    protected override FrameworkElement GetLinePartUIElement(ClassificationTag tag,
                                                             Telerik.WinForms.SyntaxEditor.Core.Text.Span span,
                                                             UIUpdateContext updateContext)
    {
        if (tag.ClassificationType != MyTextSearchHighlightTagger.TelerikClassificationType)
        {
            return null;
        }

        TextFormatDefinition textFormatting = updateContext.Editor.TextFormatDefinitions.
            GetTextFormatDefinition(MyTextSearchHighlightTagger.TelerikClassificationType);
        Telerik.WinControls.SyntaxEditor.UI.Rect rect = updateContext.Editor.GetLinePartBoundingRectangle(span, true);


        Telerik.WinControls.SyntaxEditor.UI.Rectangle rectangle = this.GetElementFromPool<Telerik.WinControls.SyntaxEditor.UI.Rectangle>();
        rectangle.Width = rect.Width;
        rectangle.Height = rect.Height;
        rectangle.Fill = textFormatting.Background;

        rectangle.Stroke = textFormatting.Border.Brush;
        rectangle.StrokeThickness = textFormatting.Border.Thickness.Left;

        return rectangle;
    }

    protected override void ResetPooledElementProperties(object element)
    {
    }
}

private void radTextBox1_TextChanged(object sender, EventArgs e)
{
    this.radSyntaxEditor1.SyntaxEditorElement.HighlightAllMatches(this.radTextBox1.Text);
}
       

See Also