From: Olaf Wintermann Date: Sun, 12 Apr 2026 14:47:51 +0000 (+0200) Subject: refactor window creation and add window data object X-Git-Url: https://uap-core.de/gitweb/?a=commitdiff_plain;h=75399945ac08f05a08a20bd1cf00626c7aba7e23;p=note.git refactor window creation and add window data object --- diff --git a/application/src/main.rs b/application/src/main.rs index a1b0279..f2d9840 100644 --- a/application/src/main.rs +++ b/application/src/main.rs @@ -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(); } } diff --git a/ui-rs/src/ui/button.rs b/ui-rs/src/ui/button.rs index d88407a..ab6dd11 100644 --- a/ui-rs/src/ui/button.rs +++ b/ui-rs/src/ui/button.rs @@ -27,7 +27,7 @@ pub enum LabelType { pub type ToggleButtonCreate = fn(*const UiObject, *const UiToggleArgs); -impl toolkit::UiObject { +impl toolkit::UiObject { widget_fn!(button, button_builder, ButtonBuilder); widget_fn!(togglebutton, togglebutton_builder, ToggleBuilder); widget_fn!(checkbox, checkbox_builder, ToggleBuilder); diff --git a/ui-rs/src/ui/container.rs b/ui-rs/src/ui/container.rs index 05aadd8..359fe64 100644 --- a/ui-rs/src/ui/container.rs +++ b/ui-rs/src/ui/container.rs @@ -10,8 +10,8 @@ macro_rules! container_fn { ($fn_name:ident, $builder_fn:ident, $builder_ty:ident) => { pub fn $fn_name(&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) { 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 = fn(obj: &toolkit::UiObject); -pub struct ContainerBuilder<'a> { +pub struct ContainerBuilder<'a, T> { args: *mut UiContainerArgs, - obj: &'a mut toolkit::UiObject, + obj: &'a mut toolkit::UiObject, create: ContainerCreate } @@ -66,12 +66,12 @@ fn grid_create(obj: *mut UiObject, args: *const UiContainerArgs) { } } -impl toolkit::UiObject { +impl toolkit::UiObject { 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(&mut self, create_ui: F) - where F: FnOnce(&mut toolkit::UiObject) { + where F: FnOnce(&mut toolkit::UiObject) { 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(&mut self, create_ui: F) - where F: FnOnce(&mut toolkit::UiObject) { + where F: FnOnce(&mut toolkit::UiObject) { (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, create: FrameCreate } @@ -292,12 +292,12 @@ fn scrolledwindow_create(obj: *mut UiObject, args: *const UiFrameArgs) { } } -impl toolkit::UiObject { +impl toolkit::UiObject { 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(&mut self, create_ui: F) - where F: FnOnce(&mut toolkit::UiObject) { + where F: FnOnce(&mut toolkit::UiObject) { (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, create: SplitpaneCreate } @@ -528,11 +528,11 @@ fn vsplitpane_create(obj: *mut UiObject, args: *const UiSplitPaneArgs) { } -impl toolkit::UiObject { +impl toolkit::UiObject { 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(&mut self, create_ui: F) - where F: FnOnce(&mut toolkit::UiObject) { + where F: FnOnce(&mut toolkit::UiObject) { (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, create: SidebarCreate } @@ -736,10 +736,10 @@ fn right_panel_create(obj: *mut UiObject, args: *const UiSidebarArgs) { } -impl toolkit::UiObject { +impl toolkit::UiObject { 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(&mut self, create_ui: F) - where F: FnOnce(&mut toolkit::UiObject) { + where F: FnOnce(&mut toolkit::UiObject) { (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 } -pub struct TabBuilder<'a> { - obj: &'a mut toolkit::UiObject +pub struct TabBuilder<'a, T> { + obj: &'a mut toolkit::UiObject } -impl<'a> TabBuilder<'a> { +impl<'a, T> TabBuilder<'a, T> { pub fn tab(&mut self, title: &str, create_ui: F) where - F: FnOnce(&mut toolkit::UiObject) + F: FnOnce(&mut toolkit::UiObject) { unsafe { let title = CString::new(title).unwrap(); @@ -884,17 +884,17 @@ impl<'a> TabBuilder<'a> { } } -impl toolkit::UiObject { +impl toolkit::UiObject { pub fn tabview(&mut self, build: F, ui: U) where - F: Fn(&mut TabViewBuilder), - U: FnOnce(&mut TabBuilder) { + F: Fn(&mut TabViewBuilder), + U: FnOnce(&mut TabBuilder) { 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(&mut self, create_ui: F) - where F: FnOnce(&mut TabBuilder) { + where F: FnOnce(&mut TabBuilder) { unsafe { ui_tabview_create(self.obj.ptr, self.args); } diff --git a/ui-rs/src/ui/text.rs b/ui-rs/src/ui/text.rs index 59be488..54710a4 100644 --- a/ui-rs/src/ui/text.rs +++ b/ui-rs/src/ui/text.rs @@ -15,7 +15,7 @@ pub struct TextAreaBuilder { obj: *const UiObject } -impl toolkit::UiObject { +impl toolkit::UiObject { 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 toolkit::UiObject { widget_fn!(textfield, textfield_builder, TextFieldBuilder); widget_fn!(passwordfield, passwordfield_builder, TextFieldBuilder); widget_fn!(frameless_textfield, frameless_textfield_builder, TextFieldBuilder); diff --git a/ui-rs/src/ui/toolkit.rs b/ui-rs/src/ui/toolkit.rs index 35c62e0..07d0938 100644 --- a/ui-rs/src/ui/toolkit.rs +++ b/ui-rs/src/ui/toolkit.rs @@ -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 { + pub ptr: *mut ffi::UiObject, + pub _data: PhantomData } pub struct UiText { diff --git a/ui-rs/src/ui/window.rs b/ui-rs/src/ui/window.rs index 8a5f113..ec01779 100644 --- a/ui-rs/src/ui/window.rs +++ b/ui-rs/src/ui/window.rs @@ -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 toolkit::UiObject { 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(title: &str, kind: WindowType, mut data: T, create_ui: F) -> toolkit::UiObject +where F: FnOnce(&mut toolkit::UiObject, &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:: { 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(title: &str, data: T, create_ui: F) -> toolkit::UiObject +where F: FnOnce(&mut toolkit::UiObject, &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(title: &str, data: T, create_ui: F) -> toolkit::UiObject +where F: FnOnce(&mut toolkit::UiObject, &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(title: &str, sidebar: bool, data: T, create_ui: F) -> toolkit::UiObject +where F: FnOnce(&mut toolkit::UiObject, &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(title: &str, data: T, create_ui: F) -> toolkit::UiObject +where F: FnOnce(&mut toolkit::UiObject, &mut T) +{ + window_create(title, WindowType::Simple, data, create_ui) }