]> uap-core.de Git - rssreader.git/commitdiff
add ui for creating categories and feeds
authorOlaf Wintermann <olaf.wintermann@gmail.com>
Tue, 12 Aug 2025 12:04:08 +0000 (14:04 +0200)
committerOlaf Wintermann <olaf.wintermann@gmail.com>
Tue, 12 Aug 2025 12:04:08 +0000 (14:04 +0200)
rss-application/src/main/kotlin/de/unixwork/rssreader/MainWindow.kt
ui-java/src/main/java/de/unixwork/ui/DialogWindowBuilder.java
ui-java/src/main/java/de/unixwork/ui/EventWrapper.java
ui-java/src/main/java/de/unixwork/ui/UiObject.java
ui-java/src/main/java/de/unixwork/ui/UiObjectFuncs.java
ui-kotlin/src/main/kotlin/de/unixwork/ui/kotlin/Toplevel.kt
ui-kotlin/src/main/kotlin/de/unixwork/ui/kotlin/Window.kt

index 473b0150dbd4c1aec6c2c2dbfb0655248665c457..1b8d9dfbf33477a511a439be58021d408de58fe2 100644 (file)
@@ -1,10 +1,9 @@
 package de.unixwork.rssreader
 
 import de.unixwork.ui.SubListItem
-import de.unixwork.ui.UiObject
-import de.unixwork.ui.UiSourceList
 import de.unixwork.ui.kotlin.Toplevel
 import de.unixwork.ui.kotlin.sidebarWindow
+import de.unixwork.ui.kotlin.dialogWindow
 
 class MainWindow {
     val window : Toplevel
@@ -20,10 +19,10 @@ class MainWindow {
                     }
                     hbox(margin = 4, spacing = 4) {
                         button(icon = "list-add") {
-
+                            createFeedDialog()
                         }
                         button(icon = "folder-new") {
-
+                            createCategoryDialog()
                         }
                     }
                 }
@@ -44,7 +43,67 @@ class MainWindow {
         }
     }
 
+    private fun createFeedDialog() {
+        val w = dialogWindow(
+            parent = window.ui,
+            title = "Add Feed",
+            lbutton1 = "Add",
+            rbutton4 = "Cancel",
+            onClick = { ev ->
+                ev.`object`.close()
+            },
+            modal = true)
+        {
+            grid(
+                margin = 12,
+                columnspacing = 8,
+                rowspacing = 8,
+                defhfill = true,
+                defvfill = true,
+                fill = true)
+            {
+                row {
+                    rlabel("Category")
+                    dropdown<String>(varname = "group", hexpand = true) { elm, column ->
+                        ""
+                    }
+                }
+                row {
+                    rlabel("Name")
+                    textfield(varname = "name", hexpand = true)
+                }
+                row {
+                    rlabel("URLs", overrideDefaults = true, hfill = true) // overrideDefaults for disabling default vfill
+                    textarea(varname = "url", hexpand = true, vexpand = true, vfill = true)
+                }
+            }
+        }
+        w.show()
+    }
 
+    private fun createCategoryDialog() {
+        val w = dialogWindow(
+            parent = window.ui,
+            title = "Add Category",
+            lbutton1 = "Add",
+            modal = true)
+        {
+            grid(
+                margin = 12,
+                columnspacing = 8,
+                rowspacing = 8,
+                defhfill = true,
+                defvfill = true,
+                fill = true)
+            {
+                row {
+                    rlabel("Name")
+                    textfield(varname = "name", hexpand = true)
+                }
+            }
+        }
+        w.show()
+    }
 
     fun show() {
         window.show()
index 0efdae6d2bd41ea07de3c640ccdf56d05d29c813..40a3857f9232927feca8c73cba2e72aad1cb9f02 100644 (file)
@@ -125,13 +125,14 @@ public class DialogWindowBuilder {
             ui.dialogwindow_args_set_width.invoke(args, width);
             ui.dialogwindow_args_set_height.invoke(args, height);
 
-            UiObject obj = UiObjectFuncs.instance.dialogWindow(parent.ptr, args);
             if(onClick != null) {
-                EventWrapper event = new EventWrapper(obj, onClick);
+                EventWrapper event = new EventWrapper(onClick);
                 ui.dialogwindow_args_set_onclick.invoke(args, event.getCallback());
                 ui.dialogwindow_args_set_onclickdata.invoke(args, event.getUserData());
             }
 
+            UiObject obj = UiObjectFuncs.instance.dialogWindow(parent.ptr, args);
+
             ui.dialogwindow_args_free.invoke(args);
             return obj;
         } catch (Throwable e) {
index 4d3af33377541a64ef1957b12dc61824e02dac74..5f72a7bef32133f72cc1cff5496f8c22fdbaaa1a 100644 (file)
@@ -34,7 +34,7 @@ public class EventWrapper {
             long index = toolkit.addOneshotEventHandler(handler);
             userdata = MemorySegment.ofAddress(index);
         } else {
-            callback = toolkit.eventHandler;
+            callback = toolkit.globalEventHandler;
             long index = toolkit.addEventHandler(handler);
             userdata = MemorySegment.ofAddress(index);
         }
index 7a8879308137f9ec270731b12131fb472a23a152..bfcafae6ef71b05980c081f8d1d866fea2f17c0b 100644 (file)
@@ -49,6 +49,10 @@ public class UiObject extends Context {
         UiObjectFuncs.instance.show(this);
     }
 
+    public void close() {
+        UiObjectFuncs.instance.close(this);
+    }
+
     public long addEventHandler(EventHandler handler) {
         eventHandlers.add(handler);
         return eventHandlers.size() - 1;
index faeb691f6e82865b0e3374dbd904c1717dd0f43d..c5190fb5bc4db0abbfeb75fb1bbc8c4b4cb31ab1 100644 (file)
@@ -7,6 +7,7 @@ class UiObjectFuncs {
     static UiObjectFuncs instance;
 
     public MethodHandle ui_show;
+    public MethodHandle ui_close;
     public MethodHandle ui_window;
     public MethodHandle ui_sidebar_window;
     public MethodHandle ui_simple_window;
@@ -27,6 +28,7 @@ class UiObjectFuncs {
         FunctionDescriptor sigv_mmmm = FunctionDescriptor.ofVoid(ValueLayout.ADDRESS, ValueLayout.ADDRESS, ValueLayout.ADDRESS, ValueLayout.ADDRESS);
 
         MemorySegment ui_show_addr = lib.find("ui_show").orElseThrow();
+        MemorySegment ui_close_addr = lib.find("ui_close").orElseThrow();
         MemorySegment ui_window_addr = lib.find("ui_window").orElseThrow();
         MemorySegment ui_sidebar_window_addr = lib.find("ui_sidebar_window").orElseThrow();
         MemorySegment ui_simple_window_addr = lib.find("ui_simple_window").orElseThrow();
@@ -36,6 +38,7 @@ class UiObjectFuncs {
         MemorySegment ui_savefiledialog_addr = lib.find("ui_savefiledialog").orElseThrow();
 
         ui_show = linker.downcallHandle(ui_show_addr, sigv_m);
+        ui_close = linker.downcallHandle(ui_close_addr, sigv_m);
         ui_window = linker.downcallHandle(ui_window_addr, sigm_mm);
         ui_sidebar_window = linker.downcallHandle(ui_sidebar_window_addr, sigm_mm);
         ui_simple_window = linker.downcallHandle(ui_simple_window_addr, sigm_mm);
@@ -106,6 +109,12 @@ class UiObjectFuncs {
         }
     }
 
+    void close(UiObject obj) {
+        try {
+            ui_close.invoke(obj.ptr);
+        } catch (Throwable e) {}
+    }
+
     public void openFileDialog(UiObject obj, int mode, EventHandler callback) {
         EventWrapper ew = new EventWrapper(callback, true);
         try {
index d337cb31197e2cd1d69a31c8b3ca4140ba28b59c..3180c884b7e9340c89c83f6bb98701c68b29a2c9 100644 (file)
@@ -22,6 +22,9 @@ import de.unixwork.ui.UiString
 import de.unixwork.ui.UiWidget
 import de.unixwork.ui.WebView
 import de.unixwork.ui.Label
+import de.unixwork.ui.ListViewBuilder
+import de.unixwork.ui.UiText
+import java.awt.TextArea
 
 class Toplevel(obj: UiObject) {
     val ui: UiObject = obj
@@ -30,6 +33,10 @@ class Toplevel(obj: UiObject) {
         ui.show()
     }
 
+    fun close() {
+        ui.close()
+    }
+
     operator fun invoke(block: Toplevel.() -> Unit) {
         block()
     }
@@ -700,7 +707,8 @@ class Toplevel(obj: UiObject) {
         )
     }
 
-    fun <T>listview(
+    fun <T>createListView(
+        list: ListViewBuilder<T>,
         varname: String? = null,
         value: UiList<T>? = null,
         fill: Boolean = false,
@@ -715,7 +723,6 @@ class Toplevel(obj: UiObject) {
         styleClass: String? = null,
         getvalue: ListValueConverter<T>? = null
     ): UiWidget {
-        val list = ListView.list<T>(ui)
         varname?.let {
             list.varname(varname)
         }
@@ -758,6 +765,74 @@ class Toplevel(obj: UiObject) {
         return list.create()
     }
 
+    fun <T>listview(
+        varname: String? = null,
+        value: UiList<T>? = null,
+        fill: Boolean = false,
+        hexpand: Boolean = false,
+        vexpand: Boolean = false,
+        hfill: Boolean = false,
+        vfill: Boolean = false,
+        overrideDefaults: Boolean = false,
+        colspan: Int = -1,
+        rowspan: Int = -1,
+        name: String? = null,
+        styleClass: String? = null,
+        getvalue: ListValueConverter<T>? = null
+    ): UiWidget {
+        val list = ListView.list<T>(ui)
+        return createListView(
+            list = list,
+            varname = varname,
+            value = value,
+            fill = fill,
+            hexpand = hexpand,
+            vexpand = vexpand,
+            hfill = hfill,
+            vfill = vfill,
+            overrideDefaults = overrideDefaults,
+            colspan = colspan,
+            rowspan = rowspan,
+            name = name,
+            styleClass = styleClass,
+            getvalue = getvalue
+        )
+    }
+
+    fun <T>dropdown(
+        varname: String? = null,
+        value: UiList<T>? = null,
+        fill: Boolean = false,
+        hexpand: Boolean = false,
+        vexpand: Boolean = false,
+        hfill: Boolean = false,
+        vfill: Boolean = false,
+        overrideDefaults: Boolean = false,
+        colspan: Int = -1,
+        rowspan: Int = -1,
+        name: String? = null,
+        styleClass: String? = null,
+        getvalue: ListValueConverter<T>? = null
+    ): UiWidget {
+        val list = ListView.dropdown<T>(ui)
+        return createListView(
+            list = list,
+            varname = varname,
+            value = value,
+            fill = fill,
+            hexpand = hexpand,
+            vexpand = vexpand,
+            hfill = hfill,
+            vfill = vfill,
+            overrideDefaults = overrideDefaults,
+            colspan = colspan,
+            rowspan = rowspan,
+            name = name,
+            styleClass = styleClass,
+            getvalue = getvalue
+        )
+    }
+
     fun <T>sourcelist(
         varname: String? = null,
         sourceList: UiSourceList? = null,
@@ -816,6 +891,64 @@ class Toplevel(obj: UiObject) {
         return list.create()
     }
 
+    fun textarea(
+        varname: String? = null,
+        value: UiText? = null,
+        fill: Boolean = false,
+        hexpand: Boolean = false,
+        vexpand: Boolean = false,
+        hfill: Boolean = false,
+        vfill: Boolean = false,
+        overrideDefaults: Boolean = false,
+        colspan: Int = -1,
+        rowspan: Int = -1,
+        name: String? = null,
+        styleClass: String? = null,
+        onChange: EventHandler? = null
+    ): UiWidget {
+        val textarea = Text.textarea(ui)
+        varname?.let {
+            textarea.varname(it)
+        }
+        value?.let {
+            textarea.value(it)
+        }
+        if(fill) {
+            textarea.fill(fill);
+        }
+        if(hexpand) {
+            textarea.hexpand(true)
+        }
+        if(vexpand) {
+            textarea.vexpand(true)
+        }
+        if(hfill) {
+            textarea.hfill(true)
+        }
+        if(vfill) {
+            textarea.vfill(true)
+        }
+        if(colspan > 0) {
+            textarea.colspan(colspan)
+        }
+        if(rowspan > 0) {
+            textarea.rowspan(rowspan)
+        }
+        if(overrideDefaults) {
+            textarea.overrideDefaults(true)
+        }
+        name?.let {
+            textarea.name(it)
+        }
+        styleClass?.let {
+            textarea.styleClass(it)
+        }
+        onChange?.let {
+            textarea.onChange(onChange)
+        }
+        return textarea.create()
+    }
+
     private fun createTextField(
         textfield: TextFieldBuilder,
         varname: String? = null,
index a1c048f1f5bb1c6af7662918ac9e31520bdf7eb2..a45d72011ddc7d43540fe07e5611d685d46f8f10 100644 (file)
@@ -67,6 +67,7 @@ fun dialog(
 
 fun dialogWindow(
     parent: UiObject,
+    title: String? = null,
     modal: Boolean? = null,
     titlebarButtons: Boolean? = null,
     showCloseButton: Boolean? = null,
@@ -81,6 +82,9 @@ fun dialogWindow(
     ui: (Toplevel.() -> Unit)?): Toplevel
 {
     val builder = DialogWindowBuilder(parent)
+    title?.let {
+        builder.title(it)
+    }
     modal?.let {
         builder.modal(it)
     }