# HG changeset patch # User Olaf Wintermann # Date 1732187093 -3600 # Node ID 473c03f85197c643f031d3ae34f5021c169ab9e9 # Parent 80edb1a93f7af837c9194da49f2fe55f41df4520 add menu builder API diff -r 80edb1a93f7a -r 473c03f85197 application/main.c --- a/application/main.c Sun Nov 17 15:21:50 2024 +0100 +++ b/application/main.c Thu Nov 21 12:04:53 2024 +0100 @@ -369,6 +369,23 @@ ui_menuitem(.label = "Test"); } + UiMenuBuilder *menubuilder; + ui_contextmenu(&menubuilder) { + ui_menuitem(.label = "Context Item 1"); + ui_menuitem(.label = "Context Item 2"); + ui_menu("Context Submenu") { + ui_menuitem(.label = "Context Sub Item"); + } + } + + ui_menu("Edit") { + ui_menuitem(.label = "Undo"); + ui_menuseparator(); + ui_menu("Submenu") { + ui_menuitem(.label = "Subitem"); + } + } + ui_toolbar_item("Test", .label = "Test", .onclick = action_toolbar_button); ui_toolbar_item("Test2", .label = "New Window", .onclick = action_toolbar_newwindow); ui_toolbar_item("Test3", .label = "Dialog", .onclick = action_toolbar_dialog); diff -r 80edb1a93f7a -r 473c03f85197 ui/common/menu.c --- a/ui/common/menu.c Sun Nov 17 15:21:50 2024 +0100 +++ b/ui/common/menu.c Thu Nov 21 12:04:53 2024 +0100 @@ -35,23 +35,27 @@ #include -static UiMenu *menus_begin; -static UiMenu *menus_end; -static CxList *current; +static UiMenuBuilder *current_builder; +static UiMenuBuilder global_builder; static int menu_item_counter = 0; +void uic_menu_init(void) { + global_builder.current = cxLinkedListCreate(cxDefaultAllocator, NULL, CX_STORE_POINTERS); + current_builder = &global_builder; +} + static void add_menu(UiMenu *menu) { cx_linked_list_add( - (void**)&menus_begin, - (void**)&menus_end, + (void**)¤t_builder->menus_begin, + (void**)¤t_builder->menus_end, offsetof(UiMenu, item.prev), offsetof(UiMenu, item.next), menu); } static void add_item(UiMenuItemI *item) { - UiMenu *menu = cxListAt(current, 0); + UiMenu *menu = cxListAt(current_builder->current, 0); cx_linked_list_add( (void**)&menu->items_begin, (void**)&menu->items_end, @@ -86,11 +90,7 @@ return NULL; } -void ui_menu_create(const char *label) { - if(!current) { - current = cxLinkedListCreate(cxDefaultAllocator, NULL, CX_STORE_POINTERS); - } - +void ui_menu_create(const char *label) { // create menu UiMenu *menu = malloc(sizeof(UiMenu)); mitem_set_id(&menu->item); @@ -105,7 +105,7 @@ menu->end = 0; - if (cxListSize(current) == 0) { + if (cxListSize(current_builder->current) == 0) { add_menu(menu); } else { @@ -115,16 +115,15 @@ } UIEXPORT void ui_menu_end(void) { - cxListRemove(current, 0); + cxListRemove(current_builder->current, 0); + if(cxListSize(current_builder->current) == 0) { + current_builder = &global_builder; + } } void ui_menuitem_create(UiMenuItemArgs args) { - if (!current) { - return; // error? - } - UiMenuItem* item = malloc(sizeof(UiMenuItem)); mitem_set_id(&item->item); item->item.prev = NULL; @@ -142,10 +141,6 @@ } void ui_menuseparator() { - if(!current) { - return; - } - UiMenuItemI *item = malloc(sizeof(UiMenuItemI)); item->id[0] = 0; item->prev = NULL; @@ -156,10 +151,6 @@ } void ui_menu_toggleitem_create(UiMenuToggleItemArgs args) { - if(!current) { - return; - } - UiMenuCheckItem *item = malloc(sizeof(UiMenuCheckItem)); mitem_set_id(&item->item); item->item.prev = NULL; @@ -178,10 +169,6 @@ } void ui_menu_radioitem_create(UiMenuToggleItemArgs args) { - if (!current) { - return; - } - UiMenuCheckItem* item = malloc(sizeof(UiMenuCheckItem)); mitem_set_id(&item->item); item->item.prev = NULL; @@ -200,10 +187,6 @@ } void ui_menu_itemlist_create(UiMenuItemListArgs args) { - if(!current) { - return; - } - UiMenuItemList*item = malloc(sizeof(UiMenuItemList)); mitem_set_id(&item->item); item->item.prev = NULL; @@ -218,10 +201,6 @@ } void ui_menu_checkitemlist_create(UiMenuItemListArgs args) { - if (!current) { - return; - } - UiMenuItemList* item = malloc(sizeof(UiMenuItemList)); mitem_set_id(&item->item); item->item.prev = NULL; @@ -235,10 +214,6 @@ } void ui_menu_radioitemlist_create(UiMenuItemListArgs args) { - if (!current) { - return; - } - UiMenuItemList* item = malloc(sizeof(UiMenuItemList)); mitem_set_id(&item->item); item->item.prev = NULL; @@ -253,27 +228,101 @@ void uic_add_menu_to_stack(UiMenu* menu) { - if (!current) { - current = cxLinkedListCreate(cxDefaultAllocator, NULL, CX_STORE_POINTERS); - } - - cxListInsert(current, 0, menu); + cxListInsert(current_builder->current, 0, menu); } UiMenu* uic_get_menu_list(void) { - return menus_begin; + return current_builder->menus_begin; } UIEXPORT void ui_menu_close(void) { - UiMenu* menu = cxListAt(current, 0); + UiMenu* menu = cxListAt(current_builder->current, 0); menu->end = 1; } UIEXPORT int ui_menu_is_open(void) { - UiMenu* menu = cxListAt(current, 0); + UiMenu* menu = cxListAt(current_builder->current, 0); if (menu->end) { ui_menu_end(); return 0; } return 1; } + + +void ui_contextmenu_builder(UiMenuBuilder **out_builder) { + UiMenuBuilder *builder = malloc(sizeof(UiMenuBuilder)); + builder->menus_begin = NULL; + builder->menus_end = NULL; + builder->current = cxLinkedListCreate(cxDefaultAllocator, NULL, CX_STORE_POINTERS); + current_builder = builder; + *out_builder = builder; + + ui_menu_create(NULL); +} + + + +static void free_menuitem(UiMenuItemI *item) { + switch(item->type) { + default: break; + case UI_MENU: { + UiMenu *menu = (UiMenu*)item; + UiMenuItemI *m = menu->items_begin; + while(m) { + UiMenuItemI *next = m->next; + free_menuitem(m); + m = next; + } + break; + } + case UI_MENU_ITEM: { + UiMenuItem *i = (UiMenuItem*)item; + free(i->groups); + free(i->label); + free(i->stockid); + free(i->icon); + break; + } + case UI_MENU_CHECK_ITEM: { + UiMenuCheckItem *i = (UiMenuCheckItem*)item; + free(i->groups); + free(i->label); + free(i->stockid); + free(i->icon); + free(i->varname); + break; + } + case UI_MENU_RADIO_ITEM: { + UiMenuRadioItem *i = (UiMenuRadioItem*)item; + free(i->groups); + free(i->label); + free(i->stockid); + free(i->icon); + //free(i->varname); + break; + } + case UI_MENU_ITEM_LIST: { + break; + } + case UI_MENU_CHECKITEM_LIST: { + break; + } + case UI_MENU_RADIOITEM_LIST: { + break; + } + } + + free(item); +} + +void ui_menubuilder_free(UiMenuBuilder *builder) { + UiMenuItemI *m = &builder->menus_begin->item; + while(m) { + UiMenuItemI *next = m->next; + free_menuitem(m); + m = next; + } + cxListDestroy(builder->current); + free(builder); +} diff -r 80edb1a93f7a -r 473c03f85197 ui/common/menu.h --- a/ui/common/menu.h Sun Nov 17 15:21:50 2024 +0100 +++ b/ui/common/menu.h Thu Nov 21 12:04:53 2024 +0100 @@ -76,9 +76,9 @@ struct UiMenuItem { UiMenuItemI item; ui_callback callback; - const char *label; - const char *stockid; - const char *icon; + char *label; + char *stockid; + char *icon; void *userdata; int *groups; size_t ngroups; @@ -86,10 +86,10 @@ struct UiMenuCheckItem { UiMenuItemI item; - const char* label; - const char* stockid; - const char* icon; - const char* varname; + char *label; + char *stockid; + char *icon; + char *varname; ui_callback callback; void *userdata; int *groups; @@ -98,11 +98,11 @@ struct UiMenuRadioItem { UiMenuItemI item; - const char* label; - const char* stockid; - const char* icon; + char *label; + char *stockid; + char *icon; ui_callback callback; - void* userdata; + void *userdata; int *groups; size_t ngroups; }; @@ -112,10 +112,19 @@ ui_getvaluefunc getvalue; ui_callback callback; void *userdata; - const char *varname; + char *varname; }; + +struct UiMenuBuilder { + UiMenu *menus_begin; + UiMenu *menus_end; + CxList *current; +}; + +void uic_menu_init(void); + UiMenu* uic_get_menu_list(void); void uic_add_menu_to_stack(UiMenu* menu); diff -r 80edb1a93f7a -r 473c03f85197 ui/gtk/menu.c --- a/ui/gtk/menu.c Sun Nov 17 15:21:50 2024 +0100 +++ b/ui/gtk/menu.c Thu Nov 21 12:04:53 2024 +0100 @@ -355,6 +355,7 @@ * widget menu functions */ +/* static gboolean ui_button_press_event(GtkWidget *widget, GdkEvent *event, GtkMenu *menu) { if(event->type == GDK_BUTTON_PRESS) { GdkEventButton *e = (GdkEventButton*)event; @@ -389,6 +390,7 @@ gtk_menu_popup(menu, NULL, NULL, 0, 0, 0, gtk_get_current_event_time()); #endif } +*/ void ui_widget_menuitem(UiObject *obj, char *label, ui_callback f, void *userdata) { ui_widget_menuitem_gr(obj, label, f, userdata, -1); diff -r 80edb1a93f7a -r 473c03f85197 ui/gtk/toolkit.c --- a/ui/gtk/toolkit.c Sun Nov 17 15:21:50 2024 +0100 +++ b/ui/gtk/toolkit.c Thu Nov 21 12:04:53 2024 +0100 @@ -78,6 +78,7 @@ ui_css_init(); uic_docmgr_init(); + uic_menu_init(); uic_toolbar_init(); ui_image_init(); uic_load_app_properties(); diff -r 80edb1a93f7a -r 473c03f85197 ui/ui/menu.h --- a/ui/ui/menu.h Sun Nov 17 15:21:50 2024 +0100 +++ b/ui/ui/menu.h Thu Nov 21 12:04:53 2024 +0100 @@ -86,28 +86,17 @@ 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_checkitem_deprecated(char *label, ui_callback f, void *userdata); -UIEXPORT void ui_checkitem_nv_deprecated(char *label, char *vname); - -UIEXPORT void ui_menuitem_list_deprecated(UiList *items, ui_callback f, void *userdata); - UIEXPORT void ui_menu_end(void); // TODO: private /* * widget menu functions */ -UIEXPORT UIMENU ui_contextmenu(UiObject *obj); -UIEXPORT UIMENU ui_contextmenu_w(UiObject *obj, UIWIDGET widget); + +#define ui_contextmenu(builder) for(ui_contextmenu_builder(builder);ui_menu_is_open();ui_menu_close()) + +UIEXPORT void ui_contextmenu_builder(UiMenuBuilder **out_builder); +UIEXPORT void ui_menubuilder_free(UiMenuBuilder *builder); +UIEXPORT UIMENU ui_contextmenu_create(UiMenuBuilder *builder, UiObject *obj, UIWIDGET widget); UIEXPORT void ui_contextmenu_popup(UIMENU menu); UIEXPORT void ui_widget_menuitem(UiObject *obj, char *label, ui_callback f, void *userdata); diff -r 80edb1a93f7a -r 473c03f85197 ui/ui/toolkit.h --- a/ui/ui/toolkit.h Sun Nov 17 15:21:50 2024 +0100 +++ b/ui/ui/toolkit.h Thu Nov 21 12:04:53 2024 +0100 @@ -174,15 +174,16 @@ typedef struct UiListSelection UiListSelection; /* begin opaque types */ -typedef struct UiContext UiContext; -typedef struct UiContainer UiContainer; +typedef struct UiContext UiContext; +typedef struct UiContainer UiContainer; +typedef struct UiMenuBuilder UiMenuBuilder; -typedef struct UiIcon UiIcon; -typedef struct UiImage UiImage; +typedef struct UiIcon UiIcon; +typedef struct UiImage UiImage; -typedef struct UiDnD UiDnD; +typedef struct UiDnD UiDnD; -typedef struct UiThreadpool UiThreadpool; +typedef struct UiThreadpool UiThreadpool; /* end opaque types */ typedef struct UiTabbedPane UiTabbedPane; diff -r 80edb1a93f7a -r 473c03f85197 ui/winui/toolkit.cpp --- a/ui/winui/toolkit.cpp Sun Nov 17 15:21:50 2024 +0100 +++ b/ui/winui/toolkit.cpp Thu Nov 21 12:04:53 2024 +0100 @@ -166,6 +166,7 @@ uic_init_global_context(); uic_docmgr_init(); + uic_menu_init(); uic_toolbar_init(); uic_load_app_properties();