]> uap-core.de Git - note.git/commitdiff
add SourceListBuilder
authorOlaf Wintermann <olaf.wintermann@gmail.com>
Mon, 20 Apr 2026 19:01:07 +0000 (21:01 +0200)
committerOlaf Wintermann <olaf.wintermann@gmail.com>
Mon, 20 Apr 2026 19:01:07 +0000 (21:01 +0200)
application/src/main.rs
ui-rs/src/ui/application.rs
ui-rs/src/ui/ffi.rs
ui-rs/src/ui/list.rs

index 77dc750cd59c393687a7212b1739c7fd748394a4..45fdf7c237981a96c15cf70cf5d98a415197d4cb 100644 (file)
@@ -14,7 +14,9 @@ struct App;
 struct TestData {
     i: i32,
     #[bind("list")]
-    list: UiList<i32>
+    list: UiList<i32>,
+    #[bind]
+    sublists: UiList<SubList<String>>
 }
 
 #[ui_actions]
@@ -40,18 +42,19 @@ fn create_window() {
             e.data.i += 1;
         }).create();
         obj.button_builder().label("Action").action("my_action").create();
-        let mut model = TableModel::new();
-        model.add_column("Name", ColumnType::String, -1);
-        obj.tableview_builder::<i32>().fill(true).varname("list").model(&model).getvalue(|elm, _row, _col| {
-            ListValue::String(elm.to_string())
-        }).create();
+        //let mut model = TableModel::new();
+        //model.add_column("Name", ColumnType::String, -1);
+        //obj.tableview_builder::<i32>().fill(true).varname("list").model(&model).getvalue(|elm, _row, _col| {
+        //    ListValue::String(elm.to_string())
+        //}).create();
+        obj.sourcelist_builder::<String>().fill(true).value(&data.sublists).create();
     });
 
     window.show();
 }
 
 impl ui::Application for App {
-    fn on_startup(&self) {
+    fn on_startup(&mut self) {
         create_window();
     }
 }
index 275b3b853c318c5b2c13a770ba48173b98f88079..a3398421b9c18d5665ec92e771f849f93db9d8cb 100644 (file)
@@ -4,9 +4,9 @@ use std::ffi::{c_char, c_int, c_void, CString};
 use crate::ui::ffi::{UiCallback, UiEvent};
 
 pub trait Application {
-    fn on_startup(&self);
+    fn on_startup(&mut self);
 
-    fn on_exit(&self) { }
+    fn on_exit(&mut self) { }
 }
 
 
index 0bb02f2dcc160b893fad48461895a4a85ef43980..5a19f5bfb897cb8877f1b420e296a6950ad1de65 100644 (file)
@@ -57,6 +57,16 @@ pub struct UiListSelection {
     _private: [u8; 0],
 }
 
+#[repr(C)]
+pub struct UiSubListItem {
+    _private: [u8; 0],
+}
+
+#[repr(C)]
+pub struct UiMenuBuilder {
+    _private: [u8; 0],
+}
+
 pub type UiCallback = Option<extern "C" fn(event: *const UiEvent, *mut c_void)>;
 pub type UiDestructor = extern "C" fn(object: *mut c_void);
 
@@ -126,7 +136,17 @@ pub struct UiListArgs {
     _private: [u8; 0],
 }
 
+#[repr(C)]
+pub struct UiSourceListArgs {
+    _private: [u8; 0],
+}
+
 #[repr(C)]
 pub struct UiModel {
     _private: [u8; 0],
+}
+
+#[repr(C)]
+pub struct UiSubList {
+    _private: [u8; 0],
 }
\ No newline at end of file
index b878bce80c73ca0dc9fc6b10f10fb56e50ff885f..eee2c4c0fb41f8f5925b6a4c80b7e2332d54c4ae 100644 (file)
@@ -1,7 +1,7 @@
 #![allow(dead_code)]
 
-use crate::ui::ffi::{UiObject, UiListArgs, UiCallback, UiList};
-use crate::ui::{ffi, toolkit, ui_list_get, ui_list_get_data};
+use crate::ui::ffi::{UiObject, UiListArgs, UiCallback, UiList, UiSourceListArgs};
+use crate::ui::{event, ffi, toolkit, ui_list_get, ui_list_get_data, EventWrapper};
 use std::ffi::{c_char, c_int, c_void};
 use std::ffi::CString;
 use std::marker::PhantomData;
@@ -32,8 +32,19 @@ pub struct TableViewBuilder<'a, T, E> {
     _marker: PhantomData<E>
 }
 
+pub struct SourceListBuilder<'a, T, E> {
+    args: *mut UiSourceListArgs,
+    obj: &'a mut toolkit::UiObject<T>,
+    _marker: PhantomData<E>
+}
+
 pub struct TableModel {
-    pub handle: *mut ffi::UiModel,
+    handle: *mut ffi::UiModel,
+}
+
+pub struct SubList<T> {
+    handle: *mut ffi::UiSubList,
+    list: toolkit::UiList<T>
 }
 
 pub enum ColumnType {
@@ -52,6 +63,7 @@ pub type ListBuilderCreate = fn(*const UiObject, *const UiListArgs);
 impl<T> toolkit::UiObject<T> {
     widget_typed_fn!(listview, listview_builder, ListViewBuilder);
     widget_typed_fn!(tableview, tableview_builder, TableViewBuilder);
+    widget_typed_fn!(sourcelist, sourcelist_builder, SourceListBuilder);
 
     pub fn listview_builder<'a, E>(&'a mut self) -> ListViewBuilder<'a, T, E> {
         unsafe {
@@ -73,6 +85,13 @@ impl<T> toolkit::UiObject<T> {
             TableViewBuilder { args: args, obj: self, create: tableview_create, model: std::ptr::null_mut(), has_getvalue_func: false, _marker: PhantomData }
         }
     }
+    
+    pub fn sourcelist_builder<'a, E>(&'a mut self) -> SourceListBuilder<'a, T, E> {
+        unsafe {
+            let args = ui_sourcelist_args_new();
+            SourceListBuilder { args: args, obj: self, _marker: PhantomData }
+        }
+    }
 }
 
 fn list_create(obj: *const UiObject, args: *const UiListArgs) {
@@ -451,6 +470,189 @@ impl<'a, T, E> TableViewBuilder<'a, T, E> {
     }
 }
 
+impl<'a, T, E> SourceListBuilder<'a, T, E> {
+    pub fn create(&mut self) {
+        unsafe {
+            ui_sourcelist_create(self.obj.ptr, self.args);
+        }
+    }
+
+    pub fn fill(&mut self, fill: bool) -> &mut Self {
+        unsafe {
+            ui_sourcelist_args_set_fill(self.args, if fill { 1 } else { 0 });
+        }
+        self
+    }
+
+    pub fn hexpand(&mut self, value: bool) -> &mut Self {
+        unsafe {
+            ui_sourcelist_args_set_hexpand(self.args, if value { 1 } else { 0 });
+        }
+        self
+    }
+
+    pub fn vexpand(&mut self, value: bool) -> &mut Self {
+        unsafe {
+            ui_sourcelist_args_set_vexpand(self.args, if value { 1 } else { 0 });
+        }
+        self
+    }
+
+    pub fn hfill(&mut self, value: bool) -> &mut Self {
+        unsafe {
+            ui_sourcelist_args_set_hfill(self.args, if value { 1 } else { 0 });
+        }
+        self
+    }
+
+    pub fn vfill(&mut self, value: bool) -> &mut Self {
+        unsafe {
+            ui_sourcelist_args_set_vfill(self.args, if value { 1 } else { 0 });
+        }
+        self
+    }
+
+    pub fn override_defaults(&mut self, value: bool) -> &mut Self {
+        unsafe {
+            ui_sourcelist_args_set_override_defaults(self.args, if value { 1 } else { 0 });
+        }
+        self
+    }
+
+    pub fn margin(&mut self, value: i32) -> &mut Self {
+        unsafe {
+            ui_sourcelist_args_set_margin(self.args, value);
+        }
+        self
+    }
+
+    pub fn margin_left(&mut self, value: i32) -> &mut Self {
+        unsafe {
+            ui_sourcelist_args_set_margin_left(self.args, value);
+        }
+        self
+    }
+
+    pub fn margin_right(&mut self, value: i32) -> &mut Self {
+        unsafe {
+            ui_sourcelist_args_set_margin_right(self.args, value);
+        }
+        self
+    }
+
+    pub fn margin_top(&mut self, value: i32) -> &mut Self {
+        unsafe {
+            ui_sourcelist_args_set_margin_top(self.args, value);
+        }
+        self
+    }
+
+    pub fn margin_bottom(&mut self, value: i32) -> &mut Self {
+        unsafe {
+            ui_sourcelist_args_set_margin_bottom(self.args, value);
+        }
+        self
+    }
+
+    pub fn colspan(&mut self, value: i32) -> &mut Self {
+        unsafe {
+            ui_sourcelist_args_set_colspan(self.args, value);
+        }
+        self
+    }
+
+    pub fn rowspan(&mut self, value: i32) -> &mut Self {
+        unsafe {
+            ui_sourcelist_args_set_rowspan(self.args, value);
+        }
+        self
+    }
+
+    pub fn name(&mut self, value: &str) -> &mut Self {
+        let cstr = CString::new(value).unwrap();
+        unsafe {
+            ui_sourcelist_args_set_name(self.args, cstr.as_ptr());
+        }
+        self
+    }
+
+    pub fn style_class(&mut self, value: &str) -> &mut Self {
+        let cstr = CString::new(value).unwrap();
+        unsafe {
+            ui_sourcelist_args_set_style_class(self.args, cstr.as_ptr());
+        }
+        self
+    }
+
+    pub fn varname(&mut self, varname: &str) -> &mut Self {
+        let cstr = CString::new(varname).unwrap();
+        unsafe {
+            ui_sourcelist_args_set_varname(self.args, cstr.as_ptr());
+        }
+        self
+    }
+    pub fn value(&mut self, value: &toolkit::UiList<SubList<E>>) -> &mut Self {
+        unsafe {
+            ui_sourcelist_args_set_dynamic_sublists(self.args, value.ptr);
+        }
+        self
+    }
+
+    pub fn getvalue<F>(&mut self, f: F) -> &mut Self
+    where F: Fn(&E, i32, i32) -> ListValue<'a> + 'static {
+        unsafe {
+            let wrapper = Box::new(GetValueWrapper { callback: Box::new(f), is_table: false });
+            let ptr = self.obj.ctx.reg_box(wrapper);
+            ui_sourcelist_args_set_getvalue_func(self.args, sourcelist_getvalue_wrapper::<E>);
+            ui_sourcelist_args_set_getvalue_userdata(self.args, ptr as *mut c_void);
+        }
+        self
+    }
+
+    pub fn header_is_item(&mut self, value: bool) -> &mut Self {
+        unsafe {
+            ui_sourcelist_args_set_header_is_item(self.args, if value { 1 } else { 0 });
+        }
+        self
+    }
+
+    pub fn onactivate<F>(&mut self, f: F) -> &mut Self
+    where F: FnMut(&mut event::Event<T>) + 'static {
+        let wrapper = Box::new(EventWrapper { callback: Box::new(f) });
+        let ptr = self.obj.ctx.reg_box(wrapper);
+        unsafe {
+            ui_sourcelist_args_set_onactivate(self.args, Some(event::event_wrapper::<T>));
+            ui_sourcelist_args_set_onactivatedata(self.args, ptr as *mut c_void);
+        }
+        self
+    }
+
+    pub fn onbuttonclick<F>(&mut self, f: F) -> &mut Self
+    where F: FnMut(&mut event::Event<T>) + 'static {
+        let wrapper = Box::new(EventWrapper { callback: Box::new(f) });
+        let ptr = self.obj.ctx.reg_box(wrapper);
+        unsafe {
+            ui_sourcelist_args_set_onbuttonclick(self.args, Some(event::event_wrapper::<T>));
+            ui_sourcelist_args_set_onbuttonclickdata(self.args, ptr as *mut c_void);
+        }
+        self
+    }
+
+    pub fn visibility_states(&mut self, states: &[i32]) -> &mut Self {
+        unsafe {
+            ui_sourcelist_args_set_visibility_states(self.args, states.as_ptr(), states.len() as c_int);
+        }
+        self
+    }
+
+    pub fn states(&mut self, states: &[i32]) -> &mut Self {
+        unsafe {
+            ui_sourcelist_args_set_states(self.args, states.as_ptr(), states.len() as c_int);
+        }
+        self
+    }
+}
+
 
 // TableModel implementation
 
@@ -531,6 +733,25 @@ pub extern "C" fn null_getvalue_wrapper(_list: *const ffi::UiList, _elm_ptr: *co
     std::ptr::null_mut()
 }
 
+pub extern "C" fn sourcelist_getvalue_wrapper<T>(
+    _list: *const ffi::UiList,
+    _sublist_userdata: *mut c_void,
+    _row_data: *mut c_void,
+    _index: c_int,
+    _item: *mut ffi::UiSubListItem,
+    _userdata: *mut c_void)
+{
+    // TODO
+}
+
+type SLGetValueFunc = extern "C" fn(
+        list: *const ffi::UiList,
+        sublist_userdata: *mut c_void,
+        row_data: *mut c_void,
+        index: c_int,
+        item: *mut ffi::UiSubListItem,
+        userdata: *mut c_void);
+
 
 extern "C" {
     fn malloc(size: usize) -> *mut c_void;
@@ -538,6 +759,7 @@ extern "C" {
     fn ui_listview_create(obj: *const UiObject, args: *const UiListArgs);
     fn ui_dropdown_create(obj: *const UiObject, args: *const UiListArgs);
     fn ui_table_create(obj: *const UiObject, args: *const UiListArgs);
+    fn ui_sourcelist_create(obj: *const UiObject, args: *const UiSourceListArgs);
 
     fn ui_list_args_new() -> *mut UiListArgs;
     fn ui_list_args_set_fill(args: *mut UiListArgs, fill: c_int);
@@ -562,7 +784,6 @@ extern "C" {
     fn ui_list_args_set_model(args: *mut UiListArgs, model: *mut ffi::UiModel);
     fn ui_list_args_set_getvalue_func2(args: *mut UiListArgs, func: GetValueFunc);
     fn ui_list_args_set_getvalue_data(args: *mut UiListArgs, data: *mut c_void);
-    fn ui_list_args_set_enablestate(args: *mut UiListArgs, state: c_int);
     fn ui_list_args_set_states(args: *mut UiListArgs, states: *const c_int, numstates: c_int);
     fn ui_list_args_set_visibility_states(args: *mut UiListArgs, states: *const c_int, numstates: c_int);
     fn ui_list_args_free(args: *mut UiListArgs);
@@ -572,4 +793,33 @@ extern "C" {
     fn ui_model_ref(model: *mut ffi::UiModel);
     fn ui_model_unref(model: *mut ffi::UiModel);
 
+    fn ui_sourcelist_args_new() -> *mut UiSourceListArgs;
+    fn ui_sourcelist_args_set_fill(args: *mut UiSourceListArgs, fill: c_int);
+    fn ui_sourcelist_args_set_hexpand(args: *mut UiSourceListArgs, value: c_int);
+    fn ui_sourcelist_args_set_vexpand(args: *mut UiSourceListArgs, value: c_int);
+    fn ui_sourcelist_args_set_hfill(args: *mut UiSourceListArgs, value: c_int);
+    fn ui_sourcelist_args_set_vfill(args: *mut UiSourceListArgs, value: c_int);
+    fn ui_sourcelist_args_set_override_defaults(args: *mut UiSourceListArgs, value: c_int);
+    fn ui_sourcelist_args_set_margin(args: *mut UiSourceListArgs, value: c_int);
+    fn ui_sourcelist_args_set_margin_left(args: *mut UiSourceListArgs, value: c_int);
+    fn ui_sourcelist_args_set_margin_right(args: *mut UiSourceListArgs, value: c_int);
+    fn ui_sourcelist_args_set_margin_top(args: *mut UiSourceListArgs, value: c_int);
+    fn ui_sourcelist_args_set_margin_bottom(args: *mut UiSourceListArgs, value: c_int);
+    fn ui_sourcelist_args_set_colspan(args: *mut UiSourceListArgs, value: c_int);
+    fn ui_sourcelist_args_set_rowspan(args: *mut UiSourceListArgs, value: c_int);
+    fn ui_sourcelist_args_set_name(args: *mut UiSourceListArgs, name: *const c_char);
+    fn ui_sourcelist_args_set_style_class(args: *mut UiSourceListArgs, classname: *const c_char);
+    fn ui_sourcelist_args_set_varname(args: *mut UiSourceListArgs, varname: *const c_char);
+    fn ui_sourcelist_args_set_dynamic_sublists(args: *mut UiSourceListArgs, ivalue: *mut UiList);
+    fn ui_sourcelist_args_set_getvalue_func(args: *mut UiSourceListArgs, func: SLGetValueFunc);
+    fn ui_sourcelist_args_set_getvalue_userdata(args: *mut UiSourceListArgs, data: *mut c_void);
+    fn ui_sourcelist_args_set_onactivate(args: *mut UiSourceListArgs, callback: UiCallback);
+    fn ui_sourcelist_args_set_onactivatedata(args: *mut UiSourceListArgs, data: *mut c_void);
+    fn ui_sourcelist_args_set_onbuttonclick(args: *mut UiSourceListArgs, allback: UiCallback);
+    fn ui_sourcelist_args_set_onbuttonclickdata(args: *mut UiSourceListArgs, data: *mut c_void);
+    fn ui_sourcelist_args_set_contextmenu(args: *mut UiSourceListArgs, menu: *mut ffi::UiMenuBuilder);
+    fn ui_sourcelist_args_set_header_is_item(args: *mut UiSourceListArgs, value: c_int);
+    fn ui_sourcelist_args_set_states(args: *mut UiSourceListArgs, states: *const c_int, numstates: c_int);
+    fn ui_sourcelist_args_set_visibility_states(args: *mut UiSourceListArgs, states: *const c_int, numstates: c_int);
+    fn ui_sourcelist_args_free(args: *mut UiSourceListArgs);
 }
\ No newline at end of file