public MethodHandle menu_itemlist_create;
public MethodHandle contextmenu_builder;
- public MethodHandle menubuilder_free;
+ public MethodHandle menubuilder_ref;
+ public MethodHandle menubuilder_unref;
public MethodHandle toolbar_item_create;
public MethodHandle toolbar_toggleitem_create;
MemorySegment ui_menu_itemlist_create_addr = lib.find("ui_menu_itemlist_create").orElseThrow();
MemorySegment ui_contextmenu_builder_addr = lib.find("ui_contextmenu_builder").orElseThrow();
- MemorySegment ui_menubuilder_free_addr = lib.find("ui_menubuilder_free").orElseThrow();
+ MemorySegment ui_menubuilder_ref_addr = lib.find("ui_menubuilder_ref").orElseThrow();
+ MemorySegment ui_menubuilder_unref_addr = lib.find("ui_menubuilder_unref").orElseThrow();
MemorySegment ui_toolbar_item_create_addr = lib.find("ui_toolbar_item_create").orElseThrow();
MemorySegment ui_toolbar_toggleitem_create_addr = lib.find("ui_toolbar_toggleitem_create").orElseThrow();
menu_itemlist_create = linker.downcallHandle(ui_menu_itemlist_create_addr, sigv_m);
contextmenu_builder = linker.downcallHandle(ui_contextmenu_builder_addr, sigv_mm);
- menubuilder_free = linker.downcallHandle(ui_menubuilder_free_addr, sigv_m);
+ menubuilder_ref = linker.downcallHandle(ui_menubuilder_ref_addr, sigv_m);
+ menubuilder_unref = linker.downcallHandle(ui_menubuilder_unref_addr, sigv_m);
toolbar_item_create = linker.downcallHandle(ui_toolbar_item_create_addr, sigv_mm);
toolbar_toggleitem_create = linker.downcallHandle(ui_toolbar_toggleitem_create_addr, sigv_mm);
private HashMap<Integer, ThreadCallback> threadCallbacks = new HashMap<>();
+ private ArrayList<Menu> sourceListMenuBuilderCache = new ArrayList<>();
+
private Toolkit(String appName) {
// load shared library
System.loadLibrary("uitk");
FunctionDescriptor sigm_m = FunctionDescriptor.of(ValueLayout.ADDRESS, ValueLayout.ADDRESS); // void* func(void*)
FunctionDescriptor sigm_mi = FunctionDescriptor.of(ValueLayout.ADDRESS, ValueLayout.ADDRESS, ValueLayout.JAVA_INT); // void* func(void*, int)
FunctionDescriptor sigi_m = FunctionDescriptor.of(ValueLayout.JAVA_INT, ValueLayout.ADDRESS); // int func(void*)
+ FunctionDescriptor sigv_m = FunctionDescriptor.ofVoid(ValueLayout.ADDRESS);
FunctionDescriptor sigv = FunctionDescriptor.ofVoid();
FunctionDescriptor sigv_b = FunctionDescriptor.ofVoid(ValueLayout.JAVA_BOOLEAN);
app_save_settings = linker.downcallHandle(app_save_settings_addr, sigv);
app_exit_on_shutdown = linker.downcallHandle(app_exit_on_shutdown_addr, sigv_b);
+ MemorySegment ui_sourcelist_set_update_callback_addr = lib.find("ui_sourcelist_set_update_callback").orElseThrow();
+ MethodHandle ui_sourcelist_set_update_callback = linker.downcallHandle(ui_sourcelist_set_update_callback_addr, sigv_m);
+
// init java based UiList implementation
try {
MethodHandle listFirstMethod = MethodHandles.lookup().findStatic(
int.class,
MemorySegment.class,
MemorySegment.class));
+ MethodHandle scListUpdated = MethodHandles.lookup().findStatic(
+ Toolkit.class,
+ "sourceListUpdated",
+ MethodType.methodType(void.class));
MethodHandle getStyleMethod = MethodHandles.lookup().findStatic(
Toolkit.class,
"getStyle",
ValueLayout.ADDRESS,
ValueLayout.ADDRESS),
staticArena);
+
+ MemorySegment scListUpdatedPtr = linker.upcallStub(scListUpdated, FunctionDescriptor.ofVoid(), staticArena);
+ ui_sourcelist_set_update_callback.invoke(scListUpdatedPtr);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
+ } catch (Throwable e) {
+ throw new RuntimeException(e);
}
// threadfunc wrapper
long ctxPtr = userdata.getAtIndex(ValueLayout.JAVA_LONG, 0);
long converterIndex = userdata.getAtIndex(ValueLayout.JAVA_LONG, 1);
- Context ctx = Toolkit.getInstance().getContext(ctxPtr);
+ Toolkit tk = Toolkit.getInstance();
+ Context ctx = tk.getContext(ctxPtr);
SubListValueConverter conv = ctx.getSubListValueConverter((int)converterIndex);
UiList uilist = Toolkit.listPtrToObject(list);
ui.sublist_item_set_button_label.invoke(out_item, cstr);
}
if(item.buttonMenu != null) {
+ MemorySegment menuBuilder = MemorySegment.NULL;
+ if(tk.sourceListMenuBuilderCache.size() <= 32) {
+ // Cache up to 32 menubuilder objects
+ // The cache is cleaned by the sourceListUpdated() method
+ menuBuilder = item.buttonMenu.createMenuBuilderCached();
+ if(!tk.sourceListMenuBuilderCache.contains(item.buttonMenu)) {
+ tk.sourceListMenuBuilderCache.add(item.buttonMenu);
+ // the menuBuilder is owned by the cache
+ MenuFuncs.getInstance().menubuilder_ref.invoke(menuBuilder);
+ }
+ } else {
+ // the sourcelist takes ownership of the menubuilder
+ menuBuilder = item.buttonMenu.createMenuBuilder();
+ }
+
ui.sublist_item_set_button_menu.invoke(out_item, item.buttonMenu.createMenuBuilder());
}
if(item.badge != null) {
}
}
+ public static void sourceListUpdated() {
+ for(Menu menu : Toolkit.getInstance().sourceListMenuBuilderCache) {
+ menu.cleanupMenuBuilder();
+ }
+ }
+
public static boolean getStyle(MemorySegment list, MemorySegment elm, int row, int col, MemorySegment userdata, MemorySegment stylePtr) {
if(userdata == MemorySegment.NULL) {
return false;