From 8642ad9b0f2a625eb7339e4a68ed7197134eb11b Mon Sep 17 00:00:00 2001 From: Olaf Wintermann Date: Sun, 31 Aug 2025 11:31:31 +0200 Subject: [PATCH] implement list/table getstyle func --- .../de/unixwork/rssreader/MainWindow.kt | 3 + .../main/java/de/unixwork/ui/ArgFuncs.java | 6 ++ .../src/main/java/de/unixwork/ui/Context.java | 13 ++++ .../de/unixwork/ui/ListStyleProvider.java | 6 ++ .../java/de/unixwork/ui/ListViewBuilder.java | 28 +++++++-- .../java/de/unixwork/ui/TableViewBuilder.java | 11 ++++ .../main/java/de/unixwork/ui/TextStyle.java | 62 +++++++++++++++++++ .../src/main/java/de/unixwork/ui/Toolkit.java | 54 +++++++++++++++- .../java/de/unixwork/ui/ToolkitFuncs.java | 19 ++++++ .../kotlin/de/unixwork/ui/kotlin/Toplevel.kt | 5 ++ 10 files changed, 199 insertions(+), 8 deletions(-) create mode 100644 ui-java/src/main/java/de/unixwork/ui/ListStyleProvider.java create mode 100644 ui-java/src/main/java/de/unixwork/ui/TextStyle.java diff --git a/rss-application/src/main/kotlin/de/unixwork/rssreader/MainWindow.kt b/rss-application/src/main/kotlin/de/unixwork/rssreader/MainWindow.kt index 3ea9eed..d27fabc 100644 --- a/rss-application/src/main/kotlin/de/unixwork/rssreader/MainWindow.kt +++ b/rss-application/src/main/kotlin/de/unixwork/rssreader/MainWindow.kt @@ -71,6 +71,9 @@ class MainWindow { feedList.items.selected?.let { feedList.selectItem(it) } + }, + getstyle = { elm, col, style -> + false } ) { elm, col -> 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 03818b4..0e4ec9b 100644 --- a/ui-java/src/main/java/de/unixwork/ui/ArgFuncs.java +++ b/ui-java/src/main/java/de/unixwork/ui/ArgFuncs.java @@ -313,6 +313,8 @@ class ArgFuncs { MethodHandle list_args_set_getvalue_func; MethodHandle list_args_set_getvalue_func2; MethodHandle list_args_set_getvalue_data; + MethodHandle list_args_set_getstyle_func; + MethodHandle list_args_set_getstyle_data; MethodHandle list_args_set_onactivate; MethodHandle list_args_set_onactivatedata; MethodHandle list_args_set_onselection; @@ -720,6 +722,8 @@ class ArgFuncs { MemorySegment ui_list_args_set_getvalue_func_addr = lib.find("ui_list_args_set_getvalue_func").orElseThrow(); MemorySegment ui_list_args_set_getvalue_func2_addr = lib.find("ui_list_args_set_getvalue_func2").orElseThrow(); MemorySegment ui_list_args_set_getvalue_data_addr = lib.find("ui_list_args_set_getvalue_data").orElseThrow(); + MemorySegment ui_list_args_set_getstyle_func_addr = lib.find("ui_list_args_set_getstyle_func").orElseThrow(); + MemorySegment ui_list_args_set_getstyle_data_addr = lib.find("ui_list_args_set_getstyle_data").orElseThrow(); MemorySegment ui_list_args_set_onactivate_addr = lib.find("ui_list_args_set_onactivate").orElseThrow(); MemorySegment ui_list_args_set_onactivatedata_addr = lib.find("ui_list_args_set_onactivatedata").orElseThrow(); MemorySegment ui_list_args_set_onselection_addr = lib.find("ui_list_args_set_onselection").orElseThrow(); @@ -1118,6 +1122,8 @@ class ArgFuncs { list_args_set_getvalue_func = linker.downcallHandle(ui_list_args_set_getvalue_func_addr, sigv_mm); list_args_set_getvalue_func2 = linker.downcallHandle(ui_list_args_set_getvalue_func2_addr, sigv_mm); list_args_set_getvalue_data = linker.downcallHandle(ui_list_args_set_getvalue_data_addr, sigv_mm); + list_args_set_getstyle_func = linker.downcallHandle(ui_list_args_set_getstyle_func_addr, sigv_mm); + list_args_set_getstyle_data = linker.downcallHandle(ui_list_args_set_getstyle_data_addr, sigv_mm); list_args_set_onactivate = linker.downcallHandle(ui_list_args_set_onactivate_addr, sigv_mm); list_args_set_onactivatedata = linker.downcallHandle(ui_list_args_set_onactivatedata_addr, sigv_mm); list_args_set_onselection = linker.downcallHandle(ui_list_args_set_onselection_addr, sigv_mm); 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 b924217..7032847 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 styleProviders = new ArrayList<>(); private ArrayList sublistConverters = new ArrayList<>(); protected void setCtx(MemorySegment ptr) { @@ -102,6 +103,14 @@ public abstract class Context { return funcData; } + public MemorySegment registerStyleProvider(ListStyleProvider provider) { + MemorySegment funcData = arena.allocate(ValueLayout.JAVA_LONG, 2); + funcData.setAtIndex(ValueLayout.JAVA_LONG, 0, ptr.address()); + funcData.setAtIndex(ValueLayout.JAVA_LONG, 1, styleProviders.size()); + styleProviders.add(provider); + return funcData; + } + public MemorySegment registerSubListValueConverter(SubListValueConverter converter) { MemorySegment funcData = arena.allocate(ValueLayout.JAVA_LONG, 2); funcData.setAtIndex(ValueLayout.JAVA_LONG, 0, ptr.address()); @@ -118,6 +127,10 @@ public abstract class Context { return converters.get(index); } + public ListStyleProvider getStyleProvider(int index) { + return styleProviders.get(index); + } + public SubListValueConverter getSubListValueConverter(int index) { return sublistConverters.get(index); } diff --git a/ui-java/src/main/java/de/unixwork/ui/ListStyleProvider.java b/ui-java/src/main/java/de/unixwork/ui/ListStyleProvider.java new file mode 100644 index 0000000..7c8f4e3 --- /dev/null +++ b/ui-java/src/main/java/de/unixwork/ui/ListStyleProvider.java @@ -0,0 +1,6 @@ +package de.unixwork.ui; + +@FunctionalInterface +public interface ListStyleProvider { + public boolean getStyle(T elm, int column, TextStyle style); +} diff --git a/ui-java/src/main/java/de/unixwork/ui/ListViewBuilder.java b/ui-java/src/main/java/de/unixwork/ui/ListViewBuilder.java index aefab56..b6faf60 100644 --- a/ui-java/src/main/java/de/unixwork/ui/ListViewBuilder.java +++ b/ui-java/src/main/java/de/unixwork/ui/ListViewBuilder.java @@ -19,7 +19,8 @@ public class ListViewBuilder extends AbstractWidgetBuilder { private UiList list; // TODO: model // TODO: static elements - private ListValueConverter getvalue; + private ListValueConverter getvalue; + private ListStyleProvider getstyle; private EventHandler onActivate; private EventHandler onSelection; private EventHandler onDragStart; @@ -101,6 +102,11 @@ public class ListViewBuilder extends AbstractWidgetBuilder { return this; } + public ListViewBuilder getstyle(ListStyleProvider getstyle) { + this.getstyle = getstyle; + return this; + } + public ListViewBuilder onActivate(EventHandler onActivate) { this.onActivate = onActivate; return this; @@ -174,11 +180,21 @@ public class ListViewBuilder extends AbstractWidgetBuilder { if(list != null) { ui.list_args_set_value.invoke(args, list.valuePtr); } - if(getvalue != null) { - // always use the Toolkit.getValue wrapper function - ui.list_args_set_getvalue_func2.invoke(args, Toolkit.getInstance().getValue); - MemorySegment userdata = obj.registerValueConverter(getvalue); - ui.list_args_set_getvalue_data.invoke(args, userdata); + + if(getvalue == null) { + getvalue = (elm, col) -> { + return elm.toString(); + }; + } + // always use the Toolkit.getValue wrapper function + ui.list_args_set_getvalue_func2.invoke(args, Toolkit.getInstance().getValue); + MemorySegment userdata = obj.registerValueConverter(getvalue); + ui.list_args_set_getvalue_data.invoke(args, userdata); + + if(getstyle != null) { + ui.list_args_set_getstyle_func.invoke(args, Toolkit.getInstance().getStyle); + MemorySegment getstyledata = obj.registerStyleProvider(getstyle); + ui.list_args_set_getstyle_data.invoke(args, getstyledata); } if (onActivate != null) { diff --git a/ui-java/src/main/java/de/unixwork/ui/TableViewBuilder.java b/ui-java/src/main/java/de/unixwork/ui/TableViewBuilder.java index 87439a0..544eacc 100644 --- a/ui-java/src/main/java/de/unixwork/ui/TableViewBuilder.java +++ b/ui-java/src/main/java/de/unixwork/ui/TableViewBuilder.java @@ -20,6 +20,7 @@ public class TableViewBuilder extends AbstractWidgetBuilder { private TableModel model; // TODO: static elements private ListValueConverter getvalue; + private ListStyleProvider getstyle; private EventHandler onActivate; private EventHandler onSelection; private EventHandler onDragStart; @@ -108,6 +109,11 @@ public class TableViewBuilder extends AbstractWidgetBuilder { return this; } + public TableViewBuilder getstyle(ListStyleProvider getstyle) { + this.getstyle = getstyle; + return this; + } + public TableViewBuilder onActivate(EventHandler onActivate) { this.onActivate = onActivate; return this; @@ -187,6 +193,11 @@ public class TableViewBuilder extends AbstractWidgetBuilder { MemorySegment userdata = obj.registerValueConverter(getvalue); ui.list_args_set_getvalue_data.invoke(args, userdata); } + if(getstyle != null) { + ui.list_args_set_getstyle_func.invoke(args, Toolkit.getInstance().getStyle); + MemorySegment getstyledata = obj.registerStyleProvider(getstyle); + ui.list_args_set_getstyle_data.invoke(args, getstyledata); + } if(model != null) { modelPtr = model.createModel(obj); ui.list_args_set_model.invoke(args, modelPtr); diff --git a/ui-java/src/main/java/de/unixwork/ui/TextStyle.java b/ui-java/src/main/java/de/unixwork/ui/TextStyle.java new file mode 100644 index 0000000..ef903ec --- /dev/null +++ b/ui-java/src/main/java/de/unixwork/ui/TextStyle.java @@ -0,0 +1,62 @@ +package de.unixwork.ui; + +import java.awt.*; +import java.lang.foreign.MemorySegment; + +public class TextStyle { + private boolean bold; + private boolean italic; + private boolean underline; + private Color color; + + public Color getColor() { + return color; + } + + public void setColor(Color color) { + this.color = color; + } + + public boolean isUnderline() { + return underline; + } + + public void setUnderline(boolean underline) { + this.underline = underline; + } + + public boolean isItalic() { + return italic; + } + + public void setItalic(boolean italic) { + this.italic = italic; + } + + public boolean isBold() { + return bold; + } + + public void setBold(boolean bold) { + this.bold = bold; + } + + protected void applySettings(MemorySegment style) { + ToolkitFuncs ui = ToolkitFuncs.getInstance(); + try { + ui.textstyle_set_bold.invoke(style, bold); + ui.textstyle_set_italic.invoke(style, italic); + ui.textstyle_set_underline.invoke(style, underline); + if(color != null) { + int r = color.getRed(); + int g = color.getGreen(); + int b = color.getBlue(); + ui.textstyle_set_color.invoke(style, r, g, b); + } else { + ui.textstyle_enable_color.invoke(style, false); + } + } catch (Throwable e) { + throw new RuntimeException(e); + } + } +} 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 9718176..8a8dbc5 100644 --- a/ui-java/src/main/java/de/unixwork/ui/Toolkit.java +++ b/ui-java/src/main/java/de/unixwork/ui/Toolkit.java @@ -40,6 +40,7 @@ public class Toolkit { protected MemorySegment getValue; protected MemorySegment sourceListGetValue; + protected MemorySegment getStyle; protected MemorySegment threadFuncPtr; @@ -138,7 +139,7 @@ public class Toolkit { // list/table getvaluefunc wrapper try { - MethodHandle getvalue = MethodHandles.lookup().findStatic( + MethodHandle getValueMethod = MethodHandles.lookup().findStatic( Toolkit.class, "getValue", MethodType.methodType(MemorySegment.class, @@ -158,9 +159,19 @@ public class Toolkit { int.class, MemorySegment.class, MemorySegment.class)); + MethodHandle getStyleMethod = MethodHandles.lookup().findStatic( + Toolkit.class, + "getStyle", + MethodType.methodType(boolean.class, + MemorySegment.class, + MemorySegment.class, + int.class, + int.class, + MemorySegment.class, + MemorySegment.class)); getValue = linker.upcallStub( - getvalue, + getValueMethod, FunctionDescriptor.of(ValueLayout.ADDRESS, ValueLayout.ADDRESS, ValueLayout.ADDRESS, @@ -179,6 +190,16 @@ public class Toolkit { ValueLayout.ADDRESS, ValueLayout.ADDRESS), staticArena); + getStyle = linker.upcallStub( + getStyleMethod, + FunctionDescriptor.of(ValueLayout.JAVA_BOOLEAN, + ValueLayout.ADDRESS, + ValueLayout.ADDRESS, + ValueLayout.JAVA_INT, + ValueLayout.JAVA_INT, + ValueLayout.ADDRESS, + ValueLayout.ADDRESS), + staticArena); } catch (NoSuchMethodException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { @@ -529,6 +550,35 @@ public class Toolkit { } } + public static boolean getStyle(MemorySegment list, MemorySegment elm, int row, int col, MemorySegment userdata, MemorySegment stylePtr) { + if(userdata == MemorySegment.NULL) { + return false; + } + // userdata: contains the context ptr and styleprovider index + userdata = userdata.reinterpret(16); // long[2] + long ctxPtr = userdata.getAtIndex(ValueLayout.JAVA_LONG, 0); + long styleProviderIndex = userdata.getAtIndex(ValueLayout.JAVA_LONG, 1); + + var listfuncs = ListFuncs.getInstance(); + + var uilist = Toolkit.listPtrToObject(list); + + Object listElm = null; + try { + listElm = uilist.get((int) row); + } catch (Throwable e) { + return false; + } + + var ctx = Toolkit.getInstance().getContext(ctxPtr); + var getstyle = ctx.getStyleProvider((int)styleProviderIndex); + var style = new TextStyle(); + boolean ret = getstyle.getStyle(listElm, col, style); + style.applySettings(stylePtr); + + return ret; + } + // converts a C toolkit UiList* pointer to a java UiList object protected static UiList listPtrToObject(MemorySegment list) { ListFuncs listfuncs = ListFuncs.getInstance(); 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 885640d..19a4bcb 100644 --- a/ui-java/src/main/java/de/unixwork/ui/ToolkitFuncs.java +++ b/ui-java/src/main/java/de/unixwork/ui/ToolkitFuncs.java @@ -67,6 +67,12 @@ public class ToolkitFuncs { public MethodHandle model_add_column; public MethodHandle model_free; + public MethodHandle textstyle_set_bold; + public MethodHandle textstyle_set_italic; + public MethodHandle textstyle_set_underline; + public MethodHandle textstyle_set_color; + public MethodHandle textstyle_enable_color; + public MethodHandle call_mainthread; public MethodHandle ui_malloc; @@ -89,6 +95,7 @@ public class ToolkitFuncs { 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); + FunctionDescriptor sigv_miii = FunctionDescriptor.ofVoid(ValueLayout.ADDRESS, ValueLayout.JAVA_INT, ValueLayout.JAVA_INT, ValueLayout.JAVA_INT); FunctionDescriptor sigv_mmimi = FunctionDescriptor.ofVoid(ValueLayout.ADDRESS, ValueLayout.ADDRESS, ValueLayout.JAVA_INT, ValueLayout.ADDRESS, ValueLayout.JAVA_INT); MemorySegment object_get_context_addr = lib.find("ui_object_get_context").orElseThrow(); @@ -152,6 +159,12 @@ public class ToolkitFuncs { MemorySegment model_add_column_addr = lib.find("ui_model_add_column").orElseThrow(); MemorySegment model_free_addr = lib.find("ui_model_free").orElseThrow(); + MemorySegment textstyle_set_bold_addr = lib.find("ui_textstyle_set_bold").orElseThrow(); + MemorySegment textstyle_set_italic_addr = lib.find("ui_textstyle_set_italic").orElseThrow(); + MemorySegment textstyle_set_underline_addr = lib.find("ui_textstyle_set_underline").orElseThrow(); + MemorySegment textstyle_set_color_addr = lib.find("ui_textstyle_set_color").orElseThrow(); + MemorySegment textstyle_enable_color_addr = lib.find("ui_textstyle_enable_color").orElseThrow(); + MemorySegment call_mainthread_addr = lib.find("ui_call_mainthread").orElseThrow(); MemorySegment ui_malloc_addr = lib.find("ui_malloc").orElseThrow(); @@ -223,6 +236,12 @@ public class ToolkitFuncs { model_add_column = linker.downcallHandle(model_add_column_addr, sigv_mmimi); model_free = linker.downcallHandle(model_free_addr, sigv_mm); + textstyle_set_bold = linker.downcallHandle(textstyle_set_bold_addr, sigv_mb); + textstyle_set_italic = linker.downcallHandle(textstyle_set_italic_addr, sigv_mb); + textstyle_set_underline = linker.downcallHandle(textstyle_set_underline_addr, sigv_mb); + textstyle_set_color = linker.downcallHandle(textstyle_set_color_addr, sigv_miii); + textstyle_enable_color = linker.downcallHandle(textstyle_enable_color_addr, sigv_mb); + call_mainthread = linker.downcallHandle(call_mainthread_addr, sigv_mm); ui_malloc = linker.downcallHandle(ui_malloc_addr, sigm_ml); diff --git a/ui-kotlin/src/main/kotlin/de/unixwork/ui/kotlin/Toplevel.kt b/ui-kotlin/src/main/kotlin/de/unixwork/ui/kotlin/Toplevel.kt index c17fe8c..573b895 100644 --- a/ui-kotlin/src/main/kotlin/de/unixwork/ui/kotlin/Toplevel.kt +++ b/ui-kotlin/src/main/kotlin/de/unixwork/ui/kotlin/Toplevel.kt @@ -24,6 +24,7 @@ import de.unixwork.ui.UiWidget import de.unixwork.ui.WebView import de.unixwork.ui.Label import de.unixwork.ui.LinkButtonType +import de.unixwork.ui.ListStyleProvider import de.unixwork.ui.ListViewBuilder import de.unixwork.ui.TabViewType import de.unixwork.ui.TableModel @@ -1034,6 +1035,7 @@ class Toplevel(obj: UiObject) { styleClass: String? = null, onActivate: EventHandler? = null, onSelection: EventHandler? = null, + getstyle: ListStyleProvider? = null, getvalue: ListValueConverter? = null ): UiWidget { val table = ListView.table(ui) @@ -1080,6 +1082,9 @@ class Toplevel(obj: UiObject) { onSelection?.let { table.onSelection(it) } + getstyle?.let { + table.getstyle(it) + } getvalue?.let { table.getvalue(it) } -- 2.47.3