From 2a3be78ec4bb1adb02108b4723bf2763a8a1b50f Mon Sep 17 00:00:00 2001 From: Olaf Wintermann Date: Sun, 6 Jul 2025 21:42:14 +0200 Subject: [PATCH] add first java AppMenu functions --- .../src/main/java/de/unixwork/ui/AppMenu.java | 51 +++++++++++++++++++ .../main/java/de/unixwork/ui/MenuFuncs.java | 41 +++++++++++++-- .../src/main/java/de/unixwork/ui/MenuUI.java | 6 +++ .../src/main/java/de/unixwork/ui/Toolkit.java | 4 ++ 4 files changed, 97 insertions(+), 5 deletions(-) create mode 100644 ui-java/src/main/java/de/unixwork/ui/AppMenu.java create mode 100644 ui-java/src/main/java/de/unixwork/ui/MenuUI.java diff --git a/ui-java/src/main/java/de/unixwork/ui/AppMenu.java b/ui-java/src/main/java/de/unixwork/ui/AppMenu.java new file mode 100644 index 0000000..d98a751 --- /dev/null +++ b/ui-java/src/main/java/de/unixwork/ui/AppMenu.java @@ -0,0 +1,51 @@ +package de.unixwork.ui; + +import java.lang.foreign.Arena; +import java.lang.foreign.MemorySegment; + +// currently toolkit menu functions don't copy the string args +// for persistent strings we need to allocate them in the static toolkit arena + +public class AppMenu { + public static void menu(String label, MenuUI callback) { + MenuFuncs ui = MenuFuncs.getInstance(); + Toolkit toolkit = Toolkit.getInstance(); + try { + MemorySegment cstr = toolkit.getStaticArena().allocateFrom(label); + ui.menu_create.invoke(cstr); + callback.callback(); + ui.menu_end.invoke(); + } catch (Throwable e) { + throw new RuntimeException(e); + } + } + + public static void menuItem(String label, EventHandler onClick) { + AppMenu.menuItem(label, null, onClick); + } + + public static void menuItem(String label, String icon, EventHandler onClick) { + MenuFuncs ui = MenuFuncs.getInstance(); + ArgFuncs a = ArgFuncs.getInstance(); + Toolkit toolkit = Toolkit.getInstance(); + Arena arena = toolkit.getStaticArena(); + try { + MemorySegment args = (MemorySegment) a.menuitem_args_new.invoke(); + if(label != null) { + MemorySegment cstr = arena.allocateFrom(label); + a.menuitem_args_set_label.invoke(args, cstr); + } + if(icon != null) { + MemorySegment cstr = arena.allocateFrom(icon); + a.menuitem_args_set_icon.invoke(args, cstr); + } + if(onClick != null) { + // TODO + } + ui.menuitem_create.invoke(args); + a.menuitem_args_free.invoke(args); + } catch (Throwable e) { + throw new RuntimeException(e); + } + } +} diff --git a/ui-java/src/main/java/de/unixwork/ui/MenuFuncs.java b/ui-java/src/main/java/de/unixwork/ui/MenuFuncs.java index 93def93..31b6c91 100644 --- a/ui-java/src/main/java/de/unixwork/ui/MenuFuncs.java +++ b/ui-java/src/main/java/de/unixwork/ui/MenuFuncs.java @@ -6,15 +6,46 @@ import java.lang.invoke.MethodHandle; public class MenuFuncs { static MenuFuncs instance; - public MethodHandle button_create; + public MethodHandle menu_end; + public MethodHandle menu_close; + public MethodHandle menu_is_open; + + public MethodHandle menu_create; + public MethodHandle menuitem_create; + public MethodHandle menu_toggleitem_create; + public MethodHandle menu_radioitem_create; + public MethodHandle menu_separator; + public MethodHandle menu_itemlist_create; private MenuFuncs(Linker linker, SymbolLookup lib) { - // void* func(void*, void*) - FunctionDescriptor sigm_mm = FunctionDescriptor.of(ValueLayout.ADDRESS, ValueLayout.ADDRESS, ValueLayout.ADDRESS); + // void func(void*) + FunctionDescriptor sigv_m = FunctionDescriptor.ofVoid(ValueLayout.ADDRESS); + // void func() + FunctionDescriptor sigv = FunctionDescriptor.ofVoid(); + // int func() + FunctionDescriptor sigi = FunctionDescriptor.of(ValueLayout.JAVA_INT); + + MemorySegment ui_menu_end_addr = lib.find("ui_menu_end").orElseThrow(); + MemorySegment ui_menu_close_addr = lib.find("ui_menu_close").orElseThrow(); + MemorySegment ui_menu_is_open_addr = lib.find("ui_menu_is_open").orElseThrow(); + + MemorySegment ui_menu_create_addr = lib.find("ui_menu_create").orElseThrow(); + MemorySegment ui_menuitem_create_addr = lib.find("ui_menuitem_create").orElseThrow(); + MemorySegment ui_menu_toggleitem_create_addr = lib.find("ui_menu_toggleitem_create").orElseThrow(); + MemorySegment ui_menu_radioitem_create_addr = lib.find("ui_menu_radioitem_create").orElseThrow(); + MemorySegment ui_menu_separator_addr = lib.find("ui_menu_separator").orElseThrow(); + MemorySegment ui_menu_itemlist_create_addr = lib.find("ui_menu_itemlist_create").orElseThrow(); - MemorySegment ui_button_create_addr = lib.find("ui_button_create").orElseThrow(); + menu_end = linker.downcallHandle(ui_menu_end_addr, sigv); + menu_close = linker.downcallHandle(ui_menu_close_addr, sigv); + menu_is_open = linker.downcallHandle(ui_menu_is_open_addr, sigi); - button_create = linker.downcallHandle(ui_button_create_addr, sigm_mm); + menu_create = linker.downcallHandle(ui_menu_create_addr, sigv_m); + menuitem_create = linker.downcallHandle(ui_menuitem_create_addr, sigv_m); + menu_toggleitem_create = linker.downcallHandle(ui_menu_toggleitem_create_addr, sigv_m); + menu_radioitem_create = linker.downcallHandle(ui_menu_radioitem_create_addr, sigv_m); + menu_separator = linker.downcallHandle(ui_menu_separator_addr, sigv); + menu_itemlist_create = linker.downcallHandle(ui_menu_itemlist_create_addr, sigv_m); } static MenuFuncs getInstance() { diff --git a/ui-java/src/main/java/de/unixwork/ui/MenuUI.java b/ui-java/src/main/java/de/unixwork/ui/MenuUI.java new file mode 100644 index 0000000..bd2ceb8 --- /dev/null +++ b/ui-java/src/main/java/de/unixwork/ui/MenuUI.java @@ -0,0 +1,6 @@ +package de.unixwork.ui; + +@FunctionalInterface +public interface MenuUI { + public void callback(); +} \ No newline at end of file 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 fcc1d59..15523e2 100644 --- a/ui-java/src/main/java/de/unixwork/ui/Toolkit.java +++ b/ui-java/src/main/java/de/unixwork/ui/Toolkit.java @@ -69,6 +69,10 @@ public class Toolkit { return isObjRegEnabled; } + public Arena getStaticArena() { + return staticArena; + } + private void initFunctions() { FunctionDescriptor sigv_v = FunctionDescriptor.ofVoid(); // void func(void) FunctionDescriptor sigm_m = FunctionDescriptor.of(ValueLayout.ADDRESS, ValueLayout.ADDRESS); // void* func(void*) -- 2.47.3