package bluej.extmgr;

import javax.swing.JMenuItem;
import javax.swing.SwingUtilities;
import java.util.ArrayList;
import java.util.List;

import bluej.utility.javafx.FXBiConsumer;
import javafx.application.Platform;
import javafx.collections.ObservableList;
import javafx.event.Event;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.SeparatorMenuItem;
import javafx.stage.WindowEvent;

import bluej.pkgmgr.Project;
import bluej.utility.javafx.FXPlatformRunnable;
import bluej.utility.javafx.FXPlatformSupplier;
import bluej.utility.javafx.FXRunnable;
import bluej.utility.javafx.FXSupplier;
import bluej.utility.javafx.JavaFXUtil;
import threadchecker.OnThread;
import threadchecker.Tag;


| Manages the interface between a menu and extensions. | An instance of this class is attached to each popup menu that extensions | may add items to. | | @author Damiano Bolla, University of Kent at Canterbury, 2003,2004,2005 | @OnThread(Tag.FXPlatform) public final class FXMenuManager { private final ExtensionsManager extMgr; private final SeparatorMenuItem menuSeparator; @OnThread(Tag.Any) private final ContextMenu popupMenu; @OnThread(Tag.Any) private final Menu menu; @OnThread(Tag.Any) public synchronized void setMenuGenerator(ExtensionMenu menuGenerator) { this.menuGenerator = menuGenerator; } @OnThread(value = Tag.Any,requireSynchronized = true) private ExtensionMenu menuGenerator;
| Constructor for the MenuManager object. | | @param aPopupMenu The menu that extensions are attaching to. | @param menuGenerator | public FXMenuManager(ContextMenu aPopupMenu, ExtensionsManager extMgr, ExtensionMenu menuGenerator) { this.extMgr = extMgr; this.menuGenerator = menuGenerator; menuSeparator = new SeparatorMenuItem(); this.popupMenu = aPopupMenu; popupMenu.setOnShowing(this::menuWillBecomeVisible); this.menu = null; } public FXMenuManager(Menu aMenu, ExtensionsManager extMgr, ExtensionMenu menuGenerator) { this.extMgr = extMgr; this.menuGenerator = menuGenerator; menuSeparator = new SeparatorMenuItem(); this.menu = aMenu; menu.setOnShowing(this::menuWillBecomeVisible); this.popupMenu = null; }
| Add all the menu currently available to the menu. | This may be called any time BlueJ feels that the menu needs to be updated. | | @param onThisProject a specific project to look for, or null for all projects. | @OnThread(Tag.SwingIsFX) public synchronized void addExtensionMenu(Project onThisProject) { List<JMenuItem> menuItems = extMgr.getMenuItems(menuGenerator, onThisProject); FXBiConsumer<JMenuItem, MenuItem> extraConvert = (swingItem, fxItem) -> { fxItem.getProperties().put("bluej.extmgr.ExtensionWrapper", swingItem.getClientProperty("bluej.extmgr.ExtensionWrapper")); fxItem.getProperties().put("bluej.extmgr.JMenuItem", swingItem); }; final FXPlatformRunnable addItems = popupMenu != null ? JavaFXUtil.swingMenuItemsToContextMenu(popupMenu, menuItems, this, extraConvert) : supplierToRunnable(JavaFXUtil.swingMenuToFX(menuItems, this, () -> this.menu, extraConvert)); Platform.runLater(() -> { final ObservableList<MenuItem> items = getItems(); ArrayList<MenuItem> oldPopupItems = new ArrayList<>(items); for (MenuItem aComponent : oldPopupItems) { ExtensionWrapper aWrapper = (ExtensionWrapper) aComponent.getProperties().get( "bluej.extmgr.ExtensionWrapper"); if (aWrapper == null) { continue; } items.remove(aComponent); } items.remove(menuSeparator); if (!menuItems.isEmpty()) { items.add(menuSeparator); addItems.run(); } }); } @OnThread(Tag.Any) private FXPlatformRunnable supplierToRunnable(FXPlatformSupplier<Menu> menuFXSupplier) { return () -> {menuFXSupplier.get(); }; } private ObservableList getItems() { if (popupMenu != null) return popupMenu.getItems(); else{ return menu.getItems(); } }
| Notify to all valid extensions that this menu Item is about to be displayed. | | @param event The associated event | private void menuWillBecomeVisible(Event event) { int itemsCount = 0; final ObservableList<MenuItem> items = getItems(); ArrayList<MenuItem> popupMenuItems = new ArrayList<>(items); for (MenuItem aComponent : popupMenuItems) { ExtensionWrapper aWrapper = (ExtensionWrapper) aComponent.getProperties().get( "bluej.extmgr.ExtensionWrapper"); if (aWrapper == null) { continue; } JMenuItem swingItem = (JMenuItem)aComponent.getProperties().get("bluej.extmgr.JMenuItem"); SwingUtilities.invokeLater(() -> { if (!aWrapper.isValid()) { Platform.runLater(() -> { items.remove(aComponent); }); } else { synchronized (this) { aWrapper.safePostMenuItem(menuGenerator, swingItem); } } }); itemsCount++; } if (itemsCount <= 0) { items.remove(menuSeparator); } } }

.   - FXMenuManager
.   setMenuGenerator
.   FXMenuManager
.   FXMenuManager
.   addExtensionMenu
.   supplierToRunnable
.   getItems
.   menuWillBecomeVisible




198 neLoCode + 12 LoComm