diff --git a/src/libui_sdl/libui/ui.h b/src/libui_sdl/libui/ui.h index 6e51d444..31ca5a9a 100644 --- a/src/libui_sdl/libui/ui.h +++ b/src/libui_sdl/libui/ui.h @@ -273,6 +273,7 @@ _UI_EXTERN uiMenuItem *uiMenuAppendCheckItem(uiMenu *m, const char *name); _UI_EXTERN uiMenuItem *uiMenuAppendQuitItem(uiMenu *m); _UI_EXTERN uiMenuItem *uiMenuAppendPreferencesItem(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 uiMenu *uiNewMenu(const char *name); diff --git a/src/libui_sdl/libui/windows/menu.cpp b/src/libui_sdl/libui/windows/menu.cpp index 6112fc13..2310e614 100644 --- a/src/libui_sdl/libui/windows/menu.cpp +++ b/src/libui_sdl/libui/windows/menu.cpp @@ -15,6 +15,7 @@ static BOOL hasAbout = FALSE; struct uiMenu { WCHAR *name; uiMenuItem **items; + BOOL ischild; size_t len; size_t cap; }; @@ -28,6 +29,7 @@ struct uiMenuItem { BOOL disabled; // template for new instances; kept in sync with everything else BOOL checked; HMENU *hmenus; + uiMenu* popupchild; size_t len; size_t cap; }; @@ -39,6 +41,7 @@ enum { typePreferences, typeAbout, typeSeparator, + typeSubmenu, }; #define grow 32 @@ -140,6 +143,7 @@ static uiMenuItem *newItem(uiMenu *m, int type, const char *name) item->name = toUTF16(name); break; } + item->popupchild = NULL; if (item->type != typeSeparator) { item->id = curID; @@ -156,6 +160,34 @@ static uiMenuItem *newItem(uiMenu *m, int type, const char *name) 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) { return newItem(m, typeRegular, name); @@ -216,13 +248,17 @@ uiMenu *uiNewMenu(const char *name) len++; m->name = toUTF16(name); + m->ischild = FALSE; return m; } +static HMENU makeMenu(uiMenu *m); + static void appendMenuItem(HMENU menu, uiMenuItem *item) { UINT uFlags; + UINT_PTR id = item->id; uFlags = MF_SEPARATOR; if (item->type != typeSeparator) { @@ -231,8 +267,13 @@ static void appendMenuItem(HMENU menu, uiMenuItem *item) uFlags |= MF_DISABLED | MF_GRAYED; if (item->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"); if (item->len >= item->cap) { @@ -269,6 +310,7 @@ HMENU makeMenubar(void) logLastError(L"error creating menubar"); for (i = 0; i < len; i++) { + if (menus[i]->ischild) continue; menu = makeMenu(menus[i]); if (AppendMenuW(menubar, MF_POPUP | MF_STRING, (UINT_PTR) menu, menus[i]->name) == 0) logLastError(L"error appending menu to menubar");