# HG changeset patch # User Olaf Wintermann # Date 1396516342 -7200 # Node ID 012418e7dc9046107ec7e405745b7283bd4e0a24 # Parent 2dda1ad6dc7a9d4d30c470e51aa1576c6685846e added groups for menu items (GTK, Motif) diff -r 2dda1ad6dc7a -r 012418e7dc90 application/main.c --- 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); diff -r 2dda1ad6dc7a -r 012418e7dc90 ui/cocoa/menu.m --- 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;jtoplevel = 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;inumgroups;k++) { + if(groups[i] == gw->groups[k]) { + check[k] = 1; + } + } + } + + int enable = 1; + for(int i=0;inumgroups;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); +} + diff -r 2dda1ad6dc7a -r 012418e7dc90 ui/common/context.h --- 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 } diff -r 2dda1ad6dc7a -r 012418e7dc90 ui/gtk/button.c --- 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); diff -r 2dda1ad6dc7a -r 012418e7dc90 ui/gtk/menu.c --- 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 #include #include +#include #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); diff -r 2dda1ad6dc7a -r 012418e7dc90 ui/gtk/menu.h --- 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 { diff -r 2dda1ad6dc7a -r 012418e7dc90 ui/gtk/toolkit.c --- 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); +} diff -r 2dda1ad6dc7a -r 012418e7dc90 ui/gtk/toolkit.h --- 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 } diff -r 2dda1ad6dc7a -r 012418e7dc90 ui/gtk/window.c --- 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--; diff -r 2dda1ad6dc7a -r 012418e7dc90 ui/motif/menu.c --- 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 #include +#include #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; } diff -r 2dda1ad6dc7a -r 012418e7dc90 ui/motif/menu.h --- 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 { diff -r 2dda1ad6dc7a -r 012418e7dc90 ui/motif/toolkit.c --- 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); +} diff -r 2dda1ad6dc7a -r 012418e7dc90 ui/ui/toolkit.h --- 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);