Sat, 05 Apr 2014 18:41:30 +0200
added groups for toolbar items and copy & paste (GTK, Motif)
/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 2014 Olaf Wintermann. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <inttypes.h> #include "context.h" #include "../ui/window.h" #include "document.h" UiContext* uic_context(UiObject *toplevel, UcxMempool *mp) { UiContext *ctx = ucx_mempool_malloc(mp, sizeof(UiContext)); ctx->mempool = mp; 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(); gtk_window_add_accel_group(GTK_WINDOW(toplevel->widget), ctx->accel_group); #endif return ctx; } UiVar* uic_getvar(UiContext *ctx, char *name) { // check document variables first UiVar *var = uic_document_getvar( uic_getdocument(ctx->toplevel->document), name); // check window vars if(!var) { var = ucx_map_cstr_get(ctx->vars, name); } return var; } UiVar* uic_connect_var(UiContext *ctx, char *name, int type) { // TODO: get current map UcxMap *from = ctx->vars; UiVar *var = uic_getvar(ctx, name); if(var) { // the value is registered // a little type check if(var->type != type) { fprintf(stderr, "UI Error: var %s has incompatible type.\n", name); return NULL; } else { // register the current document/wdata map // if the document is closed, the var will be moved to this map var->from = from; return var; } } else { // create an empty value and add it first to the window variables // it can be moved to the document vars later void *value = uic_create_value(ctx->mempool->allocator, type); if(!value) { fprintf(stderr, "UI Error: Cannot create empty value.\n"); return NULL; } UiVar *var = ucx_mempool_malloc(ctx->mempool, sizeof(UiVar)); var->value = value; var->type = type; var->isextern = 0; var->from = from; ucx_map_cstr_put(ctx->vars, name, var); return var; } } void* uic_create_value(UcxAllocator *a, int type) { switch(type) { case UI_VAR_INTEGER: { UiInteger *i = a->calloc( a->pool, 1, sizeof(UiInteger)); return i; } case UI_VAR_STRING: { UiString *s = a->calloc( a->pool, 1, sizeof(UiInteger)); return s; } } return NULL; } // public API int ui_getint(UiObject *obj, char *name) { UiVar *var = uic_getvar(obj->ctx, name); if(var) { if(var->type == UI_VAR_INTEGER) { UiInteger *i = var->value; if(i->get) { return i->get(i); } else { fprintf( stderr, "UI Error: variable %s is not connected.\n", name); } } else { fprintf( stderr, "UI Error: requested variable %s is not an integer.\n", name); } } else { fprintf(stderr, "UI Error: unkown variable %s.\n", name); } return 0; } void ui_set_group(UiContext *ctx, int group) { 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) { int i = ucx_list_find(ctx->groups, (void*)(intptr_t)group, NULL, NULL); if(i != -1) { 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) { int nelm = ucx_list_size(ctx->groups); int *groups = calloc(sizeof(int), nelm); int i = 0; UCX_FOREACH(elm, ctx->groups) { groups[i++] = (int)elm->data; } *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, void *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); }