/* * The Unified Mapping Platform (JUMP) is an extensible, interactive GUI * for visualizing and manipulating spatial features with geometry and attributes. * * Copyright (C) 2003 Vivid Solutions * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * For more information, contact: * * Vivid Solutions * Suite #1A * 2328 Government Street * Victoria BC V8T 5G5 * Canada * * (250)385-6040 * www.vividsolutions.com */ package com.vividsolutions.jump.workbench.ui.plugin; import java.awt.Component; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import javax.swing.Icon; import javax.swing.JCheckBoxMenuItem; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JPopupMenu; import javax.swing.MenuElement; import javax.swing.SwingUtilities; import javax.swing.event.MenuEvent; import javax.swing.event.MenuListener; import javax.swing.event.PopupMenuEvent; import javax.swing.event.PopupMenuListener; import org.openjump.core.ui.plugin.AbstractUiPlugIn; import org.openjump.core.ui.swing.listener.EnableCheckMenuItemShownListener; import org.openjump.core.ui.swing.listener.MenuItemShownMenuListener; import com.vividsolutions.jts.util.Assert; import com.vividsolutions.jump.util.CollectionUtil; import com.vividsolutions.jump.util.StringUtil; import com.vividsolutions.jump.workbench.WorkbenchContext; import com.vividsolutions.jump.workbench.plugin.AbstractPlugIn; import com.vividsolutions.jump.workbench.plugin.EnableCheck; import com.vividsolutions.jump.workbench.plugin.EnableCheckFactory; import com.vividsolutions.jump.workbench.plugin.MultiEnableCheck; import com.vividsolutions.jump.workbench.plugin.PlugIn; import com.vividsolutions.jump.workbench.ui.GUIUtil; import com.vividsolutions.jump.workbench.ui.LayerViewPanel; import com.vividsolutions.jump.workbench.ui.MenuNames; import com.vividsolutions.jump.workbench.ui.task.TaskMonitorManager; /** * Adds a plug-in to the JUMP Workbench as a menu item. */ // TODO - Refactoring: Rename this class to PlugInMenuInstaller [Jon Aquino // 10/22/2003] public class FeatureInstaller { private interface Menu { void insert(JMenuItem menuItem, int i); String getText(); int getItemCount(); void add(JMenuItem menuItem); } private WorkbenchContext workbenchContext; private TaskMonitorManager taskMonitorManager = new TaskMonitorManager(); private EnableCheckFactory checkFactory; private static Map plugin_EnableCheckMap = new HashMap(); private static Map repeatMenuItemMap = new HashMap(); private static RepeatableMenuItem[] RepeatableMenuItemArray = {null, null, null}; public FeatureInstaller(WorkbenchContext workbenchContext) { this.workbenchContext = workbenchContext; checkFactory = new EnableCheckFactory(workbenchContext); } /** @deprecated Use the EnableCheckFactory methods instead */ public MultiEnableCheck createLayersSelectedCheck() { return new MultiEnableCheck().add( checkFactory.createWindowWithLayerNamePanelMustBeActiveCheck()).add( checkFactory.createAtLeastNLayersMustBeSelectedCheck(1)); } /** @deprecated Use the EnableCheckFactory methods instead */ public MultiEnableCheck createOneLayerSelectedCheck() { return new MultiEnableCheck().add( checkFactory.createWindowWithLayerNamePanelMustBeActiveCheck()).add( checkFactory.createExactlyNLayersMustBeSelectedCheck(1)); } /** @deprecated Use the EnableCheckFactory methods instead */ public MultiEnableCheck createVectorsExistCheck() { return new MultiEnableCheck().add( checkFactory.createWindowWithLayerViewPanelMustBeActiveCheck()).add( checkFactory.createAtLeastNVectorsMustBeDrawnCheck(1)); } /** @deprecated Use the EnableCheckFactory methods instead */ public MultiEnableCheck createFenceExistsCheck() { return new MultiEnableCheck().add( checkFactory.createWindowWithLayerViewPanelMustBeActiveCheck()).add( checkFactory.createFenceMustBeDrawnCheck()); } public void addMenuSeparator(String menu) { addMenuSeparator(new String[] { menu }); } public void addMenuSeparator(String[] menuPath) { JMenu mainMenu = menuBarMenu(menuPath[0]); addMenuSeparator(createMenusIfNecessary(mainMenu, behead(menuPath))); } public void addMenuSeparator(JMenu menu) { Component separator = null; Component exitMenu = null; if (menu.getText().equals(MenuNames.FILE)) { // Ensure separator and Exit appear last separator = menu.getMenuComponent(menu.getMenuComponentCount() - 2); exitMenu = menu.getMenuComponent(menu.getMenuComponentCount() - 1); menu.remove(separator); menu.remove(exitMenu); } menu.addSeparator(); if (menu.getText().equals(MenuNames.FILE)) { menu.add(separator); menu.add(exitMenu); } } private void associate(JMenuItem menuItem, PlugIn plugIn) { menuItem.addActionListener(AbstractPlugIn.toActionListener(plugIn, workbenchContext, taskMonitorManager)); } public String[] behead(String[] a1) { String[] a2 = new String[a1.length - 1]; System.arraycopy(a1, 1, a2, 0, a2.length); return a2; } public void addMainMenuItem(PlugIn executable, String menuName, String menuItemName, Icon icon, EnableCheck enableCheck) { addMainMenuItem(executable, new String[] { menuName }, menuItemName, false, icon, enableCheck); } public void addLayerViewMenuItem(PlugIn executable, String menuName, String menuItemName) { addLayerViewMenuItem(executable, new String[] { menuName }, menuItemName); } public void addLayerNameViewMenuItem(PlugIn executable, String menuName, String menuItemName) { addLayerNameViewMenuItem(executable, new String[] { menuName }, menuItemName); } /** * Add a menu item to the main menu that is enabled only if the active * internal frame is a LayerViewPanelProxy. */ public void addLayerViewMenuItem(PlugIn executable, String[] menuPath, String menuItemName) { addMainMenuItem(executable, menuPath, menuItemName, false, null, checkFactory.createWindowWithLayerViewPanelMustBeActiveCheck()); } /** * Add a menu item to the main menu that is enabled only if the active * internal frame is a LayerViewPanelProxy and a LayerNamePanelProxy. */ public void addLayerNameViewMenuItem(PlugIn executable, String[] menuPath, String menuItemName) { addMainMenuItem(executable, menuPath, menuItemName, false, null, new MultiEnableCheck().add( checkFactory.createWindowWithLayerViewPanelMustBeActiveCheck()).add( checkFactory.createWindowWithLayerNamePanelMustBeActiveCheck())); } /** * @param menuPath separate items with slashes; items will be created if they * do not already exist * @param menuItemName name of the menu item * @param checkBox whether to create a JCheckBoxMenuItem or a JMenuItem * @param icon an Icon or null * @param enableCheck conditions to make the plugin available to the user * @see GUIUtil#toSmallIcon */ public void addMainMenuItem(PlugIn executable, String[] menuPath, String menuItemName, boolean checkBox, Icon icon, EnableCheck enableCheck) { Map properties = extractProperties(menuItemName); menuItemName = removeProperties(menuItemName); JMenu menu = menuBarMenu(menuPath[0]); if (menu == null) { menu = (JMenu)installMnemonic(new JMenu(menuPath[0]), menuBar()); addToMenuBar(menu); } JMenu parent = createMenusIfNecessary(menu, behead(menuPath)); final JMenuItem menuItem = installMnemonic( checkBox ? new JCheckBoxMenuItem(menuItemName) : new JMenuItem( menuItemName), parent); menuItem.setIcon(icon); associate(menuItem, executable); insert(menuItem, createMenu(parent), properties); if (enableCheck != null) { addMenuItemShownListener(menuItem, toMenuItemShownListener(enableCheck)); } } public JMenuItem addMainMenuItem(final String[] menuPath, final AbstractUiPlugIn plugin, final int index) { String menuItemName = plugin.getName(); JMenu menu = menuBarMenu(menuPath[0]); if (menu == null) { menu = (JMenu)installMnemonic(new JMenu(menuPath[0]), menuBar()); addToMenuBar(menu); } JMenu parent = createMenusIfNecessary(menu, behead(menuPath)); final JMenuItem menuItem = new JMenuItem(menuItemName); installMnemonic(menuItem, parent); menuItem.setIcon(plugin.getIcon()); menuItem.addActionListener(plugin); if (index == Integer.MAX_VALUE) { parent.add(menuItem); } else if (index < 0) { int endIndex = parent.getMenuComponentCount() + index + 1; parent.add(menuItem, endIndex); } else { parent.add(menuItem, index); } EnableCheck enableCheck = plugin.getEnableCheck(); if (enableCheck != null) { addMenuItemShownListener(menuItem, new EnableCheckMenuItemShownListener( workbenchContext, enableCheck, plugin.getToolTip())); } return menuItem; } /** * Add a Plugin as a JMenuItem or a subclass of JMenuItem to the main menu * @param menuPath path from the main menu to the menu item * @param plugin the plugin associated to this menu item * @param menuItem the menu item (JMenuItem, JCheckBoxMenuItem, JMenu, JRadioButtonMenuItem) * @param index the index of the menu item in its parent menu */ //Added by Michael Michaud on 2008-04-06 //This method makes it possible to add any subclasses of JMenuItem public JMenuItem addMainMenuItem(final String[] menuPath, final AbstractUiPlugIn plugin, final JMenuItem menuItem, final int index) { String menuItemName = plugin.getName(); JMenu menu = menuBarMenu(menuPath[0]); if (menu == null) { menu = (JMenu)installMnemonic(new JMenu(menuPath[0]), menuBar()); addToMenuBar(menu); } JMenu parent = createMenusIfNecessary(menu, behead(menuPath)); installMnemonic(menuItem, parent); menuItem.setIcon(plugin.getIcon()); menuItem.addActionListener(plugin); if (index == Integer.MAX_VALUE) { parent.add(menuItem); } else if (index < 0) { int endIndex = parent.getMenuComponentCount() + index + 1; parent.add(menuItem, endIndex); } else { parent.add(menuItem, index); } EnableCheck enableCheck = plugin.getEnableCheck(); if (enableCheck != null) { addMenuItemShownListener(menuItem, new EnableCheckMenuItemShownListener( workbenchContext, enableCheck, plugin.getToolTip())); } return menuItem; } private Menu createMenu(final JMenu menu) { return new Menu() { public void insert(JMenuItem menuItem, int i) { menu.insert(menuItem, i); } public String getText() { return menu.getText(); } public int getItemCount() { return menu.getItemCount(); } public void add(JMenuItem menuItem) { menu.add(menuItem); } }; } private void insert(final JMenuItem menuItem, Menu parent, Map properties) { if (properties.get("pos") != null) { parent.insert(menuItem, Integer.parseInt((String)properties.get("pos"))); } else if (parent.getText().equals(MenuNames.FILE)) { // If menu is File, insert menu item just before Exit and its // separator [Jon Aquino] parent.insert(menuItem, parent.getItemCount() - 2); } else { parent.add(menuItem); } } private Map extractProperties(String menuItemName) { if (menuItemName.indexOf('{') == -1) { return new HashMap(); } Map properties = new HashMap(); String s = menuItemName.substring(menuItemName.indexOf('{') + 1, menuItemName.indexOf('}')); for (Iterator i = StringUtil.fromCommaDelimitedString(s).iterator(); i.hasNext();) { String property = (String)i.next(); properties.put(property.substring(0, property.indexOf(':')).trim(), property.substring(property.indexOf(':') + 1, property.length()).trim()); } return properties; } public static String removeProperties(String menuItemName) { return menuItemName.indexOf('{') > -1 ? menuItemName.substring(0, menuItemName.indexOf('{')) : menuItemName; } public static JMenuItem installMnemonic(JMenuItem menuItem, MenuElement parent) { String text = menuItem.getText(); StringUtil.replaceAll(text, "&&", "##"); int ampersandPosition = text.indexOf('&'); if (-1 < ampersandPosition && ampersandPosition + 1 < text.length()) { menuItem.setMnemonic(text.charAt(ampersandPosition + 1)); text = StringUtil.replace(text, "&", "", false); } else { installDefaultMnemonic(menuItem, parent); } // Double-ampersands get converted to single-ampersands. [Jon Aquino] StringUtil.replaceAll(text, "##", "&"); menuItem.setText(text); return menuItem; } private static void installDefaultMnemonic(JMenuItem menuItem, MenuElement parent) { outer: for (int i = 0; i < menuItem.getText().length(); i++) { // Swing stores mnemonics in upper case [Jon Aquino] char candidate = Character.toUpperCase(menuItem.getText().charAt(i)); if (!Character.isLetter(candidate)) { continue; } for (Iterator j = menuItems(parent).iterator(); j.hasNext();) { JMenuItem other = (JMenuItem)j.next(); if (other.getMnemonic() == candidate) { continue outer; } } menuItem.setMnemonic(candidate); return; } menuItem.setMnemonic(menuItem.getText().charAt(0)); } private static Collection menuItems(MenuElement element) { ArrayList menuItems = new ArrayList(); if (element instanceof JMenuBar) { for (int i = 0; i < ((JMenuBar)element).getMenuCount(); i++) { CollectionUtil.addIfNotNull(((JMenuBar)element).getMenu(i), menuItems); } } else if (element instanceof JMenu) { for (int i = 0; i < ((JMenu)element).getItemCount(); i++) { CollectionUtil.addIfNotNull(((JMenu)element).getItem(i), menuItems); } } else if (element instanceof JPopupMenu) { MenuElement[] children = ((JPopupMenu)element).getSubElements(); for (int i = 0; i < children.length; i++) { if (children[i] instanceof JMenuItem) { menuItems.add(children[i]); } } } else { Assert.shouldNeverReachHere(element.getClass().getName()); } return menuItems; } private MenuItemShownListener toMenuItemShownListener( final EnableCheck enableCheck) { return new EnableCheckMenuItemShownListener(workbenchContext, enableCheck); } /** * @return the leaf */ public JMenu createMenusIfNecessary(JMenu parent, String[] menuPath) { if (menuPath.length == 0) { return parent; } JMenu child = (JMenu)childMenuItem(menuPath[0], parent); if (child == null) { child = (JMenu)installMnemonic(new JMenu(menuPath[0]), parent); parent.add(child); } return createMenusIfNecessary(child, behead(menuPath)); } public void addMenuItemShownListener(final JMenuItem menuItem, final MenuItemShownListener menuItemShownListener) { JMenu menu = (JMenu)((JPopupMenu)menuItem.getParent()).getInvoker(); menu.addMenuListener(new MenuItemShownMenuListener(menuItem, menuItemShownListener)); } /** * @param enableCheck null to leave unspecified */ public void addPopupMenuItem(JPopupMenu popupMenu, PlugIn executable, String menuItemName, boolean checkBox, Icon icon, EnableCheck enableCheck) { Map properties = extractProperties(menuItemName); menuItemName = removeProperties(menuItemName); JMenuItem menuItem = installMnemonic(checkBox ? new JCheckBoxMenuItem( menuItemName) : new JMenuItem(menuItemName), popupMenu); menuItem.setIcon(icon); addPopupMenuItem(popupMenu, executable, new String[0], menuItem, properties, enableCheck); } /** * Add a menu item to a JPopupMenu with optional submenus defined by menuPath * Added by mmichaud on 2011-03-20 to reorganize LayerNamePanel JPopupMenu */ public void addPopupMenuItem(JPopupMenu popupMenu, PlugIn executable, String[] menuPath, String menuItemName, boolean checkBox, Icon icon, EnableCheck enableCheck) { Map properties = extractProperties(menuItemName); menuItemName = removeProperties(menuItemName); JMenuItem menuItem = installMnemonic(checkBox ? new JCheckBoxMenuItem( menuItemName) : new JMenuItem(menuItemName), popupMenu); menuItem.setIcon(icon); addPopupMenuItem(popupMenu, executable, menuPath, menuItem, properties, enableCheck); } private void addPopupMenuItem(JPopupMenu popupMenu, final PlugIn executable, final String[] menuPath, final JMenuItem menuItem, Map properties, final EnableCheck enableCheck) { associate(menuItem, executable); if (menuPath == null || menuPath.length == 0) { insert(menuItem, createMenu(popupMenu), properties); } else { JMenu menu = popupMenu(popupMenu, menuPath[0]); if (menu == null) { menu = (JMenu)popupMenu.add(new JMenu(menuPath[0])); } JMenu parent = createMenusIfNecessary(menu, behead(menuPath)); insert(menuItem, createMenu(parent), properties); } if (enableCheck != null) { popupMenu.addPopupMenuListener(new PopupMenuListener() { public void popupMenuWillBecomeVisible(PopupMenuEvent e) { toMenuItemShownListener(enableCheck).menuItemShown(menuItem); } public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { } public void popupMenuCanceled(PopupMenuEvent e) { } }); } } public void addPopupMenuSeparator(JPopupMenu popupMenu, String[] menuPath) { if (menuPath == null || menuPath.length == 0) { popupMenu.addSeparator(); } else { JMenu menu = popupMenu(popupMenu, menuPath[0]); if (menu == null) { menu = (JMenu) popupMenu.add(new JMenu(menuPath[0])); } JMenu parent = createMenusIfNecessary(menu, behead(menuPath)); parent.addSeparator(); } } /** * @return the menu with the given name, or null if no such menu exists */ public static JMenu popupMenu(JPopupMenu popupMenu, String childName) { MenuElement[] subElements = popupMenu.getSubElements(); for (int i = 0; i < subElements.length; i++) { if (!(subElements[i] instanceof JMenuItem)) { continue; } JMenuItem menuItem = (JMenuItem)subElements[i]; if (menuItem.getText().equals(childName)) { return (JMenu)menuItem; } } return null; } private Menu createMenu(final JPopupMenu popupMenu) { return new Menu() { public void insert(JMenuItem menuItem, int i) { popupMenu.insert(menuItem, i); } public String getText() { return ""; } public int getItemCount() { return popupMenu.getComponentCount(); } public void add(JMenuItem menuItem) { popupMenu.add(menuItem); } }; } public JMenuBar menuBar() { return workbenchContext.getWorkbench().getFrame().getJMenuBar(); } /** * @return the menu with the given name, or null if no such menu exists */ public JMenu menuBarMenu(String childName) { MenuElement[] subElements = menuBar().getSubElements(); for (int i = 0; i < subElements.length; i++) { if (!(subElements[i] instanceof JMenuItem)) { continue; } JMenuItem menuItem = (JMenuItem)subElements[i]; if (menuItem.getText().equals(childName)) { return (JMenu)menuItem; } } return null; } private void addToMenuBar(JMenu menu) { menuBar().add(menu); // Ensure Window and Help are placed at the end. Remove #windowMenu and // #helpMenu // *after* adding #menu, because #menu might be the Window or Help menu! // [Jon Aquino] JMenu windowMenu = menuBarMenu(MenuNames.WINDOW); JMenu helpMenu = menuBarMenu(MenuNames.HELP); // Customized workbenches may not have Window or Help menus [Jon Aquino] if (windowMenu != null) { menuBar().remove(windowMenu); } if (helpMenu != null) { menuBar().remove(helpMenu); } if (windowMenu != null) { menuBar().add(windowMenu); } if (helpMenu != null) { menuBar().add(helpMenu); } } public static JMenuItem childMenuItem(String childName, MenuElement menu) { if (menu instanceof JMenu) { return childMenuItem(childName, ((JMenu)menu).getPopupMenu()); } MenuElement[] childMenuItems = menu.getSubElements(); for (int i = 0; i < childMenuItems.length; i++) { if (childMenuItems[i] instanceof JMenuItem && ((JMenuItem)childMenuItems[i]).getText().equals(childName)) { return ((JMenuItem)childMenuItems[i]); } } return null; } /** * Workaround for Java Bug 4809393: "Menus disappear prematurely after * displaying modal dialog" Evidently fixed in Java 1.5. The workaround is to * wrap #actionPerformed with SwingUtilities#invokeLater. */ public void addMainMenuItemWithJava14Fix(PlugIn executable, String[] menuPath, String menuItemName, boolean checkBox, Icon icon, EnableCheck enableCheck) { addMainMenuItem(executable, menuPath, menuItemName, checkBox, icon, enableCheck); JMenuItem menuItem = FeatureInstaller.childMenuItem( FeatureInstaller.removeProperties(menuItemName), ((JMenu)createMenusIfNecessary(menuBarMenu(menuPath[0]), behead(menuPath)))); final ActionListener listener = abstractPlugInActionListener(menuItem.getActionListeners()); menuItem.removeActionListener(listener); menuItem.addActionListener(new ActionListener() { public void actionPerformed(final ActionEvent e) { SwingUtilities.invokeLater(new Runnable() { public void run() { listener.actionPerformed(e); } }); } }); } private ActionListener abstractPlugInActionListener( ActionListener[] actionListeners) { for (int i = 0; i < actionListeners.length; i++) { if (actionListeners[i].getClass().getName().indexOf( AbstractPlugIn.class.getName()) > -1) { return actionListeners[i]; } } Assert.shouldNeverReachHere(); return null; } public static JMenu addMainMenu(FeatureInstaller featureInstaller, final String[] menuPath, String menuName, int index) { JMenu menu = new JMenu(menuName); JMenu parent = featureInstaller.createMenusIfNecessary( featureInstaller.menuBarMenu(menuPath[0]), featureInstaller.behead(menuPath)); parent.insert(menu, index); return menu; } public JMenuItem addMainMenuItem(String[] menuPath, AbstractUiPlugIn plugIn) { return addMainMenuItem(menuPath, plugIn, -1); } public void associateWithRepeat(PlugIn executable) { JPopupMenu popupMenu = LayerViewPanel.popupMenu(); if (! plugin_EnableCheckMap.containsKey(executable)) return; //if this executable already associated with a repeat menu then nothing to do for (int i = 0; i < RepeatableMenuItemArray.length; i++) { if (RepeatableMenuItemArray[i] != null) if (RepeatableMenuItemArray[i].isSetTo(executable)) return; } //we are going to be moving executables to different repeatMenuItems //so remove all menuListeners for (int i = 0; i < RepeatableMenuItemArray.length; i++) { if (RepeatableMenuItemArray[i] == null) break; PopupMenuListener menuListener = RepeatableMenuItemArray[i].getMenuListener(); if (menuListener != null) popupMenu.removePopupMenuListener(menuListener); } //this plugin not on list of repeats //so pull down existing repeats and add this to top for (int i = RepeatableMenuItemArray.length - 1; i > 0 ; i--) { if (RepeatableMenuItemArray[i - 1] == null) //nothing to move continue; //at this point we have one above to pull down PlugIn prevExec = RepeatableMenuItemArray[i - 1].getExecutable(); EnableCheck prevEnableCheck = (EnableCheck)plugin_EnableCheckMap.get(prevExec); if (RepeatableMenuItemArray[i] == null) { RepeatableMenuItem repeatMenuItem = new RepeatableMenuItem(prevExec, prevEnableCheck); popupMenu.insert(repeatMenuItem.getMenuItem(), i + 3); RepeatableMenuItemArray[i] = repeatMenuItem; } else { RepeatableMenuItemArray[i].setExecutable(prevExec, prevEnableCheck); } } EnableCheck enableCheck = (EnableCheck)plugin_EnableCheckMap.get(executable); if (RepeatableMenuItemArray[0] == null) { RepeatableMenuItem repeatMenuItem = new RepeatableMenuItem(executable, enableCheck); popupMenu.insert(repeatMenuItem.getMenuItem(), 2); popupMenu.insert(new JPopupMenu.Separator(), 2); RepeatableMenuItemArray[0] = repeatMenuItem; } else { RepeatableMenuItemArray[0].setExecutable(executable, enableCheck); } //now add all listeners to popupMenu for (int i = 0; i < RepeatableMenuItemArray.length; i++) { if (RepeatableMenuItemArray[i] == null) break; PopupMenuListener menuListener = RepeatableMenuItemArray[i].getMenuListener(); if (menuListener != null) popupMenu.addPopupMenuListener(menuListener); } } private class RepeatableMenuItem { private PlugIn executable = null; private JMenuItem menuItem = null; private PopupMenuListener menuListener = null; public RepeatableMenuItem(PlugIn executable, final EnableCheck enableCheck) { this.menuItem = new JMenuItem("Repeat"); setExecutable(executable, enableCheck); } public void setExecutable(PlugIn executable, final EnableCheck enableCheck) { this.executable = executable; ActionListener[] al = menuItem.getActionListeners(); for (int i = 0; i < al.length; i++) menuItem.removeActionListener(al[0]); menuItem.addActionListener(AbstractPlugIn.toActionListener(executable, workbenchContext, taskMonitorManager)); this.menuItem.setText("Repeat: " + executable.getName()); if (enableCheck == null) { this.menuListener = null; } else { this.menuListener = new PopupMenuListener() { public void popupMenuWillBecomeVisible(PopupMenuEvent e) { toMenuItemShownListener(enableCheck).menuItemShown(menuItem); } public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {} public void popupMenuCanceled(PopupMenuEvent e) {} }; } } JMenuItem getMenuItem() { return menuItem; } PlugIn getExecutable() { return executable; } PopupMenuListener getMenuListener() { return menuListener; } boolean isSetTo(PlugIn executable) { return this.executable == executable; } } /** * @author Larry Becker * Needed this class to be not anonymous so it's type could be determined at runtime. */ public class JumpMenuListener implements MenuListener { MenuItemShownListener menuItemShownListener; JMenuItem menuItem; public JumpMenuListener(MenuItemShownListener menuItemShownListener, JMenuItem menuItem) { super(); this.menuItemShownListener = menuItemShownListener; this.menuItem = menuItem; } public void menuSelected(MenuEvent e) { menuItemShownListener.menuItemShown(menuItem); } public void menuCanceled(MenuEvent e) { } public void menuDeselected(MenuEvent e) { } } }