First Menu Bar Item Disappears When FileChooser is Invoked


#1

Hi all,

I'm having some strange behaviour (doubtless my fault) with the menu bar and FileChooser. Whenever I choose an option on the menu that invokes a FileChooser,  the first menu bar item disappears (I have tried invoking it from a different menu bar item and it is always the first item that disappears).

To make this clear, I'll reiterate. Before invoking things, I have a menu containing two drop downs

File, Edit

I choose File->Load

which invokes a static method in another class containing...

    FileChooser myChooser ("Please select a file to open",
                               File::getSpecialLocation (File::userHomeDirectory),
                               "*.arr");

    if (myChooser.browseForFileToOpen())
    {
       // do things with the file browser <-- even with just this comment I get the problem
    }
    else
    {

        return false;
    }

Then, while the FileChooser is open (i.e. before I select a file and click 'ok'), the menu bar displays...

Edit 

(i.e. the "File" item disappears.)

 

Here are my command Ids:

enum CommandIDs
{
    newArrangement              = 0x2000,
    save                        = 0x2001,
    saveAs                      = 0x2002,
    load                        = 0x2003
};

Here are the methods I implement when inheriting MenuBarModel:


//==============================================
PopupMenu MyComponent::getMenuForIndex (int topLevelMenuIndex, const String& menuName)
{
    ApplicationCommandManager* commandManager = &(mainWindow.commandManager);
    
    PopupMenu menu;
    
    if (topLevelMenuIndex == 0)
    {        
        menu.addCommandItem(commandManager, newArrangement);
        menu.addCommandItem(commandManager, save);
        menu.addCommandItem(commandManager, saveAs);
        menu.addCommandItem(commandManager, load);
        menu.addSeparator();
        menu.addCommandItem (commandManager, StandardApplicationCommandIDs::quit);
    }
    else if (topLevelMenuIndex == 1)
    {
        menu.addSeparator();
    }
    
    return menu;
}

//==============================================
StringArray MyComponent::getMenuBarNames()
{
    StringArray menuBarNames;

    const char* const names[] = { "File", "Edit", nullptr };

    return StringArray (names);
}


//==============================================
void MyComponent::menuItemSelected (int menuItemID, int topLevelMenuIndex)
{
    
}

And these are the methods inherited from ApplicationCommandTarget:

//==============================================
ApplicationCommandTarget* MyComponent::getNextCommandTarget()
{
    return findFirstTargetParentComponent();
}


//==============================================
void MyComponent::getAllCommands (Array <CommandID>& commands)
{
    // this returns the set of all commands that this target can perform..
    const CommandID ids[] = {
        newArrangement,
        save,
        saveAs,
        load
    };
    
    commands.addArray (ids, numElementsInArray (ids));
}


//==============================================
bool MyComponent::perform (const InvocationInfo& info)
{    
    switch (info.commandID)
    {
        case newArrangement:
        {
            ((MyApplication*) JUCEApplication::getInstance())->createNewEmptySession();
            break;
        }
            
        case save:
        {
            FileIO::save(applicationTree);
            break;
        }
            
        case saveAs:
        {
            FileIO::saveAs(applicationTree);
            break;
        }
            
        case load:
        {
            ValueTree newApplicationTree;
            FileIO::load(newApplicationTree);

            ((MyApplication*) JUCEApplication::getInstance())->createNewSessionWithTree(newApplicationTree);
            break;
        }
            
        default:
        {
            return false;
        }
    };
    
    return true;
}


//==============================================
void MyComponent::getCommandInfo (CommandID commandID, ApplicationCommandInfo& result)
{    
    switch (commandID)
    {
        case newArrangement:
            result.setInfo("New Arrangement", "Start a new Arrangement", "Category 1",  0);
            result.setTicked (false);
            result.setActive(true);
            result.addDefaultKeypress ('g', ModifierKeys::commandModifier);
            break;
            
        case save:
            result.setInfo("Save", "Save the current arrangement", "Category 1", 0);
            result.setTicked(false);
            result.setActive(true);
            result.addDefaultKeypress('s', ModifierKeys::commandModifier);
            break;
            
        case saveAs:
            result.setInfo("Save As...", "Save the current arrangement", "Category 1", 0);
            result.setTicked(false);
            result.setActive(true);
            result.addDefaultKeypress('u', ModifierKeys::commandModifier);
            break;
            
        case load:
            result.setInfo("Load", "Load a new arrangement", "Category 1", 0);
            result.setTicked(false);
            result.setActive(true);
            result.addDefaultKeypress('o', ModifierKeys::commandModifier);
            break;
            
        default:
            break;
    }
    
}

 

Thanks in advance for any help!

Adam


#2

No.. That's deliberate. But you're mis-interpreting what's going on. It's not removing your first menu item, it's removing your entire menu bar, and replacing it with just a temporary "Edit" menu while the file-chooser is open.

This stops people doing irritating things like quitting the app or invoking other commands while the chooser's open, which can cause horrible recursion problems.


#3

There seems to be an issue here now (Juce 5.2.0 on OS X 10.12.6). Every time I open up a file chooser I get another edit on the menu bar. It just keeps piling them up from left to right. Note that I am not specifically creating any menu for my app.


#4

This has already been fixed on the develop branch.


#5

Are you sure this fix was checked in? Updated to develop and same issue is occuring.


#6

Can you reproduce it in the Dialogs section of the JUCE demo? With the master branch I can trigger the stacking “Edit” items by clicking on the Choose Directory File Browser, but on the develop branch the issue is fixed - the dialogs code has changed quite a lot since the last JUCE release.


#7

Fixed here.

Edit: forgot to include the link


#8

I agree in the demo it is fixed. In fact the “edit” option never even appears in the demo when I bring up the FileChooser. However, the demo is using:
fc = new FileChooser (…
fc->launchAsync (…

and I am using:
FileChooser myChooser (“Select File”,…
(myChooser.browseForFileToOpen() …

is browseForFileToOpen and browseForDirectory not the correct way to use these anymore?


#9

You can use either.

I didn’t realise that this issue only appeared when the dialog was opened modally and Fabian’s commit fixes things.


#10

Fixed.

Thanks.