# BurgerMenuComponent doesn't follow ApplicationCommandManager

**URL:** <https://forum.juce.com/t/burgermenucomponent-doesnt-follow-applicationcommandmanager/52932>\
**Category:** General JUCE discussion\
**Created:** [September 8, 2022, 3:41pm UTC](https://forum.juce.com/t/burgermenucomponent-doesnt-follow-applicationcommandmanager/52932 "2022-09-08T15:41:09Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![mjokipii](https://avatars.discourse-cdn.com/v4/letter/m/e47c2d/32.png) [@mjokipii](https://forum.juce.com/u/mjokipii)\
**Post date:** [September 8, 2022, 3:41pm UTC](https://forum.juce.com/t/burgermenucomponent-doesnt-follow-applicationcommandmanager/52932/1 "2022-09-08T15:41:09Z")

</div>

I’m trying to make use of BurgerMenuComponent with ApplicationCommanManager, but can’t seem to get the menu to respond to any changes in the command statuses (e.g. enabled/disabled).

The command manager invokes the update correctly and the menu bar model responds by calling listeners with `this` as the model. So far so good.

```auto
void MenuBarModel::handleAsyncUpdate()
{
    listeners.call ([this] (Listener& l) { l.menuBarItemsChanged (this); });
}

```

The burger menu handles this by calling setModel:

```auto
void BurgerMenuComponent::menuBarItemsChanged (MenuBarModel* menuBarModel)
{
    setModel (menuBarModel);
}

```

…which ignores the update unless the model is actually different from current:

```auto
void BurgerMenuComponent::setModel (MenuBarModel* newModel)
{
    if (newModel != model)
    {
        if (model != nullptr)
            model->removeListener (this);

        model = newModel;

        if (model != nullptr)
            model->addListener (this);

        refresh();
        listBox.updateContent();
    }
}

```

This can’t be right? Surely the refresh and list box update should be called?

---

<div class="post-metadata">

**Author:** ![stephenk](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/stephenk/32/15198_2.png) [@stephenk](https://forum.juce.com/u/stephenk)\
**Post date:** [September 8, 2022, 4:03pm UTC](https://forum.juce.com/t/burgermenucomponent-doesnt-follow-applicationcommandmanager/52932/2 "2022-09-08T16:03:24Z")

</div>

Have you tried the MenusDemo from the DemoRunner? I was able to get the BurgerMenu component to work in an app, with the Application Manager, by following that. In fact, I integrated that whole thing of being able to switch between Global Menu (Mac), MenuBar inside Window, and BurgerMenu for testing purposes.

```auto
        burgerMenu.setModel (menuBarPosition == MenuBarPosition::burger ? getMenuModel() : nullptr);

```

And then I have my own MenuModel… I could take a more deep look if you need it…

```auto
MenuBarModel* MainComponent::getMenuModel()
{
    return menuModel.get();
}

```

---

<div class="post-metadata">

**Author:** ![mjokipii](https://avatars.discourse-cdn.com/v4/letter/m/e47c2d/32.png) [@mjokipii](https://forum.juce.com/u/mjokipii)\
**Post date:** [September 8, 2022, 4:52pm UTC](https://forum.juce.com/t/burgermenucomponent-doesnt-follow-applicationcommandmanager/52932/3 "2022-09-08T16:52:50Z")

</div>

I also followed that to get the basics running. I can get the menu items to show and trigger commands, but no changes to the commands get updated. I don’t think the DemoRunner even attempts to show that functionality.

---

<div class="post-metadata">

**Author:** ![stephenk](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/stephenk/32/15198_2.png) [@stephenk](https://forum.juce.com/u/stephenk)\
**Post date:** [September 8, 2022, 5:22pm UTC](https://forum.juce.com/t/burgermenucomponent-doesnt-follow-applicationcommandmanager/52932/5 "2022-09-08T17:22:57Z")

</div>

Yeah, you’re right. I just checked and my BurgerMenu doesn’t update enabled/disabled either, unless I change that function to:

```auto
void BurgerMenuComponent::setModel (MenuBarModel* newModel)
{
    if (newModel != model)
    {
        if (model != nullptr)
            model->removeListener (this);

        model = newModel;

        if (model != nullptr)
            model->addListener (this);
    }

    refresh();
    listBox.updateContent();
}

```

---

<div class="post-metadata">

**Author:** ![mjokipii](https://avatars.discourse-cdn.com/v4/letter/m/e47c2d/32.png) [@mjokipii](https://forum.juce.com/u/mjokipii)\
**Post date:** [September 9, 2022, 9:59am UTC](https://forum.juce.com/t/burgermenucomponent-doesnt-follow-applicationcommandmanager/52932/6 "2022-09-09T09:59:38Z")

</div>

Thanks! Getting closer. With the above modification the PopupMenu::Item states get updated in the burger menu, but it seems that the `listBox.updateContent()` is not sufficient, but needs to be followed by explicit `listBox.repaint()` for the changes to appear on screen.

Now i’m wondering why the burger menu items need to be clicked twice to trigger the commands. Having the menu open and after clicking elsewhere in the app, the first click on the menu only highlights the item, only the next click will trigger a command. This is very odd behaviour as well.

---

<div class="post-metadata">

**Author:** ![mjokipii](https://avatars.discourse-cdn.com/v4/letter/m/e47c2d/32.png) [@mjokipii](https://forum.juce.com/u/mjokipii)\
**Post date:** [September 9, 2022, 10:13am UTC](https://forum.juce.com/t/burgermenucomponent-doesnt-follow-applicationcommandmanager/52932/7 "2022-09-09T10:13:04Z")

</div>

The commands are invoked in the mouseUp handler. The clicks aren’t working because the burger menu never gets the mouseUp event it needs. Right now i don’t fully understand why the list box methods aren’t used for the interactions. This seems like a weird way of doing it and it doesn’t seem to work properly either.

```auto
void BurgerMenuComponent::mouseUp (const MouseEvent& event)
{
    auto rowIndex = listBox.getSelectedRow();

    if (rowIndex == lastRowClicked && rowIndex < rows.size()
         && event.source.getIndex() == inputSourceIndexOfLastClick)
    {
        auto& row = rows.getReference (rowIndex);

        if (! row.isMenuHeader)
        {
            listBox.selectRow (-1);

            lastRowClicked = -1;
            inputSourceIndexOfLastClick = -1;

            topLevelIndexClicked = row.topLevelMenuIndex;
            auto& item = row.item;

            if (auto* managerOfChosenCommand = item.commandManager)
            {
                ApplicationCommandTarget::InvocationInfo info (item.itemID);
                info.invocationMethod = ApplicationCommandTarget::InvocationInfo::fromMenu;

                managerOfChosenCommand->invoke (info, true);
            }

            postCommandMessage (item.itemID);
        }
    }
}

```

---

<div class="post-metadata">

**Author:** ![mjokipii](https://avatars.discourse-cdn.com/v4/letter/m/e47c2d/32.png) [@mjokipii](https://forum.juce.com/u/mjokipii)\
**Post date:** [September 9, 2022, 10:55am UTC](https://forum.juce.com/t/burgermenucomponent-doesnt-follow-applicationcommandmanager/52932/8 "2022-09-09T10:55:36Z")

</div>

Maybe someone from the JUCE devs could elaborate on the reasons behind the burger menu’s handling of user interaction in such awkward way?

I would need to get this working ASAP and right now the only way seems to involve ditching the current way on triggering the commands from the mouseUp handler. Is there danger of invoking unindented commands if the commands would be handled by the `listBoxItemClicked` method? Anything else to consider?

---

<div class="post-metadata">

**Author:** ![stephenk](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/stephenk/32/15198_2.png) [@stephenk](https://forum.juce.com/u/stephenk)\
**Post date:** [September 10, 2022, 8:34pm UTC](https://forum.juce.com/t/burgermenucomponent-doesnt-follow-applicationcommandmanager/52932/9 "2022-09-10T20:34:43Z")

</div>

I took a look at this some more just for the heck of it. The problem is that the refresh() function always resets the `lastRowClicked` variable to -1. So by making the setModel() function always call refresh(), you click on a command and the mouse down causes a refresh() so by the time you get the mouse up, the lastRowClicked has been reset and nothing happens. But if you _don’t_ call refresh() from setModel(), then the menu commands don’t get their enabled/disabled states updated.

So I came up with a hack that fixes it, at least it seems to. The idea is to call refresh(), but not reset the lastRowClicked in certain cases.

Of course, I never like hacking JUCE unless it’s unavoidable, but something is not working right here, and I’m not recommending these changes as a real fix, but until someone from the JUCE team such as @reuk or @attila can take a look at it,

In the juce\_BurgerMenuComponent.h header, change the declaration of the refresh() function to:

```auto
    void refresh(bool resetLastRow = true);

```

In juce\_BurgerMenuComponent.cpp, change the first part of the refresh() function to:

```auto
void BurgerMenuComponent::refresh(bool resetLastRow)
{
    if (resetLastRow)
        lastRowClicked = inputSourceIndexOfLastClick = -1;

```

And make this modification to the setModel() function:

```auto
void BurgerMenuComponent::setModel (MenuBarModel* newModel)
{
    if (newModel != model)
    {
        if (model != nullptr)
            model->removeListener (this);

        model = newModel;

        if (model != nullptr)
            model->addListener (this);

        refresh();
        listBox.updateContent();
    }
    
    // BURGER_FIX:
    else
    {
        refresh(false);
        listBox.updateContent();
    }
}

```

I’m sure there’s probably a different/better way to fix it, but I would like to know what someone from JUCE thinks. And whether this works for you…

---

<div class="post-metadata">

**Author:** ![mjokipii](https://avatars.discourse-cdn.com/v4/letter/m/e47c2d/32.png) [@mjokipii](https://forum.juce.com/u/mjokipii)\
**Post date:** [September 10, 2022, 9:08pm UTC](https://forum.juce.com/t/burgermenucomponent-doesnt-follow-applicationcommandmanager/52932/10 "2022-09-10T21:08:30Z")

</div>

That’s very interesting - thanks!. At this point the symptoms at your end seem to differ a bit from what i see here. Could it be that you’re testing on Windows or something. I’m on Mac.

IIRC the same kind of symptoms were caused by the `mouseUp` really not getting called at all on the first click after `refresh` and `updateContent` for some reason.

I fixed this by moving all logic from `mouseUp` to `listBoxItemClicked` as IMHO that’s how it should be. Got rid of all those state variables in the process. Of course i’m extremely curious to learn why it wasn’t implemented like that in the first place @fr810. So far my fix seems to work on Mac and Windows.

---

<div class="post-metadata">

**Author:** ![stephenk](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/stephenk/32/15198_2.png) [@stephenk](https://forum.juce.com/u/stephenk)\
**Post date:** [September 10, 2022, 9:11pm UTC](https://forum.juce.com/t/burgermenucomponent-doesnt-follow-applicationcommandmanager/52932/11 "2022-09-10T21:11:56Z")

</div>

No, I’m on a Mac as well. That’s curious… but glad you found a workaround.
