# HG changeset patch # User Olaf Wintermann # Date 1697044298 -7200 # Node ID 93b9f502cb88866f04bc5ba33cdc03f06a65982c # Parent 7ebc5a747c6fe309280c9f0e10f2a675bb86b84f add toolbar appmenu and menu buttons diff -r 7ebc5a747c6f -r 93b9f502cb88 make/vs/testapp/main.c --- a/make/vs/testapp/main.c Wed Oct 11 10:54:24 2023 +0200 +++ b/make/vs/testapp/main.c Wed Oct 11 19:11:38 2023 +0200 @@ -73,6 +73,9 @@ printf("onchange: %d\n", event->intval); } +void action_toolbar_button(UiEvent* event, void *data) { + printf("toolbar action\n"); +} void action_listselection_changed(UiEvent* event, void* data) { @@ -257,7 +260,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, int nCmdShow) -{ +{ ui_init("app1", 0, NULL); ui_onstartup(application_startup, NULL); @@ -268,9 +271,31 @@ ui_submenu_end(); ui_menuitem("Exit", NULL, NULL); - ui_toolbar_item("Test", .label = "Test"); + ui_toolbar_item("Test", .label = "Test", .onclick = action_toolbar_button); + ui_toolbar_toggleitem("Toggle", .label = "Toggle", .onchange = action_toolbar_button); + ui_toolbar_toggleitem("Toggle2", .label = "Toggle2", .onchange = action_toolbar_button); + 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_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_toolbar_add_default("Test"); + ui_toolbar_add_default("Toggle"); + ui_toolbar_add_default("Toggle2"); + ui_toolbar_add_default("Toggle3"); + ui_toolbar_add_default("Menu"); ui_main(); diff -r 7ebc5a747c6f -r 93b9f502cb88 ui/common/menu.c --- a/ui/common/menu.c Wed Oct 11 10:54:24 2023 +0200 +++ b/ui/common/menu.c Wed Oct 11 19:11:38 2023 +0200 @@ -74,6 +74,8 @@ menu->items_begin = NULL; menu->items_end = NULL; menu->parent = NULL; + + menu->end = 0; add_menu(menu); cxListAdd(current, menu); @@ -89,12 +91,14 @@ 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 - cxListInsert(current, 0, menu); + uic_add_menu_to_stack(menu); } void ui_submenu_end() { @@ -104,6 +108,10 @@ 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); } @@ -248,9 +256,27 @@ add_item((UiMenuItemI*)item); } - +void uic_add_menu_to_stack(UiMenu* menu) { + cxListInsert(current, 0, menu); +} UiMenu* uic_get_menu_list(void) { return menus_begin; } + + + +UIEXPORT void ui_menu_close(void) { + UiMenu* menu = cxListAt(current, 0); + menu->end = 1; +} + +UIEXPORT int ui_menu_is_open(void) { + UiMenu* menu = cxListAt(current, 0); + if (menu->end) { + ui_menu_end(); + return 0; + } + return 1; +} diff -r 7ebc5a747c6f -r 93b9f502cb88 ui/common/menu.h --- a/ui/common/menu.h Wed Oct 11 10:54:24 2023 +0200 +++ b/ui/common/menu.h Wed Oct 11 19:11:38 2023 +0200 @@ -72,6 +72,7 @@ UiMenuItemI *items_begin; UiMenuItemI *items_end; UiMenu *parent; + int end; }; struct UiMenuItem { @@ -119,6 +120,8 @@ UiMenu* uic_get_menu_list(void); +void uic_add_menu_to_stack(UiMenu* menu); + #ifdef __cplusplus } #endif diff -r 7ebc5a747c6f -r 93b9f502cb88 ui/common/toolbar.c --- a/ui/common/toolbar.c Wed Oct 11 10:54:24 2023 +0200 +++ b/ui/common/toolbar.c Wed Oct 11 19:11:38 2023 +0200 @@ -34,6 +34,9 @@ static CxList* toolbar_defaults; +static UiToolbarMenuItem* ui_appmenu; + + void uic_toolbar_init(void) { toolbar_items = cxHashMapCreate(cxDefaultAllocator, CX_STORE_POINTERS, 16); toolbar_defaults = cxLinkedListCreateSimple(CX_STORE_POINTERS); @@ -79,6 +82,33 @@ cxMapPut(toolbar_items, name, item); } +static UiToolbarMenuArgs menuargs_copy(UiToolbarMenuArgs args) { + UiToolbarMenuArgs newargs; + newargs.label = nl_strdup(args.label); + newargs.stockid = nl_strdup(args.stockid); + newargs.icon = nl_strdup(args.icon); + return newargs; +} + +UIEXPORT void ui_toolbar_menu_create(const char* name, UiToolbarMenuArgs args) { + UiToolbarMenuItem* item = malloc(sizeof(UiToolbarMenuItem)); + item->item.type = UI_TOOLBAR_MENU; + memset(&item->menu, 0, sizeof(UiMenu)); + item->args = menuargs_copy(args); + + item->end = 0; + + if (!name) { + // special appmenu + ui_appmenu = item; + } else { + // toplevel menu + cxMapPut(toolbar_items, name, item); + } + + uic_add_menu_to_stack(&item->menu); +} + CxMap* uic_get_toolbar_items(void) { return toolbar_items; @@ -100,3 +130,7 @@ UiToolbarItemI* uic_toolbar_get_item(const char* name) { return cxMapGet(toolbar_items, name); } + +UiToolbarMenuItem* uic_get_appmenu(void) { + return ui_appmenu; +} diff -r 7ebc5a747c6f -r 93b9f502cb88 ui/common/toolbar.h --- a/ui/common/toolbar.h Wed Oct 11 10:54:24 2023 +0200 +++ b/ui/common/toolbar.h Wed Oct 11 19:11:38 2023 +0200 @@ -34,6 +34,8 @@ #include #include +#include "menu.h" + #ifdef __cplusplus extern "C" { #endif @@ -43,9 +45,12 @@ typedef struct UiToolbarItem UiToolbarItem; typedef struct UiToolbarToggleItem UiToolbarToggleItem; +typedef struct UiToolbarMenuItem UiToolbarMenuItem; + enum UiToolbarItemType { UI_TOOLBAR_ITEM = 0, - UI_TOOLBAR_TOGGLEITEM + UI_TOOLBAR_TOGGLEITEM, + UI_TOOLBAR_MENU }; typedef enum UiToolbarItemType UiToolbarItemType; @@ -64,6 +69,14 @@ UiToolbarToggleItemArgs args; }; +struct UiToolbarMenuItem { + UiToolbarItemI item; + UiMenu menu; + UiToolbarMenuArgs args; + int end; +}; + + void uic_toolbar_init(void); CxMap* uic_get_toolbar_items(void); @@ -73,6 +86,8 @@ UiToolbarItemI* uic_toolbar_get_item(const char* name); +UiToolbarMenuItem* uic_get_appmenu(void); + #ifdef __cplusplus } #endif diff -r 7ebc5a747c6f -r 93b9f502cb88 ui/ui/menu.h --- a/ui/ui/menu.h Wed Oct 11 10:54:24 2023 +0200 +++ b/ui/ui/menu.h Wed Oct 11 19:11:38 2023 +0200 @@ -39,8 +39,8 @@ * application menu functions */ UIEXPORT void ui_menu(char *label); -UIEXPORT void ui_submenu(char *label); -UIEXPORT void ui_submenu_end(); +UIEXPORT void ui_submenu(char *label); // deprecated +UIEXPORT void ui_submenu_end(); // deprecated UIEXPORT void ui_menuitem(char *label, ui_callback f, void *userdata); UIEXPORT void ui_menuitem_st(char *stockid, ui_callback f, void *userdata); @@ -54,6 +54,8 @@ UIEXPORT void ui_menuitem_list(UiList *items, ui_callback f, void *userdata); +UIEXPORT void ui_menu_end(void); + /* * widget menu functions */ @@ -66,6 +68,11 @@ UIEXPORT void ui_widget_menuitem_gr(UiObject *obj, char *label, ui_callback f, void *userdata, ...); UIEXPORT void ui_widget_menuitem_stgr(UiObject *obj, char *stockid, ui_callback f, void *userdata, ...); + +// used for macro +UIEXPORT void ui_menu_close(void); +UIEXPORT int ui_menu_is_open(void); + #ifdef __cplusplus } #endif diff -r 7ebc5a747c6f -r 93b9f502cb88 ui/ui/toolbar.h --- a/ui/ui/toolbar.h Wed Oct 11 10:54:24 2023 +0200 +++ b/ui/ui/toolbar.h Wed Oct 11 19:11:38 2023 +0200 @@ -55,13 +55,22 @@ void* onchangedata; } UiToolbarToggleItemArgs; +typedef struct UiToolbarMenuArgs { + const char* label; + const char* stockid; + const char* icon; +} UiToolbarMenuArgs; + #define ui_toolbar_item(name, ...) ui_toolbar_item_create(name, (UiToolbarItemArgs){ __VA_ARGS__ } ) -#define ui_toolbar_toggleitem(name, ...) ui_toolbar_item_create(name, (UiToolbarItemArgs){ __VA_ARGS__ } ) +#define ui_toolbar_toggleitem(name, ...) ui_toolbar_toggleitem_create(name, (UiToolbarToggleItemArgs){ __VA_ARGS__ } ) + +#define ui_toolbar_menu(obj, ...) for(ui_toolbar_menu_create(obj, (UiToolbarMenuArgs){ __VA_ARGS__ });ui_menu_is_open();ui_menu_close()) + UIEXPORT void ui_toolbar_item_create(const char* name, UiToolbarItemArgs args); UIEXPORT void ui_toolbar_toggleitem_create(const char* name, UiToolbarToggleItemArgs args); - +UIEXPORT void ui_toolbar_menu_create(const char* name, UiToolbarMenuArgs args); void ui_toolitem_deprecated(char *name, char *label, ui_callback f, void *udata); @@ -72,16 +81,18 @@ void ui_toolitem_img(char *name, char *label, char *img, ui_callback f, void *udata); void ui_toolitem_toggle(const char *name, const char *label, const char *img, UiInteger *i); -void ui_toolitem_toggle_st(const char *name, const char *stockid, UiInteger *i); -void ui_toolitem_toggle_nv(const char *name, const char *label, const char *img, const char *intvar); -void ui_toolitem_toggle_stnv(const char *name, const char *stockid, const char *intvar); +void ui_toolitem_toggle_st_deprecated(const char *name, const char *stockid, UiInteger *i); +void ui_toolitem_toggle_nv_deprecated(const char *name, const char *label, const char *img, const char *intvar); +void ui_toolitem_toggle_stnv_deprecated(const char *name, const char *stockid, const char *intvar); -void ui_toolbar_combobox(char *name, UiList *list, ui_getvaluefunc getvalue, ui_callback f, void *udata); -void ui_toolbar_combobox_str(char *name, UiList *list, ui_callback f, void *udata); -void ui_toolbar_combobox_nv(char *name, char *listname, ui_getvaluefunc getvalue, ui_callback f, void *udata); +void ui_toolbar_combobox_deprecated(char *name, UiList *list, ui_getvaluefunc getvalue, ui_callback f, void *udata); +void ui_toolbar_combobox_str_deprecated(char *name, UiList *list, ui_callback f, void *udata); +void ui_toolbar_combobox_nv_deprecated(char *name, char *listname, ui_getvaluefunc getvalue, ui_callback f, void *udata); UIEXPORT void ui_toolbar_add_default(const char *name); + + #ifdef __cplusplus } #endif diff -r 7ebc5a747c6f -r 93b9f502cb88 ui/winui/MainWindow.xaml --- a/ui/winui/MainWindow.xaml Wed Oct 11 10:54:24 2023 +0200 +++ b/ui/winui/MainWindow.xaml Wed Oct 11 19:11:38 2023 +0200 @@ -9,7 +9,8 @@ mc:Ignorable="d"> - + + diff -r 7ebc5a747c6f -r 93b9f502cb88 ui/winui/appmenu.cpp --- a/ui/winui/appmenu.cpp Wed Oct 11 10:54:24 2023 +0200 +++ b/ui/winui/appmenu.cpp Wed Oct 11 19:11:38 2023 +0200 @@ -153,3 +153,20 @@ static void add_menuitem_list_widget(winrt::Windows::Foundation::Collections::IVector parent, int i, UiMenuItemI* item, UiObject* obj) { } + + + +winrt::Microsoft::UI::Xaml::Controls::MenuFlyout ui_create_menu_flyout(UiObject* obj, UiMenu* menudef) { + MenuFlyout flyout = MenuFlyout(); + + UiMenuItemI* it = menudef->items_begin; + int index = 0; + while (it) { + createMenuItem[it->type](flyout.Items(), index, it, obj); + + it = it->next; + index++; + } + + return flyout; +} diff -r 7ebc5a747c6f -r 93b9f502cb88 ui/winui/appmenu.h --- a/ui/winui/appmenu.h Wed Oct 11 10:54:24 2023 +0200 +++ b/ui/winui/appmenu.h Wed Oct 11 19:11:38 2023 +0200 @@ -46,3 +46,5 @@ winrt::Microsoft::UI::Xaml::Controls::MenuBar ui_create_menubar(UiObject* obj); +winrt::Microsoft::UI::Xaml::Controls::MenuFlyout ui_create_menu_flyout(UiObject* obj, UiMenu* menudef); + diff -r 7ebc5a747c6f -r 93b9f502cb88 ui/winui/commandbar.cpp --- a/ui/winui/commandbar.cpp Wed Oct 11 10:54:24 2023 +0200 +++ b/ui/winui/commandbar.cpp Wed Oct 11 19:11:38 2023 +0200 @@ -35,6 +35,7 @@ #include "../common/context.h" #include "button.h" +#include "appmenu.h" using namespace winrt; using namespace Microsoft::UI::Xaml; @@ -43,9 +44,12 @@ using namespace Microsoft::UI::Xaml::Markup; using namespace Windows::UI::Xaml::Interop; -static void create_item(UiObject* obj, CommandBar cb, UiToolbarItemI* i); -static void create_cmditem(UiObject* obj, CommandBar cb, UiToolbarItem* item); -static void create_toggleitem(UiObject* obj, CommandBar cb, UiToolbarToggleItem* item); +static void create_item(UiObject* obj, Windows::Foundation::Collections::IObservableVector cb, UiToolbarItemI* i); +static void create_cmditem(UiObject* obj, Windows::Foundation::Collections::IObservableVector cb, UiToolbarItem* item); +static void create_toggleitem(UiObject* obj, Windows::Foundation::Collections::IObservableVector cb, UiToolbarToggleItem* item); +static void create_menuitem(UiObject* obj, Windows::Foundation::Collections::IObservableVector cb, UiToolbarMenuItem* item); + +static void create_appmenu_items(UiObject* obj, Windows::Foundation::Collections::IObservableVector cb, UiToolbarMenuItem* i); CommandBar ui_create_toolbar(UiObject *obj) { @@ -60,12 +64,20 @@ if (!item) { exit(-1); // TODO: maybe an error dialog? } - create_item(obj, cb, item); + create_item(obj, cb.PrimaryCommands(), item); } + + // add appmenu + UiToolbarMenuItem* appmenu = uic_get_appmenu(); + if (appmenu) { + create_appmenu_items(obj, cb.SecondaryCommands(), appmenu); + } + + return cb; } -static void create_item(UiObject* obj, CommandBar cb, UiToolbarItemI* i) { +static void create_item(UiObject* obj, Windows::Foundation::Collections::IObservableVector cb, UiToolbarItemI* i) { switch (i->type) { case UI_TOOLBAR_ITEM: { create_cmditem(obj, cb, (UiToolbarItem*)i); @@ -75,14 +87,48 @@ create_toggleitem(obj, cb, (UiToolbarToggleItem*)i); break; } + case UI_TOOLBAR_MENU: { + create_menuitem(obj, cb, (UiToolbarMenuItem*)i); + break; + } } } -static void create_cmditem(UiObject* obj, CommandBar cb, UiToolbarItem* item) { +static void create_appmenu_items(UiObject* obj, Windows::Foundation::Collections::IObservableVector cb, UiToolbarMenuItem* i) { + for (UiMenuItemI* mi = i->menu.items_begin; mi; mi = mi->next) { + // convert UiMenuItemI to UiToolbarItemI + switch (mi->type) { + case UI_MENU_SUBMENU: { + UiMenu* mitem = (UiMenu*)mi; + UiToolbarMenuItem tbitem; + memset(&tbitem, 0, sizeof(UiToolbarMenuItem)); + tbitem.item.type = UI_TOOLBAR_MENU; + tbitem.args.label = mitem->label; + tbitem.menu.items_begin = mitem->items_begin; + tbitem.menu.items_end = mitem->items_end; + create_menuitem(obj, cb, &tbitem); + break; + } + case UI_MENU_ITEM: { + UiMenuItem* mitem = (UiMenuItem*)mi; + UiToolbarItem tbitem; + memset(&tbitem, 0, sizeof(UiToolbarItem)); + tbitem.item.type = UI_TOOLBAR_ITEM; + tbitem.args.label = mitem->label; + tbitem.args.onclick = mitem->callback; + tbitem.args.onclickdata = mitem->userdata; + create_cmditem(obj, cb, &tbitem); + break; + } + } + } +} + +static void create_cmditem(UiObject* obj, Windows::Foundation::Collections::IObservableVector cb, UiToolbarItem* item) { AppBarButton button = AppBarButton(); if (item->args.label) { wchar_t* wlabel = str2wstr(item->args.label, nullptr); - button.Content(box_value(wlabel)); + button.Label(wlabel); free(wlabel); } @@ -101,16 +147,14 @@ }); } - cb.PrimaryCommands().Append(button); + cb.Append(button); } - - -static void create_toggleitem(UiObject *obj, CommandBar cb, UiToolbarToggleItem* item) { +static void create_toggleitem(UiObject *obj, Windows::Foundation::Collections::IObservableVector cb, UiToolbarToggleItem* item) { AppBarToggleButton button = AppBarToggleButton(); if (item->args.label) { wchar_t* wlabel = str2wstr(item->args.label, nullptr); - button.Content(box_value(wlabel)); + button.Label(wlabel); free(wlabel); } @@ -138,7 +182,21 @@ togglebutton_register_callback(button, obj, args); - cb.PrimaryCommands().Append(button); + cb.Append(button); } +static void create_menuitem(UiObject* obj, Windows::Foundation::Collections::IObservableVector cb, UiToolbarMenuItem* item) { + AppBarButton button = AppBarButton(); + if (item->args.label) { + wchar_t* wlabel = str2wstr(item->args.label, nullptr); + button.Label(wlabel); + free(wlabel); + } + MenuFlyoutItem mi = MenuFlyoutItem(); + + MenuFlyout flyout = ui_create_menu_flyout(obj, &item->menu); + button.Flyout(flyout); + + cb.Append(button); +} diff -r 7ebc5a747c6f -r 93b9f502cb88 ui/winui/toolkit.cpp --- a/ui/winui/toolkit.cpp Wed Oct 11 10:54:24 2023 +0200 +++ b/ui/winui/toolkit.cpp Wed Oct 11 19:11:38 2023 +0200 @@ -123,6 +123,7 @@ } +#include void ui_init(const char* appname, int argc, char** argv) { application_name = appname; diff -r 7ebc5a747c6f -r 93b9f502cb88 ui/winui/winui.vcxproj --- a/ui/winui/winui.vcxproj Wed Oct 11 10:54:24 2023 +0200 +++ b/ui/winui/winui.vcxproj Wed Oct 11 19:11:38 2023 +0200 @@ -88,7 +88,7 @@ - _DEBUG;DISABLE_XAML_GENERATED_MAIN;UI_WINUI;UI_WINUI_PCH;%(PreprocessorDefinitions) + _DEBUG;DISABLE_XAML_GENERATED_MAIN__;UI_WINUI;UI_WINUI_PCH;%(PreprocessorDefinitions) $(SolutionDir)..\..\ucx;%(AdditionalIncludeDirectories) @@ -110,6 +110,23 @@ + + + + + + + + + + + + + + + + + diff -r 7ebc5a747c6f -r 93b9f502cb88 ui/winui/winui.vcxproj.filters --- a/ui/winui/winui.vcxproj.filters Wed Oct 11 10:54:24 2023 +0200 +++ b/ui/winui/winui.vcxproj.filters Wed Oct 11 19:11:38 2023 +0200 @@ -36,6 +36,57 @@ + + public + + + public + + + public + + + public + + + public + + + public + + + public + + + public + + + public + + + public + + + public + + + public + + + public + + + public + + + public + + + public + + + public + @@ -64,6 +115,9 @@ {59f97886-bf49-4b3f-9ef6-fa7a84f3ab56} + + {2b58fe46-d27b-4335-b63c-13ec2204fa24} +