Highlighting Style Registries
Highlighting style registries provide a mapping from classification types to highlighting styles. They tell SyntaxEditor how the various ranges of classified text should appear within the text area.
Basic Concepts
A classification type (which could represent an identifier, comment, etc.) is a logical category that can be assigned to ranges of text via a tagger for the IClassificationTag type. Classifications are made within the text/parsing framework and therefore are not tied to the user interface.
A highlighting style registry takes these classification types and maps them to highlighting styles. Highlighting styles define formatting options that should be applied to text. Therefore via the use of highlighting style registries allows the editor to determine how classified text should be rendered.
Highlighting style registries are implementations of the IHighlightingStyleRegistry interface. The HighlightingStyleRegistry class implements this interface.
The Ambient Registry
The ambient registry is a static registry that is always available and is generally what is used by the editor. It is available via the AmbientHighlightingStyleRegistry class.
This code shows how to get an instance of the ambient registry:
IHighlightingStyleRegistry registry = AmbientHighlightingStyleRegistry.Instance;
Registering and Unregistering Entries
A registry entry consists of an IClassificationType and IHighlightingStyle pair.
Registrations can be made by calling the IHighlightingStyleRegistry.Register method. Registrations can be removed by calling the IHighlightingStyleRegistry.Unregister method.
This code registers a highlighting style in the style
variable for the common Comment
classification type in the ambient registry:
AmbientHighlightingStyleRegistry.Instance.Register(ClassificationTypes.Comment, style);
An overload for the Register method indicates whether any existing entry for the IClassificationType should be overwritten. The overload in the sample code above will not override an existing entry if one is found.
Enumerating Classification Types and Highlighting Styles
The IHighlightingStyleRegistry.ClassificationTypes property returns the collection of IClassificationType objects that are currently registered.
The IHighlightingStyleRegistry.HighlightingStyles property returns the collection of IHighlightingStyle objects that are currently registered.
Classification Type Sort Order
The IHighlightingStyleRegistry.ClassificationTypes collection is sorted in a special order. This allows you to be able to bind the collection to a list in an application options dialog.
The base sorting is performed on the IClassificationType.Description property. If a IClassificationType implements IOrderable, it is sorted before any IClassificationType that doesn't implement IOrderable. The IOrderable implementation can be used to indicate the keys of other IClassificationType after which the classification type should be sorted.
Special Classification Types (Plain Text, Line Numbers, Indicator Margin, etc.)
There are several classification types that have special meaning for SyntaxEditor, all of which are available as properties on the DisplayItemClassificationTypeProvider class. These classification types are special cased to allow for end user customization of things such as the default text format, line number margin, indicator margin, visible whitespace, etc.
The classification types on DisplayItemClassificationTypeProvider are not used unless they are registered.
Registration into the ambient highlighting style registry can be performed with this code:
new DisplayItemClassificationTypeProvider().RegisterAll();
These are the special IClassificationType properties on DisplayItemClassificationTypeProvider:
Member | Description |
---|---|
BreakpointDisabled Property |
Gets the IClassificationType to use for a disabled breakpoint. Only the border is editable in the default IHighlightingStyle that is registered for this classification type. |
BreakpointEnabled Property |
Gets the IClassificationType to use for an enabled breakpoint. Only the foreground and background are editable in the default IHighlightingStyle that is registered for this classification type. |
CodeSnippetDependentField Property |
Gets the IClassificationType to use for a code snippet dependent field. Only the border is editable in the default IHighlightingStyle that is registered for this classification type. |
CodeSnippetField Property |
Gets the IClassificationType to use for a code snippet field. Only the background is editable in the default IHighlightingStyle that is registered for this classification type. |
CollapsedText Property |
Gets the IClassificationType to use for collapsed text. Only the foreground is editable in the default IHighlightingStyle that is registered for this classification type. |
CollapsibleRegion Property |
Gets the IClassificationType to use for collapsible regions. Only the foreground and background are editable in the default IHighlightingStyle that is registered for this classification type. |
ColumnGuides Property |
Gets the IClassificationType to use for column guides when IColumnGuide.Color is not explicitly set. Only the background is editable in the default IHighlightingStyle that is registered for this classification type. |
CurrentLine Property |
Gets the IClassificationType to use for the current line highlight. Only the background and border are editable in the default IHighlightingStyle that is registered for this classification type. |
CurrentStatement Property |
Gets the IClassificationType to use for a current statement. Only the foreground and background are editable in the default IHighlightingStyle that is registered for this classification type. |
DelimiterMatching Property |
Gets the IClassificationType to use for the delimiter matching highlight. Only the background is editable in the default IHighlightingStyle that is registered for this classification type. |
FindMatchHighlight Property |
Gets the IClassificationType to use for a find match highlight. Only the background is editable in the default IHighlightingStyle that is registered for this classification type. |
FindScopeHighlight Property |
Gets the IClassificationType to use for a find scope highlight. Only the background is editable in the default IHighlightingStyle that is registered for this classification type. |
InactiveSelectedText Property |
Gets the IClassificationType to use for the selected text background when the view doesn't have focus. Only the background is editable in the default IHighlightingStyle that is registered for this classification type. |
IndentationGuides Property |
Gets the IClassificationType to use for indentation guides. Only the background is editable in the default IHighlightingStyle that is registered for this classification type. |
IndicatorMargin Property |
Gets the IClassificationType to use for the indicator margin. Only the background is editable in the default IHighlightingStyle that is registered for this classification type. |
LineNumbers Property |
Gets the IClassificationType to use for the line number margin. Only the foreground and background are editable in the default IHighlightingStyle that is registered for this classification type. |
OutliningMarginSquare Property |
Gets the IClassificationType to use for outlining margin squares. Only the foreground and background are editable in the default IHighlightingStyle that is registered for this classification type. |
OutliningMarginVerticalRule Property |
Gets the IClassificationType to use for outlining margin vertical rules. Only the foreground is editable in the default IHighlightingStyle that is registered for this classification type. |
PlainText Property |
Gets the IClassificationType to use for default text in the text area. Only the foreground and background are editable in the default IHighlightingStyle that is registered for this classification type. |
RevertedChangesMark Property |
Gets the IClassificationType to use for reverted changes marks. Only the background is editable in the default IHighlightingStyle that is registered for this classification type. |
SavedChangesMark Property |
Gets the IClassificationType to use for saved changes marks. Only the background is editable in the default IHighlightingStyle that is registered for this classification type. |
SelectedText Property |
Gets the IClassificationType to use for the selected text background when the view has focus. Only the background is editable in the default IHighlightingStyle that is registered for this classification type. |
UnsavedChangesMark Property |
Gets the IClassificationType to use for unsaved changes marks. Only the background is editable in the default IHighlightingStyle that is registered for this classification type. |
VisibleWhitespace Property |
Gets the IClassificationType to use for visible whitespace. Only the foreground is editable in the default IHighlightingStyle that is registered for this classification type. |
Highlighting Styles Options Dialog
Please see the samples for a QuickStart on how to create a highlighting styles options dialog that allows the end user to customize all aspects of the editor's display.
Importing Visual Studio Settings
The AmbientHighlightingStyleRegistry allows for importing of Visual Studio settings files (.vssettings) to theme SyntaxEditor.
SyntaxEditor after importing some custom VS settings
You can see in the screenshot above that everything from basic text to the line number margin is themed. This is all done using the highlighting style registry and the special classification types in DisplayItemClassificationTypeProvider (see above). All of these colors, etc. can be configured by the end user as well.
This code imports a .vssettings file (pre-loaded in a Stream
variable named stream
) to theme the control:
AmbientHighlightingStyleRegistry.Instance.ImportHighlightingStyles(stream);
Defining and Using an Alternate Default Registry
In most cases, the AmbientHighlightingStyleRegistry is the only registry you need to use. However in some scenarios, you may wish to support more than one highlighting style registry, for instance one for text editors and one for console windows. Each registry can have different style settings for its known classification types. In these scenarios, you can use the ambient registry for text editors and can create a custom HighlightingStyleRegistry to use for console windows. In fact, any number of custom registries can be created as needed.
The SyntaxEditor.HighlightingStyleRegistry property is used to indicate which IHighlightingStyleRegistry to use when mapping classification types to highlighting styles. If the property is left unassigned, then the AmbientHighlightingStyleRegistry is used.
Back to the example scenario, for any SyntaxEditor that will be used as a console window, you would assign the custom IHighlightingStyleRegistry for console windows to that editor instance.
This code creates a custom registry and assigns it to a console window SyntaxEditor:
SyntaxEditor console = new SyntaxEditor();
IHighlightingStyleRegistry consoleWindowRegistry = new HighlightingStyleRegistry();
consoleWindowRegistry.Description = "Console Window";
console.DefaultHighlightingStyleRegistry = consoleWindowRegistry;
You must populate the entries into the custom registry.
Note that the SyntaxLanguageDefinitionSerializer class has a HighlightingStyleRegistry property where the registry it should use can be specified. A TextExporterFactory (used when exporting text) constructor overload also accepts a custom IHighlightingStyleRegistry. In all cases, if no custom registry is specified, the AmbientHighlightingStyleRegistry is used.
Another alternate registry can be designated for use in printer output only. See the Print Options topic for more information.
Classification Tags Providing an Alternate Registry
Although most of the time, the classification types used by classification taggers are registered into the IHighlightingStyleRegistry instance used by the editor, there are cases where you may wish to not add certain classification types into that registry.
One possible scenario is if you wish to have some classification types that should not be included in the list of classification types that are configuarable by the end user. Another is if your classification tagger just keeps its types private.
In these scenarios, it's possible to have an IClassificationTag specify an alternate IHighlightingStyleRegistry to use. This is done by having the IClassificationTag implement the IHighlightingStyleRegistryProvider interface. The classification tag returns the custom registry via the HighlightingStyleRegistry property. Classification taggers can use the StyleRegistryClassificationTag class for this purpose. When the normal highlighting style registry is fine for use, use the smaller ClassificationTag class instead.
Switching to a Dark Theme
All of the default styles registered by DisplayItemClassificationTypeProvider and the built-in language implementations are intended to be used on an editor with a light background. However in cases where a dark application theme has been applied, these default styles will not be very appealing.
The Actipro Themes system supports dark themes, such as Metro Dark. You can attach to the ThemeManager.CurrentThemeChanged event to know when the current theme is changed by the end user. In this case, add some detection for whether the current theme has changed from a light to dark, or dark to light one. If a theme is changing but both the old and new themes were light background themes, nothing needs to be done.
Let's see an example of how to reset the AmbientHighlightingStyleRegistry instance. In cases where the end user is changing to a light theme from a dark theme, or vice versa, add this in the CurrentThemeChanged event handler:
// Unregister all classification types
var classificationTypes = AmbientHighlightingStyleRegistry.Instance.ClassificationTypes.ToArray();
foreach (var classificationType in classificationTypes)
AmbientHighlightingStyleRegistry.Instance.Unregister(classificationType);
// Re-register common classification types
new DisplayItemClassificationTypeProvider().RegisterAll();
// NOTE: Possibly load up syntax language instances you use so their various customized styles get registered
The above code unregisters all the registered classification tyeps from the ambient registry. Then it re-registers the display item classification types and optionally loads up syntax languages that are used by the app so their customized classification types and styles get re-registered. At this point, the registry is ready to go for light themes.
If a dark theme is becoming active, there is some additional work to do. Each of the styles that have been registered into the registry needs to be altered to look good on a dark background.
One way to do this is to enumerate through the registered styles and update the foreground and background colors as appropriate. You could have stored some pre-defined colors in a custom data structure and used that to know how to update the styles.
Alternatively, you could use the feature described in the "Importing Visual Studio Settings" section above. The Sample Browser shows an example of this. It has a pre-defined "Dark.vssettings" file that includes a number of style definitions that render well on dark editor backgrounds. After the code above is executed, this "Dark.vssettings" file is loaded and it will update the styles of any styles that have already been registered on the registry.
Note
Don't forget to also update the static CommonImageSourceProvider.DefaultImageSet property appropriately after a theme change to ensure the proper image theme is loaded for IntelliPrompt.