libui/windows: add support for submenus

This commit is contained in:
StapleButter 2017-10-30 03:11:45 +01:00
parent 3881b2615b
commit 84a842c6f3
2 changed files with 44 additions and 1 deletions

View File

@ -273,6 +273,7 @@ _UI_EXTERN uiMenuItem *uiMenuAppendCheckItem(uiMenu *m, const char *name);
_UI_EXTERN uiMenuItem *uiMenuAppendQuitItem(uiMenu *m); _UI_EXTERN uiMenuItem *uiMenuAppendQuitItem(uiMenu *m);
_UI_EXTERN uiMenuItem *uiMenuAppendPreferencesItem(uiMenu *m); _UI_EXTERN uiMenuItem *uiMenuAppendPreferencesItem(uiMenu *m);
_UI_EXTERN uiMenuItem *uiMenuAppendAboutItem(uiMenu *m); _UI_EXTERN uiMenuItem *uiMenuAppendAboutItem(uiMenu *m);
_UI_EXTERN uiMenuItem *uiMenuAppendSubmenu(uiMenu *m, const char *name, uiMenu* child);
_UI_EXTERN void uiMenuAppendSeparator(uiMenu *m); _UI_EXTERN void uiMenuAppendSeparator(uiMenu *m);
_UI_EXTERN uiMenu *uiNewMenu(const char *name); _UI_EXTERN uiMenu *uiNewMenu(const char *name);

View File

@ -15,6 +15,7 @@ static BOOL hasAbout = FALSE;
struct uiMenu { struct uiMenu {
WCHAR *name; WCHAR *name;
uiMenuItem **items; uiMenuItem **items;
BOOL ischild;
size_t len; size_t len;
size_t cap; size_t cap;
}; };
@ -28,6 +29,7 @@ struct uiMenuItem {
BOOL disabled; // template for new instances; kept in sync with everything else BOOL disabled; // template for new instances; kept in sync with everything else
BOOL checked; BOOL checked;
HMENU *hmenus; HMENU *hmenus;
uiMenu* popupchild;
size_t len; size_t len;
size_t cap; size_t cap;
}; };
@ -39,6 +41,7 @@ enum {
typePreferences, typePreferences,
typeAbout, typeAbout,
typeSeparator, typeSeparator,
typeSubmenu,
}; };
#define grow 32 #define grow 32
@ -140,6 +143,7 @@ static uiMenuItem *newItem(uiMenu *m, int type, const char *name)
item->name = toUTF16(name); item->name = toUTF16(name);
break; break;
} }
item->popupchild = NULL;
if (item->type != typeSeparator) { if (item->type != typeSeparator) {
item->id = curID; item->id = curID;
@ -156,6 +160,34 @@ static uiMenuItem *newItem(uiMenu *m, int type, const char *name)
return item; return item;
} }
uiMenuItem *uiMenuAppendSubmenu(uiMenu *m, const char *name, uiMenu* child)
{
uiMenuItem *item;
if (menusFinalized)
userbug("You can not create a new menu item after menus have been finalized.");
if (m->len >= m->cap) {
m->cap += grow;
m->items = (uiMenuItem **) uiRealloc(m->items, m->cap * sizeof (uiMenuItem *), "uiMenuitem *[]");
}
item = uiNew(uiMenuItem);
m->items[m->len] = item;
m->len++;
item->type = typeSubmenu;
item->name = toUTF16(name);
item->popupchild = child;
child->ischild = TRUE;
uiMenuItemOnClicked(item, defaultOnClicked, NULL);
return item;
}
uiMenuItem *uiMenuAppendItem(uiMenu *m, const char *name) uiMenuItem *uiMenuAppendItem(uiMenu *m, const char *name)
{ {
return newItem(m, typeRegular, name); return newItem(m, typeRegular, name);
@ -216,13 +248,17 @@ uiMenu *uiNewMenu(const char *name)
len++; len++;
m->name = toUTF16(name); m->name = toUTF16(name);
m->ischild = FALSE;
return m; return m;
} }
static HMENU makeMenu(uiMenu *m);
static void appendMenuItem(HMENU menu, uiMenuItem *item) static void appendMenuItem(HMENU menu, uiMenuItem *item)
{ {
UINT uFlags; UINT uFlags;
UINT_PTR id = item->id;
uFlags = MF_SEPARATOR; uFlags = MF_SEPARATOR;
if (item->type != typeSeparator) { if (item->type != typeSeparator) {
@ -231,8 +267,13 @@ static void appendMenuItem(HMENU menu, uiMenuItem *item)
uFlags |= MF_DISABLED | MF_GRAYED; uFlags |= MF_DISABLED | MF_GRAYED;
if (item->checked) if (item->checked)
uFlags |= MF_CHECKED; uFlags |= MF_CHECKED;
if (item->popupchild)
{
uFlags |= MF_POPUP;
id = (UINT_PTR)makeMenu(item->popupchild);
}
} }
if (AppendMenuW(menu, uFlags, item->id, item->name) == 0) if (AppendMenuW(menu, uFlags, id, item->name) == 0)
logLastError(L"error appending menu item"); logLastError(L"error appending menu item");
if (item->len >= item->cap) { if (item->len >= item->cap) {
@ -269,6 +310,7 @@ HMENU makeMenubar(void)
logLastError(L"error creating menubar"); logLastError(L"error creating menubar");
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
if (menus[i]->ischild) continue;
menu = makeMenu(menus[i]); menu = makeMenu(menus[i]);
if (AppendMenuW(menubar, MF_POPUP | MF_STRING, (UINT_PTR) menu, menus[i]->name) == 0) if (AppendMenuW(menubar, MF_POPUP | MF_STRING, (UINT_PTR) menu, menus[i]->name) == 0)
logLastError(L"error appending menu to menubar"); logLastError(L"error appending menu to menubar");