In This Article

IntelliPrompt Quick Info Provider

Languages can choose to support IntelliPrompt quick info popups that are automatically displayed when the pointer moves over text and/or other parts of the editor, such as margins.

Basic Concepts

Context Retrieval

The IQuickInfoProvider defines two GetContext method overloads, both of quick are expected to return a context object given a certain parameter. One overload accepts an IHitTestResult (from a pointer event) and the other overload accepts a zero-based text offset.

A context object can be anything, but it should be some custom type that gives enough information to provide to the RequestSession method later and have that method be able to create a quick info session based on the context. It also must implement value equality via an Equals method override.

Implementors of these methods should use code to examine the context of the hit test result or offset in the view. This may involve token scanning and/or AST examination if available. The context data (in a method declaration, in a type declaration, in a documentation comment, etc.) should be wrapped within the context object retuned by the GetContext methods.

How Contexts Are Used

Context objects should always be stored in the IQuickInfoSession.Context property. As pointer movements occur, a quick info provider repeatedly calls the GetContext method with related pointer hit test results. If the context of an open quick info session matches (value equality) the GetContext return value, the provider knows that no new quick info session needs to be displayed. If GetContext returns a null value, then any existing open quick info session should be closed. If GetContext returns a context that doesn't match the existing session's context, or there is no existing open session, the RequestSession method is called, passing along the new context to use.

Important

All context objects must implement an Equals method override so that value equality functions properly.

Requesting a Session

The final method in the IQuickInfoProvider interface is RequestSession. This method is automatically called whenever a new context object has been retrieved that should be used to create and open a new quick info session.

Implementations of this method should create a new quick info session, store the passed context in its Context property, build its content based on the data in the context object, and open the quick info session (show it).

The QuickInfoProviderBase Base Class

The IQuickInfoProvider interface implements IEditorViewPointerInputEventSink and thus is able to process pointer (e.g., pointer) input from within a SyntaxEditor. There is some complicated code needed to do this processing, which is wrapped up in the handy abstract QuickInfoProviderBase class.

The easiest way to implement an IQuickInfoProvider for a language is to inherit the QuickInfoProviderBase class. Then just override its abstract members.

By default, its virtual GetContext overload that takes an IHitTestResult is designed to see if the hit is over a character in the text area and if so, call the other abstract GetContext overload that accepts an offset. This is done since most of the time, a quick info provider will be used for showing quick info popups related to text content. To support quick info popups for other parts of the editor, override the GetContext overload that takes an IHitTestResult.

A QuickInfoProviderBase-based provider will automatically close a quick info session it created when appropriate. However, to do this, it needs to know which Type of context objects can be returned by its GetContext methods. The ContextTypes property must be implemented to provide this information. For instance, if a quick info provider can return a context object of type KeywordQuickInfoContext from GetContext, then the ContextTypes should return the KeywordQuickInfoContext type.

Registering with a Language

Any object that implements IQuickInfoProvider can be associated with a syntax language by registering it as an IQuickInfoProvider service on the language.

This code registers a quick info provider in the quickInfoProvider variable with the syntax language that is already declared in the language variable:

language.RegisterService(quickInfoProvider);

Ordering Providers

The IQuickInfoProvider interface inherits the IOrderable interface. When multiple language services are registered that implement IQuickInfoProvider, they can be ordered. The highest priority provider will be used first. If it indicates that a session was opened, no other providers will be used. If it indicates that a session was not opened, the next provider is checked, and so on. This allows for layering of multiple providers.

Showing Quick Info Based on a Button Click

Many applications provide some sort of Display Quick Info button in their application toolbar. When displaying quick info popups in this mode, pointer move/hover input should be ignored until the next quick info session is requested.

This code handles a button click event and shows how to properly focus the editor, get the current IQuickInfoProvider, create a context based on the offset of the caret, and request a quick info session:

private void OnShowQuickInfoButtonClick(object sender, RoutedEventArgs e) {
	// Focus the editor
	editor.Focus();

	// Get the IQuickInfoProvider that is registered with the language
	IQuickInfoProvider provider = editor.Document.Language.GetService<IQuickInfoProvider>();
	if (provider != null) {
		// Create a context
		object context = provider.GetContext(editor.ActiveView, editor.Caret.Offset);

		if (context != null) {
			// Request that a session is created based on the context, and disable pointer tracking since
			//   this request is initiated from a button click
			provider.RequestSession(editor.ActiveView, context, false);
		}
	}
}

Built-In Quick Info Provider for Collapsed Outlining Nodes

When using the code outlining features, sometimes the end user will collapse outlining nodes. By default, nothing happens when the pointer is hovered over a collapsed outlining node adornment (normally a box with "..." in it). However, there is a built-in IQuickInfoProvider implementation called CollapsedRegionQuickInfoProvider that watches for pointer hovers over collapsed regions and will automatically show a quick info tip with the contained content on pointer hovers.

To enable this feature simply register a CollapsedRegionQuickInfoProvider instance as a service on your language. Note that if you register other IQuickInfoProvider services, make sure they are not handling scenarios that would normally be picked up by the CollapsedRegionQuickInfoProvider. You could order them after the CollapsedRegionQuickInfoProvider (see Ordering Providers section above) to ensure they occur after it is already checked.

This code registers the built-in CollapsedRegionQuickInfoProvider service with the syntax language that is already declared in the language variable:

language.RegisterService(new CollapsedRegionQuickInfoProvider());

The content displayed in the quick info tip will be syntax highlighted by default. Set the IsSyntaxHighlightingEnabled property to false to display plain text without syntax highlighting.

If you wish to customize the content of the popup from its default, create a class that inherits CollapsedRegionQuickInfoProvider and override its GetContent method. That method is passed the source IEditorView and TextSnapshotRange, and returns the content to display for that snapshot range. Then register an instance of this custom class as the service instead.

Built-In Quick Info Provider for Squiggle Tags

When using the parsing framework and the ParseErrorTagger (or other custom tagger that uses SquiggleTag tags), there will be squiggle adornments in the document window. By default, nothing happens when the pointer is hovered over these adornments. However, there is a built-in IQuickInfoProvider implementation called SquiggleTagQuickInfoProvider that watches for pointer hovers over squiggle adorned regions and will automatically show a quick info tip with the parse error description on pointer hovers.

To enable this feature, simple register a SquiggleTagQuickInfoProvider instance as a service on your language. Note that if you register other IQuickInfoProvider services, make sure they are not handling scenarios that would normally be picked up by the SquiggleTagQuickInfoProvider. You could order them after the SquiggleTagQuickInfoProvider (see Ordering Providers section above) to ensure they occur after it is already checked.

This code registers the built-in SquiggleTagQuickInfoProvider service with the syntax language that is already declared in the language variable:

language.RegisterService(new SquiggleTagQuickInfoProvider());

Implementation Notes

SquiggleTagQuickInfoProvider works by looking for any tags that are at the text offset under the pointer when a pointer hover event is detected. It uses an ITagAggregator for tag type ISquiggleTag that queries each appropriate tagger with a single snapshot range containing the target offset.

Since nothing within SyntaxEditor caches displayed squiggle tags, taggers must return at least one tag that contains the target offset for quick info to show.

Collection taggers are often a good choice for marking errors. They work like a collection where you can add/remove tags like SquiggleTag. In fact, our very own ParseErrorTagger is a CollectionTagger. Collection taggers are described in detail in the Taggers and Tagger Providers topic and support the SquiggleTagQuickInfoProvider requirements well.