The Allegro Wiki is migrating to github at https://github.com/liballeg/allegro_wiki/wiki

Difference between revisions of "Native Menu Proposal"

From Allegro Wiki
Jump to: navigation, search
(Created page with 'Allegro's native dialog add-on provides a way to access basic OS dialogs (message boxes, file selectors, etc). This is a proposal to add support for native menus as part of the a…')
 
(added implementation note and link to docs)
 
(4 intermediate revisions by the same user not shown)
Line 2: Line 2:
  
 
<b>This proposal is a draft.</b> It is likely to change as it is implemented.
 
<b>This proposal is a draft.</b> It is likely to change as it is implemented.
 +
 +
This has been mostly implemented on the 5.1 branch. See The [http://alleg.sourceforge.net/a5docs/refman/native_dialog.html#menus documentation] for the actual API.
  
 
== API ==
 
== API ==
Line 19: Line 21:
 
};
 
};
  
/* creating/modifying */
+
 
 +
/* creating/modifying menus */
 
ALLEGRO_MENU *al_create_menu(void);
 
ALLEGRO_MENU *al_create_menu(void);
 +
ALLEGRO_MENU *al_build_menu(ALLEGRO_MENU_INFO *info);
 
int al_append_menu_item(ALLEGRO_MENU *parent, char const *title, int id, int flags, ALLEGRO_MENU *popup);
 
int al_append_menu_item(ALLEGRO_MENU *parent, char const *title, int id, int flags, ALLEGRO_MENU *popup);
int al_insert_menu_item(ALLEGRO_MENU *parent, int index, char const *title, int id, int flags, ALLEGRO_MENU *popup);
+
int al_insert_menu_item(ALLEGRO_MENU *parent, int before_id, char const *title, int id, int flags, ALLEGRO_MENU *popup);
void al_remove_menu_item(ALLEGRO_MENU *menu, int index);
+
bool al_remove_menu_item(ALLEGRO_MENU *menu, int id);
void al_set_menu_item_flags(ALLEGRO_MENU *menu, int index, int flags);
 
 
ALLEGRO_MENU *al_clone_menu(ALLEGRO_MENU *menu);
 
ALLEGRO_MENU *al_clone_menu(ALLEGRO_MENU *menu);
 
void al_destroy_menu(ALLEGRO_MENU *menu);
 
void al_destroy_menu(ALLEGRO_MENU *menu);
  
/* querying */
+
/* properties */
int al_get_menu_index_by_id(ALLEGRO_MENU *menu, int id);
+
int al_get_menu_item_flags(ALLEGRO_MENU *menu, int id);
int al_get_menu_index_by_name(ALLEGRO_MENU *menu, int const char *title);
+
void al_set_menu_item_flags(ALLEGRO_MENU *menu, int id, int flags);
 
+
void al_toggle_menu_item_flags(ALLEGRO_MENU *menu, int id, int flags);
/* events */
+
 +
/* querying menus */
 +
bool al_find_menu_item(ALLEGRO_MENU *haystack, int id, ALLEGRO_MENU **menu, int *index);
 +
 +
/* menu events */
 
ALLEGRO_EVENT_SOURCE *al_get_default_menu_event_source(void);
 
ALLEGRO_EVENT_SOURCE *al_get_default_menu_event_source(void);
 
ALLEGRO_EVENT_SOURCE *al_enable_menu_event_source(ALLEGRO_MENU *menu);
 
ALLEGRO_EVENT_SOURCE *al_enable_menu_event_source(ALLEGRO_MENU *menu);
 
void al_disable_menu_event_source(ALLEGRO_MENU *menu);
 
void al_disable_menu_event_source(ALLEGRO_MENU *menu);
 
+
/* displaying */
+
/* displaying menus */
void al_set_display_menu(ALLEGRO_DISPLAY *display, ALLEGRO_MENU *menu);
+
bool al_set_display_menu(ALLEGRO_DISPLAY *display, ALLEGRO_MENU *menu);
void al_popup_menu(ALLEGRO_MENU *popup, ALLEGRO_DISPLAY *display, int x, int y);
+
bool al_popup_menu(ALLEGRO_MENU *popup, ALLEGRO_DISPLAY *display, int x, int y);
void al_hide_menu(ALLEGRO_MENU *menu);
+
ALLEGRO_MENU *al_remove_display_menu(ALLEGRO_DISPLAY *menu);
 
 
  
 
</highlightSyntax>
 
</highlightSyntax>
Line 67: Line 73:
 
* There is no way yet to specify keyboard triggers.
 
* There is no way yet to specify keyboard triggers.
  
* A higher level function like <tt>al_build_menu(ALLEGRO_MENU_INFO *info)</tt> that takes a complete menu structure could be useful to make the creation process less verbose.
+
* The public functions have "id" parameters that represent a menu id. The entire menu structure is queried for that id, including child menus. If the "id" parameter is zero or negative, then its absolute value is assumed to be the index position of the menu item.  
  
 
=== OS X ===
 
=== OS X ===

Latest revision as of 08:16, July 12, 2011

Allegro's native dialog add-on provides a way to access basic OS dialogs (message boxes, file selectors, etc). This is a proposal to add support for native menus as part of the add-on.

This proposal is a draft. It is likely to change as it is implemented.

This has been mostly implemented on the 5.1 branch. See The documentation for the actual API.

API

<highlightSyntax language="c"> typedef struct ALLEGRO_MENU ALLEGRO_MENU;

enum ALLEGRO_MENU_ITEM_FLAGS {

 ALLEGRO_MENU_ITEM_CHECKED  = 1,
 ALLEGRO_MENU_ITEM_DISABLED = 2

};

struct ALLEGRO_EVENT_MENU_ITEM {

 ALLEGRO_DISPLAY *display;
 ALLEGRO_MENU *menu;
 int id;

};


/* creating/modifying menus */ ALLEGRO_MENU *al_create_menu(void); ALLEGRO_MENU *al_build_menu(ALLEGRO_MENU_INFO *info); int al_append_menu_item(ALLEGRO_MENU *parent, char const *title, int id, int flags, ALLEGRO_MENU *popup); int al_insert_menu_item(ALLEGRO_MENU *parent, int before_id, char const *title, int id, int flags, ALLEGRO_MENU *popup); bool al_remove_menu_item(ALLEGRO_MENU *menu, int id); ALLEGRO_MENU *al_clone_menu(ALLEGRO_MENU *menu); void al_destroy_menu(ALLEGRO_MENU *menu);

/* properties */ int al_get_menu_item_flags(ALLEGRO_MENU *menu, int id); void al_set_menu_item_flags(ALLEGRO_MENU *menu, int id, int flags); void al_toggle_menu_item_flags(ALLEGRO_MENU *menu, int id, int flags);

/* querying menus */ bool al_find_menu_item(ALLEGRO_MENU *haystack, int id, ALLEGRO_MENU **menu, int *index);

/* menu events */ ALLEGRO_EVENT_SOURCE *al_get_default_menu_event_source(void); ALLEGRO_EVENT_SOURCE *al_enable_menu_event_source(ALLEGRO_MENU *menu); void al_disable_menu_event_source(ALLEGRO_MENU *menu);

/* displaying menus */ bool al_set_display_menu(ALLEGRO_DISPLAY *display, ALLEGRO_MENU *menu); bool al_popup_menu(ALLEGRO_MENU *popup, ALLEGRO_DISPLAY *display, int x, int y); ALLEGRO_MENU *al_remove_display_menu(ALLEGRO_DISPLAY *menu);

</highlightSyntax>

Basic Use Case

<highlightSyntax language="c"> ALLEGRO_MENU *file = al_create_menu(); al_append_menu_item(file, "Open", OPEN_ID, 0, NULL); al_append_menu_item(file, "Exit", EXIT_ID, 0, NULL);

ALLEGRO_MENU *menu = al_create_menu(); al_append_menu_item(menu, "File", 0, 0, file);

al_set_display_menu(display, menu); </highlightSyntax>

Implementation Notes

  • An ALLEGRO_MENU can only be attached to a single display at a time. A menu that is attached to a display cannot be used as a popup. The al_clone_menu() is intended to be used for the case where the same menu should be displayed on multiple displays.
  • Events are sent via the closest source found in the menu hierarchy. If none is found (al_enable_menu_event_source() was not ever used), then they are sent via a default source.
  • There is no way yet to specify a bitmap icon. If an ALLEGRO_BITMAP is used, then it would have to be converted to the OS's native bitmap format.
  • There is no way yet to specify keyboard triggers.
  • The public functions have "id" parameters that represent a menu id. The entire menu structure is queried for that id, including child menus. If the "id" parameter is zero or negative, then its absolute value is assumed to be the index position of the menu item.

OS X

The system menu is always built (with certain default menu items), even if no user menu has been set. So when a user menu is set, those default menu items should be automatically inserted in a transparent manner.

OS X uses a single application menu as opposed to a per window menu. This presents a problem because the API is designed to work with a per-window menu. Some solutions:

  1. Automatically detect when a display gains focus, and update the menu accordingly. If the newly focused display has no menu, then nothing would happen to the existing system menu. If possible, this would be the preferred solution. While it may not be how first-class OS X applications operate, it provides the most transparent cross platform solution.
  2. Always show the most recent menu as set via al_set_display_menu() regardless of the current display. The user would have to explicitly call that function every time a different display gains focus. When a display is destroyed, the user would have to call al_set_display_menu(NULL, NULL). (The first parameter would actually just be ignored, so it could be anything, including the pointer of the destroyed display.)