Wed, 11 Oct 2023 22:59:42 +0200
new menu api
make/vs/testapp/main.c | file | annotate | diff | comparison | revisions | |
ui/common/menu.c | file | annotate | diff | comparison | revisions | |
ui/common/menu.h | file | annotate | diff | comparison | revisions | |
ui/ui/menu.h | file | annotate | diff | comparison | revisions | |
ui/ui/toolkit.h | file | annotate | diff | comparison | revisions | |
ui/winui/appmenu.cpp | file | annotate | diff | comparison | revisions | |
ui/winui/commandbar.cpp | file | annotate | diff | comparison | revisions | |
ui/winui/toolkit.cpp | file | annotate | diff | comparison | revisions |
--- a/make/vs/testapp/main.c Wed Oct 11 19:11:38 2023 +0200 +++ b/make/vs/testapp/main.c Wed Oct 11 22:59:42 2023 +0200 @@ -228,7 +228,7 @@ ui_combobox(obj, .list = wdata->list, .onselection= action_listselection_changed, .onactivate= action_onactivate); ui_newline(obj); - ui_tabview(obj, .colspan = 3, .vexpand = true, .hexpand = true, .tabview = UI_TABVIEW_NAVIGATION_TOP2) { + ui_tabview(obj, .colspan = 3, .vexpand = true, .hexpand = true, .tabview = UI_TABVIEW_NAVIGATION_SIDE) { ui_tab(obj, "Tab 1") { ui_button(obj, .label = "Tab 1 Button"); } @@ -264,12 +264,16 @@ ui_init("app1", 0, NULL); ui_onstartup(application_startup, NULL); - ui_menu("File"); - ui_menuitem("Test", NULL, NULL); - ui_submenu("Sub"); - ui_menuitem("subitem", NULL, NULL); - ui_submenu_end(); - ui_menuitem("Exit", NULL, NULL); + ui_menu("File") { + ui_menuitem(.label = "Item 1"); + ui_menuitem(.label = "Item 2"); + ui_menuseparator(); + ui_menu("File Sub") { + ui_menuitem(.label = "Sub Item"); + } + + ui_menuitem(.label = "Exit"); + } ui_toolbar_item("Test", .label = "Test", .onclick = action_toolbar_button); ui_toolbar_toggleitem("Toggle", .label = "Toggle", .onchange = action_toolbar_button); @@ -277,20 +281,20 @@ ui_toolbar_toggleitem("Toggle3", .label = "Toggle3", .onchange = action_toolbar_button); ui_toolbar_menu("Menu", .label = "Menu") { - ui_menuitem("TB Test", NULL, NULL); - ui_submenu("TB Sub"); - ui_menuitem("TB subitem", NULL, NULL); - ui_submenu_end(); + + ui_menuitem(.label = "x", NULL, NULL); + ui_menu("TB Sub") { + ui_menuitem("TB subitem", NULL, NULL); + } } ui_toolbar_menu(NULL, .label = "Menu") { ui_menuitem("Secondary Test", NULL, NULL); - ui_submenu("Secondary Sub"); - ui_menuitem("Secondary subitem", NULL, NULL); - ui_submenu_end(); + ui_menu("Secondary Sub") { + ui_menuitem("Secondary subitem", NULL, NULL); + } } - ui_toolbar_add_default("Test"); ui_toolbar_add_default("Toggle"); ui_toolbar_add_default("Toggle2");
--- a/ui/common/menu.c Wed Oct 11 19:11:38 2023 +0200 +++ b/ui/common/menu.c Wed Oct 11 22:59:42 2023 +0200 @@ -29,6 +29,7 @@ #include "menu.h" #include <stdarg.h> +#include <string.h> #include <cx/linked_list.h> #include <cx/array_list.h> @@ -56,12 +57,31 @@ item); } -void ui_menu(char *label) { +static char* nl_strdup(const char* s) { + return s ? strdup(s) : NULL; +} + +static int* copy_groups(int* groups, size_t *ngroups) { + *ngroups = 0; + if (!groups) { + return NULL; + } + + size_t n; + for (n = 0; groups[n] > -1; n++) { } + + if (ngroups > 0) { + int* newarray = calloc(n, sizeof(int)); + memcpy(newarray, groups, n); + *ngroups = n; + return newarray; + } + return NULL; +} + +void ui_menu_create(const char *label) { if(!current) { current = cxLinkedListCreate(cxDefaultAllocator, NULL, CX_STORE_POINTERS); - } else { - // free current menu hierarchy - cxListClear(current); } // create menu @@ -76,107 +96,39 @@ menu->parent = NULL; menu->end = 0; - - add_menu(menu); - cxListAdd(current, menu); -} -void ui_submenu(char *label) { - UiMenu *menu = malloc(sizeof(UiMenu)); - menu->item.prev = NULL; - menu->item.next = NULL; - menu->item.type = UI_MENU_SUBMENU; - - menu->label = label; - menu->items_begin = NULL; - menu->items_end = NULL; - menu->parent = NULL; - - menu->end = 0; - - // add submenu to current menu - add_item((UiMenuItemI*)menu); - - // set the submenu to current menu + if (current->size == 0) { + add_menu(menu); + } + else { + add_item((UiMenuItemI*)menu); + } uic_add_menu_to_stack(menu); } -void ui_submenu_end() { - if(current->size < 2) { - return; - } - cxListRemove(current, 0); -} - UIEXPORT void ui_menu_end(void) { cxListRemove(current, 0); } -void ui_menuitem(char *label, ui_callback f, void *userdata) { - ui_menuitem_gr(label, f, userdata, -1); -} + -void ui_menuitem_st(char *stockid, ui_callback f, void *userdata) { - ui_menuitem_stgr(stockid, f, userdata, -1); -} +void ui_menuitem_create(UiMenuItemArgs args) { + if (!current) { + return; // error? + } -void ui_menuitem_gr(char *label, ui_callback f, void *userdata, ...) { - if(!current) { - return; - } - - UiMenuItem *item = malloc(sizeof(UiMenuItem)); + UiMenuItem* item = malloc(sizeof(UiMenuItem)); item->item.prev = NULL; item->item.next = NULL; item->item.type = UI_MENU_ITEM; - - item->label = label; - item->userdata = userdata; - item->callback = f; - item->groups = NULL; - - // add groups - va_list ap; - va_start(ap, userdata); - int group; - while((group = va_arg(ap, int)) != -1) { - if(!item->groups) { - item->groups = cxArrayListCreate(cxDefaultAllocator, NULL, sizeof(int), 8); - } - cxListAdd(item->groups, &group); - } - va_end(ap); - - add_item((UiMenuItemI*)item); -} -void ui_menuitem_stgr(char *stockid, ui_callback f, void *userdata, ...) { - if(!current) { - return; - } - - UiStMenuItem *item = malloc(sizeof(UiStMenuItem)); - item->item.prev = NULL; - item->item.next = NULL; - item->item.type = UI_MENU_STOCK_ITEM; - - item->stockid = stockid; - item->userdata = userdata; - item->callback = f; - item->groups = NULL; - - // add groups - va_list ap; - va_start(ap, userdata); - int group; - while((group = va_arg(ap, int)) != -1) { - if(!item->groups) { - item->groups = cxArrayListCreate(cxDefaultAllocator, NULL, sizeof(int), 8); - } - cxListAdd(item->groups, &group); - } - va_end(ap); - + item->label = nl_strdup(args.label); + item->stockid = nl_strdup(args.stockid); + item->icon = nl_strdup(args.icon); + item->userdata = args.onclickdata; + item->callback = args.onclick; + item->groups = copy_groups(args.groups, &item->ngroups); + add_item((UiMenuItemI*)item); } @@ -193,69 +145,97 @@ add_item((UiMenuItemI*)item); } -void ui_checkitem(char *label, ui_callback f, void *userdata) { +void ui_menu_toggleitem_create(UiMenuToggleItemArgs args) { if(!current) { return; } - UiCheckItem *item = malloc(sizeof(UiCheckItem)); + UiMenuCheckItem *item = malloc(sizeof(UiMenuCheckItem)); item->item.prev = NULL; item->item.next = NULL; item->item.type = UI_MENU_CHECK_ITEM; - item->label = label; - item->callback = f; - item->userdata = userdata; - - add_item((UiMenuItemI*)item); -} -void ui_checkitem_nv(char *label, char *vname) { - if(!current) { - return; - } - - UiCheckItemNV *item = malloc(sizeof(UiCheckItemNV)); - item->item.prev = NULL; - item->item.next = NULL; - item->item.type = UI_MENU_CHECK_ITEM_NV; - item->varname = vname; - item->label = label; + item->label = nl_strdup(args.label); + item->stockid = nl_strdup(args.stockid); + item->icon = nl_strdup(args.icon); + item->varname = nl_strdup(args.varname); + item->userdata = args.onchangedata; + item->callback = args.onchange; + item->groups = copy_groups(args.groups, &item->ngroups); add_item((UiMenuItemI*)item); } -void ui_menuitem_list(UiList *items, ui_callback f, void *userdata) { +void ui_menu_radioitem_create(UiMenuToggleItemArgs args) { + if (!current) { + return; + } + + UiMenuCheckItem* item = malloc(sizeof(UiMenuCheckItem)); + item->item.prev = NULL; + item->item.next = NULL; + item->item.type = UI_MENU_CHECK_ITEM; + + item->label = nl_strdup(args.label); + item->stockid = nl_strdup(args.stockid); + item->icon = nl_strdup(args.icon); + item->varname = nl_strdup(args.varname); + item->userdata = args.onchangedata; + item->callback = args.onchange; + item->groups = copy_groups(args.groups, &item->ngroups); + + add_item((UiMenuItemI*)item); +} + +void ui_menu_itemlist_create(UiMenuItemListArgs args) { if(!current) { return; } - UiMenuItemList *item = malloc(sizeof(UiMenuItemList)); + UiMenuItemList*item = malloc(sizeof(UiMenuItemList)); item->item.prev = NULL; item->item.next = NULL; item->item.type = UI_MENU_ITEM_LIST; - item->callback = f; - item->userdata = userdata; - item->list = items; + item->callback = args.onselect; + item->userdata = args.onselectdata; + item->varname = nl_strdup(args.varname); add_item((UiMenuItemI*)item); } -void ui_menuitem_list_nv(const char *varname, ui_callback f, void *userdata) { - if(!current) { +void ui_menu_checkitemlist_create(UiMenuItemListArgs args) { + if (!current) { return; } - - UiMenuItemListNV *item = malloc(sizeof(UiMenuItemListNV)); + + UiMenuItemList* item = malloc(sizeof(UiMenuItemList)); item->item.prev = NULL; item->item.next = NULL; item->item.type = UI_MENU_ITEM_LIST; - item->callback = f; - item->userdata = userdata; - item->varname = varname; - + item->callback = args.onselect; + item->userdata = args.onselectdata; + item->varname = nl_strdup(args.varname); + add_item((UiMenuItemI*)item); } +void ui_menu_radioitemlist_create(UiMenuItemListArgs args) { + if (!current) { + return; + } + + UiMenuItemList* item = malloc(sizeof(UiMenuItemList)); + item->item.prev = NULL; + item->item.next = NULL; + item->item.type = UI_MENU_ITEM_LIST; + item->callback = args.onselect; + item->userdata = args.onselectdata; + item->varname = nl_strdup(args.varname); + + add_item((UiMenuItemI*)item); +} + + void uic_add_menu_to_stack(UiMenu* menu) { cxListInsert(current, 0, menu); } @@ -264,9 +244,6 @@ return menus_begin; } - - - UIEXPORT void ui_menu_close(void) { UiMenu* menu = cxListAt(current, 0); menu->end = 1;
--- a/ui/common/menu.h Wed Oct 11 19:11:38 2023 +0200 +++ b/ui/common/menu.h Wed Oct 11 22:59:42 2023 +0200 @@ -40,21 +40,18 @@ typedef struct UiMenuItemI UiMenuItemI; typedef struct UiMenu UiMenu; typedef struct UiMenuItem UiMenuItem; -typedef struct UiStMenuItem UiStMenuItem; -typedef struct UiCheckItem UiCheckItem; -typedef struct UiCheckItemNV UiCheckItemNV; +typedef struct UiMenuCheckItem UiMenuCheckItem; +typedef struct UiMenuRadioItem UiMenuRadioItem; typedef struct UiMenuItemList UiMenuItemList; -typedef struct UiMenuItemListNV UiMenuItemListNV; enum UiMenuItemType { UI_MENU = 0, - UI_MENU_SUBMENU, UI_MENU_ITEM, - UI_MENU_STOCK_ITEM, UI_MENU_CHECK_ITEM, - UI_MENU_CHECK_ITEM_NV, + UI_MENU_RADIO_ITEM, UI_MENU_ITEM_LIST, - UI_MENU_ITEM_LIST_NV, + UI_MENU_CHECKITEM_LIST, + UI_MENU_RADIOITEM_LIST, UI_MENU_SEPARATOR }; @@ -78,45 +75,44 @@ struct UiMenuItem { UiMenuItemI item; ui_callback callback; - char *label; + const char *label; + const char *stockid; + const char *icon; void *userdata; - CxList *groups; + int *groups; + size_t ngroups; }; -struct UiStMenuItem { +struct UiMenuCheckItem { UiMenuItemI item; + const char* label; + const char* stockid; + const char* icon; + const char* varname; ui_callback callback; - char *stockid; void *userdata; - CxList *groups; + int *groups; + size_t ngroups; }; -struct UiCheckItem { +struct UiMenuRadioItem { UiMenuItemI item; - char *label; + const char* label; + const char* stockid; + const char* icon; ui_callback callback; - void *userdata; -}; - -struct UiCheckItemNV { - UiMenuItemI item; - char *label; - char *varname; + void* userdata; + int *groups; + size_t ngroups; }; struct UiMenuItemList { UiMenuItemI item; ui_callback callback; void *userdata; - UiList *list; + const char* varname; }; -struct UiMenuItemListNV { - UiMenuItemI item; - ui_callback callback; - void *userdata; - const char *varname; -}; UiMenu* uic_get_menu_list(void);
--- a/ui/ui/menu.h Wed Oct 11 19:11:38 2023 +0200 +++ b/ui/ui/menu.h Wed Oct 11 22:59:42 2023 +0200 @@ -35,24 +35,67 @@ extern "C" { #endif -/* - * application menu functions - */ -UIEXPORT void ui_menu(char *label); -UIEXPORT void ui_submenu(char *label); // deprecated -UIEXPORT void ui_submenu_end(); // deprecated + +typedef struct UiMenuItemArgs { + const char* label; + const char* stockid; + const char* icon; + + ui_callback onclick; + void* onclickdata; + + const int* groups; +} UiMenuItemArgs; + +typedef struct UiMenuToggleItemArgs { + const char* label; + const char* stockid; + const char* icon; + + const char* varname; + ui_callback onchange; + void* onchangedata; + + const int* groups; +} UiMenuToggleItemArgs; -UIEXPORT void ui_menuitem(char *label, ui_callback f, void *userdata); +typedef struct UiMenuItemListArgs { + const char* varname; + ui_callback onselect; + void* onselectdata; +} UiMenuItemListArgs; + +#define ui_menu(label) for(ui_menu_create(label);ui_menu_is_open();ui_menu_close()) + +#define ui_menuitem(...) ui_menuitem_create((UiMenuItemArgs){ __VA_ARGS__ }) +#define ui_menu_toggleitem(...) ui_menu_toggleitem_create((UiMenuToggleItemArgs){ __VA_ARGS__ }) +#define ui_menu_radioitem(...) ui_menu_radioitem_create((UiMenuToggleItemArgs){ __VA_ARGS__ }) + +UIEXPORT void ui_menu_create(const char* label); +UIEXPORT void ui_menuitem_create(UiMenuItemArgs args); +UIEXPORT void ui_menu_toggleitem_create(UiMenuToggleItemArgs args); +UIEXPORT void ui_menu_radioitem_create(UiMenuToggleItemArgs args); + +UIEXPORT void ui_menuseparator(); + +UIEXPORT void ui_menu_itemlist_create(UiMenuItemListArgs args); +UIEXPORT void ui_menu_toggleitemlist_create(UiMenuItemListArgs args); +UIEXPORT void ui_menu_radioitemlist_create(UiMenuItemListArgs args); + +UIEXPORT void ui_menu_deprecated(char *label); +UIEXPORT void ui_submenu_deprecated(char *label); // deprecated +UIEXPORT void ui_submenu_end_deprecated(); // deprecated + +UIEXPORT void ui_menuitem_deprecated(char *label, ui_callback f, void *userdata); UIEXPORT void ui_menuitem_st(char *stockid, ui_callback f, void *userdata); UIEXPORT void ui_menuitem_gr(char *label, ui_callback f, void *userdata, ...); UIEXPORT void ui_menuitem_stgr(char *stockid, ui_callback f, void *userdata, ...); -UIEXPORT void ui_menuseparator(); -UIEXPORT void ui_checkitem(char *label, ui_callback f, void *userdata); -UIEXPORT void ui_checkitem_nv(char *label, char *vname); +UIEXPORT void ui_checkitem_deprecated(char *label, ui_callback f, void *userdata); +UIEXPORT void ui_checkitem_nv_deprecated(char *label, char *vname); -UIEXPORT void ui_menuitem_list(UiList *items, ui_callback f, void *userdata); +UIEXPORT void ui_menuitem_list_deprecated(UiList *items, ui_callback f, void *userdata); UIEXPORT void ui_menu_end(void);
--- a/ui/ui/toolkit.h Wed Oct 11 19:11:38 2023 +0200 +++ b/ui/ui/toolkit.h Wed Oct 11 22:59:42 2023 +0200 @@ -135,6 +135,8 @@ #endif #define UI_GROUP_SELECTION 20000 + +#define UI_GROUPS(...) (int[]){ __VA_ARGS__, -1 } /* public types */ typedef int UiBool;
--- a/ui/winui/appmenu.cpp Wed Oct 11 19:11:38 2023 +0200 +++ b/ui/winui/appmenu.cpp Wed Oct 11 22:59:42 2023 +0200 @@ -47,21 +47,21 @@ static void add_menu_widget(winrt::Windows::Foundation::Collections::IVector<winrt::Microsoft::UI::Xaml::Controls::MenuFlyoutItemBase> parent, int i, UiMenuItemI* item, UiObject* obj); static void add_menuitem_widget(winrt::Windows::Foundation::Collections::IVector<winrt::Microsoft::UI::Xaml::Controls::MenuFlyoutItemBase> parent, int i, UiMenuItemI* item, UiObject* obj); -static void add_menuitem_st_widget(winrt::Windows::Foundation::Collections::IVector<winrt::Microsoft::UI::Xaml::Controls::MenuFlyoutItemBase> parent, int i, UiMenuItemI* item, UiObject* obj); static void add_menuseparator_widget(winrt::Windows::Foundation::Collections::IVector<winrt::Microsoft::UI::Xaml::Controls::MenuFlyoutItemBase> parent, int i, UiMenuItemI* item, UiObject* obj); static void add_checkitem_widget(winrt::Windows::Foundation::Collections::IVector<winrt::Microsoft::UI::Xaml::Controls::MenuFlyoutItemBase> parent, int i, UiMenuItemI* item, UiObject* obj); -static void add_checkitemnv_widget(winrt::Windows::Foundation::Collections::IVector<winrt::Microsoft::UI::Xaml::Controls::MenuFlyoutItemBase> parent, int i, UiMenuItemI* item, UiObject* obj); +static void add_radioitem_widget(winrt::Windows::Foundation::Collections::IVector<winrt::Microsoft::UI::Xaml::Controls::MenuFlyoutItemBase> parent, int i, UiMenuItemI* item, UiObject* obj); static void add_menuitem_list_widget(winrt::Windows::Foundation::Collections::IVector<winrt::Microsoft::UI::Xaml::Controls::MenuFlyoutItemBase> parent, int i, UiMenuItemI* item, UiObject* obj); +static void add_menucheckitem_list_widget(winrt::Windows::Foundation::Collections::IVector<winrt::Microsoft::UI::Xaml::Controls::MenuFlyoutItemBase> parent, int i, UiMenuItemI* item, UiObject* obj); +static void add_menuradioitem_list_widget(winrt::Windows::Foundation::Collections::IVector<winrt::Microsoft::UI::Xaml::Controls::MenuFlyoutItemBase> parent, int i, UiMenuItemI* item, UiObject* obj); static ui_menu_add_f createMenuItem[] = { /* UI_MENU */ add_menu_widget, - /* UI_MENU_SUBMENU */ add_menu_widget, /* UI_MENU_ITEM */ add_menuitem_widget, - /* UI_MENU_STOCK_ITEM */ add_menuitem_st_widget, /* UI_MENU_CHECK_ITEM */ add_checkitem_widget, - /* UI_MENU_CHECK_ITEM_NV */ add_checkitemnv_widget, + /* UI_MENU_RADIO_ITEM */ NULL, // TODO /* UI_MENU_ITEM_LIST */ add_menuitem_list_widget, - /* UI_MENU_ITEM_LIST_NV */ NULL, // TODO + /* UI_MENU_CHECKITEM_LIST */ NULL, // TODO + /* UI_MENU_RADIOITEM_LIST */ NULL, // TODO /* UI_MENU_SEPARATOR */ add_menuseparator_widget };
--- a/ui/winui/commandbar.cpp Wed Oct 11 19:11:38 2023 +0200 +++ b/ui/winui/commandbar.cpp Wed Oct 11 22:59:42 2023 +0200 @@ -98,7 +98,7 @@ for (UiMenuItemI* mi = i->menu.items_begin; mi; mi = mi->next) { // convert UiMenuItemI to UiToolbarItemI switch (mi->type) { - case UI_MENU_SUBMENU: { + case UI_MENU: { UiMenu* mitem = (UiMenu*)mi; UiToolbarMenuItem tbitem; memset(&tbitem, 0, sizeof(UiToolbarMenuItem));
--- a/ui/winui/toolkit.cpp Wed Oct 11 19:11:38 2023 +0200 +++ b/ui/winui/toolkit.cpp Wed Oct 11 22:59:42 2023 +0200 @@ -125,9 +125,22 @@ #include <MddBootstrap.h> +void ui_appsdk_bootstrap(void) { + const UINT32 majorMinorVersion{ 0x00010002 }; + PCWSTR versionTag{ L"" }; + const PACKAGE_VERSION minVersion{}; + + const HRESULT hr = MddBootstrapInitialize(majorMinorVersion, versionTag, minVersion); + if (FAILED(hr)) { + exit(102); + } +} + void ui_init(const char* appname, int argc, char** argv) { application_name = appname; + //ui_appsdk_bootstrap(); + uic_toolbar_init(); }