ui/motif/menu.c

changeset 101
7b3a3130be44
parent 100
d2bd73d28ff1
--- a/ui/motif/menu.c	Thu Dec 12 20:01:43 2024 +0100
+++ b/ui/motif/menu.c	Mon Jan 06 22:22:55 2025 +0100
@@ -36,8 +36,278 @@
 #include "stock.h"
 #include "container.h"
 #include "../common/context.h"
+#include "../common/menu.h"
+#include "../common/types.h"
 #include "../ui/window.h"
 
 #include <cx/linked_list.h>
 #include <cx/array_list.h>
 
+
+static ui_menu_add_f createMenuItem[] = {
+    /* UI_MENU                 */ add_menu_widget,
+    /* UI_MENU_ITEM            */ add_menuitem_widget,
+    /* UI_MENU_CHECK_ITEM      */ add_checkitem_widget,
+    /* UI_MENU_RADIO_ITEM      */ add_radioitem_widget,
+    /* UI_MENU_ITEM_LIST       */ add_menuitem_list_widget,
+    /* UI_MENU_CHECKITEM_LIST  */ add_menuitem_list_widget,
+    /* UI_MENU_RADIOITEM_LIST  */ add_menuitem_list_widget,
+    /* UI_MENU_SEPARATOR       */ add_menuseparator_widget
+};
+
+void ui_create_menubar(UiObject *obj, Widget window) {
+    UiMenu *menus_begin = uic_get_menu_list();
+    if(!menus_begin) {
+        return;
+    }
+    
+    Widget menubar = XmCreateMenuBar(window, "menubar", NULL, 0);
+    XtManageChild(menubar);
+    
+    UiMenu *ls = menus_begin;
+    while(ls) {
+        UiMenu *menu = ls;
+        add_menu_widget(menubar, 0, &menu->item, obj);
+        ls = (UiMenu*)ls->item.next;
+    }
+}
+
+void ui_add_menu_items(Widget parent, int i, UiMenu *menu, UiObject *obj) {
+    UiMenuItemI *it = menu->items_begin;
+    int index = 0;
+    while(it) {
+        createMenuItem[it->type](parent, index, it, obj);
+        it = it->next;
+        index++;
+    }
+}
+
+void add_menu_widget(Widget parent, int i, UiMenuItemI *item, UiObject *obj) {
+    UiMenu *menu = (UiMenu*)item;
+    Arg args[4];
+    int n = 0;
+    
+    XmString s = NULL;
+    if(menu->label) {
+        s = XmStringCreateLocalized((char*)menu->label);
+        XtSetArg(args[n], XmNlabelString, s); n++;
+    }
+    
+    Widget submenu = XmVaCreateSimplePulldownMenu(parent, "menu_pulldown", i, NULL, NULL);
+    XtSetArg(args[n], XmNsubMenuId, submenu); n++;
+    Widget menuItem = XtCreateManagedWidget(
+            "menuitem",
+            xmCascadeButtonWidgetClass,
+            parent,
+            args,
+            n);
+    
+    
+    if(s) {
+        XmStringFree(s);
+    }
+    
+    ui_add_menu_items(submenu, i, menu, obj);
+}
+
+void add_menuitem_widget(Widget parent, int i, UiMenuItemI *item, UiObject *obj) {
+    UiMenuItem *it = (UiMenuItem*)item;
+    
+    XmString s = NULL;
+    Arg args[4];
+    int n = 0;
+    if(it->label) {
+        s = XmStringCreateLocalized((char*)it->label);
+        XtSetArg(args[n], XmNlabelString, s); n++;
+    }
+    
+    Widget mitem = XtCreateManagedWidget(
+            "menubutton",
+            xmPushButtonWidgetClass,
+            parent,
+            args,
+            n);
+    if(s) {
+        XmStringFree(s);
+    }
+    
+    if(it->callback) {
+        UiEventData *eventdata = malloc(sizeof(UiEventData));
+        eventdata->callback = it->callback;
+        eventdata->userdata = it->userdata;
+        eventdata->obj = obj;
+        eventdata->value = 0;
+        XtAddCallback(
+                mitem,
+                XmNactivateCallback,
+                (XtCallbackProc)ui_push_button_callback,
+                eventdata);
+       XtAddCallback(
+                mitem,
+                XmNdestroyCallback,
+                (XtCallbackProc)ui_destroy_eventdata,
+                eventdata);
+    }
+    
+    ui_set_widget_groups(obj->ctx, mitem, it->groups);
+}
+
+void add_menuseparator_widget(Widget p, int i, UiMenuItemI *item, UiObject *obj) {
+    Widget s = XmCreateSeparatorGadget (p, "menuseparator", NULL, 0);
+    XtManageChild(s);
+}
+
+void add_checkitem_widget(Widget p, int i, UiMenuItemI *item, UiObject *obj) {
+    UiMenuCheckItem *it = (UiMenuCheckItem*)item;
+    
+    Arg args[4];
+    int n = 0;
+    XmString s = NULL;
+    if(it->label) {
+        s = XmStringCreateLocalized(it->label);
+        XtSetArg(args[n], XmNlabelString, s); n++;
+    }
+    
+    //XtSetArg(args[n], XmNvisibleWhenOff, 0); n++;
+    Widget checkbox = XtCreateManagedWidget(
+            "menutogglebutton",
+            xmToggleButtonWidgetClass,
+            p,
+            args,
+            n);
+    if(s) {
+        XmStringFree(s);
+    }
+    
+    ui_bind_togglebutton(obj, checkbox, it->varname, NULL, it->callback, it->userdata, 0);
+    
+    ui_set_widget_groups(obj->ctx, checkbox, it->groups);
+}
+
+void add_radioitem_widget(Widget p, int index, UiMenuItemI *item, UiObject *obj) {
+    UiMenuRadioItem *it = (UiMenuRadioItem*)item;
+    
+    Arg args[4];
+    int n = 0;
+    XmString s = NULL;
+    if(it->label) {
+        s = XmStringCreateLocalized(it->label);
+        XtSetArg(args[n], XmNlabelString, s); n++;
+    }
+    XtSetArg(args[n], XmNindicatorType, XmONE_OF_MANY_ROUND); n++;
+    
+    Widget button = XmCreateToggleButton(p, "menuradiobutton", args, n);
+    XtManageChild(button);
+    
+    ui_bind_radiobutton(obj, button, NULL, it->varname, it->callback, it->userdata, 0);
+}
+
+void add_menuitem_list_widget(Widget p, int i, UiMenuItemI *item, UiObject *obj) {
+    UiMenuItemList *il = (UiMenuItemList*)item;
+    const CxAllocator *a = obj->ctx->allocator;
+    
+    UiActiveMenuItemList *ls = cxMalloc(
+            a,
+            sizeof(UiActiveMenuItemList));
+    ls->object = obj;
+    ls->menu = p;
+    ls->index = i;
+    ls->oldcount = 0;
+    ls->getvalue = il->getvalue;
+    ls->callback = il->callback;
+    ls->userdata = il->userdata;
+    ls->addseparator = il->addseparator;
+    
+    ls->var = uic_create_var(ui_global_context(), il->varname, UI_VAR_LIST); //uic_widget_var(obj->ctx, obj->ctx, NULL, il->varname, UI_VAR_LIST);
+    UiList *list = ls->var->value;
+    
+    UiObserver *observer = ui_observer_new((ui_callback)ui_update_menuitem_list, ls);
+    list->observers = ui_obsvlist_add(list->observers, observer);
+    uic_list_register_observer_destructor(obj->ctx, list, observer);
+    
+    ui_update_menuitem_list(NULL, ls);
+}
+
+void ui_update_menuitem_list(UiEvent *event, UiActiveMenuItemList *list) {
+    XmString s = NULL;
+    Arg args[4];
+    int n;
+    
+    UiList *ls;
+    if(list->var && list->var->value) {
+        ls = list->var->value;
+    } else {
+        return;
+    }
+    
+    if(list->oldcount > 0) {
+        Widget *children;
+        int nc;
+        
+        XtVaGetValues(
+                list->menu,
+                XmNchildren,
+                &children,
+                XmNnumChildren,
+                &nc,
+                NULL);
+        
+        for(int i=0;i<list->oldcount;i++) {
+            XtDestroyWidget(children[list->index + i]);
+        }
+    }
+    
+    void* elm = ui_list_first(ls);
+    int i = 0;
+    if(elm && list->addseparator) {
+        XtSetArg(args[0], XmNpositionIndex, list->index);
+        Widget s = XmCreateSeparatorGadget(list->menu, "menuseparator", args, 1);
+        XtManageChild(s);
+        i++;
+    }
+    
+    ui_getvaluefunc getvalue = list->getvalue;
+    int pos = list->index;
+    while(elm) {
+        n = 0;
+        char *label = (char*) (getvalue ? getvalue(elm, 0) : elm);
+        if(label) {
+            s = XmStringCreateLocalized(label);
+            XtSetArg(args[n], XmNlabelString, s); n++;
+        }
+        XtSetArg(args[n], XmNpositionIndex, pos+i); n++;
+        
+        Widget mitem = XtCreateManagedWidget(
+                "menubutton",
+                xmPushButtonWidgetClass,
+                list->menu,
+                args,
+                n);
+        if(s) {
+            XmStringFree(s);
+        }
+
+        if(list->callback) {
+            UiEventData *eventdata = malloc(sizeof(UiEventData));
+            eventdata->callback = list->callback;
+            eventdata->userdata = list->userdata;
+            eventdata->obj = list->object;
+            eventdata->value = 0;
+            XtAddCallback(
+                    mitem,
+                    XmNactivateCallback,
+                    (XtCallbackProc)ui_push_button_callback,
+                    eventdata);
+            XtAddCallback(
+                    mitem,
+                    XmNdestroyCallback,
+                    (XtCallbackProc)ui_destroy_eventdata,
+                    eventdata);
+        }
+        
+        elm = ui_list_next(ls);
+        i++;
+    }
+    
+    list->oldcount = i;
+}

mercurial