ui/common/context.c

changeset 108
77254bd6dccb
parent 103
6606616eca9f
child 110
c00e968d018b
--- a/ui/common/context.c	Sat Apr 05 17:57:04 2025 +0200
+++ b/ui/common/context.c	Sun Jul 20 22:04:39 2025 +0200
@@ -58,6 +58,7 @@
     memset(ctx, 0, sizeof(UiContext));
     ctx->mp = mp;
     ctx->allocator = mp->allocator;
+    ctx->destroy_handler = cxArrayListCreate(ctx->allocator, NULL, sizeof(UiDestroyHandler), 16);
     ctx->obj = toplevel;
     ctx->vars = cxHashMapCreate(mp->allocator, CX_STORE_POINTERS, 16);
     
@@ -66,7 +67,7 @@
     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;
+    ctx->detach_document2 = uic_context_detach_document;
     
 #if UI_GTK2 || UI_GTK3
     if(toplevel && toplevel->widget) {
@@ -82,6 +83,13 @@
     return ctx->parent ? uic_root_context(ctx->parent) : ctx;
 }
 
+void uic_context_add_destructor(UiContext *ctx, cx_destructor_func func, void *data) {
+    UiDestroyHandler handler;
+    handler.destructor = func;
+    handler.data = data;
+    cxListAdd(ctx->destroy_handler, &handler);
+}
+
 void uic_context_prepare_close(UiContext *ctx) {
     cxListClear(ctx->groups);
     cxListClear(ctx->group_widgets);
@@ -120,11 +128,12 @@
     CxMapIterator mi = cxMapIterator(ctx->vars);
     cx_foreach(CxMapEntry*, entry, mi) {
         UiVar *var = entry->value;
-        if(var->from && var->from_ctx && var->from_ctx != ctx) {
+        // var->from && var->from_ctx && var->from_ctx != ctx
+        if(var->from) {
             uic_save_var2(var);
             uic_copy_binding(var, var->from, FALSE);
-            cxMapPut(var->from_ctx->vars_unbound, *entry->key, var->from);
-            var->from_ctx = ctx;
+            cxMapPut(var->from->from_ctx->vars_unbound, *entry->key, var->from);
+            var->from = NULL;
         }
     }
     
@@ -137,7 +146,7 @@
     }
 }
 
-void uic_context_detach_document2(UiContext *ctx, void *document) {
+void uic_context_detach_document(UiContext *ctx, void *document) {
     // find the document in the documents list
     size_t docIndex = cxListFind(ctx->documents, document);
     if(!cxListIndexValid(ctx->documents, docIndex)) {
@@ -209,6 +218,7 @@
     var = ui_malloc(ctx, sizeof(UiVar));
     var->type = type;
     var->value = uic_create_value(ctx, type);
+    var->original_value = NULL;
     var->from = NULL;
     var->from_ctx = ctx;
 
@@ -227,6 +237,7 @@
     var->from = NULL;
     var->from_ctx = ctx;
     var->value = value;
+    var->original_value = NULL;
     var->type = UI_VAR_SPECIAL;
     return var;
 }
@@ -286,10 +297,19 @@
     }
     
     void *fromvalue = from->value;
+    void *tovalue = to->value;
     // update var
     if(copytodoc) {
-        to->from = from;
-        to->from_ctx = from->from_ctx;
+        to->from = from; // from which UiVar are the bindings copied
+        from->original_value = fromvalue; // save original value otherwise it would be lost
+        // widgets store a reference to the UiVar with their value
+        // the UiVar object must be updated to contain the current value object
+        from->value = tovalue;
+    } else {
+        if(to->original_value) {
+            to->value = to->original_value;
+            tovalue = to->value;
+        }
     }
     
     ui_setop_enable(TRUE);
@@ -301,7 +321,7 @@
         case UI_VAR_SPECIAL: break;
         case UI_VAR_INTEGER: {
             UiInteger *f = fromvalue;
-            UiInteger *t = to->value;
+            UiInteger *t = tovalue;
             if(!f->obj) break;
             uic_int_copy(f, t);
             t->set(t, t->value);
@@ -309,7 +329,7 @@
         }
         case UI_VAR_DOUBLE: {
             UiDouble *f = fromvalue;
-            UiDouble *t = to->value;
+            UiDouble *t = tovalue;
             if(!f->obj) break;
             uic_double_copy(f, t);
             t->set(t, t->value);
@@ -317,48 +337,32 @@
         }
         case UI_VAR_STRING: {
             UiString *f = fromvalue;
-            UiString *t = to->value;
+            UiString *t = tovalue;
             if(!f->obj) break;
             uic_string_copy(f, t);
             char *tvalue = t->value.ptr ? t->value.ptr : "";
+            char *fvalue = f->value.ptr ? f->value.ptr : "";
             t->set(t, tvalue);
             break;
         }
         case UI_VAR_TEXT: {
             UiText *f = fromvalue;
-            UiText *t = to->value;
+            UiText *t = tovalue;
             if(!f->obj) break;
             uic_text_copy(f, t);
             t->restore(t);
             break;
         }
-        case UI_VAR_LIST: {
-            // TODO: not sure how correct this is
-
-            UiList *f = from->value;
-            UiList *t = to->value;
-            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;
-            if(t->update) {
-                t->update(t, -1);
-            }
-            ui_notify(t2->observers, NULL); // TODO: why not t?
-            
+        case UI_VAR_LIST: {         
+            UiList *f = fromvalue;
+            UiList *t = tovalue;
+            uic_list_copy(f, t);
+            ui_list_update(t);
             break;
         }
         case UI_VAR_RANGE: {
             UiRange *f = fromvalue;
-            UiRange *t = to->value;
+            UiRange *t = tovalue;
             if(!f->obj) break;
             uic_range_copy(f, t);
             t->setextent(t, t->extent);
@@ -368,7 +372,7 @@
         }
         case UI_VAR_GENERIC: {
             UiGeneric *f = fromvalue;
-            UiGeneric *t = to->value;
+            UiGeneric *t = tovalue;
             if(!f->obj) break;
             uic_generic_copy(f, t);
             t->set(t, t->value, t->type);
@@ -405,7 +409,7 @@
     }
 }
 
-void uic_reg_var(UiContext *ctx, char *name, UiVarType type, void *value) {
+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
@@ -463,8 +467,8 @@
     uic_context_attach_document(ctx, document);
 }
 
-void ui_detach_document2(UiContext *ctx, void *document) {
-    uic_context_detach_document2(ctx, document);
+void ui_detach_document(UiContext *ctx, void *document) {
+    uic_context_detach_document(ctx, document);
 }
 
 void ui_context_closefunc(UiContext *ctx, ui_callback fnc, void *udata) {
@@ -472,10 +476,18 @@
     ctx->close_data = udata;
 }
 
-UIEXPORT void ui_context_destroy(UiContext *ctx) {
+void ui_context_destroy(UiContext *ctx) {
+    CxIterator i = cxListIterator(ctx->destroy_handler);
+    cx_foreach(UiDestroyHandler *, h, i) {
+        h->destructor(h->data);
+    }
     cxMempoolFree(ctx->mp);
 }
 
+UiContext* ui_context_parent(UiContext *ctx) {
+    return ctx->parent;
+}
+
 
 void ui_set_group(UiContext *ctx, int group) {
     if(!cxListIndexValid(ctx->groups, cxListFind(ctx->groups, &group))) {

mercurial