diff -r fe49cff3c571 -r bb7da585debc ui/common/context.c --- a/ui/common/context.c Sun May 23 09:44:43 2021 +0200 +++ b/ui/common/context.c Sat Jan 04 16:38:48 2025 +0100 @@ -32,15 +32,20 @@ #include #include +#include +#include +#include + #include "context.h" #include "../ui/window.h" #include "document.h" #include "types.h" + static UiContext* global_context; void uic_init_global_context(void) { - UcxMempool *mp = ucx_mempool_new(32); + CxMempool *mp = cxBasicMempoolCreate(32); global_context = uic_context(NULL, mp); } @@ -48,17 +53,22 @@ return global_context; } -UiContext* uic_context(UiObject *toplevel, UcxMempool *mp) { - UiContext *ctx = ucx_mempool_malloc(mp, sizeof(UiContext)); +UiContext* uic_context(UiObject *toplevel, CxMempool *mp) { + UiContext *ctx = cxMalloc(mp->allocator, sizeof(UiContext)); memset(ctx, 0, sizeof(UiContext)); - ctx->mempool = mp; + ctx->mp = mp; + ctx->allocator = mp->allocator; ctx->obj = toplevel; - ctx->vars = ucx_map_new_a(mp->allocator, 16); + ctx->vars = cxHashMapCreate(mp->allocator, CX_STORE_POINTERS, 16); + + ctx->documents = cxLinkedListCreate(mp->allocator, cx_cmp_intptr, CX_STORE_POINTERS); + ctx->group_widgets = cxLinkedListCreate(mp->allocator, cx_cmp_ptr, sizeof(UiGroupWidget)); + ctx->groups = cxArrayListCreate(mp->allocator, cx_cmp_int, sizeof(int), 32); ctx->attach_document = uic_context_attach_document; ctx->detach_document2 = uic_context_detach_document2; -#ifdef UI_GTK +#if UI_GTK2 || UI_GTK3 if(toplevel && toplevel->widget) { ctx->accel_group = gtk_accel_group_new(); gtk_window_add_accel_group(GTK_WINDOW(toplevel->widget), ctx->accel_group); @@ -72,9 +82,14 @@ return ctx->parent ? uic_root_context(ctx->parent) : ctx; } +void uic_context_prepare_close(UiContext *ctx) { + cxListClear(ctx->groups); + cxListClear(ctx->group_widgets); +} + void uic_context_attach_document(UiContext *ctx, void *document) { - ctx->documents = ucx_list_append_a(ctx->mempool->allocator, ctx->documents, document); - ctx->document = ctx->documents->data; + cxListAdd(ctx->documents, document); + ctx->document = document; UiContext *doc_ctx = ui_document_context(document); @@ -82,25 +97,18 @@ // as any document variable UiContext *var_ctx = ctx; while(var_ctx) { - if(var_ctx->vars_unbound && var_ctx->vars_unbound->count > 0) { - UcxMapIterator i = ucx_map_iterator(var_ctx->vars_unbound); - UiVar *var; - // rmkeys holds all keys, that shall be removed from vars_unbound - UcxKey *rmkeys = calloc(var_ctx->vars_unbound->count, sizeof(UcxKey)); - size_t numkeys = 0; - UCX_MAP_FOREACH(key, var, i) { - UiVar *docvar = ucx_map_get(doc_ctx->vars, key); + if(var_ctx->vars_unbound && cxMapSize(var_ctx->vars_unbound) > 0) { + CxIterator i = cxMapIterator(var_ctx->vars_unbound); + cx_foreach(CxMapEntry*, entry, i) { + printf("attach %s\n", entry->key->data); + UiVar *var = entry->value; + UiVar *docvar = cxMapGet(doc_ctx->vars, *entry->key); if(docvar) { // bind var to document var uic_copy_binding(var, docvar, TRUE); - rmkeys[numkeys++] = key; // save the key for removal + cxIteratorFlagRemoval(i); } } - // now that we may have bound some vars to the document, - // we can remove them from the unbound map - for(size_t k=0;kvars_unbound, rmkeys[k]); - } } var_ctx = ctx->parent; @@ -108,56 +116,63 @@ } static void uic_context_unbind_vars(UiContext *ctx) { - UcxMapIterator i = ucx_map_iterator(ctx->vars); - UiVar *var; - UCX_MAP_FOREACH(key, var, i) { + CxIterator i = cxMapIterator(ctx->vars); + cx_foreach(CxMapEntry*, entry, i) { + UiVar *var = entry->value; if(var->from && var->from_ctx) { uic_save_var2(var); uic_copy_binding(var, var->from, FALSE); - ucx_map_put(var->from_ctx->vars_unbound, key, var->from); + cxMapPut(var->from_ctx->vars_unbound, *entry->key, var->from); var->from_ctx = ctx; } } - UCX_FOREACH(elm, ctx->documents) { - UiContext *subctx = ui_document_context(elm->data); - uic_context_unbind_vars(subctx); + if(ctx->documents) { + i = cxListIterator(ctx->documents); + cx_foreach(void *, doc, i) { + UiContext *subctx = ui_document_context(doc); + uic_context_unbind_vars(subctx); + } } } void uic_context_detach_document2(UiContext *ctx, void *document) { // find the document in the documents list - UcxList *doc = NULL; - UCX_FOREACH(elm, ctx->documents) { - if(elm->data == document) { - doc = elm; - break; - } - } - if(!doc) { - return; // document is not a subdocument of this context + ssize_t docIndex = cxListFind(ctx->documents, document); + if(docIndex < 0) { + return; } - ctx->documents = ucx_list_remove_a(ctx->mempool->allocator, ctx->documents, doc); - ctx->document = ctx->documents ? ctx->documents->data : NULL; + cxListRemove(ctx->documents, docIndex); + ctx->document = cxListAt(ctx->documents, 0); UiContext *docctx = ui_document_context(document); uic_context_unbind_vars(docctx); // unbind all doc/subdoc vars from the parent } void uic_context_detach_all(UiContext *ctx) { - UcxList *ls = ucx_list_clone(ctx->documents, NULL, NULL); - UCX_FOREACH(elm, ls) { - ctx->detach_document2(ctx, elm->data); + // copy list + CxList *ls = cxLinkedListCreate(cxDefaultAllocator, NULL, CX_STORE_POINTERS); + CxIterator i = cxListIterator(ctx->documents); + cx_foreach(void *, doc, i) { + cxListAdd(ls, doc); } - ucx_list_free(ls); + + // detach documents + i = cxListIterator(ls); + cx_foreach(void *, doc, i) { + ctx->detach_document2(ctx, doc); + } + + cxListDestroy(ls); } -static UiVar* ctx_getvar(UiContext *ctx, UcxKey key) { - UiVar *var = ucx_map_get(ctx->vars, key); - if(!var) { - UCX_FOREACH(elm, ctx->documents) { - UiContext *subctx = ui_document_context(elm->data); +static UiVar* ctx_getvar(UiContext *ctx, CxHashKey key) { + UiVar *var = cxMapGet(ctx->vars, key); + if(!var && ctx->documents) { + CxIterator i = cxListIterator(ctx->documents); + cx_foreach(void *, doc, i) { + UiContext *subctx = ui_document_context(doc); var = ctx_getvar(subctx, key); if(var) { break; @@ -168,11 +183,18 @@ } UiVar* uic_get_var(UiContext *ctx, const char *name) { - UcxKey key = ucx_key(name, strlen(name)); + CxHashKey key = cx_hash_key(name, strlen(name)); return ctx_getvar(ctx, key); } UiVar* uic_create_var(UiContext *ctx, const char *name, UiVarType type) { + if(ctx->vars_unbound) { + UiVar *unbound = cxMapGet(ctx->vars_unbound, name); + if(unbound) { + return unbound; + } + } + UiVar *var = uic_get_var(ctx, name); if(var) { if(var->type == type) { @@ -188,14 +210,25 @@ var->from = NULL; var->from_ctx = ctx; + cxMempoolSetDestructor(var, (cx_destructor_func)uic_unbind_var); + if(!ctx->vars_unbound) { - ctx->vars_unbound = ucx_map_new_a(ctx->mempool->allocator, 16); + ctx->vars_unbound = cxHashMapCreate(ctx->allocator, CX_STORE_POINTERS, 16); } - ucx_map_cstr_put(ctx->vars_unbound, name, var); + cxMapPut(ctx->vars_unbound, name, var); return var; } +UiVar* uic_create_value_var(UiContext* ctx, void* value) { + UiVar *var = (UiVar*)ui_malloc(ctx, sizeof(UiVar)); + var->from = NULL; + var->from_ctx = ctx; + var->value = value; + var->type = UI_VAR_SPECIAL; + return var; +} + void* uic_create_value(UiContext *ctx, UiVarType type) { void *val = NULL; switch(type) { @@ -224,10 +257,25 @@ val = ui_range_new(ctx, NULL); break; } + case UI_VAR_GENERIC: { + val = ui_generic_new(ctx, NULL); + } } return val; } + +UiVar* uic_widget_var(UiContext* toplevel, UiContext* current, void* value, const char* varname, UiVarType type) { + if (value) { + return uic_create_value_var(current, value); + } + if (varname) { + return uic_create_var(toplevel, varname, type); + } + return NULL; +} + + void uic_copy_binding(UiVar *from, UiVar *to, UiBool copytodoc) { // check type if(from->type != to->type) { @@ -283,11 +331,24 @@ break; } case UI_VAR_LIST: { - UiList *f = fromvalue; + // TODO: not sure how correct this is + + UiList *f = from->value; UiList *t = to->value; - if(!f->obj) break; - uic_list_copy(f, t); - t->update(t, -1); + if (f->obj) { + t->obj = f->obj; + t->update = f->update; + t->getselection = f->getselection; + t->setselection = f->setselection; + } + + UiVar tmp = *from; + *from = *to; + *to = tmp; + + UiList* t2 = to->value; + ui_notify(t2->observers, NULL); + break; } case UI_VAR_RANGE: { @@ -300,6 +361,14 @@ t->set(t, t->value); break; } + case UI_VAR_GENERIC: { + UiGeneric *f = fromvalue; + UiGeneric *t = to->value; + if(!f->obj) break; + uic_generic_copy(f, t); + t->set(t, t->value, t->type); + break; + } } } @@ -312,6 +381,7 @@ case UI_VAR_TEXT: uic_text_save(var->value); break; case UI_VAR_LIST: break; case UI_VAR_RANGE: uic_range_save(var->value); break; + case UI_VAR_GENERIC: uic_generic_save(var->value); break; } } @@ -324,6 +394,7 @@ case UI_VAR_TEXT: uic_text_unbind(var->value); break; case UI_VAR_LIST: uic_list_unbind(var->value); break; case UI_VAR_RANGE: uic_range_unbind(var->value); break; + case UI_VAR_GENERIC: uic_generic_unbind(var->value); break; } } @@ -358,9 +429,9 @@ var->value = value; var->from = NULL; var->from_ctx = ctx; - size_t oldcount = ctx->vars->count; - ucx_map_cstr_put(ctx->vars, name, var); - if(ctx->vars->count != oldcount + 1) { + size_t oldcount = cxMapSize(ctx->vars); + cxMapPut(ctx->vars, name, var); + if(cxMapSize(ctx->vars) != oldcount + 1) { fprintf(stderr, "UiError: var '%s' already exists\n", name); } @@ -375,8 +446,7 @@ } void uic_remove_bound_var(UiContext *ctx, UiVar *var) { - // TODO: implement - printf("TODO: implement uic_remove_bound_var\n"); + // TODO } @@ -395,10 +465,14 @@ ctx->close_data = udata; } +UIEXPORT void ui_context_destroy(UiContext *ctx) { + cxMempoolDestroy(ctx->mp); +} + 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); + if(cxListFind(ctx->groups, &group) == -1) { + cxListAdd(ctx->groups, &group); } // enable/disable group widgets @@ -406,10 +480,9 @@ } void ui_unset_group(UiContext *ctx, int group) { - int i = ucx_list_find(ctx->groups, (void*)(intptr_t)group, NULL, NULL); + int i = cxListFind(ctx->groups, &group); if(i != -1) { - UcxList *elm = ucx_list_get(ctx->groups, i); - ctx->groups = ucx_list_remove_a(ctx->mempool->allocator, ctx->groups, elm); + cxListRemove(ctx->groups, i); } // enable/disable group widgets @@ -417,28 +490,16 @@ } int* ui_active_groups(UiContext *ctx, int *ngroups) { - if(!ctx->groups) { - return NULL; - } - - int nelm = ucx_list_size(ctx->groups); - int *groups = calloc(sizeof(int), nelm); - - int i = 0; - UCX_FOREACH(elm, ctx->groups) { - groups[i++] = (intptr_t)elm->data; - } - - *ngroups = nelm; - return groups; + *ngroups = cxListSize(ctx->groups); + return cxListAt(ctx->groups, 0); } 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; + CxIterator i = cxListIterator(ctx->group_widgets); + cx_foreach(UiGroupWidget *, gw, i) { char *check = calloc(1, gw->numgroups); for(int i=0;ienable(gw->widget, enable); } - - if(groups) { - free(groups); - } } void ui_widget_set_groups(UiContext *ctx, UIWIDGET widget, ui_enablefunc enable, ...) { // get groups - UcxList *groups = NULL; + CxList *groups = cxArrayListCreate(cxDefaultAllocator, NULL, sizeof(int), 16); va_list ap; va_start(ap, enable); int group; while((group = va_arg(ap, int)) != -1) { - groups = ucx_list_append(groups, (void*)(intptr_t)group); + cxListAdd(groups, &group); } va_end(ap); uic_add_group_widget(ctx, widget, enable, groups); - ucx_list_free(groups); + cxListDestroy(groups); +} + +size_t uic_group_array_size(const int *groups) { + int i; + for(i=0;groups[i] >= 0;i++) { } + return i; +} + +void uic_add_group_widget(UiContext *ctx, void *widget, ui_enablefunc enable, CxList *groups) { + uic_add_group_widget_i(ctx, widget, enable, cxListAt(groups, 0), cxListSize(groups)); } -void uic_add_group_widget(UiContext *ctx, void *widget, ui_enablefunc enable, UcxList *groups) { - UcxMempool *mp = ctx->mempool; - UiGroupWidget *gw = ucx_mempool_malloc(mp, sizeof(UiGroupWidget)); +void uic_add_group_widget_i(UiContext *ctx, void *widget, ui_enablefunc enable, const int *groups, size_t numgroups) { + const CxAllocator *a = ctx->allocator; + UiGroupWidget gw; - gw->widget = widget; - gw->enable = enable; - 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; + gw.widget = widget; + gw.enable = enable; + gw.numgroups = numgroups; + gw.groups = cxCalloc(a, numgroups, sizeof(int)); + + // copy groups + if(groups) { + memcpy(gw.groups, groups, gw.numgroups * sizeof(int)); } - ctx->group_widgets = ucx_list_append_a( - mp->allocator, - ctx->group_widgets, - gw); + cxListAdd(ctx->group_widgets, &gw); +} + +void uic_remove_group_widget(UiContext *ctx, void *widget) { + (void)cxListFindRemove(ctx->group_widgets, widget); +} + +UIEXPORT void *ui_allocator(UiContext *ctx) { + return (void*)ctx->allocator; +} + +void* ui_cx_mempool(UiContext *ctx) { + return ctx->mp; } void* ui_malloc(UiContext *ctx, size_t size) { - return ctx ? ucx_mempool_malloc(ctx->mempool, size) : NULL; + return ctx ? cxMalloc(ctx->allocator, size) : NULL; } void* ui_calloc(UiContext *ctx, size_t nelem, size_t elsize) { - return ctx ? ucx_mempool_calloc(ctx->mempool, nelem, elsize) : NULL; + return ctx ? cxCalloc(ctx->allocator, nelem, elsize) : NULL; } void ui_free(UiContext *ctx, void *ptr) { - if(ctx) { - ucx_mempool_free(ctx->mempool, ptr); + if(ctx && ptr) { + cxFree(ctx->allocator, ptr); } } void* ui_realloc(UiContext *ctx, void *ptr, size_t size) { - return ctx ? ucx_mempool_realloc(ctx->mempool, ptr, size) : NULL; + return ctx ? cxRealloc(ctx->allocator, ptr, size) : NULL; } +UIEXPORT char* ui_strdup(UiContext *ctx, const char *str) { + if(!ctx) { + return NULL; + } + cxstring s = cx_str(str); + cxmutstr d = cx_strdup_a(ctx->allocator, s); + return d.ptr; +}