ui/common/document.c

changeset 2
eeb50c534497
parent 1
eb5269000bc8
child 3
c1a75454b444
--- 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) {
-    
-}

mercurial