ui/common/context.c

changeset 902
6872b59217a7
parent 885
28ecfe5399ae
child 905
41614c767451
--- a/ui/common/context.c	Mon Nov 17 11:28:47 2025 +0100
+++ b/ui/common/context.c	Mon Nov 17 14:27:48 2025 +0100
@@ -114,7 +114,7 @@
             UiVar *docvar = cxMapGet(doc_ctx->vars, *entry->key);
             if(docvar) {
                 // bind var to document var
-                uic_copy_binding(var, docvar, TRUE);
+                uic_copy_var_binding(var, docvar, TRUE);
                 cxIteratorFlagRemoval(i);
             }
         }
@@ -130,7 +130,7 @@
         // var->from && var->from_ctx && var->from_ctx != ctx
         uic_save_var(var);
         if(var->from) {
-            uic_copy_binding(var, var->from, FALSE);
+            uic_copy_var_binding(var, var->from, FALSE);
             cxMapPut(var->from->from_ctx->vars, *entry->key, var->from);
             var->from = NULL;
         }
@@ -213,7 +213,8 @@
     var->original_value = NULL;
     var->from = NULL;
     var->from_ctx = ctx;
-
+    var->bound = FALSE;
+    
     cxMempoolSetDestructor(var, (cx_destructor_func)uic_unbind_var);
 
     cxMapPut(ctx->vars, name, var);
@@ -266,6 +267,40 @@
     return val;
 }
 
+// destroys a value, that was created by uic_create_value
+void uic_destroy_value(UiContext *ctx, UiVarType type, void *value) {
+    switch(type) {
+        default: {
+            ui_free(ctx, value);
+            break;
+        }
+        case UI_VAR_SPECIAL: break;
+        case UI_VAR_STRING: {
+            UiString *s = value;
+            if(s->value.free) {
+                s->value.free(s->value.ptr);
+            }
+            ui_free(ctx, value);
+        }
+        case UI_VAR_TEXT: {
+            UiText *t = value;
+            if(t->value.free) {
+                t->value.free(t->value.ptr);
+                t->value.free = NULL;
+                t->value.ptr = NULL;
+            }
+            if(t->destroy) {
+                t->destroy(t);
+            }
+            ui_free(ctx, value);
+        }
+        case UI_VAR_LIST: {
+            ui_list_free(ctx, value);
+            break;
+        }
+    }
+}
+
 
 UiVar* uic_widget_var(UiContext *toplevel, UiContext *current, void *value, const char *varname, UiVarType type) {
     if (value) {
@@ -278,7 +313,7 @@
 }
 
 
-void uic_copy_binding(UiVar *from, UiVar *to, UiBool copytodoc) {
+void uic_copy_var_binding(UiVar *from, UiVar *to, UiBool copytodoc) {
     // check type
     if(from->type != to->type) {
         fprintf(stderr, "UI Error: var has incompatible type.\n");
@@ -301,32 +336,36 @@
         }
     }
     
-    ui_setop_enable(TRUE);
+    uic_copy_value_binding(from->type, from, to);
+}
+
+void uic_copy_value_binding(UiVarType type, void *from, void *to) {
+     ui_setop_enable(TRUE);
     
     // copy binding
-    // we don't copy the observer, because the from var has never one
-    switch(from->type) {
+    // we don't copy the observer, because the from value never has oberservers
+    switch(type) {
         default: fprintf(stderr, "uic_copy_binding: wtf!\n"); break;
         case UI_VAR_SPECIAL: break;
         case UI_VAR_INTEGER: {
-            UiInteger *f = fromvalue;
-            UiInteger *t = tovalue;
+            UiInteger *f = from;
+            UiInteger *t = to;
             if(!f->obj) break;
             uic_int_copy(f, t);
             t->set(t, t->value);
             break;
         }
         case UI_VAR_DOUBLE: {
-            UiDouble *f = fromvalue;
-            UiDouble *t = tovalue;
+            UiDouble *f = from;
+            UiDouble *t = to;
             if(!f->obj) break;
             uic_double_copy(f, t);
             t->set(t, t->value);
             break;
         }
         case UI_VAR_STRING: {
-            UiString *f = fromvalue;
-            UiString *t = tovalue;
+            UiString *f = from;
+            UiString *t = to;
             if(!f->obj) break;
             uic_string_copy(f, t);
             char *tvalue = t->value.ptr ? t->value.ptr : "";
@@ -335,23 +374,23 @@
             break;
         }
         case UI_VAR_TEXT: {
-            UiText *f = fromvalue;
-            UiText *t = tovalue;
+            UiText *f = from;
+            UiText *t = to;
             if(!f->obj) break;
             uic_text_copy(f, t);
             t->restore(t);
             break;
         }
         case UI_VAR_LIST: {         
-            UiList *f = fromvalue;
-            UiList *t = tovalue;
+            UiList *f = from;
+            UiList *t = to;
             uic_list_copy(f, t);
             ui_list_update(t);
             break;
         }
         case UI_VAR_RANGE: {
-            UiRange *f = fromvalue;
-            UiRange *t = tovalue;
+            UiRange *f = from;
+            UiRange *t = to;
             if(!f->obj) break;
             uic_range_copy(f, t);
             t->setextent(t, t->extent);
@@ -360,8 +399,8 @@
             break;
         }
         case UI_VAR_GENERIC: {
-            UiGeneric *f = fromvalue;
-            UiGeneric *t = tovalue;
+            UiGeneric *f = from;
+            UiGeneric *t = to;
             if(!f->obj) break;
             uic_generic_copy(f, t);
             t->set(t, t->value, t->type);
@@ -398,58 +437,47 @@
     }
 }
 
+const char *uic_type2str(UiVarType type) {
+    switch(type) {
+        default: return "";
+        case UI_VAR_INTEGER: return "int";
+        case UI_VAR_DOUBLE: return "double";
+        case UI_VAR_STRING: return "string";
+        case UI_VAR_TEXT: return "text";
+        case UI_VAR_LIST: return "list";
+        case UI_VAR_RANGE: return "range";
+        case UI_VAR_GENERIC: return "generic";
+    }
+}
+
 void uic_reg_var(UiContext *ctx, const char *name, UiVarType type, void *value) {
-    // TODO: do we need/want this? Why adding vars to a context after
-    // widgets reference these? Workarounds:
-    // 1. add vars to ctx before creating ui
-    // 2. create ui, create new document with vars, attach doc
-    // also it would be possible to create a function, that scans unbound vars
-    // and connects them to available vars
-    /*
-    UiContext *rootctx = uic_root_context(ctx); 
-    UiVar *b = NULL;
-    if(rootctx->bound) {
-        // some widgets are already bound to some vars
-        b = ucx_map_cstr_get(rootctx->bound, name);
-        if(b) {
-            // a widget is bound to a var with this name
-            // if ctx is the root context we can remove the var from bound
-            // because set_doc or detach can't fuck things up
-            if(ctx == rootctx) {
-                ucx_map_cstr_remove(ctx->bound, name);
-                // TODO: free stuff
-            }
+    UiVar *var = cxMapGet(ctx->vars, name);
+    if(!var) {
+        // create new var and add it to the context var map
+        var = ui_malloc(ctx, sizeof(UiVar));
+        cxMapPut(ctx->vars, name, var);
+    } else {
+        // override var with new value
+        if(var->type != type) {
+            fprintf(stderr, "Error: var %s type mismatch: %s - %s\n", name, uic_type2str(var->type), type);
+            return;
         }
+        if(var->bound) {
+            fprintf(stderr, "Error: var %s already bound\n", name);
+            return;
+        }
+        UiInteger *prev_value = var->value;
+        uic_copy_value_binding(type, prev_value, value);
+        uic_destroy_value(var->from_ctx, var->type, var->value);
     }
-    */
     
-    // create new var and add it to doc's vars
-    UiVar *var = ui_malloc(ctx, sizeof(UiVar));
     var->type = type;
     var->value = value;
     var->from = NULL;
     var->from_ctx = ctx;
-    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);
-    }
-    
-    // TODO: remove?
-    // a widget is already bound to a var with this name
-    // copy the binding (like uic_context_set_document)
-    /*
-    if(b) {
-        uic_copy_binding(b, var, TRUE);
-    }
-    */
+    var->bound = TRUE;
 }
 
-void uic_remove_bound_var(UiContext *ctx, UiVar *var) {
-    // TODO
-}
-
-
 // public API
 
 void ui_attach_document(UiContext *ctx, void *document) {

mercurial