From 3daf6d49132302cc644f0230d4a4a0e7091f6866 Mon Sep 17 00:00:00 2001 From: Olaf Wintermann Date: Thu, 16 Apr 2026 08:52:32 +0200 Subject: [PATCH] add init functions for UiInteger, UiString and UiText --- ui-rs/src/ui/ffi.rs | 5 ++ ui-rs/src/ui/toolkit.rs | 141 +++++++++++++++++++++++++--------------- 2 files changed, 95 insertions(+), 51 deletions(-) diff --git a/ui-rs/src/ui/ffi.rs b/ui-rs/src/ui/ffi.rs index c75f4a7..75aa128 100644 --- a/ui-rs/src/ui/ffi.rs +++ b/ui-rs/src/ui/ffi.rs @@ -47,6 +47,11 @@ pub struct UiList { _private: [u8; 0], } +#[repr(C)] +pub struct UiGeneric { + _private: [u8; 0], +} + #[repr(C)] pub struct UiListSelection { _private: [u8; 0], diff --git a/ui-rs/src/ui/toolkit.rs b/ui-rs/src/ui/toolkit.rs index d550975..01c3760 100644 --- a/ui-rs/src/ui/toolkit.rs +++ b/ui-rs/src/ui/toolkit.rs @@ -91,57 +91,6 @@ pub struct UiList { data: Box> } -impl UiList { - pub fn data(&mut self) -> &mut Vec { - self.data.as_mut() - } - - pub fn init(&mut self, ctx: &UiContext, name: Option<&str>) { - unsafe { - let c_string = name.map(|n| CString::new(n).unwrap()); - let c_str = c_string.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()); - let data: *mut Vec = &mut *self.data; - self.ptr = ui_list_new2(ctx.ptr, c_str, list_init::, data as *mut c_void); - } - } - - pub fn update(&mut self) { - unsafe { - ui_list_update(self.ptr); - } - } - - pub fn update_row(&mut self, row: i32) { - unsafe { - ui_list_update_row(self.ptr, row); - } - } - - pub fn selection(&mut self) -> Vec { - let mut sel = Vec::new(); - unsafe { - let selection = ui_list_get_selection_allocated(self.ptr); - let count = ui_list_selection_get_count(selection) as usize; - if count > 0 { - let indices = ui_list_selection_get_rows(selection); - sel.set_len(count as usize); - for i in 0..count { - sel.push(*indices.add(i) as i32); - } - } - ui_list_selection_free(selection); - } - sel - } - - pub fn set_selection(&mut self, sel: &Vec) { - unsafe { - ui_list_set_selected_indices(self.ptr, sel.as_ptr(), sel.len() as c_int); - } - } -} - - /* -------------------------------- Default implementation -------------------------------- */ macro_rules! value_default_impl { @@ -200,6 +149,14 @@ pub fn app_init(appname: &str) { } impl UiText { + pub fn init(&mut self, ctx: &UiContext, name: Option<&str>) { + let c_string = name.map(|n| CString::new(n).unwrap()); + let c_str = c_string.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()); + unsafe { + self.ptr = ui_text_new(ctx.ptr, c_str); + } + } + pub fn get(&self) -> String { unsafe { let cstr = ui_text_get(self.ptr); @@ -218,6 +175,13 @@ impl UiText { } impl UiString { + pub fn init(&mut self, ctx: &UiContext, name: Option<&str>) { + let c_string = name.map(|n| CString::new(n).unwrap()); + let c_str = c_string.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()); + unsafe { + self.ptr = ui_string_new(ctx.ptr, c_str); + } + } pub fn get(&self) -> String { unsafe { let cstr = ui_string_get(self.ptr); @@ -236,6 +200,14 @@ impl UiString { } impl UiInteger { + pub fn init(&mut self, ctx: &UiContext, name: Option<&str>) { + let c_string = name.map(|n| CString::new(n).unwrap()); + let c_str = c_string.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()); + unsafe { + self.ptr = ui_int_new(ctx.ptr, c_str); + } + } + pub fn get(&self) -> i64 { unsafe { ui_int_get(self.ptr) @@ -250,6 +222,67 @@ impl UiInteger { } +impl UiList { + pub fn data(&mut self) -> &mut Vec { + self.data.as_mut() + } + + pub fn init(&mut self, ctx: &UiContext, name: Option<&str>) { + let c_string = name.map(|n| CString::new(n).unwrap()); + let c_str = c_string.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()); + unsafe { + let data: *mut Vec = &mut *self.data; + self.ptr = ui_list_new2(ctx.ptr, c_str, list_init::, data as *mut c_void); + } + } + + pub fn update(&mut self) { + unsafe { + ui_list_update(self.ptr); + } + } + + pub fn update_row(&mut self, row: i32) { + unsafe { + ui_list_update_row(self.ptr, row); + } + } + + pub fn selection(&mut self) -> Vec { + let mut sel = Vec::new(); + unsafe { + let selection = ui_list_get_selection_allocated(self.ptr); + let count = ui_list_selection_get_count(selection) as usize; + if count > 0 { + let indices = ui_list_selection_get_rows(selection); + sel.set_len(count as usize); + for i in 0..count { + sel.push(*indices.add(i) as i32); + } + } + ui_list_selection_free(selection); + } + sel + } + + pub fn set_selection(&mut self, sel: &Vec) { + unsafe { + ui_list_set_selected_indices(self.ptr, sel.as_ptr(), sel.len() as c_int); + } + } +} + +impl Drop for UiList { + fn drop(&mut self) { + unsafe { + // This does not free the UiList pointer, because it could still be in use by + // UI elements, but it will have no reference to any object managed by Rust + ui_list_class_set_data(self.ptr, std::ptr::null_mut()); + } + } +} + + /* -------------------------------- List -------------------------------- */ /* @@ -337,6 +370,12 @@ type UiListGetFunc = extern "C" fn(*mut ffi::UiList, c_int) -> *mut c_void; type UiListCountFunc = extern "C" fn(*mut ffi::UiList) -> c_int; extern "C" { + fn ui_int_new(ctx: *mut ffi::UiContext, name: *const c_char) -> *mut ffi::UiInteger; + fn ui_double_new(ctx: *mut ffi::UiContext, name: *const c_char) -> *mut ffi::UiDouble; + fn ui_range_new(ctx: *mut ffi::UiContext, name: *const c_char) -> *mut ffi::UiRange; + fn ui_string_new(ctx: *mut ffi::UiContext, name: *const c_char) -> *mut ffi::UiString; + fn ui_text_new(ctx: *mut ffi::UiContext, name: *const c_char) -> *mut ffi::UiText; + fn ui_list_new2(ctx: *mut ffi::UiContext, name: *const c_char, init: UiListInitFunc, userdata: *mut c_void) -> *mut ffi::UiList; fn ui_list_class_set_first(list: *mut ffi::UiList, func: UiListFirstFunc); fn ui_list_class_set_next(list: *mut ffi::UiList, func: UiListNextFunc); -- 2.47.3