add menu builder API newapi

Thu, 21 Nov 2024 12:04:53 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Thu, 21 Nov 2024 12:04:53 +0100
branch
newapi
changeset 388
473c03f85197
parent 387
80edb1a93f7a
child 389
d15eca5fd8b3

add menu builder API

application/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/gtk/menu.c file | annotate | diff | comparison | revisions
ui/gtk/toolkit.c 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/toolkit.cpp file | annotate | diff | comparison | revisions
--- 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);
--- 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 <cx/array_list.h>
 
 
-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**)&current_builder->menus_begin,
+            (void**)&current_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);
+}
--- 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);
--- 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);
--- 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();
--- 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);
--- 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;
--- 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();

mercurial