Custom squiggle tagger with tooltip

SyntaxEditor for WPF Forum

Posted 6 years ago by Anders Ekelund
Version: 13.2.0591
Avatar

I have been trying to add tooltips to the CustomSquiggleTagger demo project, by doing the following:

1) Register SquiggleTagQuickInfoProvider on the SyntaxLanguage (like you do to get tooltips for syntax errors)

this.RegisterService(new SquiggleTagQuickInfoProvider());

 2) Setting a ContentProvider on the SquiggleTag

SquiggleTag tag = new SquiggleTag();
tag.ContentProvider = new PlainTextContentProvider("TestingTesting");

But no QuickInfo tooltip appear when I hover over the squiggle. What I am missing? Or am I on the wrong track?

Thanks,
/Anders

Comments (10)

Posted 6 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Anders,

Do you also have this line, as shown in the Getting Started #5 QuickStart?

this.RegisterService(new CodeDocumentTaggerProvider<ParseErrorTagger>(typeof(ParseErrorTagger)));


Actipro Software Support

Posted 6 years ago by Anders Ekelund
Avatar

Sadly that did not make any difference. What I am trying to do is to create my own squiggle provider that behaves similar to the parse error tagger, not use the parse error tagger directly.

After some additional experiments I found one thing that did work: Changing the sample SquiggleTagQuickInfoProvider so that it inherits from CollectionTagger<ISquiggleTag> instead of TaggerBase<ISquiggleTag>.

I don't really understand why this change would help, but at least I have something that works now.

Thanks,
/Anders

Posted 6 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Anders,

A CollectionTagger<> will require you to add tag results to it and will return them to tag aggregators as appropriate (it handle's the core plumbing for you).  This is good if you know a fixed list of tagged ranges.

A TaggerBase<> sort of tagger is more low-level and for if you want to dynamically get callbacks when tags are searched for.  You can provide your own logic and result appropriate results.  This is more of a "virtualized" way of doing tagging.


Actipro Software Support

Posted 2 years ago by Frederic Gregoire
Avatar

This is 4 years latter but I'm having the same issue. I am using the sample "AdornmentsSquigglesIntro" for a custom squiggle tagger. I want to display a tooltip over the squiggled text. My SyntaxLanguage class looks like this:

Public Sub New()
    MyBase.New("Squiggles")

    Me.RegisterService(New CodeDocumentTaggerProvider(Of CustomSquiggleTagger)
        (GetType(CustomSquiggleTagger)))

    Me.RegisterService(New SquiggleTagQuickInfoProvider())

End Sub

 

And In my CustomSquiggleTagger is the same as the sample except I added the following lines in the GetTags method:

Dim tag As New SquiggleTag()
tag.ClassificationType = ClassificationTypes.Warning
tag.ContentProvider = New PlainTextContentProvider("Testing")

 

While all the rest remains the same. I tried changing the Inherits from CollectionTagger(Of ISquiggleTag) and TaggerBase(Of ISquiggleTag) of the CustomSquiggleTagger but none of them allow me to see the tooltip when hovering over them.

Any help or suggestions on want I am doing wrong?

Thanks

Posted 2 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Frederic,

The SquiggleTagQuickInfoProvider creates a tag aggregator for the ISquiggleTag type, meaning your tagger must implement ITagger<ISquiggleTag>.  Making your CustomSquiggleTagger inherit CollectionTagger<ISquiggleTag> would accomplish that.  With that in place and the lines you have above, I would think it would work.

If you can't figure it out, please send us a new simple sample project showing the issue and we can debug it. Email our support address with a renamed .zip file extension so it doesn't get spam blocked.  Thanks!


Actipro Software Support

Posted 2 years ago by Daisuke Nakada
Avatar

Hi,

Could you look at my code to see why it does not show tooltips?

Squiggle lines are being properly displayed currently.

 

My tagger is like this:

public class CustomSquiggleTagger : CollectionTagger<ISquiggleTag> {
  private static ISquiggleTag unknownIdentifierSquiggleTag = new SquiggleTag(ClassificationTypes.Warning, new PlainTextContentProvider("not registered"));
  private ITagAggregator<ITokenTag> tokenTagAggregator;

  public CustomSquiggleTagger(ICodeDocument document)
    : base("CustomSquiggleTagger", new Ordering[] { new Ordering(TaggerKeys.Token, OrderPlacement.Before) }, document, true) {

    tokenTagAggregator = document.CreateTagAggregator<ITokenTag>();
  }

  public override IEnumerable<TagSnapshotRange<ISquiggleTag>> GetTags(NormalizedTextSnapshotRangeCollection snapshotRanges, object parameter) {
    foreach (TextSnapshotRange snapshotRange in snapshotRanges) {
      IEnumerable<TagSnapshotRange<ITokenTag>> tokenTagRanges = tokenTagAggregator.GetTags(snapshotRange);

      foreach (TagSnapshotRange<ITokenTag> tokenTagRange in tokenTagRanges) {
        if (tokenTagRange.Tag.Token.Key == "Identifier" && IsUnknownIdentifier(tokenTagRange.SnapshotRange.Text)) {
          yield return new TagSnapshotRange<ISquiggleTag>(
            new TextSnapshotRange(snapshotRange.Snapshot, tokenTagRange.SnapshotRange.TextRange),
            unknownIdentifierSquiggleTag);
        }
      }
    }
  }
}

 

And in my Language's constructor, I have this code:

this.RegisterService(new SquiggleTagQuickInfoProvider());
this.RegisterService(new CodeDocumentTaggerProvider<CustomSquiggleTagger>(typeof(CustomSquiggleTagger)));
Posted 2 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hello,

I think it's because in the quick info case, you are passing in a zero-length snapshot range to the token aggregator.  That would probably need to cover at least one offset to get a result.

Add some code like this and use this coerced target snapshot range instead:

var targetSnapshotRange = snapshotRange;
if (targetSnapshotRange.IsZeroLength)
	targetSnapshotRange = new TextSnapshotRange(targetSnapshotRange.Snapshot, targetSnapshotRange.StartOffset, targetSnapshotRange.StartOffset + 1);

I believe that will help.


Actipro Software Support

Posted 2 years ago by Daisuke Nakada
Avatar

Thank you! I modified as you taught me and it finally worked!

But I do not understand what "snapshotRange.IsZeroLength = true" means and when and why that happens.

Does it occur for CustomClassificationTagger?

On my CustomClassificationTagger's GetTags method, I am doing nothing when the length of snapshotRange is 0.

override public IEnumerable<TagSnapshotRange<IClassificationTag>> GetTags(NormalizedTextSnapshotRangeCollection snapshotRanges, object parameter) {
  foreach (TextSnapshotRange snapshotRange in snapshotRanges) {
    if (snapshotRange.IsZeroLength) {
      continue;
    }

    ...
Posted 2 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hello,

The Quick Info is asking for a zero-length snapshot range at the quick info target offset to see if there are any squiggle tags.  It's not you directly asking for it.  

However token taggers (which you call to get your squiggle data in your custom tagger) won't return tokens for a zero-length snapshot.  That's why I suggested modifying the snapshot range to be at least one character so that the token tagger returns proper results.


Actipro Software Support

Posted 2 years ago by Daisuke Nakada
Avatar

I understand. Thanks a lot.

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.