]> uap-core.de Git - rssreader.git/commitdiff
add sourcelist
authorOlaf Wintermann <olaf.wintermann@gmail.com>
Sat, 12 Jul 2025 17:07:51 +0000 (19:07 +0200)
committerOlaf Wintermann <olaf.wintermann@gmail.com>
Sat, 12 Jul 2025 17:07:51 +0000 (19:07 +0200)
ui-java/src/main/java/de/unixwork/ui/ArgFuncs.java
ui-java/src/main/java/de/unixwork/ui/Context.java
ui-java/src/main/java/de/unixwork/ui/ListFuncs.java
ui-java/src/main/java/de/unixwork/ui/ListView.java
ui-java/src/main/java/de/unixwork/ui/SourceListBuilder.java [new file with mode: 0644]
ui-java/src/main/java/de/unixwork/ui/SubList.java [new file with mode: 0644]
ui-java/src/main/java/de/unixwork/ui/SubListItem.java [new file with mode: 0644]
ui-java/src/main/java/de/unixwork/ui/SubListValueConverter.java [new file with mode: 0644]
ui-java/src/main/java/de/unixwork/ui/Toolkit.java
ui-java/src/main/java/de/unixwork/ui/ToolkitFuncs.java
ui-java/src/main/java/de/unixwork/ui/UiSourceList.java [new file with mode: 0644]

index 55e8a990762fc9de6ec296e0781bf4c3a45f99ce..e9a6d80fc44c83a8edd23e753b66dd02f3acd23a 100644 (file)
@@ -181,6 +181,28 @@ class ArgFuncs {
     MethodHandle list_args_set_groups;
     MethodHandle list_args_free;
 
+    MethodHandle sourcelist_args_new;
+    MethodHandle sourcelist_args_set_fill;
+    MethodHandle sourcelist_args_set_hexpand;
+    MethodHandle sourcelist_args_set_vexpand;
+    MethodHandle sourcelist_args_set_hfill;
+    MethodHandle sourcelist_args_set_vfill;
+    MethodHandle sourcelist_args_set_override_defaults;
+    MethodHandle sourcelist_args_set_colspan;
+    MethodHandle sourcelist_args_set_rowspan;
+    MethodHandle sourcelist_args_set_name;
+    MethodHandle sourcelist_args_set_style_class;
+    MethodHandle sourcelist_args_set_static_sublists;
+    MethodHandle sourcelist_args_set_varname;
+    MethodHandle sourcelist_args_set_dynamic_sublists;
+    MethodHandle sourcelist_args_set_getvalue_func;
+    MethodHandle sourcelist_args_set_getvalue_userdata;
+    MethodHandle sourcelist_args_set_onactivate;
+    MethodHandle sourcelist_args_set_onactivatedata;
+    MethodHandle sourcelist_args_set_onbuttonclick;
+    MethodHandle sourcelist_args_set_onbuttonclickdata;
+    MethodHandle sourcelist_args_free;
+
     private ArgFuncs(Linker linker, SymbolLookup lib) {
         FunctionDescriptor sigm = FunctionDescriptor.of(ValueLayout.ADDRESS);
         FunctionDescriptor sigv_m = FunctionDescriptor.ofVoid(ValueLayout.ADDRESS);
@@ -364,6 +386,28 @@ class ArgFuncs {
         MemorySegment ui_list_args_set_groups_addr = lib.find("ui_list_args_set_groups").orElseThrow();
         MemorySegment ui_list_args_free_addr = lib.find("ui_list_args_free").orElseThrow();
 
+        MemorySegment ui_sourcelist_args_new_addr = lib.find("ui_sourcelist_args_new").orElseThrow();
+        MemorySegment ui_sourcelist_args_set_fill_addr = lib.find("ui_sourcelist_args_set_fill").orElseThrow();
+        MemorySegment ui_sourcelist_args_set_hexpand_addr = lib.find("ui_sourcelist_args_set_hexpand").orElseThrow();
+        MemorySegment ui_sourcelist_args_set_vexpand_addr = lib.find("ui_sourcelist_args_set_vexpand").orElseThrow();
+        MemorySegment ui_sourcelist_args_set_hfill_addr = lib.find("ui_sourcelist_args_set_hfill").orElseThrow();
+        MemorySegment ui_sourcelist_args_set_vfill_addr = lib.find("ui_sourcelist_args_set_vfill").orElseThrow();
+        MemorySegment ui_sourcelist_args_set_override_defaults_addr = lib.find("ui_sourcelist_args_set_override_defaults").orElseThrow();
+        MemorySegment ui_sourcelist_args_set_colspan_addr = lib.find("ui_sourcelist_args_set_colspan").orElseThrow();
+        MemorySegment ui_sourcelist_args_set_rowspan_addr = lib.find("ui_sourcelist_args_set_rowspan").orElseThrow();
+        MemorySegment ui_sourcelist_args_set_name_addr = lib.find("ui_sourcelist_args_set_name").orElseThrow();
+        MemorySegment ui_sourcelist_args_set_style_class_addr = lib.find("ui_sourcelist_args_set_style_class").orElseThrow();
+        MemorySegment ui_sourcelist_args_set_static_sublists_addr = lib.find("ui_sourcelist_args_set_static_sublists").orElseThrow();
+        MemorySegment ui_sourcelist_args_set_varname_addr = lib.find("ui_sourcelist_args_set_varname").orElseThrow();
+        MemorySegment ui_sourcelist_args_set_dynamic_sublists_addr = lib.find("ui_sourcelist_args_set_dynamic_sublists").orElseThrow();
+        MemorySegment ui_sourcelist_args_set_getvalue_func_addr = lib.find("ui_sourcelist_args_set_getvalue_func").orElseThrow();
+        MemorySegment ui_sourcelist_args_set_getvalue_userdata_addr = lib.find("ui_sourcelist_args_set_getvalue_userdata").orElseThrow();
+        MemorySegment ui_sourcelist_args_set_onactivate_addr = lib.find("ui_sourcelist_args_set_onactivate").orElseThrow();
+        MemorySegment ui_sourcelist_args_set_onactivatedata_addr = lib.find("ui_sourcelist_args_set_onactivatedata").orElseThrow();
+        MemorySegment ui_sourcelist_args_set_onbuttonclick_addr = lib.find("ui_sourcelist_args_set_onbuttonclick").orElseThrow();
+        MemorySegment ui_sourcelist_args_set_onbuttonclickdata_addr = lib.find("ui_sourcelist_args_set_onbuttonclickdata").orElseThrow();
+        MemorySegment ui_sourcelist_args_free_addr = lib.find("ui_sourcelist_args_free").orElseThrow();
+
         menuitem_args_new = linker.downcallHandle(ui_menuitem_args_new_addr, sigm);
         menuitem_args_set_label = linker.downcallHandle(ui_menuitem_args_set_label_addr, sigv_mm);
         menuitem_args_set_stockid = linker.downcallHandle(ui_menuitem_args_set_stockid_addr, sigv_mm);
@@ -538,6 +582,28 @@ class ArgFuncs {
         list_args_set_contextmenu = linker.downcallHandle(ui_list_args_set_contextmenu_addr, sigv_mm);
         list_args_set_groups = linker.downcallHandle(ui_list_args_set_groups_addr, sigv_mm);
         list_args_free = linker.downcallHandle(ui_list_args_free_addr, sigv_m);
+
+        sourcelist_args_new = linker.downcallHandle(ui_sourcelist_args_new_addr, sigm);
+        sourcelist_args_set_fill = linker.downcallHandle(ui_sourcelist_args_set_fill_addr, sigv_mb);
+        sourcelist_args_set_hexpand = linker.downcallHandle(ui_sourcelist_args_set_hexpand_addr, sigv_mb);
+        sourcelist_args_set_vexpand = linker.downcallHandle(ui_sourcelist_args_set_vexpand_addr, sigv_mb);
+        sourcelist_args_set_hfill = linker.downcallHandle(ui_sourcelist_args_set_hfill_addr, sigv_mb);
+        sourcelist_args_set_vfill = linker.downcallHandle(ui_sourcelist_args_set_vfill_addr, sigv_mb);
+        sourcelist_args_set_override_defaults = linker.downcallHandle(ui_sourcelist_args_set_override_defaults_addr, sigv_mb);
+        sourcelist_args_set_colspan = linker.downcallHandle(ui_sourcelist_args_set_colspan_addr, sigv_mi);
+        sourcelist_args_set_rowspan = linker.downcallHandle(ui_sourcelist_args_set_rowspan_addr, sigv_mi);
+        sourcelist_args_set_name = linker.downcallHandle(ui_sourcelist_args_set_name_addr, sigv_mm);
+        sourcelist_args_set_style_class = linker.downcallHandle(ui_sourcelist_args_set_style_class_addr, sigv_mm);
+        sourcelist_args_set_static_sublists = linker.downcallHandle(ui_sourcelist_args_set_static_sublists_addr, sigv_mml);
+        sourcelist_args_set_varname = linker.downcallHandle(ui_sourcelist_args_set_varname_addr, sigv_mm);
+        sourcelist_args_set_dynamic_sublists = linker.downcallHandle(ui_sourcelist_args_set_dynamic_sublists_addr, sigv_mm);
+        sourcelist_args_set_getvalue_func = linker.downcallHandle(ui_sourcelist_args_set_getvalue_func_addr, sigv_mm);
+        sourcelist_args_set_getvalue_userdata = linker.downcallHandle(ui_sourcelist_args_set_getvalue_userdata_addr, sigv_mm);
+        sourcelist_args_set_onactivate = linker.downcallHandle(ui_sourcelist_args_set_onactivate_addr, sigv_mm);
+        sourcelist_args_set_onactivatedata = linker.downcallHandle(ui_sourcelist_args_set_onactivatedata_addr, sigv_mm);
+        sourcelist_args_set_onbuttonclick = linker.downcallHandle(ui_sourcelist_args_set_onbuttonclick_addr, sigv_mm);
+        sourcelist_args_set_onbuttonclickdata = linker.downcallHandle(ui_sourcelist_args_set_onbuttonclickdata_addr, sigv_mm);
+        sourcelist_args_free = linker.downcallHandle(ui_sourcelist_args_free_addr, sigv_m);
     }
 
     static ArgFuncs getInstance() {
index ffd680ea951c1e4e62b840cc8d8345f238772eaf..9b6317f6c477dbc6000ee2d6f28c6bfa28dcb135 100644 (file)
@@ -12,6 +12,7 @@ public abstract class Context {
 
     private ArrayList<UiList> lists = new ArrayList<>();
     private ArrayList<ListValueConverter> converters = new ArrayList<>();
+    private ArrayList<SubListValueConverter> sublistConverters = new ArrayList<>();
 
     protected void setCtx(MemorySegment ptr) {
         this.ptr = ptr;
@@ -55,6 +56,14 @@ public abstract class Context {
         return ls;
     }
 
+    public UiSourceList sourcelist() {
+        return sourcelist(null);
+    }
+
+    public UiSourceList sourcelist(String name) {
+        return new UiSourceList(this, name);
+    }
+
     public MemorySegment registerValueConverter(ListValueConverter converter) {
         MemorySegment funcData = arena.allocate(ValueLayout.JAVA_LONG, 2);
         funcData.setAtIndex(ValueLayout.JAVA_LONG, 0, ptr.address());
@@ -63,6 +72,14 @@ public abstract class Context {
         return funcData;
     }
 
+    public MemorySegment registerSubListValueConverter(SubListValueConverter converter) {
+        MemorySegment funcData = arena.allocate(ValueLayout.JAVA_LONG, 2);
+        funcData.setAtIndex(ValueLayout.JAVA_LONG, 0, ptr.address());
+        funcData.setAtIndex(ValueLayout.JAVA_LONG, 1, sublistConverters.size());
+        sublistConverters.add(converter);
+        return funcData;
+    }
+
     public UiList<?> getList(int index) {
         return lists.get(index);
     }
@@ -71,6 +88,10 @@ public abstract class Context {
         return converters.get(index);
     }
 
+    public SubListValueConverter getSubListValueConverter(int index) {
+        return sublistConverters.get(index);
+    }
+
 
     public void attach(Document doc) {
         ToolkitFuncs ui = ToolkitFuncs.getInstance();
index b0105fc5aaecec5d4c62f4ac756d0075f7f1c871..0f2c1ae91cc29fcae9b16de48f535647ddf643a4 100644 (file)
@@ -18,6 +18,13 @@ public class ListFuncs {
     public MethodHandle list_get_iter;
     public MethodHandle list_set_iter;
 
+    public MethodHandle srclist_new;
+    public MethodHandle srclist_add;
+    public MethodHandle srclist_insert;
+    public MethodHandle srclist_remove;
+    public MethodHandle srclist_clear;
+    public MethodHandle srclist_size;
+
     public MethodHandle listview_create;
     public MethodHandle table_create;
     public MethodHandle combobox_create;
@@ -28,6 +35,10 @@ public class ListFuncs {
         FunctionDescriptor sigm_mm = FunctionDescriptor.of(ValueLayout.ADDRESS, ValueLayout.ADDRESS, ValueLayout.ADDRESS);
         FunctionDescriptor sigm_m = FunctionDescriptor.of(ValueLayout.ADDRESS, ValueLayout.ADDRESS);
         FunctionDescriptor sigv_mm = FunctionDescriptor.ofVoid(ValueLayout.ADDRESS, ValueLayout.ADDRESS);
+        FunctionDescriptor sigv_mim = FunctionDescriptor.ofVoid(ValueLayout.ADDRESS, ValueLayout.JAVA_INT, ValueLayout.ADDRESS);
+        FunctionDescriptor sigv_mi = FunctionDescriptor.ofVoid(ValueLayout.ADDRESS, ValueLayout.JAVA_INT);
+        FunctionDescriptor sigv_m = FunctionDescriptor.ofVoid(ValueLayout.ADDRESS);
+        FunctionDescriptor sigi_m = FunctionDescriptor.of(ValueLayout.JAVA_INT, ValueLayout.ADDRESS);
 
         MemorySegment ui_list_class_set_first_addr = lib.find("ui_list_class_set_first").orElseThrow();
         MemorySegment ui_list_class_set_next_addr = lib.find("ui_list_class_set_next").orElseThrow();
@@ -41,6 +52,13 @@ public class ListFuncs {
         MemorySegment ui_list_get_iter_addr = lib.find("ui_list_get_iter").orElseThrow();
         MemorySegment ui_list_set_iter_addr = lib.find("ui_list_set_iter").orElseThrow();
 
+        MemorySegment ui_srclist_new_addr = lib.find("ui_srclist_new").orElseThrow();
+        MemorySegment ui_srclist_add_addr = lib.find("ui_srclist_add").orElseThrow();
+        MemorySegment ui_srclist_insert_addr = lib.find("ui_srclist_insert").orElseThrow();
+        MemorySegment ui_srclist_remove_addr = lib.find("ui_srclist_remove").orElseThrow();
+        MemorySegment ui_srclist_clear_addr = lib.find("ui_srclist_clear").orElseThrow();
+        MemorySegment ui_srclist_size_addr = lib.find("ui_srclist_size").orElseThrow();
+
         MemorySegment ui_listview_create_addr = lib.find("ui_listview_create").orElseThrow();
         MemorySegment ui_table_create_addr = lib.find("ui_table_create").orElseThrow();
         MemorySegment ui_combobox_create_addr = lib.find("ui_combobox_create").orElseThrow();
@@ -58,6 +76,13 @@ public class ListFuncs {
         list_get_iter = linker.downcallHandle(ui_list_get_iter_addr, sigm_m);
         list_set_iter = linker.downcallHandle(ui_list_set_iter_addr, sigm_mm);
 
+        srclist_new = linker.downcallHandle(ui_srclist_new_addr, sigm_m);
+        srclist_add = linker.downcallHandle(ui_srclist_add_addr, sigv_mm);
+        srclist_insert = linker.downcallHandle(ui_srclist_insert_addr, sigv_mim);
+        srclist_remove = linker.downcallHandle(ui_srclist_remove_addr, sigv_mi);
+        srclist_clear = linker.downcallHandle(ui_srclist_remove_addr, sigv_m);
+        srclist_size = linker.downcallHandle(ui_srclist_size_addr, sigi_m);
+
         listview_create = linker.downcallHandle(ui_listview_create_addr, sigm_mm);
         table_create = linker.downcallHandle(ui_table_create_addr, sigm_mm);
         combobox_create = linker.downcallHandle(ui_combobox_create_addr, sigm_mm);
index 9c6a42836078cb28de3147f5ea51a54994a3c4d8..e3ea699c7cf79c4ae230361de2f5de4a0a823486 100644 (file)
@@ -1,7 +1,5 @@
 package de.unixwork.ui;
 
-import java.lang.foreign.MemorySegment;
-
 public class ListView {
 
 
@@ -10,8 +8,13 @@ public class ListView {
         return new ListViewBuilder<T>(obj, ui.listview_create);
     }
 
-    public static <T> ListViewBuilder<T> dropdown(UiObject obj, MemorySegment userData) {
+    public static <T> ListViewBuilder<T> dropdown(UiObject obj) {
         ListFuncs ui = ListFuncs.getInstance();
         return new ListViewBuilder<T>(obj, ui.combobox_create);
     }
+
+    public static <T> SourceListBuilder<T> sourcelist(UiObject obj) {
+        ListFuncs ui = ListFuncs.getInstance();
+        return new SourceListBuilder<T>(obj, ui.sourcelist_create);
+    }
 }
diff --git a/ui-java/src/main/java/de/unixwork/ui/SourceListBuilder.java b/ui-java/src/main/java/de/unixwork/ui/SourceListBuilder.java
new file mode 100644 (file)
index 0000000..ce55734
--- /dev/null
@@ -0,0 +1,176 @@
+package de.unixwork.ui;
+
+import java.lang.foreign.Arena;
+import java.lang.foreign.MemorySegment;
+import java.lang.invoke.MethodHandle;
+import java.util.List;
+
+public class SourceListBuilder<T> extends AbstractWidgetBuilder {
+    private boolean fill;
+    private boolean hexpand;
+    private boolean vexpand;
+    private boolean hfill;
+    private boolean vfill;
+    private boolean overrideDefaults;
+    private int colspan;
+    private int rowspan;
+    private String name;
+    private String styleClass;
+    private int[] states;
+
+    private List<SubList> sublists;
+    private UiSourceList dynamicSublists;
+    private String varname;
+    private SubListValueConverter<T> getvalue;
+
+    private EventHandler onActivate;
+    private EventHandler onButtonClick;
+
+    public SourceListBuilder(UiObject obj, MethodHandle widgetConstructor) {
+        this.obj = obj;
+        this.widgetConstructor = widgetConstructor;
+        this.argsFree = ArgFuncs.getInstance().list_args_free;
+    }
+
+    public SourceListBuilder<T> fill(boolean fill) {
+        this.fill = fill;
+        return this;
+    }
+
+    public SourceListBuilder<T> hexpand(boolean hexpand) {
+        this.hexpand = hexpand;
+        return this;
+    }
+
+    public SourceListBuilder<T> vexpand(boolean vexpand) {
+        this.vexpand = vexpand;
+        return this;
+    }
+
+    public SourceListBuilder<T> hfill(boolean hfill) {
+        this.hfill = hfill;
+        return this;
+    }
+
+    public SourceListBuilder<T> vfill(boolean vfill) {
+        this.vfill = vfill;
+        return this;
+    }
+
+    public SourceListBuilder<T> overrideDefaults(boolean overrideDefaults) {
+        this.overrideDefaults = overrideDefaults;
+        return this;
+    }
+
+    public SourceListBuilder<T> colspan(int colspan) {
+        this.colspan = colspan;
+        return this;
+    }
+
+    public SourceListBuilder<T> rowspan(int rowspan) {
+        this.rowspan = rowspan;
+        return this;
+    }
+
+    public SourceListBuilder<T> name(String name) {
+        this.name = name;
+        return this;
+    }
+
+
+    public SourceListBuilder<T> styleClass(String styleClass) {
+        this.styleClass = styleClass;
+        return this;
+    }
+
+    public SourceListBuilder<T> states(int... states) {
+        this.states = states;
+        return this;
+    }
+
+    public SourceListBuilder<T> sublists(List<SubList> sublists) {
+        this.sublists = sublists;
+        return this;
+    }
+
+    public SourceListBuilder<T> dynamicSublists(UiSourceList dynamicSublists) {
+        this.dynamicSublists = dynamicSublists;
+        return this;
+    }
+
+    public SourceListBuilder<T> varname(String varname) {
+        this.varname = varname;
+        return this;
+    }
+
+    public SourceListBuilder<T> getvalue(SubListValueConverter<T> getvalue) {
+        this.getvalue = getvalue;
+        return this;
+    }
+
+    public SourceListBuilder<T> onActivate(EventHandler onActivate) {
+        this.onActivate = onActivate;
+        return this;
+    }
+
+    public SourceListBuilder<T> onButtonClick(EventHandler onButtonClick) {
+        this.onButtonClick = onButtonClick;
+        return this;
+    }
+
+    public MemorySegment createArgs(Arena arena) throws Throwable {
+        ArgFuncs ui = ArgFuncs.getInstance();
+
+        args = (MemorySegment) ui.sourcelist_args_new.invoke();
+        if (fill) {
+            ui.sourcelist_args_set_fill.invoke(args, fill);
+        }
+        if (hexpand) {
+            ui.sourcelist_args_set_hexpand.invoke(args, hexpand);
+        }
+        if (vexpand) {
+            ui.sourcelist_args_set_vexpand.invoke(args, vexpand);
+        }
+        if (hfill) {
+            ui.sourcelist_args_set_hfill.invoke(args, hfill);
+        }
+        if (vfill) {
+            ui.sourcelist_args_set_vfill.invoke(args, vfill);
+        }
+        if (overrideDefaults) {
+            ui.sourcelist_args_set_override_defaults.invoke(args, overrideDefaults);
+        }
+        if (colspan > 0) {
+            ui.sourcelist_args_set_colspan.invoke(args, colspan);
+        }
+        if (rowspan > 0) {
+            ui.sourcelist_args_set_rowspan.invoke(args, rowspan);
+        }
+        if (name != null) {
+            MemorySegment cstr = arena.allocateFrom(name);
+            ui.sourcelist_args_set_name.invoke(args, cstr);
+        }
+        if (styleClass != null) {
+            MemorySegment cstr = arena.allocateFrom(styleClass);
+            ui.sourcelist_args_set_style_class.invoke(args, cstr);
+        }
+        if(sublists != null) {
+            // TODO: static sublists
+        }
+        if(dynamicSublists != null) {
+            ui.sourcelist_args_set_dynamic_sublists.invoke(args, dynamicSublists.valuePtr);
+        }
+        if(varname != null) {
+            MemorySegment cstr = arena.allocateFrom(varname);
+            ui.sourcelist_args_set_varname.invoke(args, cstr);
+        }
+        if(getvalue != null) {
+            // always use the Toolkit.getValue wrapper function
+            ui.sourcelist_args_set_getvalue_func.invoke(args, Toolkit.getInstance().sourceListGetValue);
+            MemorySegment userdata = obj.registerSubListValueConverter(getvalue);
+            ui.sourcelist_args_set_getvalue_userdata.invoke(args, userdata);
+        }
+
+        return args;
+    }
+}
diff --git a/ui-java/src/main/java/de/unixwork/ui/SubList.java b/ui-java/src/main/java/de/unixwork/ui/SubList.java
new file mode 100644 (file)
index 0000000..f83ddf8
--- /dev/null
@@ -0,0 +1,85 @@
+package de.unixwork.ui;
+
+import java.lang.foreign.Arena;
+import java.lang.foreign.MemorySegment;
+
+public class SubList<T> {
+    private UiList<T> value;
+    private String varname;
+    private String header;
+    private boolean separator;
+    private MemorySegment userData;
+
+    public SubList() {
+
+    }
+
+    /*
+     * converts a Java SubList to a toolkit UiSubList object
+     */
+    protected MemorySegment createToolkitSublist() {
+        ToolkitFuncs ui = ToolkitFuncs.getInstance();
+        try(Arena arena = Arena.ofConfined()) {
+            MemorySegment sublist = (MemorySegment) ui.sublist_new.invoke();
+            if(value != null) {
+                ui.sublist_set_value.invoke(sublist, value.valuePtr);
+            }
+            if(varname != null) {
+                MemorySegment cstr = arena.allocateFrom(varname);
+                ui.sublist_set_varname.invoke(sublist, cstr);
+            }
+            if(header != null) {
+                MemorySegment cstr = arena.allocateFrom(header);
+                ui.sublist_set_header.invoke(sublist, cstr);
+            }
+            ui.sublist_set_separator.invoke(sublist, separator);
+            if(userData != null) {
+                ui.sublist_set_userdata.invoke(sublist, userData);
+            }
+
+            return sublist;
+        } catch (Throwable e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public UiList<T> getValue() {
+        return value;
+    }
+
+    public void setValue(UiList<T> value) {
+        this.value = value;
+    }
+
+    public String getVarname() {
+        return varname;
+    }
+
+    public void setVarname(String varname) {
+        this.varname = varname;
+    }
+
+    public String getHeader() {
+        return header;
+    }
+
+    public void setHeader(String header) {
+        this.header = header;
+    }
+
+    public boolean hasSeparator() {
+        return separator;
+    }
+
+    public void setSeparator(boolean separator) {
+        this.separator = separator;
+    }
+
+    protected MemorySegment getUserData() {
+        return userData;
+    }
+
+    protected void setUserData(MemorySegment userData) {
+        this.userData = userData;
+    }
+}
diff --git a/ui-java/src/main/java/de/unixwork/ui/SubListItem.java b/ui-java/src/main/java/de/unixwork/ui/SubListItem.java
new file mode 100644 (file)
index 0000000..5164444
--- /dev/null
@@ -0,0 +1,22 @@
+package de.unixwork.ui;
+
+public class SubListItem {
+    public String icon;
+    public String label;
+    public String buttonIcon;
+    public String buttonLabel;
+    public String badge;
+
+    public SubListItem() {
+
+    }
+
+    public SubListItem(String label) {
+        this.label = label;
+    }
+
+    public SubListItem(String icon, String label) {
+        this.icon = icon;
+        this.label = label;
+    }
+}
diff --git a/ui-java/src/main/java/de/unixwork/ui/SubListValueConverter.java b/ui-java/src/main/java/de/unixwork/ui/SubListValueConverter.java
new file mode 100644 (file)
index 0000000..615ada0
--- /dev/null
@@ -0,0 +1,6 @@
+package de.unixwork.ui;
+
+@FunctionalInterface
+public interface SubListValueConverter<T> {
+    public SubListItem getValue(T elm);
+}
index 1e2b89898ade153cf282293a0b7da855f0775fa4..c12ee79d3e18647d1f45a7bf4babf5337eaa0e3f 100644 (file)
@@ -38,6 +38,7 @@ public class Toolkit {
     protected MemorySegment listCount;
 
     protected MemorySegment getValue;
+    protected MemorySegment sourceListGetValue;
 
     private Toolkit(String appName) {
         // load shared library
@@ -138,6 +139,15 @@ public class Toolkit {
                             int.class,
                             MemorySegment.class,
                             MemorySegment.class));
+            MethodHandle scGetValue = MethodHandles.lookup().findStatic(
+                    Toolkit.class,
+                    "sourceListGetValue",
+                    MethodType.methodType(void.class,
+                            MemorySegment.class,
+                            MemorySegment.class,
+                            int.class,
+                            MemorySegment.class,
+                            MemorySegment.class));
 
             getValue = linker.upcallStub(
                     getvalue,
@@ -149,6 +159,15 @@ public class Toolkit {
                             ValueLayout.ADDRESS,
                             ValueLayout.ADDRESS),
                     staticArena);
+            sourceListGetValue = linker.upcallStub(
+                    scGetValue,
+                    FunctionDescriptor.ofVoid(
+                            ValueLayout.ADDRESS,
+                            ValueLayout.ADDRESS,
+                            ValueLayout.JAVA_INT,
+                            ValueLayout.ADDRESS,
+                            ValueLayout.ADDRESS),
+                    staticArena);
         } catch (NoSuchMethodException e) {
             throw new RuntimeException(e);
         } catch (IllegalAccessException e) {
@@ -396,4 +415,59 @@ public class Toolkit {
 
         return MemorySegment.NULL;
     }
+
+    public static void sourceListGetValue(MemorySegment sublistData, MemorySegment rowData, int index, MemorySegment out_item, MemorySegment userdata) {
+        if(userdata == MemorySegment.NULL || sublistData == MemorySegment.NULL) {
+            return;
+        }
+
+        userdata = userdata.reinterpret(16); // long[2]
+        long ctxPtr = userdata.getAtIndex(ValueLayout.JAVA_LONG, 0);
+        long converterIndex = userdata.getAtIndex(ValueLayout.JAVA_LONG, 1);
+
+        Context ctx = Toolkit.getInstance().getContext(ctxPtr);
+        SubListValueConverter conv = ctx.getSubListValueConverter((int)converterIndex);
+
+        ListFuncs listfuncs = ListFuncs.getInstance();
+
+        MemorySegment listdata = null; // long[2]
+        try {
+            listdata = ((MemorySegment)listfuncs.list_get_data.invoke(sublistData)).reinterpret(16);
+        } catch (Throwable e) {
+            throw new RuntimeException(e);
+        }
+        long listCtxPtr = listdata.getAtIndex(ValueLayout.JAVA_LONG, 0);
+        long listIndex = listdata.getAtIndex(ValueLayout.JAVA_LONG, 1);
+        Context listCtx = Toolkit.getInstance().getContext(listCtxPtr);
+        UiList uilist = listCtx.getList((int)listIndex);
+
+        ToolkitFuncs ui = ToolkitFuncs.getInstance();
+        try(Arena arena = Arena.ofShared()) {
+            Object listElm = uilist.get((int) index);
+            SubListItem item = conv.getValue(listElm);
+
+            if(item.icon != null) {
+                MemorySegment cstr = arena.allocateFrom(item.icon);
+                ui.sublist_item_set_icon.invoke(out_item, cstr);
+            }
+            if(item.label != null) {
+                MemorySegment cstr = arena.allocateFrom(item.label);
+                ui.sublist_item_set_label.invoke(out_item, cstr);
+            }
+            if(item.buttonIcon != null) {
+                MemorySegment cstr = arena.allocateFrom(item.buttonIcon);
+                ui.sublist_item_set_button_icon.invoke(out_item, cstr);
+            }
+            if(item.buttonLabel != null) {
+                MemorySegment cstr = arena.allocateFrom(item.buttonLabel);
+                ui.sublist_item_set_button_label.invoke(out_item, cstr);
+            }
+            if(item.badge != null) {
+                MemorySegment cstr = arena.allocateFrom(item.badge);
+                ui.sublist_item_set_badge.invoke(out_item, cstr);
+            }
+        } catch (Throwable e) {
+
+        }
+    }
 }
index 3df12f43880a37cbdd940d2cb5fa529916905e7b..b3d160648309308abcd7d35df609075589c5f71a 100644 (file)
@@ -22,6 +22,21 @@ public class ToolkitFuncs {
     public MethodHandle event_get_int;
     public MethodHandle event_get_set;
 
+    public MethodHandle sublist_new;
+    public MethodHandle sublist_set_value;
+    public MethodHandle sublist_set_varname;
+    public MethodHandle sublist_set_header;
+    public MethodHandle sublist_set_separator;
+    public MethodHandle sublist_set_userdata;
+    public MethodHandle sublist_free;
+
+    public MethodHandle sublist_item_set_icon;
+    public MethodHandle sublist_item_set_label;
+    public MethodHandle sublist_item_set_button_icon;
+    public MethodHandle sublist_item_set_button_label;
+    public MethodHandle sublist_item_set_badge;
+    public MethodHandle sublist_item_set_eventdata;
+
     public MethodHandle string_new;
     public MethodHandle int_new;
     public MethodHandle double_new;
@@ -50,6 +65,7 @@ public class ToolkitFuncs {
         FunctionDescriptor sigi_m = FunctionDescriptor.of(ValueLayout.JAVA_INT, ValueLayout.ADDRESS);
         FunctionDescriptor sigm_mm = FunctionDescriptor.of(ValueLayout.ADDRESS, ValueLayout.ADDRESS, ValueLayout.ADDRESS);
         FunctionDescriptor sigv_mm = FunctionDescriptor.ofVoid(ValueLayout.ADDRESS, ValueLayout.ADDRESS);
+        FunctionDescriptor sigv_mb = FunctionDescriptor.ofVoid(ValueLayout.ADDRESS, ValueLayout.JAVA_BOOLEAN);
         FunctionDescriptor sigv_m = FunctionDescriptor.ofVoid(ValueLayout.ADDRESS);
         FunctionDescriptor sigm_l = FunctionDescriptor.of(ValueLayout.ADDRESS, ValueLayout.JAVA_LONG);
 
@@ -69,6 +85,21 @@ public class ToolkitFuncs {
         MemorySegment event_get_int_addr = lib.find("ui_event_get_int").orElseThrow();
         MemorySegment event_get_set_addr = lib.find("ui_event_get_set").orElseThrow();
 
+        MemorySegment sublist_new_addr = lib.find("ui_sublist_new").orElseThrow();
+        MemorySegment sublist_set_value_addr = lib.find("ui_sublist_set_value").orElseThrow();
+        MemorySegment sublist_set_varname_addr = lib.find("ui_sublist_set_varname").orElseThrow();
+        MemorySegment sublist_set_header_addr = lib.find("ui_sublist_set_header").orElseThrow();
+        MemorySegment sublist_set_separator_addr = lib.find("ui_sublist_set_separator").orElseThrow();
+        MemorySegment sublist_set_userdata_addr = lib.find("ui_sublist_set_userdata").orElseThrow();
+        MemorySegment sublist_free_addr = lib.find("ui_sublist_free").orElseThrow();
+
+        MemorySegment sublist_item_set_icon_addr = lib.find("ui_sublist_item_set_icon").orElseThrow();
+        MemorySegment sublist_item_set_label_addr = lib.find("ui_sublist_item_set_label").orElseThrow();
+        MemorySegment sublist_item_set_button_icon_addr = lib.find("ui_sublist_item_set_button_icon").orElseThrow();
+        MemorySegment sublist_item_set_button_label_addr = lib.find("ui_sublist_item_set_button_label").orElseThrow();
+        MemorySegment sublist_item_set_badge_addr = lib.find("ui_sublist_item_set_badge").orElseThrow();
+        MemorySegment sublist_item_set_eventdata_addr = lib.find("ui_sublist_item_set_eventdata").orElseThrow();
+
         MemorySegment string_new_addr = lib.find("ui_string_new").orElseThrow();
         MemorySegment int_new_addr = lib.find("ui_int_new").orElseThrow();
         MemorySegment double_new_addr = lib.find("ui_double_new").orElseThrow();
@@ -107,6 +138,21 @@ public class ToolkitFuncs {
         event_get_int = linker.downcallHandle(event_get_int_addr, sigi_m);
         event_get_set = linker.downcallHandle(event_get_set_addr, sigi_m);
 
+        sublist_new = linker.downcallHandle(sublist_new_addr, sigm_m);
+        sublist_set_value = linker.downcallHandle(sublist_set_value_addr, sigv_mm);
+        sublist_set_varname = linker.downcallHandle(sublist_set_varname_addr, sigv_mm);
+        sublist_set_header = linker.downcallHandle(sublist_set_header_addr, sigv_mm);
+        sublist_set_separator = linker.downcallHandle(sublist_set_separator_addr, sigv_mb);
+        sublist_set_userdata = linker.downcallHandle(sublist_set_userdata_addr, sigv_mm);
+        sublist_free = linker.downcallHandle(sublist_free_addr, sigv_m);
+
+        sublist_item_set_icon = linker.downcallHandle(sublist_item_set_icon_addr, sigv_mm);
+        sublist_item_set_label = linker.downcallHandle(sublist_item_set_label_addr, sigv_mm);
+        sublist_item_set_button_icon = linker.downcallHandle(sublist_item_set_button_icon_addr, sigv_mm);
+        sublist_item_set_button_label = linker.downcallHandle(sublist_item_set_button_label_addr, sigv_mm);
+        sublist_item_set_badge = linker.downcallHandle(sublist_item_set_badge_addr, sigv_mm);
+        sublist_item_set_eventdata = linker.downcallHandle(sublist_item_set_eventdata_addr, sigv_mm);
+
         string_new = linker.downcallHandle(string_new_addr, sigm_mm);
         int_new = linker.downcallHandle(int_new_addr, sigm_mm);
         double_new = linker.downcallHandle(double_new_addr, sigm_mm);
diff --git a/ui-java/src/main/java/de/unixwork/ui/UiSourceList.java b/ui-java/src/main/java/de/unixwork/ui/UiSourceList.java
new file mode 100644 (file)
index 0000000..69218a8
--- /dev/null
@@ -0,0 +1,80 @@
+package de.unixwork.ui;
+
+import java.lang.foreign.Arena;
+import java.lang.foreign.FunctionDescriptor;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.ValueLayout;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.util.ArrayList;
+
+public class UiSourceList {
+    protected MemorySegment valuePtr;
+    private ArrayList<SubList> list = new ArrayList<>(8);
+
+    protected UiSourceList(Context ctx, String name) {
+        ToolkitFuncs ui = ToolkitFuncs.getInstance();
+        Toolkit toolkit = Toolkit.getInstance();
+        ListFuncs listFuncs = ListFuncs.getInstance();
+
+        try (Arena arena = Arena.ofConfined()) {
+            MemorySegment nameCStr = MemorySegment.NULL;
+            if(name != null) {
+                nameCStr = arena.allocateFrom(name);
+            }
+
+            valuePtr = (MemorySegment) listFuncs.srclist_new.invoke(ctx.getCtx(), nameCStr);
+        } catch (Throwable e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public void add(SubList sublist) {
+        list.add(sublist);
+        ListFuncs ui = ListFuncs.getInstance();
+        try {
+            ui.srclist_add.invoke(valuePtr, sublist.createToolkitSublist());
+        } catch (Throwable e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public void add(int index, SubList sublist) {
+        list.add(index, sublist);
+        ListFuncs ui = ListFuncs.getInstance();
+        try {
+            ui.srclist_insert.invoke(valuePtr, index, sublist.createToolkitSublist());
+        } catch (Throwable e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public void remove(int index) {
+        ListFuncs ui = ListFuncs.getInstance();
+        try {
+            list.remove(index);
+            ui.srclist_remove.invoke(valuePtr, index);
+        } catch (Throwable e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public void clear() {
+        ListFuncs ui = ListFuncs.getInstance();
+        try {
+            list.clear();
+            ui.srclist_clear.invoke(valuePtr);
+        } catch (Throwable e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public int size() {
+        return list.size();
+    }
+
+    public SubList[] toArray() {
+        return list.toArray(new SubList[0]);
+    }
+}