]> uap-core.de Git - rssreader.git/commitdiff
implement list/table getstyle func
authorOlaf Wintermann <olaf.wintermann@gmail.com>
Sun, 31 Aug 2025 09:31:31 +0000 (11:31 +0200)
committerOlaf Wintermann <olaf.wintermann@gmail.com>
Sun, 31 Aug 2025 09:31:31 +0000 (11:31 +0200)
rss-application/src/main/kotlin/de/unixwork/rssreader/MainWindow.kt
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/ListStyleProvider.java [new file with mode: 0644]
ui-java/src/main/java/de/unixwork/ui/ListViewBuilder.java
ui-java/src/main/java/de/unixwork/ui/TableViewBuilder.java
ui-java/src/main/java/de/unixwork/ui/TextStyle.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-kotlin/src/main/kotlin/de/unixwork/ui/kotlin/Toplevel.kt

index 3ea9eed3df0539f1f7d79048f9cac1c06fabc17c..d27fabcd9ff2e996941b39dc465c0b4a31f17118 100644 (file)
@@ -71,6 +71,9 @@ class MainWindow {
                             feedList.items.selected?.let {
                                 feedList.selectItem(it)
                             }
+                        },
+                        getstyle = { elm, col, style ->
+                            false
                         }
                         )
                     { elm, col ->
index 03818b4de914aacda2897941489b4e865fd17287..0e4ec9b5aea7d616b64f1e9dda72edc6e2d883c9 100644 (file)
@@ -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);
index b9242171caa4b2a151286065d7373c2eb9ea610a..7032847837c8c26c973c12d6a8abdf145b32026e 100644 (file)
@@ -12,6 +12,7 @@ public abstract class Context {
 
     private ArrayList<UiList> lists = new ArrayList<>();
     private ArrayList<ListValueConverter> converters = new ArrayList<>();
+    private ArrayList<ListStyleProvider> styleProviders = new ArrayList<>();
     private ArrayList<SubListValueConverter> 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 (file)
index 0000000..7c8f4e3
--- /dev/null
@@ -0,0 +1,6 @@
+package de.unixwork.ui;
+
+@FunctionalInterface
+public interface ListStyleProvider<T> {
+    public boolean getStyle(T elm, int column, TextStyle style);
+}
index aefab56fecea9fe733e4c492bb8c6ffb19948527..b6faf6097c4e3212cb1d2b92e314a9f5a893264b 100644 (file)
@@ -19,7 +19,8 @@ public class ListViewBuilder<T> extends AbstractWidgetBuilder {
     private UiList<T> list;
     // TODO: model
     // TODO: static elements
-    private ListValueConverter getvalue;
+    private ListValueConverter<T> getvalue;
+    private ListStyleProvider<T> getstyle;
     private EventHandler onActivate;
     private EventHandler onSelection;
     private EventHandler onDragStart;
@@ -101,6 +102,11 @@ public class ListViewBuilder<T> extends AbstractWidgetBuilder {
         return this;
     }
 
+    public ListViewBuilder<T> getstyle(ListStyleProvider<T> getstyle) {
+        this.getstyle = getstyle;
+        return this;
+    }
+
     public ListViewBuilder<T> onActivate(EventHandler onActivate) {
         this.onActivate = onActivate;
         return this;
@@ -174,11 +180,21 @@ public class ListViewBuilder<T> 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) {
index 87439a0bf38a03c44119918e97700a6af239ec54..544eacc300cafa31c55f8208eea8202854f9a4c2 100644 (file)
@@ -20,6 +20,7 @@ public class TableViewBuilder<T> extends AbstractWidgetBuilder {
     private TableModel model;
     // TODO: static elements
     private ListValueConverter getvalue;
+    private ListStyleProvider<T> getstyle;
     private EventHandler onActivate;
     private EventHandler onSelection;
     private EventHandler onDragStart;
@@ -108,6 +109,11 @@ public class TableViewBuilder<T> extends AbstractWidgetBuilder {
         return this;
     }
 
+    public TableViewBuilder<T> getstyle(ListStyleProvider<T> getstyle) {
+        this.getstyle = getstyle;
+        return this;
+    }
+
     public TableViewBuilder<T> onActivate(EventHandler onActivate) {
         this.onActivate = onActivate;
         return this;
@@ -187,6 +193,11 @@ public class TableViewBuilder<T> 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 (file)
index 0000000..ef903ec
--- /dev/null
@@ -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);
+        }
+    }
+}
index 97181767d3d3d30b9b66c29bcfca302ffb5f1e36..8a8dbc5143c7488a26007c1ae4a99cbd51f2fc0b 100644 (file)
@@ -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();
index 885640dd256a8e35efd12a317e56e8cf34683e8e..19a4bcbf0605aacec381d5919715d0e5ed2d195e 100644 (file)
@@ -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);
index c17fe8c4863c476e18354aa9f5ef854b7d8e9c83..573b895e7e8e6ce1d882176225d406644881834b 100644 (file)
@@ -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<T>? = null,
         getvalue: ListValueConverter<T>? = null
     ): UiWidget {
         val table = ListView.table<T>(ui)
@@ -1080,6 +1082,9 @@ class Toplevel(obj: UiObject) {
         onSelection?.let {
             table.onSelection(it)
         }
+        getstyle?.let {
+            table.getstyle(it)
+        }
         getvalue?.let {
             table.getvalue(it)
         }