Disabling/enabling menu items (solved)

7 posts / 0 new
Last post
trixie
trixie's picture
Offline
Last seen: 6 months 3 weeks ago
Joined: 2011-02-03 13:58
Disabling/enabling menu items (solved)

I have a menustrip created through GadTools. The individual menu items are referenced by IDs:

enum { MID_OPEN=1, MID_SAVE, MID_ABOUT, MID_QUIT };

which I pass in the nm_UserData field of the NewMenu structure.

During the course of the program, I need to enable or disable certain menu items, depending on program state. I know there is OnMenu() and OffMenu(), and how to use the ITEMNUM() macro to extract the appropriate menu number from the IDCMP_MENUPICK message.

However, I need to change the menu item state regardless of user menu selections, ie. with no IDCMP_MENUPICK messages involved. How do I get the correct menu number to pass as an argument to OnMenu() / OffMenu()? Let's say I want to disable the first two items, referenced by MID_OPEN and MID_SAVE.

Steady
Steady's picture
Offline
Last seen: 2 years 1 week ago
Joined: 2011-07-18 05:02
Hi trixie, Do you know what

Hi trixie,

Do you know what order your menus are in? If so, you can construct the MenuNumber manually using information in the Menu chapter of the RKRM.

ie) It is a 16-bit value with the bits assigned as follows:
Bit 15-11: Sub-Item number.
Bit 10-5: Menu Item number.
Bit 4-0: Menu number.

So, to select the Copy item from the Edit menu in a menu such as the one below:

  1. File Edit Swim
  2. New Cut Fast
  3. Open Copy Slow
  4. Close Paste Doggy-Paddle
  5. Quit
  6.  
  7. The MenuNumber to pass to OnMenu()/OffMenu() for Copy will be:
  8.  
  9. SUBITEM ITEM MENU
  10. 00000 000001 00001 = 0x0021

The number for Doggy-Paddle would be 0x0042 using the same formula.

Hope that helps.

Steady
Steady's picture
Offline
Last seen: 2 years 1 week ago
Joined: 2011-07-18 05:02
Oops, sorry. I made a small

Oops, sorry. I made a small (but vital) mistake. If there is no subitem/item/menu selected, then all bits for that particular part are set to 1.

So, the copy menuitem is actually:
SUB=%11111 ITEM=%000001 MENU=%00001, or 0xF821 when combined into the expected 16-bit value.

This is because there is no sub-item.

trixie
trixie's picture
Offline
Last seen: 6 months 3 weeks ago
Joined: 2011-02-03 13:58
Re: Disabling/enabling menu items (solved)

@steady

Thanks for the reply.

The thing is, I do have access to all the menu structures, and I currently handle item enabling/disabling by setting the appropriate flag in struct MenuItem. It works but it feels so low-level this direct structure manipulation! Gadtools has spared us from menu structure filling and linking - I can't believe we're still stuck with the old Intuition stuff when it comes to item enabling and disabling!

High time someone grabbed this project I suggested over at OpenAmiga.org.

AmigaOne X5000-020 / 2GB RAM / Sapphire Pulse Radeon RX 560 / AmigaOS 4.1 Final Edition Update 2

trixie
trixie's picture
Offline
Last seen: 6 months 3 weeks ago
Joined: 2011-02-03 13:58
Re: Disabling/enabling menu items (solved)

All right, I found my answers in SDK:Examples/ReAction/os4examples/Menus/Intuition/menus.c. It appears I cannot use my menu IDs passed in nm_UserData as I wanted, but at least it's a way that requires no direct manipulation of the menu structures. So I consider it a problem solved.

AmigaOne X5000-020 / 2GB RAM / Sapphire Pulse Radeon RX 560 / AmigaOS 4.1 Final Edition Update 2

Steady
Steady's picture
Offline
Last seen: 2 years 1 week ago
Joined: 2011-07-18 05:02
I guess you're talking about

I guess you're talking about the FULLMENUNUM macro. I didn't see that but it is a nicer way to achieve the same thing.

Glad you got it resolved.

trixie
trixie's picture
Offline
Last seen: 6 months 3 weeks ago
Joined: 2011-02-03 13:58
Re: Disabling/enabling menu items (solved)

I guess you're talking about the FULLMENUNUM macro.

Yes, the solution was to use the FULLMENUNUM() macro, which however needed a different use of menu IDs.

Previously I used a single enum of menu IDs (see the first post in this thread) that I stored in the nm_UserData field of the NewMenu structure. Then, in the input event loop, I identified the selected menu choices using the GTMENUITEM_USERDATA() macro.

However, to be able to use OnMenu() and OffMenu() the way I wanted, I had to do it differently. I needed an enum for all menus in the strip, such as this

  1. enum
  2. {
  3. MID_PROJECT,
  4. MID_SETTINGS
  5. };

and a number of enums corresponding to the number of menus above:

  1. /* menu 1: Project */
  2. enum
  3. {
  4. MID_PROJECT_NEW,
  5. MID_PROJECT_OPEN,
  6. MID_PROJECT_SAVE,
  7. MID_PROJECT_BAR1,
  8. MID_PROJECT_HELP,
  9. MID_PROJECT_ABOUT,
  10. MID_PROJECT_BAR2,
  11. MID_PROJECT_ICONIFY,
  12. MID_PROJECT_QUIT
  13. };
  14.  
  15. /* menu 2: Settings */
  16. enum
  17. {
  18. MID_SETTINGS_SAVEFORMAT,
  19. MID_SETTINGS_SAVEICONS
  20. };

This of course required a change in the event loop, because I could no longer use the menu user data. It now looks like this:

  1. case WMHI_MENUPICK:
  2. {
  3. struct MenuItem *item = NULL;
  4. uint16 menuNum, itemNum;
  5. uint16 menuSelection = code;
  6.  
  7.  
  8. while ( (menuSelection != MENUNULL) && (done == FALSE) )
  9. {
  10. item = IIntuition->ItemAddress(window->MenuStrip, menuSelection);
  11. if (!item) break;
  12.  
  13. menuNum = MENUNUM(menuSelection);
  14. itemNum = ITEMNUM(menuSelection);
  15.  
  16. switch (menuNum)
  17. {
  18. case MID_PROJECT:
  19. switch (itemNum)
  20. {
  21. case MID_PROJECT_NEW:
  22. /* do something */
  23. break;
  24.  
  25. case MID_PROJECT_OPEN:
  26. /* do something */
  27. break;
  28.  
  29. case MID_PROJECT_SAVE:
  30. /* do something */
  31. break;
  32.  
  33. case MID_PROJECT_HELP:
  34. /* do something */
  35. break;
  36.  
  37. case MID_PROJECT_ABOUT:
  38. /* do something */
  39. break;
  40.  
  41. case MID_PROJECT_ICONIFY:
  42. /* do something */
  43. break;
  44.  
  45. case MID_PROJECT_QUIT:
  46. done = TRUE;
  47. break;
  48. }
  49. break;
  50.  
  51. case MID_SETTINGS:
  52. switch (itemNum)
  53. {
  54. case MID_SETTINGS_SAVEFORMAT:
  55. /* do something */
  56. break;
  57.  
  58. case MID_SETTINGS_SAVEICONS:
  59. /* do something */
  60. break;
  61. }
  62. break;
  63. }
  64. /* We need to handle menu multiselect so check for other
  65.   menu selections the user may have made. */
  66. menuSelection = item->NextSelect;
  67. } /* while */
  68. }
  69. break;

All this is a little longer and more complicated than using the user data but the added benefit is that I can now turn on/off any menu item from any part of the code:

  1. /* Enable saving from the menu */
  2. IIntuition->OnMenu(window, FULLMENUNUM(MID_PROJECT, MID_PROJECT_SAVE, NOSUB));
  3.  
  4. /* Disable saving from the menu */
  5. IIntuition->OffMenu(window, FULLMENUNUM(MID_PROJECT, MID_PROJECT_SAVE, NOSUB));

AmigaOne X5000-020 / 2GB RAM / Sapphire Pulse Radeon RX 560 / AmigaOS 4.1 Final Edition Update 2

Log in or register to post comments