[FR] KnownPluginList::addToMenu() enhancement


#1

Currently the menu is built but there’s no way to set the tick mark next to the current plugin.

Here are the changes needed to accomplish this:

In juce_KnownPluginList.h

    //==============================================================================
    /** Adds all the plugin types to a popup menu so that the user can select one.

        Depending on the sort method, it may add sub-menus for categories,
        manufacturers, etc.

        Use getIndexChosenByMenu() to find out the type that was chosen.
    */
    void addToMenu (PopupMenu& menu, SortMethod sortMethod, String identifierString = String()) const;

In the implementation file juce_KnownPluginList.cpp

//==============================================================================
void KnownPluginList::addToMenu (PopupMenu& menu, const SortMethod sortMethod, String identifierString) const
{
    ScopedPointer<PluginTree> tree (createTree (sortMethod));
    PluginTreeUtils::addToMenu (*tree, menu, types, identifierString);
}
    static bool addToMenu (const KnownPluginList::PluginTree& tree, PopupMenu& m, const OwnedArray <PluginDescription>& allPlugins, String identifierString = String())
    {
        bool isTicked = false;
    
        for (int i = 0; i < tree.subFolders.size(); ++i)
        {
            const KnownPluginList::PluginTree& sub = *tree.subFolders.getUnchecked(i);

            PopupMenu subMenu;
            isTicked = addToMenu (sub, subMenu, allPlugins, identifierString);
        
            m.addSubMenu (sub.folder, subMenu, true, isTicked);
        }

        for (int i = 0; i < tree.plugins.size(); ++i)
        {
            const PluginDescription* const plugin = tree.plugins.getUnchecked(i);

            String name (plugin->name);

            if (containsDuplicateNames (tree.plugins, name))
                name << " (" << plugin->pluginFormatName << ')';
        
            const bool isItemTicked = plugin->matchesIdentifierString (identifierString);

            m.addItem (allPlugins.indexOf (plugin) + menuIdBase, name, true, isItemTicked);
        
            if (isItemTicked)
                isTicked = true;
        }
    
        return isTicked;
    }

In juce_PopupMenu.h

    void addSubMenu (const String& subMenuName,
                     const PopupMenu& subMenu,
                     bool isEnabled = true,
                     bool isTicked = false);

and in the implementation file juce_PopupMenu.cpp

void PopupMenu::addSubMenu (const String& subMenuName, const PopupMenu& subMenu, bool isActive, bool isTicked)
{
    addSubMenu (subMenuName, subMenu, isActive, nullptr, isTicked, 0);
}

This is backward compatible so won’t break any existing code.

I understand I hold no legal claim to copyright of the code or the changes to the code (or whatever other legalese you need to release you to use the mods).

Thanks,

Rail


#2

Thanks! I’ll add something like this… (There’s no need to change the menu class BTW there are already methods that can add a ticked submenu)


#3

Thanks Jules for the commit – unfortunately your logic for isTicked is off…

This works:

    static bool addToMenu (const KnownPluginList::PluginTree& tree, PopupMenu& m,
                           const OwnedArray<PluginDescription>& allPlugins,
                           const String& currentlyTickedPluginID)
    {
        bool isTicked = false;

        for (int i = 0; i < tree.subFolders.size(); ++i)
        {
            const KnownPluginList::PluginTree& sub = *tree.subFolders.getUnchecked(i);

            PopupMenu subMenu;
            isTicked = addToMenu (sub, subMenu, allPlugins, currentlyTickedPluginID);

            m.addSubMenu (sub.folder, subMenu, true, nullptr, isTicked, 0);
        }

        for (int i = 0; i < tree.plugins.size(); ++i)
        {
            const PluginDescription* const plugin = tree.plugins.getUnchecked(i);

            String name (plugin->name);

            if (containsDuplicateNames (tree.plugins, name))
                name << " (" << plugin->pluginFormatName << ')';

            const bool isItemTicked = plugin->matchesIdentifierString (currentlyTickedPluginID);
        
            if (isItemTicked)
                isTicked = true;

            m.addItem (allPlugins.indexOf (plugin) + menuIdBase, name, true, isItemTicked);
        }

        return isTicked;
    }

#4

Ah, I was trying to fix your logic there, which was incorrect in the first loop, but I didn’t notice that my fix was also not quite right. What I meant was:

static bool addToMenu (const KnownPluginList::PluginTree& tree, PopupMenu& m,
                       const OwnedArray<PluginDescription>& allPlugins,
                       const String& currentlyTickedPluginID)
{
    bool isTicked = false;

    for (int i = 0; i < tree.subFolders.size(); ++i)
    {
        const KnownPluginList::PluginTree& sub = *tree.subFolders.getUnchecked(i);

        PopupMenu subMenu;
        const bool isItemTicked = addToMenu (sub, subMenu, allPlugins, currentlyTickedPluginID);
        isTicked = isTicked || isItemTicked;

        m.addSubMenu (sub.folder, subMenu, true, nullptr, isTicked, 0);
    }

    for (int i = 0; i < tree.plugins.size(); ++i)
    {
        const PluginDescription* const plugin = tree.plugins.getUnchecked(i);

        String name (plugin->name);

        if (containsDuplicateNames (tree.plugins, name))
            name << " (" << plugin->pluginFormatName << ')';

        const bool isItemTicked = plugin->matchesIdentifierString (currentlyTickedPluginID);
        isTicked = isTicked || isItemTicked;

        m.addItem (allPlugins.indexOf (plugin) + menuIdBase, name, true, isItemTicked);
    }

    return isTicked;
}

#5

Hi Jules,

The logic in the first loop is still not right – I sent you a private message with a video

Cheers,

Rail


#6

This’ll work:

    static bool addToMenu (const KnownPluginList::PluginTree& tree, PopupMenu& m,
                           const OwnedArray<PluginDescription>& allPlugins,
                           const String& currentlyTickedPluginID)
    {
        bool isTicked = false;

        for (int i = 0; i < tree.subFolders.size(); ++i)
        {
            const KnownPluginList::PluginTree& sub = *tree.subFolders.getUnchecked(i);
            
            PopupMenu subMenu;
            const bool isItemTicked = addToMenu (sub, subMenu, allPlugins, currentlyTickedPluginID);
            isTicked = isTicked || isItemTicked;
            
            m.addSubMenu (sub.folder, subMenu, true, nullptr, isItemTicked, 0);
        }

        for (int i = 0; i < tree.plugins.size(); ++i)
        {
            const PluginDescription* const plugin = tree.plugins.getUnchecked(i);
            
            String name (plugin->name);
            
            if (containsDuplicateNames (tree.plugins, name))
                name << " (" << plugin->pluginFormatName << ')';
            
            const bool isItemTicked = plugin->matchesIdentifierString (currentlyTickedPluginID);
            isTicked = isTicked || isItemTicked;
            
            m.addItem (allPlugins.indexOf (plugin) + menuIdBase, name, true, isItemTicked);
        }

        return isTicked;
    }

Rail


#7

Yeah, I know - I quickly posted that second version before checking it, but already saw the mistake. Will push a correct version shortly… Thanks!