]> uap-core.de Git - note.git/commitdiff
refactor window creation and add window data object
authorOlaf Wintermann <olaf.wintermann@gmail.com>
Sun, 12 Apr 2026 14:47:51 +0000 (16:47 +0200)
committerOlaf Wintermann <olaf.wintermann@gmail.com>
Sun, 12 Apr 2026 14:47:51 +0000 (16:47 +0200)
application/src/main.rs
ui-rs/src/ui/button.rs
ui-rs/src/ui/container.rs
ui-rs/src/ui/text.rs
ui-rs/src/ui/toolkit.rs
ui-rs/src/ui/window.rs

index a1b0279fae469b42111eb1b47f6156bb4e49774c..f2d984042842a4f3f736662d5f9d1bf90c3451e6 100644 (file)
@@ -9,24 +9,19 @@ fn main() {
 
 struct App;
 
+struct TestData {
+    i: i32
+}
+
 impl ui::Application for App {
     fn on_startup(&self) {
-        let mut obj = ui::window("note");
-        obj.tabview(|a| {
-            a.fill(true);
-        },
-        |t| {
-            t.tab("Tab 1", |obj| {
-                obj.textarea(|t| {
-                   t.fill(true);
-                });
-            });
-            t.tab("Tab 2", |obj| {
-                obj.textarea(|t| {
-                    t.fill(true);
-                });
-            });
+        let testdata = TestData { i: 123} ;
+
+        let window = ui::window("note", testdata, |obj, data| {
+            obj.button_builder().label("Hello").create();
+            println!("test: {}", data.i);
         });
-        obj.show();
+
+        window.show();
     }
 }
index d88407a12b61228b899968d5168c9e42a1282b4c..ab6dd11a47f35f072487d257c87aa51a12d2d3a2 100644 (file)
@@ -27,7 +27,7 @@ pub enum LabelType {
 
 pub type ToggleButtonCreate = fn(*const UiObject, *const UiToggleArgs);
 
-impl toolkit::UiObject {
+impl<T> toolkit::UiObject<T> {
     widget_fn!(button, button_builder, ButtonBuilder);
     widget_fn!(togglebutton, togglebutton_builder, ToggleBuilder);
     widget_fn!(checkbox, checkbox_builder, ToggleBuilder);
index 05aadd83b34ea7a51b33140df6a1f0a5c3e3e566..359fe64803dd0242571adb371186098155e92d64 100644 (file)
@@ -10,8 +10,8 @@ macro_rules! container_fn {
     ($fn_name:ident, $builder_fn:ident, $builder_ty:ident) => {
         pub fn $fn_name<F, U>(&mut self, build: F, ui: U)
         where
-            F: Fn(&mut $builder_ty),
-            U: FnOnce(&mut toolkit::UiObject)
+            F: Fn(&mut $builder_ty<'_, T>),
+            U: FnOnce(&mut toolkit::UiObject<T>)
         {
             let mut builder = self.$builder_fn();
             build(&mut builder);
@@ -40,11 +40,11 @@ pub enum TabViewType {
 /* -------------------------------- Box/Grid Container -------------------------------- */
 
 pub type ContainerCreate = fn(*mut UiObject, *const UiContainerArgs);
-pub type CreateContainerUI = fn(obj: &toolkit::UiObject);
+pub type CreateContainerUI<T> = fn(obj: &toolkit::UiObject<T>);
 
-pub struct ContainerBuilder<'a> {
+pub struct ContainerBuilder<'a, T> {
     args: *mut UiContainerArgs,
-    obj: &'a mut toolkit::UiObject,
+    obj: &'a mut toolkit::UiObject<T>,
     create: ContainerCreate
 }
 
@@ -66,12 +66,12 @@ fn grid_create(obj: *mut UiObject, args: *const UiContainerArgs) {
     }
 }
 
-impl toolkit::UiObject {
+impl<T> toolkit::UiObject<T> {
     container_fn!(vbox, vbox_builder, ContainerBuilder);
     container_fn!(hbox, hbox_builder, ContainerBuilder);
     container_fn!(grid, grid_builder, ContainerBuilder);
 
-    pub fn vbox_builder(&mut self) -> ContainerBuilder<'_>
+    pub fn vbox_builder(&mut self) -> ContainerBuilder<'_, T>
     {
         unsafe {
             let args = ui_container_args_new();
@@ -83,7 +83,7 @@ impl toolkit::UiObject {
         }
     }
 
-    pub fn hbox_builder(&mut self) -> ContainerBuilder<'_>
+    pub fn hbox_builder(&mut self) -> ContainerBuilder<'_, T>
     {
         unsafe {
             let args = ui_container_args_new();
@@ -95,7 +95,7 @@ impl toolkit::UiObject {
         }
     }
 
-    pub fn grid_builder(&mut self) -> ContainerBuilder<'_>
+    pub fn grid_builder(&mut self) -> ContainerBuilder<'_, T>
     {
         unsafe {
             let args = ui_container_args_new();
@@ -108,7 +108,7 @@ impl toolkit::UiObject {
     }
 
     pub fn grid_row<F>(&mut self, create_ui: F)
-    where F: FnOnce(&mut toolkit::UiObject) {
+    where F: FnOnce(&mut toolkit::UiObject<T>) {
         create_ui(self);
         unsafe {
             ui_newline(self.ptr);
@@ -116,9 +116,9 @@ impl toolkit::UiObject {
     }
 }
 
-impl<'a> ContainerBuilder<'a> {
+impl<'a, T> ContainerBuilder<'a, T> {
     pub fn create<F>(&mut self, create_ui: F)
-    where F: FnOnce(&mut toolkit::UiObject) {
+    where F: FnOnce(&mut toolkit::UiObject<T>) {
         (self.create)(self.obj.ptr, self.args);
         create_ui(self.obj);
         unsafe {
@@ -256,7 +256,7 @@ impl<'a> ContainerBuilder<'a> {
     }
 }
 
-impl<'a> Drop for ContainerBuilder<'a> {
+impl<'a, T> Drop for ContainerBuilder<'a, T> {
     fn drop(&mut self) {
         unsafe {
             ui_container_args_free(self.args);
@@ -268,9 +268,9 @@ impl<'a> Drop for ContainerBuilder<'a> {
 
 pub type FrameCreate = fn(*mut UiObject, *const UiFrameArgs);
 
-pub struct FrameBuilder<'a> {
+pub struct FrameBuilder<'a, T> {
     args: *mut UiFrameArgs,
-    obj: &'a mut toolkit::UiObject,
+    obj: &'a mut toolkit::UiObject<T>,
     create: FrameCreate
 }
 
@@ -292,12 +292,12 @@ fn scrolledwindow_create(obj: *mut UiObject, args: *const UiFrameArgs) {
     }
 }
 
-impl toolkit::UiObject {
+impl<T> toolkit::UiObject<T> {
     container_fn!(frame, frame_builder, FrameBuilder);
     container_fn!(expander, expander_builder, FrameBuilder);
     container_fn!(scrolledwindow, scrolledwindow_builder, FrameBuilder);
 
-    pub fn frame_builder(&mut self) -> FrameBuilder<'_>
+    pub fn frame_builder(&mut self) -> FrameBuilder<'_, T>
     {
         unsafe {
             let args = ui_frame_args_new();
@@ -309,7 +309,7 @@ impl toolkit::UiObject {
         }
     }
 
-    pub fn expander_builder(&mut self) -> FrameBuilder<'_>
+    pub fn expander_builder(&mut self) -> FrameBuilder<'_, T>
     {
         unsafe {
             let args = ui_frame_args_new();
@@ -321,7 +321,7 @@ impl toolkit::UiObject {
         }
     }
 
-    pub fn scrolledwindow_builder(&mut self) -> FrameBuilder<'_>
+    pub fn scrolledwindow_builder(&mut self) -> FrameBuilder<'_, T>
     {
         unsafe {
             let args = ui_frame_args_new();
@@ -334,9 +334,9 @@ impl toolkit::UiObject {
     }
 }
 
-impl<'a> FrameBuilder<'a> {
+impl<'a, T> FrameBuilder<'a, T> {
     pub fn create<F>(&mut self, create_ui: F)
-    where F: FnOnce(&mut toolkit::UiObject) {
+    where F: FnOnce(&mut toolkit::UiObject<T>) {
         (self.create)(self.obj.ptr, self.args);
         create_ui(self.obj);
         unsafe {
@@ -496,7 +496,7 @@ impl<'a> FrameBuilder<'a> {
     }
 }
 
-impl<'a> Drop for FrameBuilder<'a> {
+impl<'a, T> Drop for FrameBuilder<'a, T> {
     fn drop(&mut self) {
         unsafe {
             ui_frame_args_free(self.args);
@@ -509,9 +509,9 @@ impl<'a> Drop for FrameBuilder<'a> {
 
 pub type SplitpaneCreate = fn(*mut UiObject, *const UiSplitPaneArgs );
 
-pub struct SplitPaneBuilder<'a> {
+pub struct SplitPaneBuilder<'a, T> {
     args: *mut UiSplitPaneArgs,
-    obj: &'a mut toolkit::UiObject,
+    obj: &'a mut toolkit::UiObject<T>,
     create: SplitpaneCreate
 }
 
@@ -528,11 +528,11 @@ fn vsplitpane_create(obj: *mut UiObject, args: *const UiSplitPaneArgs) {
 }
 
 
-impl toolkit::UiObject {
+impl<T> toolkit::UiObject<T> {
     container_fn!(hsplitpane, hsplitpane_builder, SplitPaneBuilder);
     container_fn!(vsplitpane, vsplitpane_builder, SplitPaneBuilder);
 
-    pub fn hsplitpane_builder(&mut self) -> SplitPaneBuilder<'_>
+    pub fn hsplitpane_builder(&mut self) -> SplitPaneBuilder<'_, T>
     {
         unsafe {
             let args = ui_splitpane_args_new();
@@ -544,7 +544,7 @@ impl toolkit::UiObject {
         }
     }
 
-    pub fn vsplitpane_builder(&mut self) -> SplitPaneBuilder<'_>
+    pub fn vsplitpane_builder(&mut self) -> SplitPaneBuilder<'_, T>
     {
         unsafe {
             let args = ui_splitpane_args_new();
@@ -557,9 +557,9 @@ impl toolkit::UiObject {
     }
 }
 
-impl<'a> SplitPaneBuilder<'a> {
+impl<'a, T> SplitPaneBuilder<'a, T> {
     pub fn create<F>(&mut self, create_ui: F)
-    where F: FnOnce(&mut toolkit::UiObject) {
+    where F: FnOnce(&mut toolkit::UiObject<T>) {
         (self.create)(self.obj.ptr, self.args);
         create_ui(self.obj);
         unsafe {
@@ -697,7 +697,7 @@ impl<'a> SplitPaneBuilder<'a> {
     }
 }
 
-impl<'a> Drop for SplitPaneBuilder<'a> {
+impl<'a, T> Drop for SplitPaneBuilder<'a, T> {
     fn drop(&mut self) {
         unsafe {
             ui_splitpane_args_free(self.args);
@@ -711,9 +711,9 @@ impl<'a> Drop for SplitPaneBuilder<'a> {
 
 pub type SidebarCreate = fn(*mut UiObject, *const UiSidebarArgs );
 
-pub struct SidebarBuilder<'a> {
+pub struct SidebarBuilder<'a, T> {
     args: *mut UiSidebarArgs,
-    obj: &'a mut toolkit::UiObject,
+    obj: &'a mut toolkit::UiObject<T>,
     create: SidebarCreate
 }
 
@@ -736,10 +736,10 @@ fn right_panel_create(obj: *mut UiObject, args: *const UiSidebarArgs) {
 }
 
 
-impl toolkit::UiObject {
+impl<T> toolkit::UiObject<T> {
     container_fn!(sidebar, sidebar_builder, SidebarBuilder);
 
-    pub fn sidebar_builder(&mut self) -> SidebarBuilder<'_>
+    pub fn sidebar_builder(&mut self) -> SidebarBuilder<'_, T>
     {
         unsafe {
             let args = ui_sidebar_args_new();
@@ -751,7 +751,7 @@ impl toolkit::UiObject {
         }
     }
 
-    pub fn left_panel_builder(&mut self) -> SidebarBuilder<'_>
+    pub fn left_panel_builder(&mut self) -> SidebarBuilder<'_, T>
     {
         unsafe {
             let args = ui_sidebar_args_new();
@@ -763,7 +763,7 @@ impl toolkit::UiObject {
         }
     }
 
-    pub fn right_panel_builder(&mut self) -> SidebarBuilder<'_>
+    pub fn right_panel_builder(&mut self) -> SidebarBuilder<'_, T>
     {
         unsafe {
             let args = ui_sidebar_args_new();
@@ -776,9 +776,9 @@ impl toolkit::UiObject {
     }
 }
 
-impl<'a> SidebarBuilder<'a> {
+impl<'a, T> SidebarBuilder<'a, T> {
     pub fn create<F>(&mut self, create_ui: F)
-    where F: FnOnce(&mut toolkit::UiObject) {
+    where F: FnOnce(&mut toolkit::UiObject<T>) {
         (self.create)(self.obj.ptr, self.args);
         create_ui(self.obj);
         unsafe {
@@ -846,7 +846,7 @@ impl<'a> SidebarBuilder<'a> {
     }
 }
 
-impl<'a> Drop for SidebarBuilder<'a> {
+impl<'a, T> Drop for SidebarBuilder<'a, T> {
     fn drop(&mut self) {
         unsafe {
             ui_sidebar_args_free(self.args);
@@ -858,19 +858,19 @@ impl<'a> Drop for SidebarBuilder<'a> {
 
 /* -------------------------------- Tabview Container -------------------------------- */
 
-pub struct TabViewBuilder<'a> {
+pub struct TabViewBuilder<'a, T> {
     args: *mut UiTabViewArgs,
-    obj: &'a mut toolkit::UiObject
+    obj: &'a mut toolkit::UiObject<T>
 }
 
-pub struct TabBuilder<'a>  {
-    obj: &'a mut toolkit::UiObject
+pub struct TabBuilder<'a, T>  {
+    obj: &'a mut toolkit::UiObject<T>
 }
 
-impl<'a> TabBuilder<'a> {
+impl<'a, T> TabBuilder<'a, T> {
     pub fn tab<F>(&mut self, title: &str, create_ui: F)
     where
-        F: FnOnce(&mut toolkit::UiObject)
+        F: FnOnce(&mut toolkit::UiObject<T>)
     {
         unsafe {
             let title = CString::new(title).unwrap();
@@ -884,17 +884,17 @@ impl<'a> TabBuilder<'a> {
     }
 }
 
-impl toolkit::UiObject {
+impl<T> toolkit::UiObject<T> {
     pub fn tabview<F, U>(&mut self, build: F, ui: U)
     where
-    F: Fn(&mut TabViewBuilder),
-    U: FnOnce(&mut TabBuilder) {
+    F: Fn(&mut TabViewBuilder<T>),
+    U: FnOnce(&mut TabBuilder<T>) {
         let mut builder = self.tabview_builder();
         build(&mut builder);
         builder.create(ui);
     }
 
-    pub fn tabview_builder(&mut self) -> TabViewBuilder<'_>
+    pub fn tabview_builder(&mut self) -> TabViewBuilder<'_, T>
     {
         unsafe {
             let args = ui_tabview_args_new();
@@ -906,9 +906,9 @@ impl toolkit::UiObject {
     }
 }
 
-impl<'a> TabViewBuilder<'a> {
+impl<'a, T> TabViewBuilder<'a, T> {
     pub fn create<F>(&mut self, create_ui: F)
-    where F: FnOnce(&mut TabBuilder) {
+    where F: FnOnce(&mut TabBuilder<T>) {
         unsafe {
             ui_tabview_create(self.obj.ptr, self.args);
         }
index 59be48813cf6135b2dcc6492f805c62840d91fa4..54710a4f82479a9e0ccf9fa603d4ce4ab48f1401 100644 (file)
@@ -15,7 +15,7 @@ pub struct TextAreaBuilder {
     obj: *const UiObject
 }
 
-impl toolkit::UiObject {
+impl<T> toolkit::UiObject<T> {
     widget_fn!(textarea, textarea_builder, TextAreaBuilder);
 
     pub fn textarea_builder(&self) -> TextAreaBuilder {
@@ -194,7 +194,7 @@ pub fn frameless_textfield_create(obj: *const UiObject, args: *const UiTextField
     }
 }
 
-impl toolkit::UiObject {
+impl<T> toolkit::UiObject<T> {
     widget_fn!(textfield, textfield_builder, TextFieldBuilder);
     widget_fn!(passwordfield, passwordfield_builder, TextFieldBuilder);
     widget_fn!(frameless_textfield, frameless_textfield_builder, TextFieldBuilder);
index 35c62e02fa878c5159adf74243a6de70ef5f7fc9..07d093874d8b58499e3cbb5f74183202f342e9d6 100644 (file)
@@ -3,8 +3,11 @@
 use std::ffi::{c_char, c_int, CStr, CString};
 use crate::ui::ffi;
 
-pub struct UiObject {
-    pub ptr: *mut ffi::UiObject
+use std::marker::PhantomData;
+
+pub struct UiObject<T> {
+    pub ptr: *mut ffi::UiObject,
+    pub _data: PhantomData<T>
 }
 
 pub struct UiText {
index 8a5f113b0d0ff39ba4d56345245ed1d118ab652d..ec01779dc98147bd1e8ff4c6fac3d0d28d45b0d8 100644 (file)
@@ -3,6 +3,7 @@
 
 use std::ffi::{c_char, c_int, c_void};
 use std::ffi::CString;
+use std::marker::PhantomData;
 use crate::ui::toolkit;
 use crate::ui::ffi::UiObject;
 
@@ -14,9 +15,12 @@ extern "C" {
 
 
     fn ui_show(ui: *const UiObject);
+
+    fn ui_object_get_windowdata(obj: *const UiObject) -> *mut c_void;
+    fn ui_object_set_windowdata(obj: *mut UiObject, data: *mut c_void);
 }
 
-impl toolkit::UiObject {
+impl<T> toolkit::UiObject<T> {
     pub fn show(&self) {
         unsafe {
             ui_show(self.ptr);
@@ -31,34 +35,55 @@ enum WindowType {
     Simple
 }
 
-fn window_create(title: &str, kind: WindowType) -> toolkit::UiObject {
-    unsafe {
+fn window_create<T, F>(title: &str, kind: WindowType, mut data: T, create_ui: F) -> toolkit::UiObject<T>
+where F: FnOnce(&mut toolkit::UiObject<T>, &mut T) {
+    // create the window
+    let objptr = unsafe {
         let str = CString::new(title).unwrap();
-
-        let objptr = match kind {
+        match kind {
             WindowType::SplitView(val) => ui_splitview_window(str.as_ptr(), val as c_int),
             WindowType::Sidebar => ui_sidebar_window(str.as_ptr()),
             WindowType::Standard => ui_window(str.as_ptr()),
             WindowType::Simple => ui_simple_window(str.as_ptr())
-        };
+        }
+    };
 
-        toolkit::UiObject { ptr: objptr }
+    // create local UiObject
+    let mut obj = toolkit::UiObject::<T> { ptr: objptr, _data: PhantomData };
+
+    // call ui building closure
+    create_ui(&mut obj, &mut data);
+
+    // store windowdata object in the UiObject
+    let window_data = Box::new(data);
+    let wdata_ptr = Box::into_raw(window_data);
+    unsafe {
+        ui_object_set_windowdata(objptr, wdata_ptr as *mut c_void);
     }
+    obj
 }
 
-pub fn window(title: &str) -> toolkit::UiObject {
-    return window_create(title, WindowType::Standard);
+pub fn window<T, F>(title: &str, data: T, create_ui: F) -> toolkit::UiObject<T>
+where F: FnOnce(&mut toolkit::UiObject<T>, &mut T)
+{
+    window_create(title, WindowType::Standard, data, create_ui)
 }
 
-pub fn sidebar_window(title: &str) -> toolkit::UiObject {
-    return window_create(title, WindowType::Sidebar);
+pub fn sidebar_window<T, F>(title: &str, data: T, create_ui: F) -> toolkit::UiObject<T>
+where F: FnOnce(&mut toolkit::UiObject<T>, &mut T)
+{
+    window_create(title, WindowType::Sidebar, data, create_ui)
 }
 
-pub fn splitview_window(title: &str, sidebar: bool) -> toolkit::UiObject {
-    return window_create(title, WindowType::SplitView(sidebar));
+pub fn splitview_window<T, F>(title: &str, sidebar: bool, data: T, create_ui: F) -> toolkit::UiObject<T>
+where F: FnOnce(&mut toolkit::UiObject<T>, &mut T)
+{
+    window_create(title, WindowType::SplitView(sidebar), data, create_ui)
 }
 
-pub fn simple_window(title: &str) -> toolkit::UiObject {
-    return window_create(title, WindowType::Simple);
+pub fn simple_window<T, F>(title: &str, data: T, create_ui: F) -> toolkit::UiObject<T>
+where F: FnOnce(&mut toolkit::UiObject<T>, &mut T)
+{
+    window_create(title, WindowType::Simple, data, create_ui)
 }