]> uap-core.de Git - note.git/commitdiff
add menubuilder main
authorOlaf Wintermann <olaf.wintermann@gmail.com>
Tue, 18 Aug 2026 19:18:10 +0000 (21:18 +0200)
committerOlaf Wintermann <olaf.wintermann@gmail.com>
Tue, 18 Aug 2026 19:18:10 +0000 (21:18 +0200)
ui-rs/src/ui/menu.rs
ui-rs/src/ui/toolkit.rs
ui/cocoa/container.m
ui/cocoa/label.m
ui/cocoa/objs.mk
ui/cocoa/text.m
ui/cocoa/webview.m
ui/cocoa/window.m
ui/common/menu.c
ui/common/menu.h
ui/ui/menu.h

index 69e9fa6911a00961330827bb5a573d5546448396..8926d33b143149080c5387bd1ccab372e47b41e9 100644 (file)
@@ -30,8 +30,9 @@
 
 use std::ffi::{c_char, c_int, c_void, CString};
 use std::marker::PhantomData;
-use crate::ui::{event, ffi, toolkit, AppContext, EventWrapper, GetValueFunc, ToggleButtonCreate, UiActions, UiContext, UiModel};
-use crate::ui::ffi::{UiCallback, UiMenuItemArgs, UiMenuItemListArgs, UiMenuToggleItemArgs, UiObject, UiToggleArgs};
+use std::ops::Deref;
+use crate::ui::{event, ffi, toolkit, ui_document_context, ui_document_new, ui_document_unref, AppContext, EventWrapper, GetValueFunc, ToggleButtonCreate, UiActions, UiContext, UiModel};
+use crate::ui::ffi::{UiCallback, UiDestructor, UiMenuBuilder, UiMenuItemArgs, UiMenuItemListArgs, UiMenuToggleItemArgs, UiObject, UiToggleArgs};
 
 impl<T: UiModel + UiActions> AppContext<T> {
     pub fn menu<F>(&self, title: &str, f: F)
@@ -230,6 +231,83 @@ impl<T: UiModel + UiActions> Drop for MenuToggleItemBuilder<T> {
     }
 }
 
+
+pub struct MenuBuilder<T: UiModel + UiActions> {
+    menu: Menu<T>,
+    doc: *mut c_void,
+    ctx: *mut ffi::UiContext,
+    builder: *mut UiMenuBuilder,
+}
+
+impl<T: UiModel + UiActions> Deref for MenuBuilder<T> {
+    type Target = Menu<T>;
+
+    fn deref(&self) -> &Self::Target {
+        &self.menu
+    }
+}
+
+impl<T: UiModel + UiActions> MenuBuilder<T> {
+    pub fn ref_by_obj(&self, obj: &toolkit::UiObject<T>) {
+        unsafe {
+            ui_menubuilder_ref_by_obj(self.builder, obj.ptr);
+        }
+    }
+}
+
+impl<T: UiModel + UiActions> Clone for MenuBuilder<T> {
+    fn clone(&self) -> Self {
+        unsafe {
+            ui_menubuilder_ref(self.builder);
+        }
+        MenuBuilder {
+            menu: Menu {
+                ctx: self.ctx,
+                _marker: PhantomData
+            },
+            doc: self.doc,
+            ctx: self.ctx,
+            builder: self.builder,
+        }
+    }
+}
+
+impl<T: UiModel + UiActions> Drop for MenuBuilder<T> {
+    fn drop(&mut self) {
+        unsafe {
+            ui_menubuilder_unref(self.builder);
+        }
+    }
+}
+
+pub fn menubuilder_new<T: UiModel + UiActions>() -> MenuBuilder<T> {
+    unsafe {
+        let doc = ui_document_new(8);
+        let ctx = ui_document_context(doc);
+        let mut builder: *mut UiMenuBuilder = std::ptr::null_mut();
+        ui_contextmenu_builder(&mut builder);
+        ui_menubuilder_set_custom_data(builder, doc, menubuilder_doc_destroy);
+        let menu = Menu {
+            ctx,
+            _marker: PhantomData,
+        };
+
+        MenuBuilder {
+            menu,
+            doc,
+            ctx,
+            builder
+        }
+    }
+}
+
+
+extern "C" fn menubuilder_doc_destroy(doc: *mut c_void) {
+    unsafe {
+        ui_document_unref(doc);
+    }
+}
+
 unsafe extern "C" {
     fn ui_menu_create(label: *const c_char);
     fn ui_menuitem_create(args: *const UiMenuItemArgs);
@@ -240,6 +318,11 @@ unsafe extern "C" {
     fn ui_menu_toggleitemlist_create(args: *const UiMenuItemListArgs);
     fn ui_menu_radioitemlist_create(args: *const UiMenuItemListArgs);
     pub fn ui_menu_end();
+    fn ui_contextmenu_builder(out_builder: *mut *mut ffi::UiMenuBuilder);
+    fn ui_menubuilder_set_custom_data(builder: *mut UiMenuBuilder, data: *mut c_void, destr: UiDestructor);
+    fn ui_menubuilder_ref_by_obj(builder: *mut ffi::UiMenuBuilder, obj: *mut ffi::UiObject);
+    fn ui_menubuilder_ref(builder: *mut ffi::UiMenuBuilder);
+    fn ui_menubuilder_unref(builder: *mut ffi::UiMenuBuilder);
 
     fn ui_menuitem_args_new() -> *mut UiMenuItemArgs;
     fn ui_menuitem_args_set_label(args: *mut UiMenuItemArgs, label: *const c_char);
index 0e57608b6795cc561372f86715fb62c3038abcc3..f575b18d7cd6cc7e134c93585f794fc9414b05d0 100644 (file)
@@ -1446,10 +1446,10 @@ unsafe extern "C" {
     fn ui_configfile(name: *const c_char) -> *mut c_char;
     pub fn ui_call_mainthread(func: UiThreadFunc, data: *mut c_void);
 
-    fn ui_document_new(size: usize) -> *mut c_void;
-    fn ui_document_ref(doc: *mut c_void);
-    fn ui_document_unref(doc: *mut c_void);
-    fn ui_document_context(doc: *mut c_void) -> *mut ffi::UiContext;
+    pub fn ui_document_new(size: usize) -> *mut c_void;
+    pub fn ui_document_ref(doc: *mut c_void);
+    pub fn ui_document_unref(doc: *mut c_void);
+    pub fn ui_document_context(doc: *mut c_void) -> *mut ffi::UiContext;
     fn ui_attach_document(ctx: *mut ffi::UiContext, doc: *mut c_void);
     fn ui_detach_document(ctx: *mut ffi::UiContext, doc: *mut c_void);
     fn ui_context_onattach(ctx: *mut ffi::UiContext, callback: UiCallback, data: *mut c_void);
index 2bd54a203bafa7edf31efed710f3a3665eb76e50..80daf77bba9b941e6801df63df3ada012ded28de 100644 (file)
@@ -45,7 +45,10 @@ static UIWIDGET ui_box_create(UiObject *obj, UiContainerArgs *args, NSUserInterf
     // add new box to the obj container chain
     uic_object_push_container(obj, container);
     
-    return (__bridge void*)box;
+    void *widget = (__bridge void*)box;
+    uic_widget_set_visibility_states(obj->ctx, widget, args->visibility_states);
+    
+    return widget;
 }
 
 UIWIDGET ui_vbox_create(UiObject *obj, UiContainerArgs *args) {
@@ -71,7 +74,10 @@ UIWIDGET ui_grid_create(UiObject *obj, UiContainerArgs *args) {
     // add new box to the obj container chain
     uic_object_push_container(obj, container);
     
-    return (__bridge void*)grid;
+    void *widget = (__bridge void*)grid;
+    uic_widget_set_visibility_states(obj->ctx, widget, args->visibility_states);
+    
+    return widget;
 }
 
 UIWIDGET ui_frame_create(UiObject *obj, UiFrameArgs *args) {
@@ -116,7 +122,10 @@ UIWIDGET ui_frame_create(UiObject *obj, UiFrameArgs *args) {
     
     uic_object_push_container(obj, container);
     
-    return (__bridge void*)frame;
+    void *widget = (__bridge void*)frame;
+    uic_widget_set_visibility_states(obj->ctx, widget, args->visibility_states);
+    
+    return widget;
 }
 
 UIWIDGET ui_expander_create(UiObject *obj, UiFrameArgs *args) {
@@ -140,7 +149,10 @@ UIWIDGET ui_scrolledwindow_create(UiObject *obj, UiFrameArgs *args) {
     UiContainer *container = ui_create_container(obj, scrollview);
     uic_object_push_container(obj, container);
     
-    return (__bridge void*)scrollview;
+    void *widget = (__bridge void*)scrollview;
+    uic_widget_set_visibility_states(obj->ctx, widget, args->visibility_states);
+    
+    return widget;
 }
 
 static int64_t tabview_get(UiInteger *i) {
@@ -165,7 +177,10 @@ UIWIDGET ui_tabview_create(UiObject *obj, UiTabViewArgs *args) {
     UiContainer *container = ui_create_container(obj, tabview);
     uic_object_push_container(obj, container);
     
-    return (__bridge void*)tabview;
+    void *widget = (__bridge void*)tabview;
+    uic_widget_set_visibility_states(obj->ctx, widget, args->visibility_states);
+    
+    return widget;
 }
 
 void ui_tab_create(UiObject *obj, const char* title) {
index 44e90451f7437c5b53c797a8e9e7e88765a84acb..36df5f70bd1ef32de892efe4ed9cedb9f7205102 100644 (file)
@@ -64,6 +64,9 @@ static UIWIDGET create_label(UiObject *obj, UiLabelArgs *args) {
         if(s->value.ptr) {
             label.stringValue = [[NSString alloc]initWithUTF8String:s->value.ptr];
         }
+        if(s->value.free) {
+            s->value.free(s->value.ptr);
+        }
     }
     
     return (__bridge void*)label;
@@ -91,6 +94,7 @@ char* ui_label_get(UiString *s) {
         s->value.free(s->value.ptr);
     }
     s->value.ptr = strdup(label.stringValue.UTF8String);
+    s->value.free = free;
     return s->value.ptr;
 }
 
@@ -100,5 +104,6 @@ void ui_label_set(UiString *s, const char *str) {
         s->value.free(s->value.ptr);
     }
     s->value.ptr = NULL;
+    s->value.free = NULL;
     label.stringValue = [[NSString alloc] initWithUTF8String:str];
 }
index a37ec4fc07fe219322efe325f6e47a198ff92fa2..4582da4c20e9ba22727b8ad09226d110f41ea8be 100644 (file)
@@ -52,6 +52,7 @@ COCOAOBJ += image.o
 COCOAOBJ += entry.o
 COCOAOBJ += TabView.o
 COCOAOBJ += action.o
+COCOAOBJ += webview.o
 
 TOOLKITOBJS += $(COCOAOBJ:%=$(COCOA_OBJPRE)%)
 TOOLKITSOURCE += $(COCOAOBJ:%.o=cocoa/%.m)
index acbffedd33a593bcc31b203fc38e6b584201f4b7..ffcc88c425b1666494d4c7c9f8debeaba4dd8dbd 100644 (file)
@@ -564,3 +564,11 @@ int ui_textfield_get_position(UIWIDGET textfield) {
 }
 
 @end
+
+
+
+/* -------------------- Path TextField -------------------- */
+
+UIWIDGET ui_path_textfield_create(UiObject* obj, UiPathTextFieldArgs *args) {
+    return NULL; // TODO: implement
+}
index a4b4dae6c5a47ef8e0e3dadcff54a3cee6afa9ce..85555993e86f33e939ae418eafb2694142ce3cf0 100644 (file)
 #import "webview.h"
 #import "Container.h"
 
+static UiWebViewData* create_webview_data(void) {
+    UiWebViewData *data = malloc(sizeof(UiWebViewData));
+    memset(data, 0, sizeof(UiWebViewData));
+    data->javascript = TRUE;
+    data->zoom = 1;
+    return data;
+}
+
 UIWIDGET ui_webview_create(UiObject *obj, UiWebviewArgs *args) {
     UiVar *var = uic_widget_var(obj->ctx, obj->ctx, args->value, args->varname, UI_VAR_GENERIC);
     
@@ -47,11 +55,8 @@ UIWIDGET ui_webview_create(UiObject *obj, UiWebviewArgs *args) {
         if(value->value) {
             ui_webview_set(value, value->value, UI_WEBVIEW_OBJECT_TYPE);
         } else {
-            UiWebViewData *data = malloc(sizeof(UiWebViewData));
-            memset(data, 0, sizeof(UiWebViewData));
+            UiWebViewData *data = create_webview_data();
             data->webview = (__bridge void*)webview;
-            data->javascript = TRUE;
-            data->zoom = 1;
             value->value = data;
         }
     }
@@ -60,10 +65,7 @@ UIWIDGET ui_webview_create(UiObject *obj, UiWebviewArgs *args) {
 }
 
 UiWebViewData* ui_webview_data_clone(UiWebViewData *data) {
-    UiWebViewData *newdata = malloc(sizeof(UiWebViewData));
-    memset(newdata, 0, sizeof(UiWebViewData));
-    newdata->zoom = 1;
-    newdata->javascript = TRUE;
+    UiWebViewData *newdata = create_webview_data();
     
     if(data) {
         newdata->uri = data->uri ? strdup(data->uri) : NULL;
@@ -98,6 +100,12 @@ void* ui_webview_get(UiGeneric *g) {
     UiWebViewData *data = g->value;
     WKWebView *webview = (__bridge WKWebView*)g->obj;
     
+    if(data == NULL) {
+        data = create_webview_data();
+        data->webview = g->obj;
+        g->value = data;
+    }
+    
     if(data->type == WEBVIEW_CONTENT_URL) {
         (void)ui_webview_get_uri(g); // this updates data->uri
     }
@@ -157,6 +165,13 @@ void ui_webview_destroy(UiGeneric *g) {
 void ui_webview_load_url(UiGeneric *g, const char *url) {
     WKWebView *webview = (__bridge WKWebView*)g->obj;
     UiWebViewData *data = g->value;
+    
+    if(data == NULL) {
+        data = create_webview_data();
+        data->webview = g->obj;
+        g->value = data;
+    }
+    
     data->type = WEBVIEW_CONTENT_URL;
     
     if(!url) {
@@ -183,6 +198,12 @@ void ui_webview_load_content(
     UiWebViewData *data = g->value;
     WKWebView *webview = (__bridge WKWebView*)g->obj;
     
+    if(data == NULL) {
+        data = create_webview_data();
+        data->webview = g->obj;
+        g->value = data;
+    }
+    
     data->type = WEBVIEW_CONTENT_CONTENT;
     
     free(data->uri);
index c027867e3ccfffd7c718cf1b595197aeed97e115..86a97b7cc8200153f2ae90d419c7cab576bb9d4a 100644 (file)
@@ -400,7 +400,7 @@ UiObject *ui_dialog_window_create(UiObject *parent, UiDialogWindowArgs *args) {
         
         EventData *event = [[EventData alloc] init:args->onclick userdata:args->onclickdata action:nil];
         event.obj = obj;
-        event.value = 2;
+        event.value = 4;
         rbutton4.target = event;
         rbutton4.action = @selector(handleEvent:);
         objc_setAssociatedObject(rbutton4, "eventdata", event, OBJC_ASSOCIATION_RETAIN);
@@ -420,7 +420,7 @@ UiObject *ui_dialog_window_create(UiObject *parent, UiDialogWindowArgs *args) {
         
         EventData *event = [[EventData alloc] init:args->onclick userdata:args->onclickdata action:nil];
         event.obj = obj;
-        event.value = 2;
+        event.value = 3;
         rbutton3.target = event;
         rbutton3.action = @selector(handleEvent:);
         objc_setAssociatedObject(rbutton3, "eventdata", event, OBJC_ASSOCIATION_RETAIN);
index 83eb2589e238701b32fbcdf5d1e2ac53e0ecbf6a..f245cf087dd64092fc940d757ccdfddf5ac975d9 100644 (file)
@@ -309,6 +309,8 @@ void ui_contextmenu_builder(UiMenuBuilder **out_builder) {
     builder->menus_begin = NULL;
     builder->menus_end = NULL;
     builder->current = cxLinkedListCreate(cxDefaultAllocator, CX_STORE_POINTERS);
+    builder->custom_data = NULL;
+    builder->custom_destr = NULL;
     builder->ref = 1;
     current_builder = builder;
     *out_builder = builder;
@@ -316,6 +318,10 @@ void ui_contextmenu_builder(UiMenuBuilder **out_builder) {
     ui_menu_create(NULL);
 }
 
+void ui_menubuilder_set_custom_data(UiMenuBuilder *builder, void *data, ui_destructor_func destr) {
+    builder->custom_destr = destr;
+    builder->custom_data = data;
+}
 
 
 static void free_menuitem(UiMenuItemI *item) {
@@ -389,3 +395,8 @@ void ui_menubuilder_unref(UiMenuBuilder *builder) {
         ui_menubuilder_free(builder);
     }
 }
+
+void ui_menubuilder_ref_by_obj(UiMenuBuilder *builder, UiObject *obj) {
+    builder->ref++;
+    ui_reg_destructor(obj->ctx, builder, (ui_destructor_func)ui_menubuilder_unref);
+}
index 510e504f100f1fa0a6a5466fbc7e67aede2848d4..f1a4aa25b9141d8c4d2cb39fd202df8b9d4312e6 100644 (file)
@@ -122,6 +122,8 @@ struct UiMenuBuilder {
     UiMenu *menus_begin;
     UiMenu *menus_end;
     CxList *current;
+    ui_destructor_func custom_destr;
+    void *custom_data;
     int ref;
 };
 
index 5ad8776419ddbc73c3c44794dd9faaa799efb264..b6850e744169ec449733536ee46b83ee71fd384a 100644 (file)
@@ -105,6 +105,7 @@ UIEXPORT void ui_menu_end(void); // TODO: private
 UIEXPORT void ui_contextmenu_builder(UiMenuBuilder **out_builder);
 UIEXPORT void ui_menubuilder_ref(UiMenuBuilder *builder);
 UIEXPORT void ui_menubuilder_unref(UiMenuBuilder *builder);
+UIEXPORT void ui_menubuilder_ref_by_obj(UiMenuBuilder *builder, UiObject *obj);
 UIEXPORT UIMENU ui_contextmenu_create(UiMenuBuilder *builder, UiObject *obj, UIWIDGET widget);
 UIEXPORT void ui_contextmenu_popup(UIMENU menu, UIWIDGET widget, int x, int y);
 
@@ -112,6 +113,8 @@ UIEXPORT void ui_contextmenu_popup(UIMENU menu, UIWIDGET widget, int x, int y);
 UIEXPORT void ui_menu_close(void);
 UIEXPORT int ui_menu_is_open(void);
 
+UIEXPORT void ui_menubuilder_set_custom_data(UiMenuBuilder *builder, void *data, ui_destructor_func destr);
+
 #ifdef __cplusplus
 }
 #endif