diff -r eb5269000bc8 -r eeb50c534497 ui/common/document.c --- a/ui/common/document.c Sun Dec 08 11:20:41 2013 +0000 +++ b/ui/common/document.c Fri Mar 21 13:20:53 2014 +0100 @@ -38,13 +38,82 @@ documents = ucx_map_new(32); } -void* ui_document_create(UiObject *obj, size_t size) { +void ui_set_document(UiObject *obj, void *document) { + UiDocument *doc = ucx_map_get(documents, ucx_key(&document, sizeof(void*))); + if(!doc) { + return; + } + doc->obj = obj; + + if(obj->document) { + ui_detach_document(obj, obj->document); + } + obj->document = document; + + UcxMapIterator i = ucx_map_iterator(doc->vars); + UiVar *var; + UCX_MAP_FOREACH(key, var, i) { + UiVar *v = ucx_map_get(obj->ctx->vars, key); + if(v) { + if(v->isextern) { + fprintf( + stderr, + "UI Error: external variable cannot be moved\n"); + return; + } + // check type + if(var->type != v->type) { + fprintf(stderr, "UI Error: var has incompatible type.\n"); + return; + } + + // copy value + uic_var_move(v, var, 1); + var->from = v->from; + + // TODO: free var struct + ucx_map_remove(obj->ctx->vars, key); + } + } + +} + +void ui_detach_document(UiObject *obj, void *document) { + UiDocument *doc = ucx_map_get(documents, ucx_key(&document, sizeof(void*))); + if(!doc) { + return; + } + + UcxMapIterator i = ucx_map_iterator(doc->vars); + UiVar *var; + UCX_MAP_FOREACH(key, var, i) { + if(var->from && var->from != doc->vars) { + // this var is bind to an outer widget, so we move it + UcxAllocator *a = var->from->allocator; + UiVar *newvar = a->malloc(a->pool, sizeof(UiVar)); + newvar->value = uic_create_value(a, var->type); + uic_var_move(var, newvar, 0); + newvar->type = var->type; + newvar->from = var->from; + newvar->isextern = 0; + + ucx_map_put(var->from, key, newvar); + + //ucx_map_remove(doc->vars, key); // TODO: dont remove! + } + } + + doc->obj->document = NULL; + doc->obj = NULL; +} + +void* ui_document_new(size_t size) { UcxMempool *mp = ucx_mempool_new(256); UiDocument *uidoc = ucx_mempool_malloc(mp, sizeof(UiDocument)); - uidoc->obj = obj; - uidoc->allocator = ucx_mempool_allocator(mp); + uidoc->obj = NULL; uidoc->mempool = mp; - uidoc->vars = ucx_map_new_a(uidoc->allocator, 16); + uidoc->vars = ucx_map_new_a(mp->allocator, 16); + uidoc->subdocument = NULL; void *document = ucx_mempool_calloc(mp, 1, size); ucx_map_put(documents, ucx_key(&document, sizeof(void*)), uidoc); @@ -75,43 +144,119 @@ return ucx_mempool_realloc(uidoc->mempool, ptr, size); } +UiDocument* uic_getdocument(void *doc) { + return doc ? ucx_map_get(documents, ucx_key(&doc, sizeof(void*))) : NULL; +} UiVar* uic_document_getvar(UiDocument *doc, char *name) { - return ucx_map_cstr_get(doc->vars, name); + return doc ? ucx_map_cstr_get(doc->vars, name) : NULL; } -void ui_document_addint(void *doc, char *name) { +void uic_document_addvar(void *doc, char *name, int type, size_t vs) { UiDocument *uidoc = ucx_map_get(documents, ucx_key(&doc, sizeof(void*))); if(!uidoc) { return; } - UiVar *dvar = uic_document_getvar(uidoc, name); - UiVar *wvar = uic_getvar(uidoc->obj, name); - if(!dvar) { - UiVar *var = ucx_mempool_malloc(uidoc->mempool, sizeof(UiVar)); - var->isextern = 0; - var->type = 1; - UiInteger *i = ucx_mempool_calloc(uidoc->mempool, 1, sizeof(UiVar)); - if(wvar && !wvar->isextern) { - *i = *(UiInteger*)wvar->value; + UiVar *newvar = ucx_mempool_malloc(uidoc->mempool, sizeof(UiVar)); + newvar->isextern = 0; + newvar->type = type; + newvar->value = ucx_mempool_calloc(uidoc->mempool, 1, vs); + newvar->from = NULL; + + uic_document_addvar_v(uidoc, name, newvar, type, vs); +} + +void uic_document_addvar_v( + UiDocument *uidoc, + char *name, + UiVar *newvar, + int type, + size_t vs) +{ + // if the window context has this variable, we remove it and put it to + // the document vars + UiVar *var = uidoc->obj ? + ucx_map_cstr_get(uidoc->obj->ctx->vars, name) : NULL; + if(var) { + // external variables cannot be moved + if(var->isextern) { + fprintf( + stderr, + "UI Error: external variable %s " + "cannot be moved to the document.\n", + name); + return; + } + + // check type + if(var->type != type) { + fprintf(stderr, "UI Error: var %s has incompatible type.\n", name); + return; + } + + // override document var with window context var + memcpy(newvar->value, var->value, vs); + + newvar->from = var->from; + + // TODO: free var struct + ucx_map_cstr_remove(uidoc->obj->ctx->vars, name); + } + + // finally, add the new variable to the document + ucx_map_cstr_put(uidoc->vars, name, newvar); +} + +void uic_document_regvar( + void *doc, + char *name, + int type, + size_t vs, + void *value) +{ + UiDocument *uidoc = ucx_map_get(documents, ucx_key(&doc, sizeof(void*))); + if(!uidoc) { + return; + } + + UiVar *newvar = ucx_mempool_malloc(uidoc->mempool, sizeof(UiVar)); + newvar->isextern = 1; + newvar->type = type; + newvar->value = value; + newvar->from = NULL; + + uic_document_addvar_v(uidoc, name, newvar, type, vs); +} + +void uic_var_move(UiVar *from, UiVar *to, int set) { + switch(from->type) { + case UI_VAR_INTEGER: { + //memcpy(to->value, from->value, sizeof(UiInteger)); + UiInteger *f = from->value; + UiInteger *t = to->value; + t->get = f->get; + t->set = f->set; + t->obj = f->obj; + if(set) { + t->set(t, t->value); + } else { + //t->value = t->get(t); + //t->value = 0; + } + break; + } + case UI_VAR_STRING: { + break; } } - - if(wvar && wvar->isextern) { - fprintf(stderr, "UI Error: window variable moved to document!\n"); - } - uic_rmvar(uidoc->obj, name); +} + +void ui_document_addint(void *doc, char *name) { + uic_document_addvar(doc, name, UI_VAR_INTEGER, sizeof(UiInteger)); } void ui_document_regint(void *doc, char *name, UiInteger *i) { - + uic_document_regvar(doc, name, UI_VAR_INTEGER, sizeof(UiInteger), i); } -void ui_document_setint(void *doc, char *name, int val) { - -} - -int ui_document_getint(void *doc, char *name) { - -}