]> uap-core.de Git - rssreader.git/commitdiff
implement ListSaveHandler callback
authorOlaf Wintermann <olaf.wintermann@gmail.com>
Tue, 30 Sep 2025 17:51:45 +0000 (19:51 +0200)
committerOlaf Wintermann <olaf.wintermann@gmail.com>
Tue, 30 Sep 2025 17:51:45 +0000 (19:51 +0200)
ui-java/src/main/java/de/unixwork/ui/ArgFuncs.java
ui-java/src/main/java/de/unixwork/ui/ListSaveHandler.java
ui-java/src/main/java/de/unixwork/ui/ListSaveWrapper.java
ui-java/src/main/java/de/unixwork/ui/TableViewBuilder.java
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/UiObject.java

index cdc010b337212dbd3acb764f0075101d3fb9e6d3..ad2c1ab7ea2d528177f79c1f24d8a22a01d64015 100644 (file)
@@ -326,6 +326,8 @@ class ArgFuncs {
     MethodHandle list_args_set_ondragcompletedata;
     MethodHandle list_args_set_ondrop;
     MethodHandle list_args_set_ondropdata;
+    MethodHandle list_args_set_onsave;
+    MethodHandle list_args_set_onsavedata;
     MethodHandle list_args_set_multiselection;
     MethodHandle list_args_set_contextmenu;
     MethodHandle list_args_set_groups;
@@ -762,6 +764,8 @@ class ArgFuncs {
         MemorySegment ui_list_args_set_ondragcompletedata_addr = lib.find("ui_list_args_set_ondragcompletedata").orElseThrow();
         MemorySegment ui_list_args_set_ondrop_addr = lib.find("ui_list_args_set_ondrop").orElseThrow();
         MemorySegment ui_list_args_set_ondropdata_addr = lib.find("ui_list_args_set_ondropdata").orElseThrow();
+        MemorySegment ui_list_args_set_onsave_addr = lib.find("ui_list_args_set_onsave").orElseThrow();
+        MemorySegment ui_list_args_set_onsavedata_addr = lib.find("ui_list_args_set_onsavedata").orElseThrow();
         MemorySegment ui_list_args_set_multiselection_addr = lib.find("ui_list_args_set_multiselection").orElseThrow();
         MemorySegment ui_list_args_set_contextmenu_addr = lib.find("ui_list_args_set_contextmenu").orElseThrow();
         MemorySegment ui_list_args_set_groups_addr = lib.find("ui_list_args_set_groups").orElseThrow();
@@ -1188,6 +1192,8 @@ class ArgFuncs {
         list_args_set_ondragcompletedata = linker.downcallHandle(ui_list_args_set_ondragcompletedata_addr, sigv_mm);
         list_args_set_ondrop = linker.downcallHandle(ui_list_args_set_ondrop_addr, sigv_mm);
         list_args_set_ondropdata = linker.downcallHandle(ui_list_args_set_ondropdata_addr, sigv_mm);
+        list_args_set_onsave = linker.downcallHandle(ui_list_args_set_onsave_addr, sigv_mm);
+        list_args_set_onsavedata = linker.downcallHandle(ui_list_args_set_onsavedata_addr, sigv_mm);
         list_args_set_multiselection = linker.downcallHandle(ui_list_args_set_multiselection_addr, sigv_mb);
         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_mmi);
index 421d222f431963ca97d8df6d3923b985dbd458e4..d1ff160cddc38abc5ef8e0232fa2f375482cd28c 100644 (file)
@@ -1,6 +1,6 @@
 package de.unixwork.ui;
 
 @FunctionalInterface
-public interface ListSaveFunc {
+public interface ListSaveHandler {
     public boolean save(UiList list, int row, int column, Object value);
 }
index 45fe5a60a30b38c4da6c3c456ab797e00ff0d443..7b9bb10b460fabda7a164f4919553d987f8ccc47 100644 (file)
@@ -1,4 +1,62 @@
 package de.unixwork.ui;
 
+import java.lang.foreign.Arena;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.ValueLayout;
+
 public class ListSaveWrapper {
+    private MemorySegment callback;
+    private MemorySegment userdata;
+
+    public ListSaveWrapper(UiObject obj, ListSaveHandler handler) {
+        Arena objArena = obj.getArena(); // very important to use the obj arena
+        callback = Toolkit.getInstance().eventHandler;
+
+        long index = obj.addListSaveHandler(handler);
+
+        userdata = objArena.allocate(ValueLayout.JAVA_LONG, 2);
+        userdata.setAtIndex(ValueLayout.JAVA_LONG, 0, obj.ptr.address());
+        userdata.setAtIndex(ValueLayout.JAVA_LONG, 1, index);
+    }
+
+    public static boolean onSaveHandler(MemorySegment list, int row, int col, MemorySegment value, MemorySegment userData) {
+        Toolkit tk = Toolkit.getInstance();
+        ToolkitFuncs ui = ToolkitFuncs.getInstance();
+
+        userData = userData.reinterpret(16);
+        long objPtr = userData.getAtIndex(ValueLayout.JAVA_LONG, 0);
+        long handlerIndex = userData.getAtIndex(ValueLayout.JAVA_LONG, 1);
+        UiObject obj = tk.getToplevelObject(objPtr);
+        if(obj == null) {
+            return false;
+        }
+        ListSaveHandler handler = obj.getListSaveHandler((int)handlerIndex);
+        if(handler == null) {
+            return false;
+        }
+
+        UiList uilist = Toolkit.listPtrToObject(list);
+
+        Object valueObj = null;
+        try {
+            if((boolean) ui.cell_value_is_string.invoke(value)) {
+                MemorySegment cstr = (MemorySegment) ui.cell_value_get_string.invoke(value);
+                valueObj = (String)cstr.getString(0);
+            } else if((boolean) ui.cell_value_is_int.invoke(value)) {
+                valueObj = ui.cell_value_get_int.invoke(value);
+            }
+        } catch (Throwable e) {
+            throw new RuntimeException(e);
+        }
+
+        return handler.save(uilist, row, col, valueObj);
+    }
+
+    public MemorySegment getCallback() {
+        return callback;
+    }
+
+    public MemorySegment getUserData() {
+        return userdata;
+    }
 }
index ecbf9b2b08b74c7e02fbc5004750c5590188c22d..71a12924c7b898794763a1da31791addf0dcfdd4 100644 (file)
@@ -27,6 +27,7 @@ public class TableViewBuilder<T> extends AbstractWidgetBuilder {
     private EventHandler onDragStart;
     private EventHandler onDragComplete;
     private EventHandler onDrop;
+    private ListSaveHandler onSave;
     private boolean multiselection;
     private Menu contextMenu;
     // TODO: contextmenu
@@ -148,6 +149,11 @@ public class TableViewBuilder<T> extends AbstractWidgetBuilder {
         return this;
     }
 
+    public TableViewBuilder<T> onSave(ListSaveHandler onSave) {
+        this.onSave = onSave;
+        return this;
+    }
+
     public TableViewBuilder<T> states(int... states) {
         this.states = states;
         return this;
@@ -242,6 +248,11 @@ public class TableViewBuilder<T> extends AbstractWidgetBuilder {
             ui.list_args_set_ondrop.invoke(args, event.getCallback());
             ui.list_args_set_ondropdata.invoke(args, event.getUserData());
         }
+        if (onSave != null) {
+            ListSaveWrapper handler = new ListSaveWrapper(obj, onSave);
+            ui.list_args_set_onsave.invoke(args, handler.getCallback());
+            ui.list_args_set_onsavedata.invoke(args, handler.getUserData());
+        }
         if (contextMenu != null) {
             menuBuilder = contextMenu.createMenuBuilder();
             ui.list_args_set_contextmenu.invoke(args, menuBuilder);
index f6cc63e179739a3499125ddab6a71f7b5d96026e..bd2e9f8716d27ff6d0cafafba787dc027d511f65 100644 (file)
@@ -50,6 +50,7 @@ public class Toolkit {
     protected MemorySegment eventHandler;
     protected MemorySegment globalEventHandler;
     protected MemorySegment oneshotEventHandler;
+    protected MemorySegment onSaveHandler;
 
     private HashMap<Integer, ThreadCallback> threadCallbacks = new HashMap<>();
 
@@ -280,6 +281,22 @@ public class Toolkit {
                 oneshotCallbackMethod,
                 handlerSig,
                 staticArena);
+
+        try {
+            MethodHandle onSaveMethod = MethodHandles.lookup().findStatic(
+                    ListSaveWrapper.class,
+                    "onSaveHandler",
+                    MethodType.methodType(boolean.class, MemorySegment.class, int.class, int.class, MemorySegment.class, MemorySegment.class));
+
+            onSaveHandler = linker.upcallStub(
+                    onSaveMethod,
+                    FunctionDescriptor.of(ValueLayout.JAVA_BOOLEAN, ValueLayout.ADDRESS, ValueLayout.JAVA_INT, ValueLayout.JAVA_INT, ValueLayout.ADDRESS, ValueLayout.ADDRESS),
+                    staticArena);
+        } catch (NoSuchMethodException e) {
+            throw new RuntimeException(e);
+        } catch (IllegalAccessException e) {
+            throw new RuntimeException(e);
+        }
     }
 
     public static Toolkit getInstance() {
index 84dd14fbfef349275e8e8b72fffd40e51c02c5e9..5e21bc035e33bda9a2b152d616c1d1a896d3524c 100644 (file)
@@ -80,6 +80,11 @@ public class ToolkitFuncs {
     public MethodHandle textstyle_set_color;
     public MethodHandle textstyle_enable_color;
 
+    public MethodHandle cell_value_is_string;
+    public MethodHandle cell_value_is_int;
+    public MethodHandle cell_value_get_string;
+    public MethodHandle cell_value_get_int;
+
     public MemorySegment ui_set_visible_addr;
     public MemorySegment ui_set_enabled_addr;
 
@@ -124,6 +129,7 @@ public class ToolkitFuncs {
         FunctionDescriptor sigv_mdd = FunctionDescriptor.ofVoid(ValueLayout.ADDRESS, ValueLayout.JAVA_DOUBLE, ValueLayout.JAVA_DOUBLE);
         FunctionDescriptor sigv_mmmi = FunctionDescriptor.ofVoid(ValueLayout.ADDRESS, ValueLayout.ADDRESS, ValueLayout.ADDRESS, ValueLayout.JAVA_INT);
         FunctionDescriptor sigv_mmmmi = FunctionDescriptor.ofVoid(ValueLayout.ADDRESS, ValueLayout.ADDRESS, ValueLayout.ADDRESS, ValueLayout.ADDRESS, ValueLayout.JAVA_INT);
+        FunctionDescriptor sigb_m = FunctionDescriptor.of(ValueLayout.JAVA_BOOLEAN, ValueLayout.ADDRESS);
 
         MemorySegment object_get_context_addr = lib.find("ui_object_get_context").orElseThrow();
 
@@ -199,6 +205,11 @@ public class ToolkitFuncs {
         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 cell_value_is_string_addr = lib.find("ui_cell_value_is_string").orElseThrow();
+        MemorySegment cell_value_is_int_addr = lib.find("ui_cell_value_is_int").orElseThrow();
+        MemorySegment cell_value_get_string_addr = lib.find("ui_cell_value_get_string").orElseThrow();
+        MemorySegment cell_value_get_int_addr = lib.find("ui_cell_value_get_int").orElseThrow();
+
         ui_set_visible_addr = lib.find("ui_set_visible").orElseThrow();
         ui_set_enabled_addr = lib.find("ui_set_enabled").orElseThrow();
         MemorySegment ui_widget_set_groups2_addr = lib.find("ui_widget_set_groups2").orElseThrow();
@@ -294,6 +305,11 @@ public class ToolkitFuncs {
         textstyle_set_color = linker.downcallHandle(textstyle_set_color_addr, sigv_miii);
         textstyle_enable_color = linker.downcallHandle(textstyle_enable_color_addr, sigv_mb);
 
+        cell_value_is_string = linker.downcallHandle(cell_value_is_string_addr, sigb_m);
+        cell_value_is_int = linker.downcallHandle(cell_value_is_int_addr, sigb_m);
+        cell_value_get_string = linker.downcallHandle(cell_value_get_string_addr, sigm_m);
+        cell_value_get_int = linker.downcallHandle(cell_value_get_int_addr, sigl_m);
+
         set_enabled = linker.downcallHandle(ui_set_enabled_addr, sigv_mi);
         set_visible = linker.downcallHandle(ui_set_visible_addr, sigv_mi);
         set_widget_groups2 = linker.downcallHandle(ui_widget_set_groups2_addr, sigv_mmmmi);
index f55031b48c633f723c53299917c1713b1f670d94..4b49d1e49a093a2422e9c1124ea4c2f82d0278ab 100644 (file)
@@ -9,6 +9,7 @@ public class UiObject extends Context {
 
     private ArrayList<EventHandler> eventHandlers = new ArrayList<>();
     private ArrayList<ObjectDestroyHandler> closeHandlers = new ArrayList<>();
+    private ArrayList<ListSaveHandler> listSaveHandlers = new ArrayList<>();
 
     private Arena arena;
 
@@ -91,6 +92,15 @@ public class UiObject extends Context {
         return eventHandlers.get(index);
     }
 
+    public long addListSaveHandler(ListSaveHandler handler) {
+        listSaveHandlers.add(handler);
+        return listSaveHandlers.size() - 1;
+    }
+
+    public ListSaveHandler getListSaveHandler(int index) {
+        return listSaveHandlers.get(index);
+    }
+
     public Arena getArena() {
         if (arena == null) {
             arena = Arena.ofShared();