0

When registering a custom language service extension, Visual Studio creates a new options entry for the language within the Text Editor node (in the Visual Studio options dialog). Beneath that node two default nodes are created named General and Tabs, whereby the General tab contains statement completion and display settings...

In the Dispay group there are three options; one of them is the Navigation Bar checkbox (which shows/hides the editor´s navigation bar). For my custom language service, this option is disabled. Of course, it´s not implemented yet.

enter image description here

I would like to know, what I have to do, to provide a navigation bar for my custom editor... I guess that there is a certain interface I have to implement in the editor´s factory, or the language service package must export a certain MEF component, or, or, ...

Matze
  • 5,100
  • 6
  • 46
  • 69
  • It turns out you actually do need to register an idle timer to get this functionality to perform as it should. Once you do that, you will get calls to `OnSynchronizeDropdowns` and also get `ParseSource` calls with a `ParseReason` of `Check` (needed if you want to display errors). – Jon Senchyna Feb 27 '14 at 16:32

2 Answers2

2

Jon Senchyna´s answer guided me into the right direction. The OnSynchronizeDropdowns method gets never called (the SDK documentation is just wrong in that case). What did the final trick was to override at least GetComboAttributes, GetEntryAttributes and GetEntryText to get text-only items for both combo boxes...

[ComVisible(true)]
public sealed class CustomTypeAndMemberDropdownBars : TypeAndMemberDropdownBars
{
    private readonly IList<string> declarations;

    private readonly IList<string> members;

    public CustomTypeAndMemberDropdownBars(
        LanguageService languageService, 
        IVsTextView view)
        : base(languageService)
    {
        // TODO: initialize declarations and members from the given text view...
        this.declarations = ...
        this.members = ...
    }

    private enum ComboIndex
    {
        Types = 0, 

        Members = 1
    }

    public override int GetComboAttributes(
        int combo, 
        out uint entries, 
        out uint entryType, 
        out IntPtr imageList)
    {
        entries = 0;
        imageList = IntPtr.Zero;

        entryType = (uint)DROPDOWNENTRYTYPE.ENTRY_TEXT;

        var comboType = (ComboIndex)combo;
        switch (comboType)
        {
            case ComboIndex.Types:
                entries = (uint)this.declarations.Count();
                break;

            case ComboIndex.Members:
                entries = (uint)this.members.Count();
                break;
        }

        return VSConstants.S_OK;
    }

    public override int GetEntryAttributes(
        int combo, 
        int entry, 
        out uint fontAttrs)
    {
        fontAttrs = (uint)DROPDOWNFONTATTR.FONTATTR_PLAIN;

        return VSConstants.S_OK;
    }

    public override int GetEntryText(
        int combo, 
        int entry, 
        out string text)
    {
        text = null;
        var comboType = (ComboIndex)combo;
        switch (comboType)
        {
            case ComboIndex.Types:
                text = this.declarations[entry];
                break;

            case ComboIndex.Members:
                text = this.members[entry];
                break;
        }

        return VSConstants.S_OK;
    }

    public override bool OnSynchronizeDropdowns(
        LanguageService languageService, 
        IVsTextView textView, 
        int line, 
        int col, 
        ArrayList dropDownTypes, 
        ArrayList dropDownMembers, 
        ref int selectedType, 
        ref int selectedMember)
    {
        return false;
    }
}
Matze
  • 5,100
  • 6
  • 46
  • 69
  • Just out of curiosity, if you set `myLanguagePreference.ShowNavigationBar` to `true` in your `LanguageService`'s `GetLanguagePreferences` function, does `OnSynchronizeDropdowns` get called? – Jon Senchyna Feb 26 '14 at 12:33
  • Also, how do you proffer your service? I found two ways on the internet that it was done. One was was to add a `ServiceCreatorCallback`. The other way was to register it via the `SOleComponentManager`. I found that using the first way caused a lot of my `LanguageService`s functionality to not work, including the navigation bar. – Jon Senchyna Feb 26 '14 at 12:34
  • Forcing the `ShowNavigationBar` property to `true` in the language preferences does not cause a call of the `OnSynchronizeDropdowns` method. – Matze Feb 26 '14 at 12:53
  • I register the language service in the `Initialize` method of my package. I am casting the current `VsPackage` instance to `IServiceContainer` and then call `AddService` to promote the language service instance. – Matze Feb 26 '14 at 12:56
  • Ahh, thought so. For some reason, when I proffer the service that way, the dropdowns don't work (not does naything else aside from syntax highlighting). When I use the old `SOleComponentManager` method of proferring, everything works. – Jon Senchyna Feb 26 '14 at 22:34
  • 1
    I opened a new [question](http://stackoverflow.com/questions/22055112/issues-proferring-language-service) for why the navigation bar (and many other pieces of functionality) only works when proffering a service "the old way". – Jon Senchyna Feb 26 '14 at 22:44
1

I believe the following steps should be what you need:

  1. In your Package class, set the ShowDropDownOptions property to true in the ProvideLanguageService attribute
  2. Create a class that implements TypeAndMemberDropdownBars
  3. In your LanguageService class, implement the CreateDropDownHelper function and have it return an instance of your TypeAndMemberDropdownBars
Jon Senchyna
  • 7,867
  • 2
  • 26
  • 46
  • This allows me to show and hide the navigation bar, but the combo boxes always remain empty; the `OnSynchronizeDropdowns` method of my `TypeAndMemberDropdownBars` implementation is never called. – Matze Feb 24 '14 at 23:10
  • I had the same issue before. I don't have access to the code right now, but I'll take a look at it tomorrow and let you know what I did. – Jon Senchyna Feb 25 '14 at 01:52
  • Can you update your question with your implementation of `CreateDropDownHelper`? – Jon Senchyna Feb 25 '14 at 22:34
  • 1
    I think I found my missing step. In my implementation of `GetLanguagePreferences`, I had to force the `ShowNavigationBar` property to `true`. – Jon Senchyna Feb 25 '14 at 22:41
  • From what I can tell, `ShowDropDownOptions ` toggles whether or not the "Navigation bar" option is selectable in the Options GUI, but whether or not it is checked is stored in the [registry](http://msdn.microsoft.com/en-us/library/bb166421(v=vs.100).aspx) – Jon Senchyna Feb 25 '14 at 22:44