]> uap-core.de Git - rssreader.git/commitdiff
add table view
authorOlaf Wintermann <olaf.wintermann@gmail.com>
Mon, 25 Aug 2025 18:49:08 +0000 (20:49 +0200)
committerOlaf Wintermann <olaf.wintermann@gmail.com>
Mon, 25 Aug 2025 18:49:08 +0000 (20:49 +0200)
ui-java/src/main/java/de/unixwork/ui/ColumnDef.java [new file with mode: 0644]
ui-java/src/main/java/de/unixwork/ui/ColumnType.java [new file with mode: 0644]
ui-java/src/main/java/de/unixwork/ui/ListView.java
ui-java/src/main/java/de/unixwork/ui/TableModel.java [new file with mode: 0644]
ui-java/src/main/java/de/unixwork/ui/TableViewBuilder.java [new file with mode: 0644]
ui-java/src/main/java/de/unixwork/ui/ToolkitFuncs.java

diff --git a/ui-java/src/main/java/de/unixwork/ui/ColumnDef.java b/ui-java/src/main/java/de/unixwork/ui/ColumnDef.java
new file mode 100644 (file)
index 0000000..1a220d4
--- /dev/null
@@ -0,0 +1,28 @@
+package de.unixwork.ui;
+
+public class ColumnDef {
+    private String title;
+    private ColumnType type;
+    private int width;
+
+    public ColumnDef(String title, ColumnType type) {
+        this.title = title;
+        this.type = type;
+    }
+
+    public ColumnDef(String title, ColumnType type, int width) {
+        this.title = title;
+        this.type = type;
+        this.width = width;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+    public ColumnType getType() {
+        return type;
+    }
+    public int getWidth() {
+        return width;
+    }
+}
diff --git a/ui-java/src/main/java/de/unixwork/ui/ColumnType.java b/ui-java/src/main/java/de/unixwork/ui/ColumnType.java
new file mode 100644 (file)
index 0000000..3d9f609
--- /dev/null
@@ -0,0 +1,7 @@
+package de.unixwork.ui;
+
+public enum ColumnType {
+    STRING,
+    ICON,
+    ICON_TEXT
+}
index e3ea699c7cf79c4ae230361de2f5de4a0a823486..5d2aa03d6a1fade1758ec4ad1669820fb4168673 100644 (file)
@@ -1,7 +1,10 @@
 package de.unixwork.ui;
 
 public class ListView {
-
+    public static <T> TableViewBuilder<T> table(UiObject obj) {
+        ListFuncs ui = ListFuncs.getInstance();
+        return new TableViewBuilder<T>(obj, ui.listview_create);
+    }
 
     public static <T> ListViewBuilder<T> list(UiObject obj) {
         ListFuncs ui = ListFuncs.getInstance();
diff --git a/ui-java/src/main/java/de/unixwork/ui/TableModel.java b/ui-java/src/main/java/de/unixwork/ui/TableModel.java
new file mode 100644 (file)
index 0000000..cc767c1
--- /dev/null
@@ -0,0 +1,64 @@
+package de.unixwork.ui;
+
+import java.lang.foreign.Arena;
+import java.lang.foreign.MemorySegment;
+import java.util.ArrayList;
+
+public class TableModel {
+    private ArrayList<ColumnDef> columns = new ArrayList<>(16);
+
+    public TableModel() {
+
+    }
+
+    public void addColumn(ColumnDef col) {
+        columns.add(col);
+    }
+
+    public void addColumn(String title, ColumnType type) {
+        columns.add(new ColumnDef(title, type));
+    }
+
+    public void addColumn(String title, ColumnType type, int width) {
+        columns.add(new ColumnDef(title, type, width));
+    }
+
+    public ArrayList<ColumnDef> getColumns() {
+        return columns;
+    }
+
+    public void clearColumns() {
+        columns.clear();
+    }
+
+    public int getColumnCount() {
+        return columns.size();
+    }
+
+    /*
+     * convert this TableModel to a native UiModel
+     */
+    protected MemorySegment createModel(Context ctx) {
+        ToolkitFuncs ui = ToolkitFuncs.getInstance();
+        MemorySegment ctxPtr = ctx.getCtx();
+
+        MemorySegment model;
+        try(Arena arena = Arena.ofConfined()) {
+            model = (MemorySegment)ui.model_new.invoke(ctxPtr);
+            for(var col : columns) {
+                int type = 0;
+                switch(col.getType()) {
+                    case ColumnType.STRING: type = 0; break;
+                    case ColumnType.ICON: type = 3; break;
+                    case ColumnType.ICON_TEXT: type = 4; break;
+                }
+                MemorySegment cstr = arena.allocateFrom(col.getTitle());
+
+                ui.model_add_column.invoke(ctxPtr, model, type, cstr, col.getWidth());
+            }
+        } catch (Throwable e) {
+            throw new RuntimeException(e);
+        }
+        return model;
+    }
+}
diff --git a/ui-java/src/main/java/de/unixwork/ui/TableViewBuilder.java b/ui-java/src/main/java/de/unixwork/ui/TableViewBuilder.java
new file mode 100644 (file)
index 0000000..5c7cc50
--- /dev/null
@@ -0,0 +1,240 @@
+package de.unixwork.ui;
+
+import java.lang.foreign.Arena;
+import java.lang.foreign.MemorySegment;
+import java.lang.invoke.MethodHandle;
+
+public class TableViewBuilder<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 String varname;
+    private UiList<T> list;
+    private TableModel model;
+    // TODO: static elements
+    private ListValueConverter getvalue;
+    private EventHandler onActivate;
+    private EventHandler onSelection;
+    private EventHandler onDragStart;
+    private EventHandler onDragComplete;
+    private EventHandler onDrop;
+    private boolean multiselection;
+    // TODO: contextmenu
+    private int[] states;
+
+    private MemorySegment modelPtr;
+
+    public TableViewBuilder(UiObject obj, MethodHandle widgetConstructor) {
+        this.obj = obj;
+        this.widgetConstructor = widgetConstructor;
+        this.argsFree = ArgFuncs.getInstance().list_args_free;
+    }
+
+    public TableViewBuilder<T> fill(boolean fill) {
+        this.fill = fill;
+        return this;
+    }
+
+    public TableViewBuilder<T> hexpand(boolean hexpand) {
+        this.hexpand = hexpand;
+        return this;
+    }
+
+    public TableViewBuilder<T> vexpand(boolean vexpand) {
+        this.vexpand = vexpand;
+        return this;
+    }
+
+    public TableViewBuilder<T> hfill(boolean hfill) {
+        this.hfill = hfill;
+        return this;
+    }
+
+    public TableViewBuilder<T> vfill(boolean vfill) {
+        this.vfill = vfill;
+        return this;
+    }
+
+    public TableViewBuilder<T> overrideDefaults(boolean overrideDefaults) {
+        this.overrideDefaults = overrideDefaults;
+        return this;
+    }
+
+    public TableViewBuilder<T> colspan(int colspan) {
+        this.colspan = colspan;
+        return this;
+    }
+
+    public TableViewBuilder<T> rowspan(int rowspan) {
+        this.rowspan = rowspan;
+        return this;
+    }
+
+    public TableViewBuilder<T> name(String name) {
+        this.name = name;
+        return this;
+    }
+
+
+    public TableViewBuilder<T> styleClass(String styleClass) {
+        this.styleClass = styleClass;
+        return this;
+    }
+
+    public TableViewBuilder<T> varname(String varname) {
+        this.varname = varname;
+        return this;
+    }
+
+    public TableViewBuilder<T> value(UiList<T> list) {
+        this.list = list;
+        return this;
+    }
+
+    public TableViewBuilder<T> model(TableModel model) {
+        this.model = model;
+        return this;
+    }
+
+    public TableViewBuilder<T> getvalue(ListValueConverter<T> getvalue) {
+        this.getvalue = getvalue;
+        return this;
+    }
+
+    public TableViewBuilder<T> onActivate(EventHandler onActivate) {
+        this.onActivate = onActivate;
+        return this;
+    }
+
+    public TableViewBuilder<T> onSelection(EventHandler onSelection) {
+        this.onSelection = onSelection;
+        return this;
+    }
+
+    public TableViewBuilder<T> onDragStart(EventHandler onDragStart) {
+        this.onDragStart = onDragStart;
+        return this;
+    }
+
+    public TableViewBuilder<T> onDragComplete(EventHandler onDragComplete) {
+        this.onDragComplete = onDragComplete;
+        return this;
+    }
+
+    public TableViewBuilder<T> onDrop(EventHandler onDrop) {
+        this.onDrop = onDrop;
+        return this;
+    }
+
+    public TableViewBuilder<T> states(int... states) {
+        this.states = states;
+        return this;
+    }
+
+    public MemorySegment createArgs(Arena arena) throws Throwable {
+        ArgFuncs ui = ArgFuncs.getInstance();
+
+        args = (MemorySegment) ui.list_args_new.invoke();
+        if (fill) {
+            ui.list_args_set_fill.invoke(args, fill);
+        }
+        if (hexpand) {
+            ui.list_args_set_hexpand.invoke(args, hexpand);
+        }
+        if (vexpand) {
+            ui.list_args_set_vexpand.invoke(args, vexpand);
+        }
+        if (hfill) {
+            ui.list_args_set_hfill.invoke(args, hfill);
+        }
+        if (vfill) {
+            ui.list_args_set_vfill.invoke(args, vfill);
+        }
+        if (overrideDefaults) {
+            ui.list_args_set_override_defaults.invoke(args, overrideDefaults);
+        }
+        if (colspan > 0) {
+            ui.list_args_set_colspan.invoke(args, colspan);
+        }
+        if (rowspan > 0) {
+            ui.list_args_set_rowspan.invoke(args, rowspan);
+        }
+        if (name != null) {
+            MemorySegment cstr = arena.allocateFrom(name);
+            ui.list_args_set_name.invoke(args, cstr);
+        }
+        if (styleClass != null) {
+            MemorySegment cstr = arena.allocateFrom(styleClass);
+            ui.list_args_set_style_class.invoke(args, cstr);
+        }
+        if(varname != null) {
+            MemorySegment cstr = arena.allocateFrom(varname);
+            ui.list_args_set_varname.invoke(args, cstr);
+        }
+        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(model != null) {
+            modelPtr = model.createModel(obj);
+            ui.list_args_set_model.invoke(args, modelPtr);
+        }
+
+        if (onActivate != null) {
+            EventWrapper event = new EventWrapper(obj, onActivate);
+            // set toolkit args
+            ui.list_args_set_onactivate.invoke(args, event.getCallback());
+            ui.list_args_set_onactivatedata.invoke(args, event.getUserData());
+        }
+        if (onSelection != null) {
+            EventWrapper event = new EventWrapper(obj, onSelection);
+            // set toolkit args
+            ui.list_args_set_onselection.invoke(args, event.getCallback());
+            ui.list_args_set_onselectiondata.invoke(args, event.getUserData());
+        }
+        if (onDragStart != null) {
+            EventWrapper event = new EventWrapper(obj, onDragStart);
+            // set toolkit args
+            ui.list_args_set_ondragstart.invoke(args, event.getCallback());
+            ui.list_args_set_ondragstartdata.invoke(args, event.getUserData());
+        }
+        if (onDragComplete != null) {
+            EventWrapper event = new EventWrapper(obj, onDragComplete);
+            // set toolkit args
+            ui.list_args_set_ondragcomplete.invoke(args, event.getCallback());
+            ui.list_args_set_ondragcompletedata.invoke(args, event.getUserData());
+        }
+        if (onDrop != null) {
+            EventWrapper event = new EventWrapper(obj, onDrop);
+            // set toolkit args
+            ui.list_args_set_ondrop.invoke(args, event.getCallback());
+            ui.list_args_set_ondropdata.invoke(args, event.getUserData());
+        }
+
+        return args;
+    }
+
+    void freeArgs() {
+        super.freeArgs();
+        ToolkitFuncs ui = ToolkitFuncs.getInstance();
+        if(model != null) {
+            try {
+                ui.model_free.invoke(obj.getCtx(), modelPtr);
+            } catch (Throwable e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+}
index a7db8b753c43a98ae9bfb1f5cef84012da76d525..0e44164a5b1a3dab7a379be69d26143ae739ac97 100644 (file)
@@ -63,6 +63,10 @@ public class ToolkitFuncs {
     public MethodHandle text_set;
     public MethodHandle text_get;
 
+    public MethodHandle model_new;
+    public MethodHandle model_add_column;
+    public MethodHandle model_free;
+
     public MethodHandle call_mainthread;
 
     public MethodHandle ui_malloc;
@@ -85,6 +89,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_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();
 
@@ -143,6 +148,10 @@ public class ToolkitFuncs {
         MemorySegment text_set_addr = lib.find("ui_text_set").orElseThrow();
         MemorySegment text_get_addr = lib.find("ui_text_get").orElseThrow();
 
+        MemorySegment model_new_addr = lib.find("ui_model_new").orElseThrow();
+        MemorySegment model_add_column_addr = lib.find("ui_model_add_column").orElseThrow();
+        MemorySegment model_free_addr = lib.find("ui_model_free").orElseThrow();
+
         MemorySegment call_mainthread_addr = lib.find("ui_call_mainthread").orElseThrow();
 
         MemorySegment ui_malloc_addr = lib.find("ui_malloc").orElseThrow();
@@ -210,6 +219,10 @@ public class ToolkitFuncs {
         text_set = linker.downcallHandle(text_set_addr, sigv_mm);
         text_get = linker.downcallHandle(text_get_addr, sigm_m);
 
+        model_new = linker.downcallHandle(model_new_addr, sigm_m);
+        model_add_column = linker.downcallHandle(model_add_column_addr, sigv_mmimi);
+        model_free = linker.downcallHandle(model_free_addr, sigv_m);
+
         call_mainthread = linker.downcallHandle(call_mainthread_addr, sigv_mm);
 
         ui_malloc = linker.downcallHandle(ui_malloc_addr, sigm_ml);