add cleanup/destroy handler for UiString, UiText and UiGeneric

Sun, 26 Oct 2025 10:07:31 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sun, 26 Oct 2025 10:07:31 +0100
changeset 875
0575ca45f1bb
parent 874
33618ae398bd
child 876
2131c806440d

add cleanup/destroy handler for UiString, UiText and UiGeneric

resource/.DS_Store file | annotate | diff | comparison | revisions
ui/cocoa/webview.h file | annotate | diff | comparison | revisions
ui/cocoa/webview.m file | annotate | diff | comparison | revisions
ui/common/context.c file | annotate | diff | comparison | revisions
ui/common/types.c file | annotate | diff | comparison | revisions
ui/ui/toolkit.h file | annotate | diff | comparison | revisions
ui/ui/webview.h file | annotate | diff | comparison | revisions
Binary file resource/.DS_Store has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/cocoa/webview.h	Sun Oct 26 10:07:31 2025 +0100
@@ -0,0 +1,58 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2025 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "toolkit.h"
+#import "../ui/webview.h"
+
+#import <WebKit/WebKit.h>
+
+
+enum WebViewDataType {
+    WEBVIEW_CONTENT_URL,
+    WEBVIEW_CONTENT_CONTENT
+};
+    
+typedef struct UiWebViewData {
+    void *webview;
+    char *uri;
+    char *mimetype;
+    char *encoding;
+    char *content;
+    size_t contentlength;
+    enum WebViewDataType type;
+    
+    double zoom;
+    UiBool javascript;
+} UiWebViewData;
+
+UiWebViewData* ui_webview_data_clone(UiWebViewData *data);
+
+void* ui_webview_get(UiGeneric *g);
+const char* ui_webview_get_type(UiGeneric *g);
+int ui_webview_set(UiGeneric *g, void *data, const char *type);
+void ui_webview_destroy(UiGeneric *g);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/cocoa/webview.m	Sun Oct 26 10:07:31 2025 +0100
@@ -0,0 +1,194 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2025 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "webview.h"
+#import "Container.h"
+
+UIWIDGET ui_webview_create(UiObject *obj, UiWebviewArgs *args) {
+    WKWebView *webview = [[WKWebView alloc]init];
+    
+    UiLayout layout = UI_ARGS2LAYOUT(args);
+    ui_container_add(obj, webview, &layout);
+    
+    UiVar *var = uic_widget_var(obj->ctx, obj->ctx, args->value, args->varname, UI_VAR_GENERIC);
+    if(var) {
+        UiGeneric *value = var->value;
+        value->get = ui_webview_get;
+        value->get_type = ui_webview_get_type;
+        value->set = ui_webview_set;
+        value->destroy = ui_webview_destroy;
+        value->obj = (__bridge void*)webview;
+        if(value->value) {
+            ui_webview_set(value, value->value, UI_WEBVIEW_OBJECT_TYPE);
+        } else {
+            UiWebViewData *data = malloc(sizeof(UiWebViewData));
+            memset(data, 0, sizeof(UiWebViewData));
+            data->webview = (__bridge void*)webview;
+            data->javascript = TRUE;
+            data->zoom = 1;
+            value->value = value;
+        }
+    }
+    
+    return (__bridge void*)webview;
+}
+
+UiWebViewData* ui_webview_data_clone(UiWebViewData *data) {
+    UiWebViewData *newdata = malloc(sizeof(UiWebViewData));
+    memset(newdata, 0, sizeof(UiWebViewData));
+    
+    if(data) {
+        newdata->uri = data->uri ? strdup(data->uri) : NULL;
+        newdata->mimetype = data->mimetype ? strdup(data->mimetype) : NULL;
+        newdata->encoding = data->encoding ? strdup(data->encoding) : NULL;
+        newdata->type = data->type;
+        newdata->javascript = data->javascript;
+        newdata->zoom = data->zoom;
+        if(data->content && data->contentlength > 0) {
+            newdata->content = malloc(data->contentlength + 1);
+            memcpy(newdata->content, data->content, data->contentlength);
+            newdata->content[data->contentlength] = 0;
+            newdata->contentlength = data->contentlength;
+        }
+    }
+    
+    return newdata;
+}
+
+void ui_webview_data_free(UiWebViewData *data) {
+    if(!data) {
+        return;
+    }
+    free(data->uri);
+    free(data->mimetype);
+    free(data->encoding);
+    free(data->content);
+    free(data);
+}
+
+void* ui_webview_get(UiGeneric *g) {
+    return ui_webview_data_clone(g->value);
+}
+
+const char* ui_webview_get_type(UiGeneric *g) {
+    return UI_WEBVIEW_OBJECT_TYPE;
+}
+
+int ui_webview_set(UiGeneric *g, void *data, const char *type) {
+    if(!data || !type) {
+        return 1;
+    }
+    if(strcmp(type, UI_WEBVIEW_OBJECT_TYPE)) {
+        return 1;
+    }
+    ui_webview_data_free(g->value);
+    g->value = ui_webview_data_clone(data);
+    
+    WKWebView *webview = (__bridge WKWebView*)g->obj;
+    UiWebViewData *webd = data;
+    if(webd->type == WEBVIEW_CONTENT_URL && webd->uri) {
+        NSURL *url = [NSURL URLWithString:[[NSString alloc] initWithUTF8String:webd->uri]];
+        if(url) {
+            NSURLRequest *req = [NSURLRequest requestWithURL:url];
+            if(req) {
+                [webview loadRequest:req];
+            }
+        }
+    } else if(webd->content) {
+        // TODO
+    }
+    
+    return 1;
+}
+
+void ui_webview_destroy(UiGeneric *g) {
+    ui_webview_data_free(g->value);
+    g->value = NULL;
+}
+
+
+void ui_webview_load_url(UiGeneric *g, const char *url) {
+    WKWebView *webview = (__bridge WKWebView*)g->obj;
+    if(url) {
+        NSURL *nsurl = [NSURL URLWithString:[[NSString alloc] initWithUTF8String:url]];
+        if(nsurl) {
+            NSURLRequest *req = [NSURLRequest requestWithURL:nsurl];
+            if(req) {
+                [webview loadRequest:req];
+            }
+        }
+    }
+}
+
+void ui_webview_load_content(
+        UiGeneric *g,
+        const char *uri,
+        const char *content,
+        size_t contentlength,
+        const char *mimetype,
+        const char *encoding)
+{
+    
+}
+
+
+void ui_webview_reload(UiGeneric *g) {
+    
+}
+
+UiBool ui_webview_can_go_back(UiGeneric *g) {
+    return FALSE;
+}
+
+UiBool ui_webview_can_go_forward(UiGeneric *g) {
+    return FALSE;
+}
+
+void ui_webview_go_back(UiGeneric *g) {
+    
+}
+
+void ui_webview_go_forward(UiGeneric *g) {
+    
+}
+
+const char * ui_webview_get_uri(UiGeneric *g) {
+    return NULL;
+}
+
+void ui_webview_enable_javascript(UiGeneric *g, UiBool enable) {
+    
+}
+
+void ui_webview_set_zoom(UiGeneric *g, double zoom) {
+    
+}
+
+double ui_webview_get_zoom(UiGeneric *g) {
+    return 0;
+}
--- a/ui/common/context.c	Sat Oct 25 21:30:41 2025 +0200
+++ b/ui/common/context.c	Sun Oct 26 10:07:31 2025 +0100
@@ -622,7 +622,7 @@
     return ctx ? cxRealloc(ctx->allocator, ptr, size) : NULL;
 }
 
-UIEXPORT char* ui_strdup(UiContext *ctx, const char *str) {
+char* ui_strdup(UiContext *ctx, const char *str) {
     if(!ctx) {
         return NULL;
     }
@@ -630,3 +630,11 @@
     cxmutstr d = cx_strdup_a(ctx->allocator, s);
     return d.ptr;
 }
+
+void  ui_reg_destructor(UiContext *ctx, void *data, ui_destructor_func destr) {
+    cxMempoolRegister(ctx->mp, data, (cx_destructor_func)destr);
+}
+
+void  ui_set_destructor(void *mem, ui_destructor_func destr) {
+    cxMempoolSetDestructor(mem, (cx_destructor_func)destr);
+}
--- a/ui/common/types.c	Sat Oct 25 21:30:41 2025 +0200
+++ b/ui/common/types.c	Sun Oct 26 10:07:31 2025 +0100
@@ -313,18 +313,32 @@
     return d;
 }
 
+static void string_destroy(UiString *s) {
+    if(s->value.free && s->value.ptr) {
+        s->value.free(s->value.ptr);
+    }
+}
+
 UiString* ui_string_new(UiContext *ctx, const char *name) {
     UiString *s = ui_malloc(ctx, sizeof(UiString));
     memset(s, 0, sizeof(UiString));
+    ui_set_destructor(s, (ui_destructor_func)string_destroy);
     if(name) {
         uic_reg_var(ctx, name, UI_VAR_STRING, s);
     }
     return s;
 }
 
+static void text_destroy(UiText *t) {
+    if(t->destroy) {
+        t->destroy(t);
+    }
+}
+
 UiText* ui_text_new(UiContext *ctx, const char *name) {
     UiText *t = ui_malloc(ctx, sizeof(UiText));
     memset(t, 0, sizeof(UiText));
+    ui_set_destructor(t, (ui_destructor_func)text_destroy);
     if(name) {
         uic_reg_var(ctx, name, UI_VAR_TEXT, t);
     }
@@ -340,9 +354,16 @@
     return r;
 }
 
-UIEXPORT UiGeneric* ui_generic_new(UiContext *ctx, const char *name) {
+static void generic_destroy(UiGeneric *g) {
+    if(g->destroy) {
+        g->destroy(g);
+    }
+}
+
+UiGeneric* ui_generic_new(UiContext *ctx, const char *name) {
     UiGeneric *g = ui_malloc(ctx, sizeof(UiGeneric));
     memset(g, 0, sizeof(UiGeneric));
+    ui_set_destructor(g, (ui_destructor_func)generic_destroy);
     if(name) {
         uic_reg_var(ctx, name, UI_VAR_GENERIC, g);
     }
--- a/ui/ui/toolkit.h	Sat Oct 25 21:30:41 2025 +0200
+++ b/ui/ui/toolkit.h	Sun Oct 26 10:07:31 2025 +0100
@@ -256,6 +256,9 @@
 
 typedef void(*ui_enablefunc)(void*, int);
 
+typedef void (*ui_destructor_func)(void *memory);
+
+
 struct UiObject {
     /*
      * native widget
@@ -405,6 +408,7 @@
     void* (*get)(UiGeneric*);
     const char* (*get_type)(UiGeneric*);
     int (*set)(UiGeneric*, void *, const char *type);
+    void (*destroy)(UiGeneric*);
     void *obj;
     
     void *value;
@@ -572,6 +576,8 @@
 UIEXPORT void  ui_free(UiContext *ctx, void *ptr);
 UIEXPORT void* ui_realloc(UiContext *ctx, void *ptr, size_t size);
 UIEXPORT char* ui_strdup(UiContext *ctx, const char *str);
+UIEXPORT void  ui_reg_destructor(UiContext *ctx, void *data, ui_destructor_func destr);
+UIEXPORT void  ui_set_destructor(void *mem, ui_destructor_func destr);
 
 // types
 
--- a/ui/ui/webview.h	Sat Oct 25 21:30:41 2025 +0200
+++ b/ui/ui/webview.h	Sun Oct 26 10:07:31 2025 +0100
@@ -36,8 +36,16 @@
 extern "C" {
 #endif
     
+/*
+ * WebView type string used by UiGeneric
+ */
 #define UI_WEBVIEW_OBJECT_TYPE "webview"
-    
+
+/*
+ * UiWebViewData* is returned by a webviews UiGeneric->get function
+ */
+typedef struct UiWebViewData UiWebViewData;
+
 typedef struct UiWebviewArgs {
     UiBool fill;
     UiBool hexpand;
@@ -75,6 +83,10 @@
         const char *mimetype,
         const char *encoding);
 
+/*
+ * Frees a UiWebViewData object returned by a webviews UiGeneric->get function
+ */
+UIEXPORT void ui_webview_data_free(UiWebViewData *data);
 
 UIEXPORT void ui_webview_reload(UiGeneric *g);
 UIEXPORT UiBool ui_webview_can_go_back(UiGeneric *g);

mercurial