Enable/Disable Menu

Context: Mac Mojave : Xojo 2019 3.1
I have one menu bar. I am using the default one and have not changed its name so it is called MainMenuBar.
Let’s say that I have a menu on that menu bar called DesignMenu with several MenuItems. For this example, I will have three MenuItems called miOne and miTwo and miThree.
miOne is not AutoEnabled. miTwo and miThree are AutoEnabled. Assume all three have a MenuHandlers that have some code in them.
As I understand the situation, there is only one place that you can run code and expect it to have any effect on the Enabled/Disabled status of MenuItems. That is in the EnableMenuItems Event Hander of the App. You can write code like miOne.Enabled = True in the action event of a button or the open event of a window, for example, and it will have absolutely no effect.

So we are focused on the code in the EnableMenuItems Event Hander of the App.
If I write here, miOne.Enabled = True, then when I click on that DesignMenu it will not be grayed out. If I do not write that code there, it will be grayed out because miOne was not Auto Enabled.
If I write here, miTwo.Enabled = False, then when I click on that DesignMenu it will be grayed out even though it was Auto Enabled.

If I want all the MenuItems to be grayed out, I can write in the Event Handler

miTwo.Enabled = False miThree.Enabled = False
miOne will be grayed out because it was not AutoEnabled. miTwo and miThree will be grayed out because you explicitly asked that they not be Enabled.

Here is my first question. Is there any way that you can gray out the display of the Menu itself? At this particular time, all its MenuItems are grayed out. The user will find this out when he clicks on the Menu. But is there a way you can telegraph this to the user before he clicks on the Menu by graying out the display of that particular Menu in the MainMenuBar?

My impression is that this is impossible. Certainly, I cannot figure out how to do this. It there is a way, I would like to know it.

And yet there is a command, DesignMenu.Enabled = False, that is accepted. Just what does it do? First of all, it does not do anything if it is not run in the EnableMenuItems Event Hander of the App. We have finally become used to that. But what happens if the code is run there? I write in the Event Hander

miOne.Enabled = True DesignMenu.Enabled = False
What happens when I run that experiment is that when I click on the DesignMenu the first time, all the items show up in black. If I let up on the mouse and click again, they are all grayed out. I find that kind of peculiar. I don’t understand why when I click on it the first time, Xojo does not just “figure out” that my intent is that have them all grayed out since I included DesignMenu.Enabled = False. Somehow that is functionally not equivalent to writing instead

miTwo.Enabled = False miThree.Enabled = False
If I do that those two items are grayed out the first time that I click on the menu.

Now Xojo seems to aware of this issue because the language includes a Method called EnableMenuItems. That is confusing because there is an Event Handler of the App that goes by this same name. An improvement with 2019r2 is that calling this Method with this name is deprecated. Now you are supposed to use App.RefreshMenuBar. It does the same thing as best I can tell, but it does not have the confusing name.

I stand to be corrected, but this seems to basically run the EnableMenuItems Event Handler of the App. It is equivalent to that first click that we had the user do above. Now when the user clicks on the Menu for the first time, everything is grayed out rather than having to wait for the second clicking on the Menu.

So as I understand the situation, if you have a Menu and you want all the items to be grayed out you have a choice. In the EnableMenuItems Event Hander of the App include the code for each MenuItem

miTwo.Enabled = False miThree.Enabled = False miFour.Enabled = False miFive.Enabled = False etc.
In some ways, the above seems simplest all though it involves multiple lines of code. The first time the user clicks on the Menu, all the MenuItems will be grayed out. An alternative is to simply write the one line of code in the EnableMenuItems Event Hander of the App

DesignMenu.Enabled = False

but if you do this without previously calling the method App.RefreshMenuBar, you will get the peculiar phenomena of the user clicking the first time and seeing all the MenuItems in black and then clicking again and seeing them all grayed out.

What I am writing above seems sort of peculiar so I am asking for a confirmation that it is correct.

  1. Is this is correct usage of DesignMenu.Enabled = False? Is that its purpose for existing?
  2. Does App.RefreshMenuBar exist simply to deal with the problem of the first click looking different than the second click if you do use DesignMenu.Enabled = False?
  3. If I am content to explicitly, one by one, go through every MenuItem like miTwo.Enabled = False then is it true that I have no reason to ever use DesignMenu.Enabled = False and I will never have any use for the method App.RefreshMenuBar? For me, if there is no other reason for these two things, I would just as soon empty my brain of their very existence.

I don’t expect there is one (and don’t know any, anyway), as Apple explicitly states, in its Human Interface Guidelines documents that top menus and sub menus must not be disabled (this is so the user always has a way to know what’s inside menus/submenus; the idea being, a top menu or sub menu appearing dimmed (disabled) would not be expected to be openable and viewable).

As for your other questions, I haven’t used recent Xojo versions enough to be sure, sorry.
I guess what you’re talking about is equivalent to the (then deprecated) EnableMenuItems method (not the event, with the same name), which serves (served?) to refresh the menu bar immediately, should it become de-synchronised (it happens sometimes, but I’m unsure when, at the moment).

No. It deals with the situation where certain user actions result in a top-level menu (one with no submenus) needing to be enabled or disabled, and you want to update the display without the user having to click on the menu bar. Normally, EnableMenuItems only runs in response to a user action. And that is the only thing that causes the menu state to visually change. App.RefreshMenuBar allows you to change the visual state of the menu in code. The fact that it happens to solve the situation you’re facing is gravy.

Note: the issue where DesignMenu.Enabled = False doesn’t work the first time sounds like a bug. Perhaps a feedback report is in order.

When you say [quote]top-level menu (one with no submenus)[/quote] do you mean top-level Menuitem? The verbiage that I am most familiar with is MenuBar (A horizontal bar containing a bunch of Menus. Each Menu, when click and held, shows a vertical list of MenuItems. Those MenuItems can contain a SubMenu which is revealed when click and holding over the individual MenuItem.

Arnaud says that what I am calling a Menu cannot be enabled or disabled. I can understand that being a thing. But the only thing visible before you click on one of the Menu’s in the MenuBar are the titles of the Menu’s. So if we grant that the appearance of these cannot be changed, what do you mean by [quote]update the display without the user having to click on the MenuBar[/quote]? And if the user has to click on a Menu to see the MenuItems, why would not that be the time for Xojo/Apple to reveal that certain MenuItems are disabled and that could be done in the EventHandler.

I appreciate your patience since I am, as I reveal, still confused.

What you refer to as a Menu is actually itself a MenuItem. It does not necessarily have to have MenuItems under it. It can stand on it’s own on the MenuBar. Thus it can be enabled or disabled. Thus you can have items on the MenuBar that act immediately when you click them, instead of displaying a list of menu items.

If the menu has menu items, you cannot assign it a MenuHandler and it won’t be visually disabled, even if all the menuitems under it are disabled. You still need to be able to click it so it will display the items, which will all be grayed out. Disabling the Menu is a shortcut to disabling all the menu items, but the Menu itself will still be active.

If the menu has no menu items, then you can assign it a MenuHandler and that MenuHandler will be called when you click the Menu. If you need to disable the Menu, you can put code in EnableMenuItems and call RefreshMenuBar to cause EnableMenuItems to be called and the menu state to be redrawn.