From e9bbe8fe709dcffa02c4b56cf0d99f94b825cb3f Mon Sep 17 00:00:00 2001 From: Olaf Wintermann Date: Sat, 12 Jul 2025 19:07:51 +0200 Subject: [PATCH] add sourcelist --- .../main/java/de/unixwork/ui/ArgFuncs.java | 66 +++++++ .../src/main/java/de/unixwork/ui/Context.java | 21 +++ .../main/java/de/unixwork/ui/ListFuncs.java | 25 +++ .../main/java/de/unixwork/ui/ListView.java | 9 +- .../de/unixwork/ui/SourceListBuilder.java | 176 ++++++++++++++++++ .../src/main/java/de/unixwork/ui/SubList.java | 85 +++++++++ .../main/java/de/unixwork/ui/SubListItem.java | 22 +++ .../de/unixwork/ui/SubListValueConverter.java | 6 + .../src/main/java/de/unixwork/ui/Toolkit.java | 74 ++++++++ .../java/de/unixwork/ui/ToolkitFuncs.java | 46 +++++ .../java/de/unixwork/ui/UiSourceList.java | 80 ++++++++ 11 files changed, 607 insertions(+), 3 deletions(-) create mode 100644 ui-java/src/main/java/de/unixwork/ui/SourceListBuilder.java create mode 100644 ui-java/src/main/java/de/unixwork/ui/SubList.java create mode 100644 ui-java/src/main/java/de/unixwork/ui/SubListItem.java create mode 100644 ui-java/src/main/java/de/unixwork/ui/SubListValueConverter.java create mode 100644 ui-java/src/main/java/de/unixwork/ui/UiSourceList.java diff --git a/ui-java/src/main/java/de/unixwork/ui/ArgFuncs.java b/ui-java/src/main/java/de/unixwork/ui/ArgFuncs.java index 55e8a99..e9a6d80 100644 --- a/ui-java/src/main/java/de/unixwork/ui/ArgFuncs.java +++ b/ui-java/src/main/java/de/unixwork/ui/ArgFuncs.java @@ -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() { diff --git a/ui-java/src/main/java/de/unixwork/ui/Context.java b/ui-java/src/main/java/de/unixwork/ui/Context.java index ffd680e..9b6317f 100644 --- a/ui-java/src/main/java/de/unixwork/ui/Context.java +++ b/ui-java/src/main/java/de/unixwork/ui/Context.java @@ -12,6 +12,7 @@ public abstract class Context { private ArrayList lists = new ArrayList<>(); private ArrayList converters = new ArrayList<>(); + private ArrayList 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(); diff --git a/ui-java/src/main/java/de/unixwork/ui/ListFuncs.java b/ui-java/src/main/java/de/unixwork/ui/ListFuncs.java index b0105fc..0f2c1ae 100644 --- a/ui-java/src/main/java/de/unixwork/ui/ListFuncs.java +++ b/ui-java/src/main/java/de/unixwork/ui/ListFuncs.java @@ -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); diff --git a/ui-java/src/main/java/de/unixwork/ui/ListView.java b/ui-java/src/main/java/de/unixwork/ui/ListView.java index 9c6a428..e3ea699 100644 --- a/ui-java/src/main/java/de/unixwork/ui/ListView.java +++ b/ui-java/src/main/java/de/unixwork/ui/ListView.java @@ -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(obj, ui.listview_create); } - public static ListViewBuilder dropdown(UiObject obj, MemorySegment userData) { + public static ListViewBuilder dropdown(UiObject obj) { ListFuncs ui = ListFuncs.getInstance(); return new ListViewBuilder(obj, ui.combobox_create); } + + public static SourceListBuilder sourcelist(UiObject obj) { + ListFuncs ui = ListFuncs.getInstance(); + return new SourceListBuilder(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 index 0000000..ce55734 --- /dev/null +++ b/ui-java/src/main/java/de/unixwork/ui/SourceListBuilder.java @@ -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 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 sublists; + private UiSourceList dynamicSublists; + private String varname; + private SubListValueConverter 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 fill(boolean fill) { + this.fill = fill; + return this; + } + + public SourceListBuilder hexpand(boolean hexpand) { + this.hexpand = hexpand; + return this; + } + + public SourceListBuilder vexpand(boolean vexpand) { + this.vexpand = vexpand; + return this; + } + + public SourceListBuilder hfill(boolean hfill) { + this.hfill = hfill; + return this; + } + + public SourceListBuilder vfill(boolean vfill) { + this.vfill = vfill; + return this; + } + + public SourceListBuilder overrideDefaults(boolean overrideDefaults) { + this.overrideDefaults = overrideDefaults; + return this; + } + + public SourceListBuilder colspan(int colspan) { + this.colspan = colspan; + return this; + } + + public SourceListBuilder rowspan(int rowspan) { + this.rowspan = rowspan; + return this; + } + + public SourceListBuilder name(String name) { + this.name = name; + return this; + } + + + public SourceListBuilder styleClass(String styleClass) { + this.styleClass = styleClass; + return this; + } + + public SourceListBuilder states(int... states) { + this.states = states; + return this; + } + + public SourceListBuilder sublists(List sublists) { + this.sublists = sublists; + return this; + } + + public SourceListBuilder dynamicSublists(UiSourceList dynamicSublists) { + this.dynamicSublists = dynamicSublists; + return this; + } + + public SourceListBuilder varname(String varname) { + this.varname = varname; + return this; + } + + public SourceListBuilder getvalue(SubListValueConverter getvalue) { + this.getvalue = getvalue; + return this; + } + + public SourceListBuilder onActivate(EventHandler onActivate) { + this.onActivate = onActivate; + return this; + } + + public SourceListBuilder 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 index 0000000..f83ddf8 --- /dev/null +++ b/ui-java/src/main/java/de/unixwork/ui/SubList.java @@ -0,0 +1,85 @@ +package de.unixwork.ui; + +import java.lang.foreign.Arena; +import java.lang.foreign.MemorySegment; + +public class SubList { + private UiList 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 getValue() { + return value; + } + + public void setValue(UiList 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 index 0000000..5164444 --- /dev/null +++ b/ui-java/src/main/java/de/unixwork/ui/SubListItem.java @@ -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 index 0000000..615ada0 --- /dev/null +++ b/ui-java/src/main/java/de/unixwork/ui/SubListValueConverter.java @@ -0,0 +1,6 @@ +package de.unixwork.ui; + +@FunctionalInterface +public interface SubListValueConverter { + public SubListItem getValue(T elm); +} diff --git a/ui-java/src/main/java/de/unixwork/ui/Toolkit.java b/ui-java/src/main/java/de/unixwork/ui/Toolkit.java index 1e2b898..c12ee79 100644 --- a/ui-java/src/main/java/de/unixwork/ui/Toolkit.java +++ b/ui-java/src/main/java/de/unixwork/ui/Toolkit.java @@ -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) { + + } + } } diff --git a/ui-java/src/main/java/de/unixwork/ui/ToolkitFuncs.java b/ui-java/src/main/java/de/unixwork/ui/ToolkitFuncs.java index 3df12f4..b3d1606 100644 --- a/ui-java/src/main/java/de/unixwork/ui/ToolkitFuncs.java +++ b/ui-java/src/main/java/de/unixwork/ui/ToolkitFuncs.java @@ -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 index 0000000..69218a8 --- /dev/null +++ b/ui-java/src/main/java/de/unixwork/ui/UiSourceList.java @@ -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 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]); + } +} -- 2.47.3