static TrayIcon installTrayIcon(S imageID, S tooltip) { ret installTrayIcon(imageID, tooltip, null); } // menuItems can also just be a PopupMenu // also, first of menuItems can be a Runnable for left-click on icon static TrayIcon installTrayIcon(fS _imageID, fS _tooltip, fO... _menuItems) ctex { ret swing(func -> TrayIcon { // convenience parameter swap :-) S imageID = _imageID, tooltip = _tooltip; if (!isSnippetID(imageID) && isSnippetID(tooltip)) { S s = tooltip; tooltip = imageID; imageID = s; } Runnable leftClick = null; O[] menuItems = _menuItems; if (l(menuItems) > 0 && menuItems[0] instanceof Runnable) { leftClick = (Runnable) menuItems[0]; menuItems = dropFirst(menuItems); } PopupMenu menu = makePopupMenu(menuItems); TrayIcon trayIcon = new TrayIcon(imageIcon(imageID).getImage(), tooltip, menu); trayIcon.setImageAutoSize(true); if (leftClick != null) { final Runnable _leftClick = leftClick; onLeftClick(trayIcon, _leftClick); } SystemTray.getSystemTray().add(trayIcon); ret trayIcon; }); }