void (List<ActionMenu> roots) { // exec at EDT if (ourLib == null) { return; } ThreadingAssertions.assertEventDispatchThread(); int[] stats = new int[]{0, 0, 0}; final int size = roots == null ? 0 : roots.size(); final List<MenuItemInternal> newRoots = new ArrayList<>(size); if (roots != null) { for (ActionMenu am : roots) { final int uid = System.identityHashCode(am); final MenuItemInternal mi = new MenuItemInternal(null, newRoots.size(), uid, GlobalMenuLib.ITEM_SUBMENU, am.getAnAction()); mi.jitem = am; mi.setLabelFromSwingPeer(am); newRoots.add(mi); if (DO_FILL_ROOTS) { final long startMs = System.currentTimeMillis(); am.removeAll(); // just for insurance am.setSelected(true); am.fillMenu(); _syncChildren(mi, am, 1, stats); // NOTE: fill root menus to avoid empty submenu showing am.removeAll(); final long elapsedMs = System.currentTimeMillis() - startMs; if (TRACE_SYNC_STATS) { _trace("filled root menu '%s', spent (in EDT) %d ms, stats: %s", String.valueOf(mi.txt), elapsedMs, _stats2str(stats)); } } } } this.roots = newRoots; _trace("set new menu roots, count=%d", size); isRootsUpdated = false; ourLib.execOnMainLoop(updateAllRoots); }