added groups for menu items (GTK, Motif)

Thu, 03 Apr 2014 11:12:22 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Thu, 03 Apr 2014 11:12:22 +0200
changeset 21
012418e7dc90
parent 20
2dda1ad6dc7a
child 22
bcf880b29bc3

added groups for menu items (GTK, Motif)

application/main.c file | annotate | diff | comparison | revisions
ui/cocoa/menu.m file | annotate | diff | comparison | revisions
ui/cocoa/toolkit.m file | annotate | diff | comparison | revisions
ui/common/context.c file | annotate | diff | comparison | revisions
ui/common/context.h file | annotate | diff | comparison | revisions
ui/gtk/button.c file | annotate | diff | comparison | revisions
ui/gtk/menu.c file | annotate | diff | comparison | revisions
ui/gtk/menu.h file | annotate | diff | comparison | revisions
ui/gtk/toolkit.c file | annotate | diff | comparison | revisions
ui/gtk/toolkit.h file | annotate | diff | comparison | revisions
ui/gtk/window.c file | annotate | diff | comparison | revisions
ui/motif/menu.c file | annotate | diff | comparison | revisions
ui/motif/menu.h file | annotate | diff | comparison | revisions
ui/motif/toolkit.c file | annotate | diff | comparison | revisions
ui/ui/toolkit.h file | annotate | diff | comparison | revisions
--- a/application/main.c	Wed Apr 02 20:31:47 2014 +0200
+++ b/application/main.c	Thu Apr 03 11:12:22 2014 +0200
@@ -76,6 +76,7 @@
     if(event->obj->document != wdata->doc1) {
         ui_set_document(event->obj, wdata->doc1);
     }
+    ui_unset_group(event->obj->ctx, 1);
 }
 
 void action_doc2(UiEvent *event, void *data) {
@@ -83,6 +84,7 @@
     if(event->obj->document != wdata->doc2) {
         ui_set_document(event->obj, wdata->doc2);
     }
+    ui_set_group(event->obj->ctx, 1);
 }
 
 void action_undo(UiEvent *event, void *data) {
@@ -116,9 +118,11 @@
     ui_menuitem_st(UI_STOCK_OPEN, action_open, NULL);
     ui_menuitem_stgr(UI_STOCK_SAVE, action_save, NULL, 1, -1);
     ui_menuseparator();
+    
     ui_menuitem("Dokument 1", action_doc1, NULL);
     ui_menuitem("Dokument 2", action_doc2, NULL);
-    void ui_menuseparator();
+    
+    ui_menuseparator();
     
     ui_checkitem_nv("Check", "check1");
     //ui_checkitem("Check", action_open, NULL);
--- a/ui/cocoa/menu.m	Wed Apr 02 20:31:47 2014 +0200
+++ b/ui/cocoa/menu.m	Thu Apr 03 11:12:22 2014 +0200
@@ -105,6 +105,7 @@
             }
         }
     }
+    free(groups);
     
     for(int j=0;j<c;j++) {
         if(check[j] == 0) {
@@ -167,7 +168,7 @@
     while((group = va_arg(ap, int)) != -1) {
         [item addGroup: group];
     }
-    
+    va_end(ap);
     
     [currentMenu addItem:item];
     
@@ -190,7 +191,7 @@
     while((group = va_arg(ap, int)) != -1) {
         [item addGroup: group];
     }
-    
+    va_end(ap);
     
     [currentMenu addItem:item];
     
--- a/ui/cocoa/toolkit.m	Wed Apr 02 20:31:47 2014 +0200
+++ b/ui/cocoa/toolkit.m	Thu Apr 03 11:12:22 2014 +0200
@@ -68,6 +68,10 @@
     }
 }
 
+void ui_set_enabled(UIWIDGET widget, int enabled) {
+    [widget setEnabled:enabled];
+}
+
 void ui_main() {
     [NSApp run];
     [pool release];
--- a/ui/common/context.c	Wed Apr 02 20:31:47 2014 +0200
+++ b/ui/common/context.c	Thu Apr 03 11:12:22 2014 +0200
@@ -43,6 +43,7 @@
     ctx->toplevel = toplevel;
     ctx->vars = ucx_map_new_a(mp->allocator, 16);
     ctx->groups = NULL;
+    ctx->group_widgets = NULL;
     
 #ifdef UI_GTK
     ctx->accel_group = gtk_accel_group_new();
@@ -158,6 +159,9 @@
     if(ucx_list_find(ctx->groups, (void*)(intptr_t)group, NULL, NULL) == -1) {
         ctx->groups = ucx_list_append_a(ctx->mempool->allocator, ctx->groups, (void*)(intptr_t)group);
     }
+    
+    // enable/disable group widgets
+    uic_check_group_widgets(ctx);
 }
 
 void ui_unset_group(UiContext *ctx, int group) {
@@ -166,6 +170,9 @@
         UcxList *elm = ucx_list_get(ctx->groups, i);
         ctx->groups = ucx_list_remove_a(ctx->mempool->allocator, ctx->groups, elm);
     }
+    
+    // enable/disable group widgets
+    uic_check_group_widgets(ctx);
 }
 
 int* ui_active_groups(UiContext *ctx, int *ngroups) {
@@ -180,3 +187,51 @@
     *ngroups = nelm;
     return groups;
 }
+
+void uic_check_group_widgets(UiContext *ctx) {
+    int ngroups = 0;
+    int *groups = ui_active_groups(ctx, &ngroups);
+    
+    UCX_FOREACH(elm, ctx->group_widgets) {
+        UiGroupWidget *gw = elm->data;
+        char *check = calloc(1, gw->numgroups);
+        
+        for(int i=0;i<ngroups;i++) {
+            for(int k=0;k<gw->numgroups;k++) {
+                if(groups[i] == gw->groups[k]) {
+                    check[k] = 1;
+                }
+            }
+        }
+        
+        int enable = 1;
+        for(int i=0;i<gw->numgroups;i++) {
+            if(check[i] == 0) {
+                enable = 0;
+                break;
+            }
+        }
+        ui_set_enabled(gw->widget, enable);
+    }
+    
+    free(groups);
+}
+
+void uic_add_group_widget(UiContext *ctx, UIWIDGET widget, UcxList *groups) {
+    UcxMempool *mp = ctx->mempool;
+    UiGroupWidget *gw = ucx_mempool_malloc(mp, sizeof(UiGroupWidget));
+    
+    gw->widget = widget;
+    gw->numgroups = ucx_list_size(groups);
+    gw->groups = ucx_mempool_calloc(mp, gw->numgroups, sizeof(int));
+    int i = 0;
+    UCX_FOREACH(elm, groups) {
+        gw->groups[i++] = (intptr_t)elm->data;
+    }
+    
+    ctx->group_widgets = ucx_list_append_a(
+            mp->allocator,
+            ctx->group_widgets,
+            gw);
+}
+
--- a/ui/common/context.h	Wed Apr 02 20:31:47 2014 +0200
+++ b/ui/common/context.h	Thu Apr 03 11:12:22 2014 +0200
@@ -38,13 +38,15 @@
 extern "C" {
 #endif
 
-typedef struct UiVar UiVar;
+typedef struct UiVar         UiVar;
+typedef struct UiGroupWidget UiGroupWidget;
 
 struct UiContext {
     UiObject      *toplevel;
     UcxMempool    *mempool;
     UcxMap        *vars; // key: char*  value: UiVar*
     UcxList       *groups; // int list
+    UcxList       *group_widgets; // UiGroupWidget* list
     
 #ifdef UI_GTK
     GtkAccelGroup *accel_group;
@@ -58,6 +60,12 @@
     UcxMap *from;
 };
 
+struct UiGroupWidget {
+    UIWIDGET widget;
+    int      *groups;
+    int      numgroups;
+};
+
 enum UiVarType {
     UI_VAR_INTEGER = 0,
     UI_VAR_STRING
@@ -68,7 +76,8 @@
 UiVar* uic_connect_var(UiContext *ctx, char *name, int type);
 void* uic_create_value(UcxAllocator *a, int type);
 
-
+void uic_check_group_widgets(UiContext *ctx);
+void uic_add_group_widget(UiContext *ctx, UIWIDGET widget, UcxList *groups);
 
 #ifdef	__cplusplus
 }
--- a/ui/gtk/button.c	Wed Apr 02 20:31:47 2014 +0200
+++ b/ui/gtk/button.c	Thu Apr 03 11:12:22 2014 +0200
@@ -51,6 +51,11 @@
                 "clicked",
                 G_CALLBACK(ui_button_clicked),
                 event);
+        g_signal_connect(
+                button,
+                "destroy",
+                G_CALLBACK(ui_destroy_userdata),
+                event);
     }
     
     UiContainer *ct = uic_get_current_container(obj);
--- a/ui/gtk/menu.c	Wed Apr 02 20:31:47 2014 +0200
+++ b/ui/gtk/menu.c	Thu Apr 03 11:12:22 2014 +0200
@@ -29,6 +29,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <inttypes.h>
+#include <stdarg.h>
 
 #include "menu.h"
 #include "toolkit.h"
@@ -80,6 +81,14 @@
 }
 
 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_gr(char *label, ui_callback f, void *userdata, ...) {
     if(!current) {
         return;
     }
@@ -90,12 +99,22 @@
     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) {
+        item->groups = ucx_list_append(item->groups, (void*)(intptr_t)group);
+    }
+    va_end(ap);
     
     UiMenu *cm = current->data;
     cm->items = ucx_list_append(cm->items, item);
 }
 
-void ui_menuitem_st(char *stockid, ui_callback f, void *userdata) {
+void ui_menuitem_stgr(char *stockid, ui_callback f, void *userdata, ...) {
     if(!current) {
         return;
     }
@@ -106,6 +125,16 @@
     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) {
+        item->groups = ucx_list_append(item->groups, (void*)(intptr_t)group);
+    }
+    va_end(ap);
     
     UiMenu *cm = current->data;
     cm->items = ucx_list_append(cm->items, item);
@@ -224,9 +253,18 @@
                 "activate",
                 G_CALLBACK(ui_menu_event_wrapper),
                 event);
+        g_signal_connect(
+                widget,
+                "destroy",
+                G_CALLBACK(ui_destroy_userdata),
+                event);
     }
     
     gtk_menu_shell_append(GTK_MENU_SHELL(parent), widget);
+    
+    if(i->groups) {
+        uic_add_group_widget(obj->ctx, widget, i->groups);
+    }
 }
 
 void add_menuitem_st_widget(
@@ -251,9 +289,18 @@
                 "activate",
                 G_CALLBACK(ui_menu_event_wrapper),
                 event);
+        g_signal_connect(
+                widget,
+                "destroy",
+                G_CALLBACK(ui_destroy_userdata),
+                event);
     }
     
     gtk_menu_shell_append(GTK_MENU_SHELL(parent), widget);
+    
+    if(i->groups) {
+        uic_add_group_widget(obj->ctx, widget, i->groups);
+    }
 }
 
 void add_menuseparator_widget(
@@ -284,6 +331,11 @@
                 "toggled",
                 G_CALLBACK(ui_menu_event_toggled),
                 event);
+        g_signal_connect(
+                widget,
+                "destroy",
+                G_CALLBACK(ui_destroy_userdata),
+                event);
     }
 }
 
@@ -336,7 +388,8 @@
         GList *mi = gtk_container_get_children(GTK_CONTAINER(list->menu));
         while(mi) {
             if(i >= list->index && i < list->index + list->oldcount) {
-                gtk_container_remove(GTK_CONTAINER(list->menu), mi->data);
+                //gtk_container_remove(GTK_CONTAINER(list->menu), mi->data);
+                gtk_widget_destroy(mi->data);
             }
             mi = mi->next;
             i++;
@@ -368,6 +421,11 @@
                 "activate",
                 G_CALLBACK(ui_menu_event_wrapper),
                 event);
+            g_signal_connect(
+                widget,
+                "destroy",
+                G_CALLBACK(ui_destroy_userdata),
+                event);
         }
         
         str = ui_list_next(list->list);
--- a/ui/gtk/menu.h	Wed Apr 02 20:31:47 2014 +0200
+++ b/ui/gtk/menu.h	Thu Apr 03 11:12:22 2014 +0200
@@ -65,6 +65,7 @@
     ui_callback    callback;
     char           *label;
     void           *userdata;
+    UcxList        *groups;
 };
 
 struct UiStMenuItem {
@@ -72,6 +73,7 @@
     ui_callback    callback;
     char           *stockid;
     void           *userdata;
+    UcxList        *groups;
 };
 
 struct UiCheckItem {
--- a/ui/gtk/toolkit.c	Wed Apr 02 20:31:47 2014 +0200
+++ b/ui/gtk/toolkit.c	Thu Apr 03 11:12:22 2014 +0200
@@ -62,5 +62,15 @@
 }
 
 void ui_show(UiObject *obj) {
+    uic_check_group_widgets(obj->ctx);
     gtk_widget_show_all(obj->widget);
 }
+
+void ui_set_enabled(UIWIDGET widget, int enabled) {
+    gtk_widget_set_sensitive(widget, enabled);
+}
+
+
+void ui_destroy_userdata(GtkWidget *object, void *userdata) {
+    free(userdata);
+}
--- a/ui/gtk/toolkit.h	Wed Apr 02 20:31:47 2014 +0200
+++ b/ui/gtk/toolkit.h	Thu Apr 03 11:12:22 2014 +0200
@@ -44,6 +44,7 @@
     int         value;
 } UiEventData;
 
+void ui_destroy_userdata(GtkWidget *object, void *userdata);
 
 #ifdef	__cplusplus
 }
--- a/ui/gtk/window.c	Wed Apr 02 20:31:47 2014 +0200
+++ b/ui/gtk/window.c	Thu Apr 03 11:12:22 2014 +0200
@@ -46,6 +46,7 @@
 
 void ui_exit_event(GtkWidget *widget, gpointer data) {
     if(wclose_fnc) {
+        // TODO: use UiEvent
         wclose_fnc(data, wclose_udata);
     }
     nwindows--;
--- a/ui/motif/menu.c	Wed Apr 02 20:31:47 2014 +0200
+++ b/ui/motif/menu.c	Thu Apr 03 11:12:22 2014 +0200
@@ -28,6 +28,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <stdarg.h>
 
 #include "menu.h"
 #include "button.h"
@@ -80,6 +81,14 @@
 }
 
 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_gr(char *label, ui_callback f, void *userdata, ...) {
     if(!current) {
         return;
     }
@@ -90,12 +99,22 @@
     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) {
+        item->groups = ucx_list_append(item->groups, (void*)(intptr_t)group);
+    }
+    va_end(ap);
     
     UiMenu *cm = current->data;
     cm->items = ucx_list_append(cm->items, item);
 }
 
-void ui_menuitem_st(char *stockid, ui_callback f, void *userdata) {
+void ui_menuitem_stgr(char *stockid, ui_callback f, void *userdata, ...) {
     if(!current) {
         return;
     }
@@ -106,6 +125,16 @@
     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) {
+        item->groups = ucx_list_append(item->groups, (void*)(intptr_t)group);
+    }
+    va_end(ap);
     
     UiMenu *cm = current->data;
     cm->items = ucx_list_append(cm->items, item);
@@ -244,6 +273,10 @@
                 event);
     }
     
+    if(mi->groups) {
+        uic_add_group_widget(obj->ctx, mitem, mi->groups);
+    }
+    
     return 1;
 }
 
@@ -299,6 +332,10 @@
                 event);
     }
     
+    if(mi->groups) {
+        uic_add_group_widget(obj->ctx, mitem, mi->groups);
+    }
+    
     return 1;
 }
 
--- a/ui/motif/menu.h	Wed Apr 02 20:31:47 2014 +0200
+++ b/ui/motif/menu.h	Thu Apr 03 11:12:22 2014 +0200
@@ -64,6 +64,7 @@
     ui_callback    callback;
     char           *label;
     void           *userdata;
+    UcxList        *groups;
 };
 
 struct UiStMenuItem {
@@ -71,6 +72,7 @@
     ui_callback    callback;
     char           *stockid;
     void           *userdata;
+    UcxList        *groups;
 };
 
 struct UiCheckItem {
--- a/ui/motif/toolkit.c	Wed Apr 02 20:31:47 2014 +0200
+++ b/ui/motif/toolkit.c	Thu Apr 03 11:12:22 2014 +0200
@@ -79,5 +79,10 @@
 }
 
 void ui_show(UiObject *obj) {
+    uic_check_group_widgets(obj->ctx);
     XtRealizeWidget(obj->widget);
 }
+
+void ui_set_enabled(UIWIDGET widget, int enabled) {
+    XtSetSensitive(widget, enabled);
+}
--- a/ui/ui/toolkit.h	Wed Apr 02 20:31:47 2014 +0200
+++ b/ui/ui/toolkit.h	Thu Apr 03 11:12:22 2014 +0200
@@ -173,6 +173,7 @@
 
 void ui_main();
 void ui_show(UiObject *obj);
+void ui_set_enabled(UIWIDGET widget, int enabled);
 
 void ui_set_document(UiObject *obj, void *document);
 void ui_detach_document(UiObject *obj, void *document);

mercurial