]> uap-core.de Git - note.git/commitdiff
add UiObjRef main
authorOlaf Wintermann <olaf.wintermann@gmail.com>
Tue, 19 May 2026 17:24:25 +0000 (19:24 +0200)
committerOlaf Wintermann <olaf.wintermann@gmail.com>
Tue, 19 May 2026 17:24:25 +0000 (19:24 +0200)
application/src/window.rs
ui-rs/src/ui/toolkit.rs
ui-rs/src/ui/window.rs

index e3a8bf33608d678fa63393c5e585a57a6b2b204b..c95d98f275bea34b18b6ba14605fe455d389b73e 100644 (file)
@@ -35,7 +35,6 @@ use crate::newnotebook::new_notebook_dialog;
 
 #[derive(UiModel)]
 pub struct MainWindow {
-    pub obj: Option<UiObject<MainWindow>>,
     pub backend: BackendHandle,
 
     #[bind]
@@ -46,7 +45,6 @@ pub struct MainWindow {
 impl MainWindow {
     pub fn new(app: &App) -> MainWindow {
         MainWindow {
-            obj: None,
             backend: app.backend.clone(),
             notebooks: UiSourceList::default()
         }
@@ -85,9 +83,8 @@ impl MainWindow {
 pub fn create_window(app: &App, ctx: &AppContext<MainWindow>) -> UiObject<MainWindow> {
     let windowdata: MainWindow = MainWindow::new(app);
 
-    let mut window = ctx.splitview_window("note", true, windowdata, |obj, data| {
+    let window = ctx.splitview_window("note", true, windowdata, |obj, data| {
         init_window_data(data, app);
-        data.obj = Some(obj.clone());
 
         obj.sidebar_builder().create(|obj|{
             obj.sourcelist(|b|{
@@ -130,10 +127,8 @@ pub fn create_window(app: &App, ctx: &AppContext<MainWindow>) -> UiObject<MainWi
     });
 
     window.show();
-    window.onclose(|event| {
-        println!("window closing");
-        event.data.obj = None;
-    });
+    //window.onclose(|event| {
+    //});
     window
 }
 
index 8f323d4a6f50e75aa3c05d668dacff1056f3b2fe..483e2a9712b7653bad6815da99f0d911b1074100 100644 (file)
@@ -29,7 +29,7 @@
 #![allow(dead_code)]
 
 use std::ffi::{c_char, c_int, c_void, CStr, CString};
-use crate::ui::{action_event_wrapper, event, ffi, ui_object_get_context, ui_object_get_windowdata, ui_reg_destructor, ActionEventWrapper, EventWrapper, SubList};
+use crate::ui::{action_event_wrapper, event, ffi, ui_object_get_context, ui_object_get_windowdata, ui_reg_destructor, ui_remove_destructor, ActionEventWrapper, Event, EventWrapper, SubList};
 
 use std::marker::PhantomData;
 use std::mem;
@@ -62,7 +62,7 @@ impl UiContext {
         }
     }
 
-    pub fn reg_box<B>(&mut self, b: Box<B>) -> *mut B  {
+    pub fn reg_box<B>(&self, b: Box<B>) -> *mut B  {
         let ptr = Box::into_raw(b);
         unsafe {
             ui_reg_destructor(self.ptr, ptr as *mut c_void, destroy_boxed::<B>);
@@ -196,6 +196,7 @@ impl<T: UiModel + UiActions> UiDoc<T> {
 
 impl<T> UiObject<T> {
     pub fn from_ptr(ptr: *mut ffi::UiObject) -> UiObject<T> {
+        assert!(!ptr.is_null());
         let ctx_ptr = unsafe { ui_object_get_context(ptr) };
         unsafe {
             ui_object_ref(ptr);
@@ -207,6 +208,10 @@ impl<T> UiObject<T> {
         }
     }
 
+    pub fn obj_ref(&self) -> UiObjRef<T> {
+        UiObjRef::from_ptr(self.ptr)
+    }
+
     pub fn window_data<F>(&mut self, mut f: F)
     where F: FnMut(&mut T) {
         unsafe {
@@ -268,6 +273,64 @@ impl<T> Drop for UiObject<T> {
     }
 }
 
+pub struct UiObjRef<T> {
+    ptr: Box<*mut ffi::UiObject>,
+    _data: PhantomData<T>
+}
+
+impl<T> UiObjRef<T> {
+    pub fn from_ptr(obj_ptr: *mut ffi::UiObject) -> UiObjRef<T> {
+        let obj_ref = UiObjRef { ptr: Box::new(obj_ptr), _data: PhantomData };
+        if !obj_ptr.is_null() {
+            let ctx = unsafe { ui_object_get_context(obj_ptr) };
+            unsafe {
+                let xptr = &*obj_ref.ptr as *const *mut ffi::UiObject;
+                ui_reg_destructor(ctx, xptr as *mut c_void, ref_obj_destroyed);
+            }
+        }
+        obj_ref
+    }
+
+    pub fn get_object(&self) -> Option<UiObject<T>> {
+        if self.ptr.is_null() {
+            None
+        } else {
+            Some(UiObject::from_ptr(*self.ptr))
+        }
+    }
+}
+
+impl<T> Drop for UiObjRef<T> {
+    fn drop(&mut self) {
+        unsafe {
+            let obj_ptr = *self.ptr;
+
+            // only unregister if the object still exists
+            if !obj_ptr.is_null() {
+                let ctx = unsafe { ui_object_get_context(obj_ptr) };
+                let xptr = &mut *self.ptr as *mut *mut ffi::UiObject;
+                ui_remove_destructor(ctx, xptr as *mut c_void);
+            }
+        }
+    }
+}
+
+extern "C" fn ref_obj_destroyed(data: *mut c_void) {
+    unsafe {
+        let ptr_ptr = data as *mut *mut ffi::UiObject;
+
+        if !ptr_ptr.is_null() {
+            *ptr_ptr = std::ptr::null_mut();
+        }
+    }
+}
+
+impl<T> Clone for UiObjRef<T> {
+    fn clone(&self) -> Self {
+        UiObjRef::from_ptr(*self.ptr)
+    }
+}
+
 pub struct UiText {
     pub ptr: *mut ffi::UiText
 }
index 6751154499e1d359c782db50fc808ac00c5a6c29..c98cf3a158dbd85e0747cfb0c03eab3ba7754e6c 100644 (file)
@@ -49,7 +49,7 @@ impl<T> toolkit::UiObject<T> {
         }
     }
 
-    pub fn onclose<F>(&mut self, f: F)
+    pub fn onclose<F>(&self, f: F)
     where F: FnMut(&mut event::Event<T>) + 'static {
         let wrapper = Box::new(EventWrapper { callback: Box::new(f) });
         let ptr = self.ctx.reg_box(wrapper);
@@ -58,19 +58,19 @@ impl<T> toolkit::UiObject<T> {
         }
     }
 
-    pub fn set_size(&mut self, width: u32, height: u32) {
+    pub fn set_size(&self, width: u32, height: u32) {
         unsafe {
             ui_window_size(self.ptr, width as c_int, height as c_int);
         }
     }
 
-    pub fn set_menubar_visible(&mut self, visible: bool) {
+    pub fn set_menubar_visible(&self, visible: bool) {
         unsafe {
             ui_window_menubar_set_visible(self.ptr, visible as c_int);
         }
     }
 
-    pub fn enable_fullscreen(&mut self, fullscreen: bool) {
+    pub fn enable_fullscreen(&self, fullscreen: bool) {
         unsafe {
             ui_window_fullscreen(self.ptr, fullscreen as c_int);
         }
@@ -499,6 +499,7 @@ extern "C" {
     fn ui_object_set_onclose(obj: *const UiObject, onclose: UiCallback, data: *mut c_void);
 
     pub fn ui_reg_destructor(ctx: *mut UiContext, data: *mut c_void, destructor: UiDestructor);
+    pub fn ui_remove_destructor(ctx: *mut UiContext, data: *mut c_void);
 
     fn ui_dialog_args_new() -> *mut UiDialogArgs;
     fn ui_dialog_args_set_title(args: *mut UiDialogArgs, title: *const c_char);