From: Olaf Wintermann Date: Fri, 3 Apr 2026 15:20:16 +0000 (+0200) Subject: refactor widget creation functions X-Git-Url: https://uap-core.de/gitweb/?a=commitdiff_plain;h=4d2bdd60223ceaad137328fb24e5626e23d7d674;p=note.git refactor widget creation functions --- diff --git a/application/src/main.rs b/application/src/main.rs index 3f3e2ce..5ade671 100644 --- a/application/src/main.rs +++ b/application/src/main.rs @@ -12,12 +12,29 @@ struct App; impl ui::Application for App { fn on_startup(&self) { let mut obj = ui::window("note"); - obj.button().label("Hello").build(); - obj.hbox().build(|obj| { - obj.button().label("HButton 1").build(); - obj.button().label("HButton 2").build(); - obj.button().label("HButton 3").build(); + obj.button(|b| { + b.label("Hello"); }); + obj.hbox_builder().build(|obj| { + obj.button(|b|{ + b.label("HButton 1"); + }); + obj.button(|b|{ + b.label("HButton 2"); + }); + obj.button(|b|{ + b.label("HButton 3"); + }); + }); + + obj.hbox(|_b| { + + }, + |obj| { + obj.button(|b|{ b.label("HButton X1"); }); + obj.button(|b|{ b.label("HButton X2"); }); + }); + obj.show(); } } diff --git a/ui-rs/src/ui/button.rs b/ui-rs/src/ui/button.rs index 0180f16..c61fad0 100644 --- a/ui-rs/src/ui/button.rs +++ b/ui-rs/src/ui/button.rs @@ -3,8 +3,9 @@ use std::ffi::{c_char, c_int, c_void}; use std::ffi::CString; -use crate::ui::toolkit; +use crate::ui::{toolkit}; use crate::ui::ffi::*; +use crate::ui::widget::widget_fn; extern "C" { fn ui_button_create(obj: *const UiObject, args: *const UiButtonArgs); @@ -91,35 +92,43 @@ pub enum LabelType { pub type ToggleButtonCreate = fn(*const UiObject, *const UiToggleArgs); impl toolkit::UiObject { - pub fn button(&self) -> ButtonBuilder { + widget_fn!(button, button_builder, ButtonBuilder); + widget_fn!(togglebutton, togglebutton_builder, ToggleBuilder); + widget_fn!(checkbox, checkbox_builder, ToggleBuilder); + widget_fn!(switch, switch_builder, ToggleBuilder); + widget_fn!(radiobutton, radiobutton_builder, ToggleBuilder); + + pub fn button_builder(&self) -> ButtonBuilder { unsafe { let args = ui_button_args_new(); ButtonBuilder { args: args, obj: self.ptr } } } - pub fn togglebutton(&self) -> ToggleBuilder { + pub fn togglebutton_builder(&self) -> ToggleBuilder { unsafe { let args = ui_toggle_args_new(); ToggleBuilder { args: args, obj: self.ptr, create: togglebutton_create } } } - pub fn checkbox(&self) -> ToggleBuilder { + + + pub fn checkbox_builder(&self) -> ToggleBuilder { unsafe { let args = ui_toggle_args_new(); ToggleBuilder { args: args, obj: self.ptr, create: checkbox_create } } } - pub fn switch(&self) -> ToggleBuilder { + pub fn switch_builder(&self) -> ToggleBuilder { unsafe { let args = ui_toggle_args_new(); ToggleBuilder { args: args, obj: self.ptr, create: switch_create } } } - pub fn radiobutton(&self) -> ToggleBuilder { + pub fn radiobutton_builder(&self) -> ToggleBuilder { unsafe { let args = ui_toggle_args_new(); ToggleBuilder { args: args, obj: self.ptr, create: radiobutton_create } @@ -168,104 +177,104 @@ impl Drop for ToggleBuilder { } impl ButtonBuilder { - pub fn build(self) { + pub fn build(&mut self) { unsafe { ui_button_create(self.obj, self.args); } } - pub fn fill(self, fill: bool) -> Self { + pub fn fill(&mut self, fill: bool) -> &mut Self { unsafe { ui_button_args_set_fill(self.args, if fill { 1 } else { 0 }); } self } - pub fn hexpand(self, value: bool) -> Self { + pub fn hexpand(&mut self, value: bool) -> &mut Self { unsafe { ui_button_args_set_hexpand(self.args, if value { 1 } else { 0 }); } self } - pub fn vexpand(self, value: bool) -> Self { + pub fn vexpand(&mut self, value: bool) -> &mut Self { unsafe { ui_button_args_set_vexpand(self.args, if value { 1 } else { 0 }); } self } - pub fn hfill(self, value: bool) -> Self { + pub fn hfill(&mut self, value: bool) -> &mut Self { unsafe { ui_button_args_set_hfill(self.args, if value { 1 } else { 0 }); } self } - pub fn vfill(self, value: bool) -> Self { + pub fn vfill(&mut self, value: bool) -> &mut Self { unsafe { ui_button_args_set_vfill(self.args, if value { 1 } else { 0 }); } self } - pub fn override_defaults(self, value: bool) -> Self { + pub fn override_defaults(&mut self, value: bool) -> &mut Self { unsafe { ui_button_args_set_override_defaults(self.args, if value { 1 } else { 0 }); } self } - pub fn margin(self, value: i32) -> Self { + pub fn margin(&mut self, value: i32) -> &mut Self { unsafe { ui_button_args_set_margin(self.args, value); } self } - pub fn margin_left(self, value: i32) -> Self { + pub fn margin_left(&mut self, value: i32) -> &mut Self { unsafe { ui_button_args_set_margin_left(self.args, value); } self } - pub fn margin_right(self, value: i32) -> Self { + pub fn margin_right(&mut self, value: i32) -> &mut Self { unsafe { ui_button_args_set_margin_right(self.args, value); } self } - pub fn margin_top(self, value: i32) -> Self { + pub fn margin_top(&mut self, value: i32) -> &mut Self { unsafe { ui_button_args_set_margin_top(self.args, value); } self } - pub fn margin_bottom(self, value: i32) -> Self { + pub fn margin_bottom(&mut self, value: i32) -> &mut Self { unsafe { ui_button_args_set_margin_bottom(self.args, value); } self } - pub fn colspan(self, value: i32) -> Self { + pub fn colspan(&mut self, value: i32) -> &mut Self { unsafe { ui_button_args_set_colspan(self.args, value); } self } - pub fn rowspan(self, value: i32) -> Self { + pub fn rowspan(&mut self, value: i32) -> &mut Self { unsafe { ui_button_args_set_rowspan(self.args, value); } self } - pub fn name(self, value: &str) -> Self { + pub fn name(&mut self, value: &str) -> &mut Self { let cstr = CString::new(value).unwrap(); unsafe { ui_button_args_set_name(self.args, cstr.as_ptr()); @@ -273,7 +282,7 @@ impl ButtonBuilder { self } - pub fn style_class(self, value: &str) -> Self { + pub fn style_class(&mut self, value: &str) -> &mut Self { let cstr = CString::new(value).unwrap(); unsafe { ui_button_args_set_style_class(self.args, cstr.as_ptr()); @@ -281,7 +290,7 @@ impl ButtonBuilder { self } - pub fn label(self, label: &str) -> Self { + pub fn label(&mut self, label: &str) -> &mut Self { let cstr = CString::new(label).unwrap(); unsafe { ui_button_args_set_label(self.args, cstr.as_ptr()); @@ -289,7 +298,7 @@ impl ButtonBuilder { self } - pub fn icon(self, icon: &str) -> Self { + pub fn icon(&mut self, icon: &str) -> &mut Self { let cstr = CString::new(icon).unwrap(); unsafe { ui_button_args_set_label(self.args, cstr.as_ptr()); @@ -297,7 +306,7 @@ impl ButtonBuilder { self } - pub fn tooltip(self, tooltip: &str) -> Self { + pub fn tooltip(&mut self, tooltip: &str) -> &mut Self { let cstr = CString::new(tooltip).unwrap(); unsafe { ui_button_args_set_tooltip(self.args, cstr.as_ptr()); @@ -305,7 +314,7 @@ impl ButtonBuilder { self } - pub fn labeltype(self, ltype: LabelType) -> Self { + pub fn labeltype(&mut self, ltype: LabelType) -> &mut Self { let lt = ltype as i32; unsafe { ui_button_args_set_labeltype(self.args, lt); @@ -317,102 +326,102 @@ impl ButtonBuilder { } impl ToggleBuilder { - pub fn build(self) { + pub fn build(&mut self) { (self.create)(self.obj, self.args) } - pub fn fill(self, fill: bool) -> Self { + pub fn fill(&mut self, fill: bool) -> &mut Self { unsafe { ui_toggle_args_set_fill(self.args, if fill { 1 } else { 0 }); } self } - pub fn hexpand(self, value: bool) -> Self { + pub fn hexpand(&mut self, value: bool) -> &mut Self { unsafe { ui_toggle_args_set_hexpand(self.args, if value { 1 } else { 0 }); } self } - pub fn vexpand(self, value: bool) -> Self { + pub fn vexpand(&mut self, value: bool) -> &mut Self { unsafe { ui_toggle_args_set_vexpand(self.args, if value { 1 } else { 0 }); } self } - pub fn hfill(self, value: bool) -> Self { + pub fn hfill(&mut self, value: bool) -> &mut Self { unsafe { ui_toggle_args_set_hfill(self.args, if value { 1 } else { 0 }); } self } - pub fn vfill(self, value: bool) -> Self { + pub fn vfill(&mut self, value: bool) -> &mut Self { unsafe { ui_toggle_args_set_vfill(self.args, if value { 1 } else { 0 }); } self } - pub fn override_defaults(self, value: bool) -> Self { + pub fn override_defaults(&mut self, value: bool) -> &mut Self { unsafe { ui_toggle_args_set_override_defaults(self.args, if value { 1 } else { 0 }); } self } - pub fn margin(self, value: i32) -> Self { + pub fn margin(&mut self, value: i32) -> &mut Self { unsafe { ui_toggle_args_set_margin(self.args, value); } self } - pub fn margin_left(self, value: i32) -> Self { + pub fn margin_left(&mut self, value: i32) -> &mut Self { unsafe { ui_toggle_args_set_margin_left(self.args, value); } self } - pub fn margin_right(self, value: i32) -> Self { + pub fn margin_right(&mut self, value: i32) -> &mut Self { unsafe { ui_toggle_args_set_margin_right(self.args, value); } self } - pub fn margin_top(self, value: i32) -> Self { + pub fn margin_top(&mut self, value: i32) -> &mut Self { unsafe { ui_toggle_args_set_margin_top(self.args, value); } self } - pub fn margin_bottom(self, value: i32) -> Self { + pub fn margin_bottom(&mut self, value: i32) -> &mut Self { unsafe { ui_toggle_args_set_margin_bottom(self.args, value); } self } - pub fn colspan(self, value: i32) -> Self { + pub fn colspan(&mut self, value: i32) -> &mut Self { unsafe { ui_toggle_args_set_colspan(self.args, value); } self } - pub fn rowspan(self, value: i32) -> Self { + pub fn rowspan(&mut self, value: i32) -> &mut Self { unsafe { ui_toggle_args_set_rowspan(self.args, value); } self } - pub fn name(self, value: &str) -> Self { + pub fn name(&mut self, value: &str) -> &mut Self { let cstr = CString::new(value).unwrap(); unsafe { ui_toggle_args_set_name(self.args, cstr.as_ptr()); @@ -420,7 +429,7 @@ impl ToggleBuilder { self } - pub fn style_class(self, value: &str) -> Self { + pub fn style_class(&mut self, value: &str) -> &mut Self { let cstr = CString::new(value).unwrap(); unsafe { ui_toggle_args_set_style_class(self.args, cstr.as_ptr()); @@ -428,7 +437,7 @@ impl ToggleBuilder { self } - pub fn label(self, label: &str) -> Self { + pub fn label(&mut self, label: &str) -> &mut Self { let cstr = CString::new(label).unwrap(); unsafe { ui_toggle_args_set_label(self.args, cstr.as_ptr()); @@ -436,7 +445,7 @@ impl ToggleBuilder { self } - pub fn icon(self, icon: &str) -> Self { + pub fn icon(&mut self, icon: &str) -> &mut Self { let cstr = CString::new(icon).unwrap(); unsafe { ui_toggle_args_set_label(self.args, cstr.as_ptr()); @@ -444,7 +453,7 @@ impl ToggleBuilder { self } - pub fn tooltip(self, tooltip: &str) -> Self { + pub fn tooltip(&mut self, tooltip: &str) -> &mut Self { let cstr = CString::new(tooltip).unwrap(); unsafe { ui_toggle_args_set_tooltip(self.args, cstr.as_ptr()); @@ -452,7 +461,7 @@ impl ToggleBuilder { self } - pub fn labeltype(self, ltype: LabelType) -> Self { + pub fn labeltype(&mut self, ltype: LabelType) -> &mut Self { let lt = ltype as i32; unsafe { ui_toggle_args_set_labeltype(self.args, lt); @@ -460,7 +469,7 @@ impl ToggleBuilder { self } - pub fn varname(self, varname: &str) -> Self { + pub fn varname(&mut self, varname: &str) -> &mut Self { let cstr = CString::new(varname).unwrap(); unsafe { ui_toggle_args_set_varname(self.args, cstr.as_ptr()); @@ -468,11 +477,11 @@ impl ToggleBuilder { self } - pub fn value(self, value: &toolkit::UiInteger) { + pub fn value(&mut self, value: &toolkit::UiInteger) { unsafe { ui_toggle_args_set_value(self.args, value.ptr); } } - // TODO: value, callback, states + // TODO: callback, states } \ No newline at end of file diff --git a/ui-rs/src/ui/container.rs b/ui-rs/src/ui/container.rs index 4a0aec2..637901a 100644 --- a/ui-rs/src/ui/container.rs +++ b/ui-rs/src/ui/container.rs @@ -5,6 +5,20 @@ use std::ffi::{c_char, c_int, c_void}; use crate::ui::ffi::*; use crate::ui::{toolkit}; +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) + { + let mut builder = self.$builder_fn(); + build(&mut builder); + builder.build(ui); + } + }; +} + extern "C" { fn ui_container_begin_close(obj: *mut UiObject); fn ui_container_finish(obj: *mut UiObject) -> c_int; @@ -66,7 +80,10 @@ fn grid_create(obj: *mut UiObject, args: *const UiContainerArgs) { } impl toolkit::UiObject { - pub fn vbox(&mut self) -> ContainerBuilder + container_fn!(vbox, vbox_builder, ContainerBuilder); + container_fn!(hbox, hbox_builder, ContainerBuilder); + + pub fn vbox_builder(&mut self) -> ContainerBuilder { unsafe { let args = ui_container_args_new(); @@ -78,7 +95,7 @@ impl toolkit::UiObject { } } - pub fn hbox(&mut self) -> ContainerBuilder + pub fn hbox_builder(&mut self) -> ContainerBuilder { unsafe { let args = ui_container_args_new(); @@ -90,7 +107,7 @@ impl toolkit::UiObject { } } - pub fn grid(&mut self) -> ContainerBuilder + pub fn grid_builder(&mut self) -> ContainerBuilder { unsafe { let args = ui_container_args_new(); @@ -104,7 +121,7 @@ impl toolkit::UiObject { } impl<'a> ContainerBuilder<'a> { - pub fn build(self, create_ui: F) + pub fn build(&mut self, create_ui: F) where F: FnOnce(&mut toolkit::UiObject) { (self.create)(self.obj.ptr, self.args); create_ui(self.obj); diff --git a/ui-rs/src/ui/mod.rs b/ui-rs/src/ui/mod.rs index 0dba993..b6b6f5e 100644 --- a/ui-rs/src/ui/mod.rs +++ b/ui-rs/src/ui/mod.rs @@ -4,6 +4,7 @@ mod application; mod window; mod button; mod container; +mod widget; pub use toolkit::*; pub use application::*; diff --git a/ui-rs/src/ui/widget.rs b/ui-rs/src/ui/widget.rs new file mode 100644 index 0000000..ca383d5 --- /dev/null +++ b/ui-rs/src/ui/widget.rs @@ -0,0 +1,29 @@ +/* + * Create a closure-based widget creation function + * + * Example: + * pub fn button_builder(&self) -> ButtonBuilder { ... } + * widget_fn!(button, button_builder, ButtonBuilder); + * + * This creates a function + * pub fn button(&self, build: F) + * + * That can be used like: + * obj.button(|b| { + * b.label("Hello"); + * } + */ +macro_rules! widget_fn { + ($fn_name:ident, $builder_fn:ident, $builder_ty:ident) => { + pub fn $fn_name(&self, build: F) + where + F: Fn(&mut $builder_ty), + { + let mut builder = self.$builder_fn(); + build(&mut builder); + builder.build(); + } + }; +} + +pub(super) use widget_fn; \ No newline at end of file