]> uap-core.de Git - note.git/commitdiff
implement UiList
authorOlaf Wintermann <olaf.wintermann@gmail.com>
Tue, 14 Apr 2026 16:07:03 +0000 (18:07 +0200)
committerOlaf Wintermann <olaf.wintermann@gmail.com>
Tue, 14 Apr 2026 16:07:03 +0000 (18:07 +0200)
application/src/main.rs
ui-rs/src/ui/list.rs [new file with mode: 0644]
ui-rs/src/ui/mod.rs
ui-rs/src/ui/text.rs
ui-rs/src/ui/toolkit.rs
ui-rs/src/ui/window.rs

index 3ed693dfc05cd1a87c6eeeae3bb5958fbc9372ee..9cca73e2135e3d8a4049fef03ed99ec953227f75 100644 (file)
@@ -1,4 +1,5 @@
 use ui_rs::ui;
+use ui_rs::ui::{UiContext, UiList};
 
 fn main() {
     ui::app_init("note");
@@ -10,19 +11,30 @@ fn main() {
 struct App;
 
 struct TestData {
-    i: i32
+    i: i32,
+    list: Option<UiList<i32>>
 }
 
 fn create_window() {
-    let testdata = TestData { i: 0 } ;
+    let testdata = TestData { i: 0, list: None } ;
+
+    let window = ui::window("note", testdata, |obj, data| {
+        let mut list = obj.list::<i32>();
+        let v = list.data();
+        v.push(10);
+        v.push(11);
+        v.push(12);
+
+        data.list = Some(list);
 
-    let window = ui::window("note", testdata, |obj, _data| {
         obj.button_builder().label("Hello").onclick(|e| {
             println!("Button clicked: {}", e.data.i);
             e.data.i += 1;
         }).create();
     });
 
+
+
     window.show();
 }
 
diff --git a/ui-rs/src/ui/list.rs b/ui-rs/src/ui/list.rs
new file mode 100644 (file)
index 0000000..3b768e4
--- /dev/null
@@ -0,0 +1,2 @@
+#![allow(dead_code)]
+
index 79da3bd99f66bcee93472adfb3e8373444505270..8e0ce222bb0836a53c11efcf3804a6e8666d93c2 100644 (file)
@@ -7,6 +7,7 @@ mod container;
 mod widget;
 mod text;
 pub mod event;
+mod list;
 
 pub use toolkit::*;
 pub use event::*;
index 3f159b67a262bf1e258f7afc49126c852df264ab..9d9dbdaae7a2a3be12a8eaff9c49b4ea9224e712 100644 (file)
@@ -1,5 +1,4 @@
 #![allow(dead_code)]
-#[allow(unused_imports)]
 
 use std::ffi::{c_char, c_int, c_void};
 use std::ffi::CString;
index 07d093874d8b58499e3cbb5f74183202f342e9d6..c0d48822792ce3c87d5e43f94c2322459cd6bb5b 100644 (file)
@@ -1,15 +1,35 @@
 #![allow(dead_code)]
 
-use std::ffi::{c_char, c_int, CStr, CString};
+use std::ffi::{c_char, c_int, c_void, CStr, CString};
 use crate::ui::ffi;
 
 use std::marker::PhantomData;
 
+pub trait UiContext {
+    fn get_context(&self) -> *mut ffi::UiContext;
+
+    fn list<T>(&self) -> UiList<T> {
+        let ctx = self.get_context();
+
+        let v: Vec<T> = Vec::new();
+        let mut b = Box::new(v);
+        let data = b.as_mut_ptr();
+
+        unsafe {
+            UiList {
+                ptr: ui_list_new2(ctx, std::ptr::null_mut(), list_init::<T>, data as *mut c_void),
+                data: b
+            }
+        }
+    }
+}
+
 pub struct UiObject<T> {
     pub ptr: *mut ffi::UiObject,
     pub _data: PhantomData<T>
 }
 
+
 pub struct UiText {
     pub ptr: *mut ffi::UiText
 }
@@ -26,6 +46,18 @@ pub struct UiDouble {
     pub ptr: *mut ffi::UiDouble
 }
 
+pub struct UiList<T> {
+    pub ptr: *mut ffi::UiList,
+    data: Box<Vec<T>>
+}
+
+impl<T> UiList<T> {
+    pub fn data(&mut self) -> &mut Vec<T> {
+        self.data.as_mut()
+    }
+}
+
+
 extern "C" {
     fn ui_init(appname: *const c_char, argc: c_int, argv: *const *const c_char);
 
@@ -100,3 +132,104 @@ impl UiInteger {
         }
     }
 }
+
+
+/* -------------------------------- List -------------------------------- */
+
+/*
+ * UiList init func, that is used by ui_list_new2
+ */
+extern "C" fn list_init<T>(_ctx: *mut ffi::UiContext, list: *mut ffi::UiList, data: *mut c_void) {
+    unsafe {
+        ui_list_class_set_data(list, data);
+        ui_list_class_set_first(list, list_first::<T>);
+        ui_list_class_set_next(list, list_next::<T>);
+        ui_list_class_set_get(list, list_get::<T>);
+        ui_list_class_set_count(list, list_count::<T>);
+    }
+}
+
+extern "C" fn list_first<T>(list: *mut ffi::UiList) -> *mut c_void {
+    unsafe {
+        let data = ui_list_get_data(list);
+        if !data.is_null() {
+            let ls = &*(data as *mut Vec<T>);
+            if ls.len() > 0 {
+                let iter = 1;
+                ui_list_set_iter(list, iter as *mut c_void);
+                return ls.as_ptr() as *mut c_void
+            }
+        }
+        std::ptr::null_mut()
+    }
+}
+
+extern "C" fn list_next<T>(list: *mut ffi::UiList) -> *mut c_void {
+    unsafe {
+        let data = ui_list_get_data(list);
+        let iter = ui_list_get_iter(list);
+
+        if !data.is_null() {
+            let ls = &*(data as *mut Vec<T>);
+            let mut index = 0;
+            if !iter.is_null() {
+                index = iter as usize;
+            }
+
+            if index < ls.len() {
+                let value = ls.as_ptr().add(index);
+                index += 1;
+                ui_list_set_iter(list, index as *mut c_void);
+                return value as *mut c_void;
+            }
+        }
+    }
+    std::ptr::null_mut()
+}
+
+extern "C" fn list_get<T>(list: *mut ffi::UiList, index: c_int) -> *mut c_void {
+    unsafe {
+        let data = ui_list_get_data(list);
+        if !data.is_null() {
+            let ls = &*(data as *mut Vec<T>);
+            let i = index as usize;
+            if i < ls.len() {
+                let value = ls.as_ptr().add(i);
+                return value as *mut c_void;
+            }
+        }
+    }
+    std::ptr::null_mut()
+}
+
+extern "C" fn list_count<T>(list: *mut ffi::UiList) -> c_int {
+    unsafe {
+        let data = ui_list_get_data(list);
+        if !data.is_null() {
+            let ls = &*(data as *mut Vec<T>);
+            return ls.len() as c_int;
+        }
+        0
+    }
+}
+
+type UiListInitFunc = extern "C" fn(*mut ffi::UiContext, *mut ffi::UiList, *mut c_void);
+type UiListDestroyFunc = extern "C" fn(*mut ffi::UiContext, *mut ffi::UiList, *mut c_void);
+type UiListFirstFunc = extern "C" fn(*mut ffi::UiList) -> *mut c_void;
+type UiListNextFunc  = extern "C" fn(*mut ffi::UiList) -> *mut c_void;
+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_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);
+    fn ui_list_class_set_get(list: *mut ffi::UiList, func: UiListGetFunc);
+    fn ui_list_class_set_count(list: *mut ffi::UiList, func: UiListCountFunc);
+    fn ui_list_class_set_data(list: *mut ffi::UiList, data: *mut c_void);
+    fn ui_list_class_set_iter(list: *mut ffi::UiList, iter: *mut c_void);
+
+    fn ui_list_get_data(list: *mut ffi::UiList) -> *mut c_void;
+    fn ui_list_get_iter(list: *mut ffi::UiList) -> *mut c_void;
+    fn ui_list_set_iter(list: *mut ffi::UiList, iter: *mut c_void);
+}
index e154e146225f9b777b0134d1e9d38b1efa61df78..46e521c4b5df05acef8d03a2af79c8c544fdf606 100644 (file)
@@ -23,6 +23,16 @@ extern "C" {
     fn ui_reg_destructor(ctx: *mut UiContext, data: *mut c_void, destructor: UiDestructor);
 }
 
+impl<T> crate::ui::UiContext for crate::ui::UiObject<T> {
+    fn get_context(&self) ->  *mut UiContext {
+        unsafe {
+            ui_object_get_context(self.ptr)
+        }
+    }
+}
+
+
+
 
 extern "C" fn destroy_boxed<T>(data: *mut c_void) {
     if data.is_null() {
@@ -43,8 +53,8 @@ impl<T> toolkit::UiObject<T> {
     pub fn reg_box<B>(&mut self, b: Box<B>) -> *mut B  {
         let ptr = Box::into_raw(b);
         unsafe {
-            let ctx = crate::ui::window::ui_object_get_context(self.ptr);
-            crate::ui::window::ui_reg_destructor(ctx, ptr as *mut c_void, destroy_boxed::<B>);
+            let ctx = ui_object_get_context(self.ptr);
+            ui_reg_destructor(ctx, ptr as *mut c_void, destroy_boxed::<B>);
         }
         ptr
     }