http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-menu-impl/src/main/java/net/sf/taverna/t2/ui/menu/impl/MenuManagerImpl.java ---------------------------------------------------------------------- diff --git a/taverna-menu-impl/src/main/java/net/sf/taverna/t2/ui/menu/impl/MenuManagerImpl.java b/taverna-menu-impl/src/main/java/net/sf/taverna/t2/ui/menu/impl/MenuManagerImpl.java deleted file mode 100644 index 29b8057..0000000 --- a/taverna-menu-impl/src/main/java/net/sf/taverna/t2/ui/menu/impl/MenuManagerImpl.java +++ /dev/null @@ -1,880 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2007 The University of Manchester - * - * Modifications to the initial code base are copyright of their - * respective authors, or their employers as appropriate. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser 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 - ******************************************************************************/ -package net.sf.taverna.t2.ui.menu.impl; - -import static java.lang.Math.min; -import static javax.help.CSH.setHelpIDString; -import static javax.swing.Action.NAME; -import static javax.swing.Action.SHORT_DESCRIPTION; -import static net.sf.taverna.t2.lang.ui.ShadedLabel.GREEN; -import static net.sf.taverna.t2.ui.menu.AbstractMenuSection.SECTION_COLOR; -import static net.sf.taverna.t2.ui.menu.DefaultContextualMenu.DEFAULT_CONTEXT_MENU; -import static net.sf.taverna.t2.ui.menu.DefaultMenuBar.DEFAULT_MENU_BAR; -import static net.sf.taverna.t2.ui.menu.DefaultToolBar.DEFAULT_TOOL_BAR; - -import java.awt.Color; -import java.awt.Component; -import java.lang.ref.WeakReference; -import java.net.URI; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.WeakHashMap; - -import javax.swing.AbstractButton; -import javax.swing.Action; -import javax.swing.ButtonGroup; -import javax.swing.JButton; -import javax.swing.JCheckBoxMenuItem; -import javax.swing.JMenu; -import javax.swing.JMenuBar; -import javax.swing.JMenuItem; -import javax.swing.JPopupMenu; -import javax.swing.JRadioButtonMenuItem; -import javax.swing.JToggleButton; -import javax.swing.JToolBar; -import javax.swing.border.EmptyBorder; - -import org.apache.taverna.lang.observer.MultiCaster; -import org.apache.taverna.lang.observer.Observable; -import org.apache.taverna.lang.observer.Observer; -import org.apache.taverna.lang.observer.SwingAwareObserver; -import net.sf.taverna.t2.lang.ui.ShadedLabel; -import net.sf.taverna.t2.ui.menu.AbstractMenuAction; -import net.sf.taverna.t2.ui.menu.AbstractMenuOptionGroup; -import net.sf.taverna.t2.ui.menu.ContextualMenuComponent; -import net.sf.taverna.t2.ui.menu.ContextualSelection; -import net.sf.taverna.t2.ui.menu.DesignOnlyAction; -import net.sf.taverna.t2.ui.menu.DesignOrResultsAction; -import net.sf.taverna.t2.ui.menu.MenuComponent; -import net.sf.taverna.t2.ui.menu.MenuComponent.MenuType; -import net.sf.taverna.t2.ui.menu.MenuManager; -import net.sf.taverna.t2.workbench.selection.SelectionManager; -import net.sf.taverna.t2.workbench.selection.events.PerspectiveSelectionEvent; -import net.sf.taverna.t2.workbench.selection.events.SelectionManagerEvent; - -import org.apache.log4j.Logger; - -/** - * Implementation of {@link MenuManager}. - * - * @author Stian Soiland-Reyes - */ -public class MenuManagerImpl implements MenuManager { - private static Logger logger = Logger.getLogger(MenuManagerImpl.class); - - private boolean needsUpdate; - /** - * Cache used by {@link #getURIByComponent(Component)} - */ - private WeakHashMap<Component, URI> componentToUri; - /** - * {@link MenuElementComparator} used for sorting menu components from the - * SPI registry. - */ - private MenuElementComparator menuElementComparator = new MenuElementComparator(); - /** - * Map of {@link URI} to it's discovered children. Populated by - * {@link #findChildren()}. - */ - private HashMap<URI, List<MenuComponent>> menuElementTree; - /** - * Multicaster to distribute messages to {@link Observer}s of this menu - * manager. - */ - private MultiCaster<MenuManagerEvent> multiCaster; - /** - * Lock for {@link #update()} - */ - private final Object updateLock = new Object(); - /** - * True if {@link #doUpdate()} is running, subsequents call to - * {@link #update()} will return immediately. - */ - private boolean updating; - /** - * Cache used by {@link #getComponentByURI(URI)} - */ - private Map<URI, WeakReference<Component>> uriToComponent; - /** - * Map from {@link URI} to defining {@link MenuComponent}. Children are in - * {@link #menuElementTree}. - */ - private Map<URI, MenuComponent> uriToMenuElement; - // Note: Not reset by #resetCollections() - private Map<URI, List<WeakReference<Component>>> uriToPublishedComponents = new HashMap<>(); - private List<MenuComponent> menuComponents = new ArrayList<>(); - - /** - * Construct the MenuManagerImpl. Observes the SPI registry and does an - * initial {@link #update()}. - */ - public MenuManagerImpl() { - multiCaster = new MultiCaster<>(this); - needsUpdate = true; - } - - /** - * {@inheritDoc} - */ - @Override - public void addMenuItemsWithExpansion(List<JMenuItem> menuItems, - JMenu parentMenu, int maxItemsInMenu, - ComponentFactory headerItemFactory) { - if (menuItems.size() <= maxItemsInMenu) { - // Just add them directly - for (JMenuItem menuItem : menuItems) - parentMenu.add(menuItem); - return; - } - int index = 0; - while (index < menuItems.size()) { - int toIndex = min(menuItems.size(), index + maxItemsInMenu); - if (toIndex == menuItems.size() - 1) - // Don't leave a single item left for the last subMenu - toIndex--; - List<JMenuItem> subList = menuItems.subList(index, toIndex); - JMenuItem firstItem = subList.get(0); - JMenuItem lastItem = subList.get(subList.size() - 1); - JMenu subMenu = new JMenu(firstItem.getText() + " ... " - + lastItem.getText()); - if (headerItemFactory != null) - subMenu.add(headerItemFactory.makeComponent()); - for (JMenuItem menuItem : subList) - subMenu.add(menuItem); - parentMenu.add(subMenu); - index = toIndex; - } - } - - @Override - public void addObserver(Observer<MenuManagerEvent> observer) { - multiCaster.addObserver(observer); - } - - @Override - public JPopupMenu createContextMenu(Object parent, Object selection, - Component relativeToComponent) { - ContextualSelection contextualSelection = new ContextualSelection( - parent, selection, relativeToComponent); - JPopupMenu popupMenu = new JPopupMenu(); - populateContextMenu(popupMenu, DEFAULT_CONTEXT_MENU, - contextualSelection); - registerComponent(DEFAULT_CONTEXT_MENU, popupMenu, true); - return popupMenu; - } - - @Override - public JMenuBar createMenuBar() { - return createMenuBar(DEFAULT_MENU_BAR); - } - - @Override - public JMenuBar createMenuBar(URI id) { - JMenuBar menuBar = new JMenuBar(); - if (needsUpdate) - update(); - populateMenuBar(menuBar, id); - registerComponent(id, menuBar, true); - return menuBar; - } - - @Override - public JToolBar createToolBar() { - return createToolBar(DEFAULT_TOOL_BAR); - } - - @Override - public JToolBar createToolBar(URI id) { - JToolBar toolbar = new JToolBar(); - if (needsUpdate) - update(); - populateToolBar(toolbar, id); - registerComponent(id, toolbar, true); - return toolbar; - } - - @Override - public synchronized Component getComponentByURI(URI id) { - WeakReference<Component> componentRef = uriToComponent.get(id); - if (componentRef == null) - return null; - // Might also be null it reference has gone dead - return componentRef.get(); - } - - @Override - public List<Observer<MenuManagerEvent>> getObservers() { - return multiCaster.getObservers(); - } - - @Override - public synchronized URI getURIByComponent(Component component) { - return componentToUri.get(component); - } - - @Override - public void removeObserver(Observer<MenuManagerEvent> observer) { - multiCaster.removeObserver(observer); - } - - @Override - public void update() { - synchronized (updateLock) { - if (updating && !needsUpdate) - return; - updating = true; - } - try { - doUpdate(); - } finally { - synchronized (updateLock) { - updating = false; - needsUpdate = false; - } - } - } - - public void update(Object service, Map<?, ?> properties) { - needsUpdate = true; - update(); - } - - /** - * Add a {@link JMenu} to the list of components as described by the menu - * component. If there are no children, the menu is not added. - * - * @param components - * List of components where to add the created {@link JMenu} - * @param menuComponent - * The {@link MenuComponent} definition for this menu - * @param isToolbar - * True if the list of components is to be added to a toolbar - */ - private void addMenu(List<Component> components, - MenuComponent menuComponent, MenuOptions menuOptions) { - URI menuId = menuComponent.getId(); - if (menuOptions.isToolbar()) { - logger.warn("Can't have menu " + menuComponent - + " within toolBar element"); - return; - } - MenuOptions childOptions = new MenuOptions(menuOptions); - List<Component> subComponents = makeComponents(menuId, childOptions); - if (subComponents.isEmpty()) { - logger.warn("No sub components found for menu " + menuId); - return; - } - - JMenu menu = new JMenu(menuComponent.getAction()); - for (Component menuItem : subComponents) - if (menuItem == null) - menu.addSeparator(); - else - menu.add(menuItem); - registerComponent(menuId, menu); - components.add(menu); - } - - /** - * Add <code>null</code> to the list of components, meaning that a separator - * is to be created. Subsequent separators are ignored, and if there are no - * components on the list already no separator will be added. - * - * @param components - * List of components - */ - private void addNullSeparator(List<Component> components) { - if (components.isEmpty()) - // Don't start with a separator - return; - if (components.get(components.size() - 1) == null) - // Already a separator in last position - return; - components.add(null); - } - - /** - * Add an {@link AbstractMenuOptionGroup option group} to the list of - * components - * - * @param components - * List of components where to add the created {@link JMenu} - * @param optionGroupId - * The {@link URI} identifying the option group - * @param isToolbar - * True if the option group is to be added to a toolbar - */ - private void addOptionGroup(List<Component> components, URI optionGroupId, - MenuOptions menuOptions) { - MenuOptions childOptions = new MenuOptions(menuOptions); - childOptions.setOptionGroup(true); - - List<Component> buttons = makeComponents(optionGroupId, childOptions); - addNullSeparator(components); - if (buttons.isEmpty()) { - logger.warn("No sub components found for option group " - + optionGroupId); - return; - } - ButtonGroup buttonGroup = new ButtonGroup(); - - for (Component button : buttons) { - if (button instanceof AbstractButton) - buttonGroup.add((AbstractButton) button); - else - logger.warn("Component of button group " + optionGroupId - + " is not an AbstractButton: " + button); - if (button == null) { - logger.warn("Separator found within button group"); - addNullSeparator(components); - } else - components.add(button); - } - addNullSeparator(components); - } - - /** - * Add a section to a list of components. - * - * @param components - * List of components - * @param sectionId - * The {@link URI} identifying the section - * @param menuOptions - * {@link MenuOptions options} for creating the menu - */ - private void addSection(List<Component> components, URI sectionId, - MenuOptions menuOptions) { - List<Component> childComponents = makeComponents(sectionId, menuOptions); - - MenuComponent sectionDef = uriToMenuElement.get(sectionId); - addNullSeparator(components); - if (childComponents.isEmpty()) { - logger.warn("No sub components found for section " + sectionId); - return; - } - Action sectionAction = sectionDef.getAction(); - if (sectionAction != null) { - String sectionLabel = (String) sectionAction.getValue(NAME); - if (sectionLabel != null) { - // No separators before the label - stripTrailingNullSeparator(components); - Color labelColor = (Color) sectionAction.getValue(SECTION_COLOR); - if (labelColor == null) - labelColor = GREEN; - ShadedLabel label = new ShadedLabel(sectionLabel, labelColor); - components.add(label); - } - } - for (Component childComponent : childComponents) - if (childComponent == null) { - logger.warn("Separator found within section " + sectionId); - addNullSeparator(components); - } else - components.add(childComponent); - addNullSeparator(components); - } - - /** - * Remove the last <code>null</code> separator from the list of components - * if it's present. - * - * @param components - * List of components - */ - private void stripTrailingNullSeparator(List<Component> components) { - if (!components.isEmpty()) { - int lastIndex = components.size() - 1; - if (components.get(lastIndex) == null) - components.remove(lastIndex); - } - } - - /** - * Perform the actual update, called by {@link #update()}. Reset all the - * collections, refresh from SPI, modify any previously published components - * and notify any observers. - */ - protected synchronized void doUpdate() { - resetCollections(); - findChildren(); - updatePublishedComponents(); - multiCaster.notify(new UpdatedMenuManagerEvent()); - } - - /** - * Find all children for all known menu components. Populates - * {@link #uriToMenuElement}. - * - */ - protected void findChildren() { - for (MenuComponent menuElement : menuComponents) { - uriToMenuElement.put(menuElement.getId(), menuElement); - logger.debug("Found menu element " + menuElement.getId() + " " - + menuElement); - if (menuElement.getParentId() == null) - continue; - List<MenuComponent> siblings = menuElementTree.get(menuElement - .getParentId()); - if (siblings == null) { - siblings = new ArrayList<>(); - synchronized (menuElementTree) { - menuElementTree.put(menuElement.getParentId(), siblings); - } - } - siblings.add(menuElement); - } -// if (uriToMenuElement.isEmpty()) { -// logger.error("No menu elements found, check classpath/Raven/SPI"); -// } - } - - /** - * Get the children which have the given URI specified as their parent, or - * an empty list if no children exist. - * - * @param id - * The {@link URI} of the parent - * @return The {@link List} of {@link MenuComponent} which have the given - * parent - */ - protected List<MenuComponent> getChildren(URI id) { - List<MenuComponent> children = null; - synchronized (menuElementTree) { - children = menuElementTree.get(id); - if (children != null) - children = new ArrayList<>(children); - } - if (children == null) - children = Collections.<MenuComponent> emptyList(); - else - Collections.sort(children, menuElementComparator); - return children; - } - - /** - * Make the list of Swing {@link Component}s that are the children of the - * given {@link URI}. - * - * @param id - * The {@link URI} of the parent which children are to be made - * @param menuOptions - * Options of the created menu, for instance - * {@link MenuOptions#isToolbar()}. - * @return A {@link List} of {@link Component}s that can be added to a - * {@link JMenuBar}, {@link JMenu} or {@link JToolBar}. - */ - protected List<Component> makeComponents(URI id, MenuOptions menuOptions) { - List<Component> components = new ArrayList<>(); - for (MenuComponent childElement : getChildren(id)) { - if (childElement instanceof ContextualMenuComponent) - ((ContextualMenuComponent) childElement) - .setContextualSelection(menuOptions - .getContextualSelection()); - /* - * Important - check this AFTER setContextualSelection so the item - * can change it's enabled-state if needed. - */ - if (!childElement.isEnabled()) - continue; - MenuType type = childElement.getType(); - Action action = childElement.getAction(); - URI childId = childElement.getId(); - if (type.equals(MenuType.action)) { - if (action == null) { - logger.warn("Skipping invalid action " + childId + " for " - + id); - continue; - } - - Component actionComponent; - if (menuOptions.isOptionGroup()) { - if (menuOptions.isToolbar()) { - actionComponent = new JToggleButton(action); - toolbarizeButton((AbstractButton) actionComponent); - } else - actionComponent = new JRadioButtonMenuItem(action); - } else { - if (menuOptions.isToolbar()) { - actionComponent = new JButton(action); - toolbarizeButton((AbstractButton) actionComponent); - } else - actionComponent = new JMenuItem(action); - } - registerComponent(childId, actionComponent); - components.add(actionComponent); - } else if (type.equals(MenuType.toggle)) { - if (action == null) { - logger.warn("Skipping invalid toggle " + childId + " for " - + id); - continue; - } - Component toggleComponent; - if (menuOptions.isToolbar()) - toggleComponent = new JToggleButton(action); - else - toggleComponent = new JCheckBoxMenuItem(action); - registerComponent(childId, toggleComponent); - components.add(toggleComponent); - } else if (type.equals(MenuType.custom)) { - Component customComponent = childElement.getCustomComponent(); - if (customComponent == null) { - logger.warn("Skipping null custom component " + childId - + " for " + id); - continue; - } - registerComponent(childId, customComponent); - components.add(customComponent); - } else if (type.equals(MenuType.optionGroup)) - addOptionGroup(components, childId, menuOptions); - else if (type.equals(MenuType.section)) - addSection(components, childId, menuOptions); - else if (type.equals(MenuType.menu)) - addMenu(components, childElement, menuOptions); - else { - logger.warn("Skipping invalid/unknown type " + type + " for " - + id); - continue; - } - } - stripTrailingNullSeparator(components); - return components; - } - - /** - * Fill the specified menu bar with the menu elements that have the given - * URI as their parent. - * <p> - * Existing elements on the menu bar will be removed. - * - * @param menuBar - * The {@link JMenuBar} to update - * @param id - * The {@link URI} of the menu bar - */ - protected void populateMenuBar(JMenuBar menuBar, URI id) { - menuBar.removeAll(); - MenuComponent menuDef = uriToMenuElement.get(id); - if (menuDef == null) - throw new IllegalArgumentException("Unknown menuBar " + id); - if (!menuDef.getType().equals(MenuType.menu)) - throw new IllegalArgumentException("Element " + id - + " is not a menu, but a " + menuDef.getType()); - MenuOptions menuOptions = new MenuOptions(); - for (Component component : makeComponents(id, menuOptions)) - if (component == null) - logger.warn("Ignoring separator in menu bar " + id); - else - menuBar.add(component); - } - - /** - * Fill the specified menu bar with the menu elements that have the given - * URI as their parent. - * <p> - * Existing elements on the menu bar will be removed. - * - * @param popupMenu - * The {@link JPopupMenu} to update - * @param id - * The {@link URI} of the menu bar - * @param contextualSelection - * The current selection for the context menu - */ - protected void populateContextMenu(JPopupMenu popupMenu, URI id, - ContextualSelection contextualSelection) { - popupMenu.removeAll(); - MenuComponent menuDef = uriToMenuElement.get(id); - if (menuDef == null) - throw new IllegalArgumentException("Unknown menuBar " + id); - if (!menuDef.getType().equals(MenuType.menu)) - throw new IllegalArgumentException("Element " + id - + " is not a menu, but a " + menuDef.getType()); - MenuOptions menuOptions = new MenuOptions(); - menuOptions.setContextualSelection(contextualSelection); - for (Component component : makeComponents(id, menuOptions)) - if (component == null) - popupMenu.addSeparator(); - else - popupMenu.add(component); - } - - /** - * Fill the specified tool bar with the elements that have the given URI as - * their parent. - * <p> - * Existing elements on the tool bar will be removed. - * - * @param toolbar - * The {@link JToolBar} to update - * @param id - * The {@link URI} of the tool bar - */ - protected void populateToolBar(JToolBar toolbar, URI id) { - toolbar.removeAll(); - MenuComponent toolbarDef = uriToMenuElement.get(id); - if (toolbarDef == null) - throw new IllegalArgumentException("Unknown toolBar " + id); - if (!toolbarDef.getType().equals(MenuType.toolBar)) - throw new IllegalArgumentException("Element " + id - + " is not a toolBar, but a " + toolbarDef.getType()); - if (toolbarDef.getAction() != null) { - String name = (String) toolbarDef.getAction().getValue(Action.NAME); - toolbar.setName(name); - } else - toolbar.setName(""); - MenuOptions menuOptions = new MenuOptions(); - menuOptions.setToolbar(true); - for (Component component : makeComponents(id, menuOptions)) { - if (component == null) { - toolbar.addSeparator(); - continue; - } - if (component instanceof JButton) { - JButton toolbarButton = (JButton) component; - toolbarButton.putClientProperty("hideActionText", true); - } - toolbar.add(component); - } - } - - /** - * Register a component that has been created. Such a component can be - * resolved through {@link #getComponentByURI(URI)}. - * - * @param id - * The {@link URI} that defined the component - * @param component - * The {@link Component} that was created. - */ - protected synchronized void registerComponent(URI id, Component component) { - registerComponent(id, component, false); - } - - /** - * Register a component that has been created. Such a component can be - * resolved through {@link #getComponentByURI(URI)}. - * - * @param id - * The {@link URI} that defined the component - * @param component - * The {@link Component} that was created. - * @param published - * <code>true</code> if the component has been published through - * {@link #createMenuBar()} or similar, and is to be - * automatically updated by later calls to {@link #update()}. - */ - protected synchronized void registerComponent(URI id, Component component, - boolean published) { - uriToComponent.put(id, new WeakReference<>(component)); - componentToUri.put(component, id); - if (published) { - List<WeakReference<Component>> publishedComponents = uriToPublishedComponents - .get(id); - if (publishedComponents == null) { - publishedComponents = new ArrayList<>(); - uriToPublishedComponents.put(id, publishedComponents); - } - publishedComponents.add(new WeakReference<>(component)); - } - setHelpStringForComponent(component, id); - } - - /** - * Reset all collections - * - */ - protected synchronized void resetCollections() { - menuElementTree = new HashMap<>(); - componentToUri = new WeakHashMap<>(); - uriToMenuElement = new HashMap<>(); - uriToComponent = new HashMap<>(); - } - - /** - * Set javax.help string to identify the component for later references to - * the help document. Note that the component (ie. the - * {@link AbstractMenuAction} must have an ID for an registration to take - * place. - * - * @param component - * The {@link Component} to set help string for - * @param componentId - * The {@link URI} to be used as identifier - */ - protected void setHelpStringForComponent(Component component, - URI componentId) { - if (componentId != null) { - String helpId = componentId.toASCIIString(); - setHelpIDString(component, helpId); - } - } - - /** - * Make an {@link AbstractButton} be configured in a "toolbar-like" way, for - * instance showing only the icon. - * - * @param actionButton - * Button to toolbarise - */ - protected void toolbarizeButton(AbstractButton actionButton) { - Action action = actionButton.getAction(); - if (action.getValue(SHORT_DESCRIPTION) == null) - action.putValue(SHORT_DESCRIPTION, action.getValue(NAME)); - actionButton.setBorder(new EmptyBorder(0, 2, 0, 2)); - // actionButton.setHorizontalTextPosition(JButton.CENTER); - // actionButton.setVerticalTextPosition(JButton.BOTTOM); - if (action.getValue(Action.SMALL_ICON) != null) { - // Don't show the text - actionButton.putClientProperty("hideActionText", true); - // Since hideActionText seems to be broken in Java 5 and/or OS X - actionButton.setText(null); - } - } - - /** - * Update all components that have been published using - * {@link #createMenuBar()} and similar. Content of such components will be - * removed and replaced by fresh components. - */ - protected void updatePublishedComponents() { - for (Entry<URI, List<WeakReference<Component>>> entry : uriToPublishedComponents - .entrySet()) - for (WeakReference<Component> reference : entry.getValue()) { - URI id = entry.getKey(); - Component component = reference.get(); - if (component == null) - continue; - if (component instanceof JToolBar) - populateToolBar((JToolBar) component, id); - else if (component instanceof JMenuBar) - populateMenuBar((JMenuBar) component, id); - else - logger.warn("Could not update published component " + id - + ": " + component.getClass()); - } - } - - public void setMenuComponents(List<MenuComponent> menuComponents) { - this.menuComponents = menuComponents; - } - - public void setSelectionManager(SelectionManager selectionManager) { - selectionManager.addObserver(new SelectionManagerObserver()); - } - - /** - * {@link Comparator} that can order {@link MenuComponent}s by their - * {@link MenuComponent#getPositionHint()}. - */ - protected static class MenuElementComparator implements - Comparator<MenuComponent> { - @Override - public int compare(MenuComponent a, MenuComponent b) { - return a.getPositionHint() - b.getPositionHint(); - } - } - - /** - * Various options for - * {@link MenuManagerImpl#makeComponents(URI, MenuOptions)} and friends. - * - * @author Stian Soiland-Reyes - */ - public static class MenuOptions { - private boolean isToolbar = false; - private boolean isOptionGroup = false; - private ContextualSelection contextualSelection = null; - - public ContextualSelection getContextualSelection() { - return contextualSelection; - } - - public void setContextualSelection( - ContextualSelection contextualSelection) { - this.contextualSelection = contextualSelection; - } - - public MenuOptions(MenuOptions original) { - this.isOptionGroup = original.isOptionGroup(); - this.isToolbar = original.isToolbar(); - this.contextualSelection = original.getContextualSelection(); - } - - public MenuOptions() { - } - - @Override - protected MenuOptions clone() { - return new MenuOptions(this); - } - - public boolean isToolbar() { - return isToolbar; - } - - public void setToolbar(boolean isToolbar) { - this.isToolbar = isToolbar; - } - - public boolean isOptionGroup() { - return isOptionGroup; - } - - public void setOptionGroup(boolean isOptionGroup) { - this.isOptionGroup = isOptionGroup; - } - } - - private final class SelectionManagerObserver extends - SwingAwareObserver<SelectionManagerEvent> { - private static final String DESIGN_PERSPECTIVE_ID = "net.sf.taverna.t2.ui.perspectives.design.DesignPerspective"; - private static final String RESULTS_PERSPECTIVE_ID = "net.sf.taverna.t2.ui.perspectives.results.ResultsPerspective"; - - @Override - public void notifySwing(Observable<SelectionManagerEvent> sender, - SelectionManagerEvent message) { - if (!(message instanceof PerspectiveSelectionEvent)) - return; - handlePerspectiveSelect((PerspectiveSelectionEvent) message); - } - - private void handlePerspectiveSelect(PerspectiveSelectionEvent event) { - String perspectiveID = event.getSelectedPerspective().getID(); - boolean isDesign = DESIGN_PERSPECTIVE_ID.equals(perspectiveID); - boolean isResults = RESULTS_PERSPECTIVE_ID.equals(perspectiveID); - - for (MenuComponent menuComponent : menuComponents) - if (!(menuComponent instanceof ContextualMenuComponent)) { - Action action = menuComponent.getAction(); - if (action instanceof DesignOnlyAction) - action.setEnabled(isDesign); - else if (action instanceof DesignOrResultsAction) - action.setEnabled(isDesign || isResults); - } - } - } -}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-menu-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/menu/AdvancedMenu.java ---------------------------------------------------------------------- diff --git a/taverna-menu-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/menu/AdvancedMenu.java b/taverna-menu-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/menu/AdvancedMenu.java deleted file mode 100644 index 9a2f37b..0000000 --- a/taverna-menu-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/menu/AdvancedMenu.java +++ /dev/null @@ -1,44 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2007 The University of Manchester - * - * Modifications to the initial code base are copyright of their - * respective authors, or their employers as appropriate. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser 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 - ******************************************************************************/ -package net.sf.taverna.t2.workbench.ui.impl.menu; - -import static java.awt.event.KeyEvent.VK_A; -import static javax.swing.Action.MNEMONIC_KEY; -import static net.sf.taverna.t2.ui.menu.DefaultMenuBar.DEFAULT_MENU_BAR; - -import java.net.URI; - -import net.sf.taverna.t2.ui.menu.AbstractMenu; - -public class AdvancedMenu extends AbstractMenu { - public static final URI ADVANCED_URI = URI - .create("http://taverna.sf.net/2008/t2workbench/menu#advanced"); - - public AdvancedMenu() { - super(DEFAULT_MENU_BAR, 1000, ADVANCED_URI, makeAction()); - } - - public static DummyAction makeAction() { - DummyAction action = new DummyAction("Advanced"); - action.putValue(MNEMONIC_KEY, Integer.valueOf(VK_A)); - return action; - } -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-menu-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/menu/EditMenu.java ---------------------------------------------------------------------- diff --git a/taverna-menu-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/menu/EditMenu.java b/taverna-menu-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/menu/EditMenu.java deleted file mode 100644 index a15237c..0000000 --- a/taverna-menu-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/menu/EditMenu.java +++ /dev/null @@ -1,43 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2007 The University of Manchester - * - * Modifications to the initial code base are copyright of their - * respective authors, or their employers as appropriate. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser 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 - ******************************************************************************/ -package net.sf.taverna.t2.workbench.ui.impl.menu; - -import static java.awt.event.KeyEvent.VK_E; -import static javax.swing.Action.MNEMONIC_KEY; -import static net.sf.taverna.t2.ui.menu.DefaultMenuBar.DEFAULT_MENU_BAR; - -import java.net.URI; - -import net.sf.taverna.t2.ui.menu.AbstractMenu; - -public class EditMenu extends AbstractMenu { - public EditMenu() { - super(DEFAULT_MENU_BAR, 20, URI - .create("http://taverna.sf.net/2008/t2workbench/menu#edit"), - makeAction()); - } - - public static DummyAction makeAction() { - DummyAction action = new DummyAction("Edit"); - action.putValue(MNEMONIC_KEY, Integer.valueOf(VK_E)); - return action; - } -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-menu-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/menu/FeedbackMenuAction.java ---------------------------------------------------------------------- diff --git a/taverna-menu-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/menu/FeedbackMenuAction.java b/taverna-menu-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/menu/FeedbackMenuAction.java deleted file mode 100644 index 6b6eb7c..0000000 --- a/taverna-menu-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/menu/FeedbackMenuAction.java +++ /dev/null @@ -1,75 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2007 The University of Manchester - * - * Modifications to the initial code base are copyright of their - * respective authors, or their employers as appropriate. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser 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 - ******************************************************************************/ -package net.sf.taverna.t2.workbench.ui.impl.menu; - -import static java.awt.Desktop.getDesktop; -import static net.sf.taverna.t2.workbench.ui.impl.menu.HelpMenu.HELP_URI; - -import java.awt.event.ActionEvent; -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; - -import javax.swing.AbstractAction; -import javax.swing.Action; - -import net.sf.taverna.t2.ui.menu.AbstractMenuAction; - -import org.apache.log4j.Logger; - -/** - * MenuItem for feedback - * - * @author alanrw - */ -public class FeedbackMenuAction extends AbstractMenuAction { - private static Logger logger = Logger.getLogger(FeedbackMenuAction.class); - - private static String FEEDBACK_URL = "http://www.taverna.org.uk/about/contact-us/feedback/"; - - public FeedbackMenuAction() { - super(HELP_URI, 20); - } - - @Override - protected Action createAction() { - return new FeedbackAction(); - } - - @SuppressWarnings("serial") - private final class FeedbackAction extends AbstractAction { - private FeedbackAction() { - super("Contact us"); - } - - @Override - public void actionPerformed(ActionEvent e) { - try { - getDesktop().browse(new URI(FEEDBACK_URL)); - } catch (IOException e1) { - logger.error("Unable to open URL", e1); - } catch (URISyntaxException e1) { - logger.error("Invalid URL syntax", e1); - } - } - } - -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-menu-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/menu/FileMenu.java ---------------------------------------------------------------------- diff --git a/taverna-menu-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/menu/FileMenu.java b/taverna-menu-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/menu/FileMenu.java deleted file mode 100644 index 61f963b..0000000 --- a/taverna-menu-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/menu/FileMenu.java +++ /dev/null @@ -1,48 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2007 The University of Manchester - * - * Modifications to the initial code base are copyright of their - * respective authors, or their employers as appropriate. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser 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 - ******************************************************************************/ -package net.sf.taverna.t2.workbench.ui.impl.menu; - -import static java.awt.event.KeyEvent.VK_F; -import static javax.swing.Action.MNEMONIC_KEY; -import static net.sf.taverna.t2.ui.menu.DefaultMenuBar.DEFAULT_MENU_BAR; - -import java.net.URI; - -import net.sf.taverna.t2.ui.menu.AbstractMenu; - -/** - * File menu - * - * @author Stian Soiland-Reyes - */ -public class FileMenu extends AbstractMenu { - public FileMenu() { - super(DEFAULT_MENU_BAR, 10, URI - .create("http://taverna.sf.net/2008/t2workbench/menu#file"), - makeAction()); - } - - public static DummyAction makeAction() { - DummyAction action = new DummyAction("File"); - action.putValue(MNEMONIC_KEY, Integer.valueOf(VK_F)); - return action; - } -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-menu-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/menu/HelpMenu.java ---------------------------------------------------------------------- diff --git a/taverna-menu-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/menu/HelpMenu.java b/taverna-menu-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/menu/HelpMenu.java deleted file mode 100644 index c4169cc..0000000 --- a/taverna-menu-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/menu/HelpMenu.java +++ /dev/null @@ -1,44 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2007 The University of Manchester - * - * Modifications to the initial code base are copyright of their - * respective authors, or their employers as appropriate. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser 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 - ******************************************************************************/ -package net.sf.taverna.t2.workbench.ui.impl.menu; - -import static java.awt.event.KeyEvent.VK_H; -import static javax.swing.Action.MNEMONIC_KEY; -import static net.sf.taverna.t2.ui.menu.DefaultMenuBar.DEFAULT_MENU_BAR; - -import java.net.URI; - -import net.sf.taverna.t2.ui.menu.AbstractMenu; - -public class HelpMenu extends AbstractMenu { - public static final URI HELP_URI = URI - .create("http://taverna.sf.net/2008/t2workbench/menu#help"); - - public HelpMenu() { - super(DEFAULT_MENU_BAR, 1024, HELP_URI, makeAction()); - } - - public static DummyAction makeAction() { - DummyAction action = new DummyAction("Help"); - action.putValue(MNEMONIC_KEY, Integer.valueOf(VK_H)); - return action; - } -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-menu-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/menu/OnlineHelpMenuAction.java ---------------------------------------------------------------------- diff --git a/taverna-menu-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/menu/OnlineHelpMenuAction.java b/taverna-menu-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/menu/OnlineHelpMenuAction.java deleted file mode 100644 index d091c8e..0000000 --- a/taverna-menu-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/menu/OnlineHelpMenuAction.java +++ /dev/null @@ -1,68 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2007 The University of Manchester - * - * Modifications to the initial code base are copyright of their - * respective authors, or their employers as appropriate. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser 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 - ******************************************************************************/ -package net.sf.taverna.t2.workbench.ui.impl.menu; - -import static java.awt.event.KeyEvent.VK_F1; -import static javax.swing.KeyStroke.getKeyStroke; -import static net.sf.taverna.t2.workbench.helper.Helper.displayDefaultHelp; -import static net.sf.taverna.t2.workbench.ui.impl.menu.HelpMenu.HELP_URI; - -import java.awt.AWTEvent; -import java.awt.event.ActionEvent; - -import javax.swing.AbstractAction; -import javax.swing.Action; - -import net.sf.taverna.t2.ui.menu.AbstractMenuAction; - -/** - * MenuItem for help - * - * @author alanrw - */ -public class OnlineHelpMenuAction extends AbstractMenuAction { - public OnlineHelpMenuAction() { - super(HELP_URI, 10); - } - - @Override - protected Action createAction() { - return new OnlineHelpAction(); - } - - @SuppressWarnings("serial") - private final class OnlineHelpAction extends AbstractAction { - private OnlineHelpAction() { - super("Online help"); - putValue(ACCELERATOR_KEY, getKeyStroke(VK_F1, 0)); - - } - - /** - * When selected, use the Helper to display the default help. - */ - @Override - public void actionPerformed(ActionEvent e) { - displayDefaultHelp((AWTEvent) e); - // TODO change helper to bean? - } - } -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-menu-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/menu/ShowLogsAndDataMenuAction.java ---------------------------------------------------------------------- diff --git a/taverna-menu-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/menu/ShowLogsAndDataMenuAction.java b/taverna-menu-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/menu/ShowLogsAndDataMenuAction.java deleted file mode 100644 index 308d51d..0000000 --- a/taverna-menu-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/menu/ShowLogsAndDataMenuAction.java +++ /dev/null @@ -1,89 +0,0 @@ -package net.sf.taverna.t2.workbench.ui.impl.menu; - -import static java.lang.Runtime.getRuntime; -import static javax.swing.JOptionPane.INFORMATION_MESSAGE; -import static javax.swing.JOptionPane.showInputDialog; -import static net.sf.taverna.t2.workbench.MainWindow.getMainWindow; -import static net.sf.taverna.t2.workbench.ui.impl.menu.AdvancedMenu.ADVANCED_URI; - -import java.awt.event.ActionEvent; -import java.io.File; - -import javax.swing.AbstractAction; -import javax.swing.Action; - -import net.sf.taverna.t2.ui.menu.AbstractMenuAction; - -import org.apache.log4j.Logger; - -import uk.org.taverna.configuration.app.ApplicationConfiguration; - -public class ShowLogsAndDataMenuAction extends AbstractMenuAction { - private static final String OPEN = "open"; - private static final String EXPLORER = "explorer"; - // TODO Consider using xdg-open instead of gnome-open - private static final String GNOME_OPEN = "gnome-open"; - private static final String WINDOWS = "Windows"; - private static final String MAC_OS_X = "Mac OS X"; - - private ApplicationConfiguration applicationConfiguration; - - public ShowLogsAndDataMenuAction() { - super(ADVANCED_URI, 200); - } - - private static Logger logger = Logger.getLogger(ShowLogsAndDataMenuAction.class); - - @Override - protected Action createAction() { - return new AbstractAction("Show logs and data folder") { - private static final long serialVersionUID = 1L; - - @Override - public void actionPerformed(ActionEvent e) { - File logsAndDataDir = applicationConfiguration.getApplicationHomeDir(); - showDirectory(logsAndDataDir, "Taverna logs and data folder"); - } - }; - } - - public static void showDirectory(File dir, String title) { - String path = dir.getAbsolutePath(); - String os = System.getProperty("os.name"); - String cmd; - boolean isWindows = false; - if (os.equals(MAC_OS_X)) - cmd = OPEN; - else if (os.startsWith(WINDOWS)) { - cmd = EXPLORER; - isWindows = true; - } else - // Assume Unix - best option is gnome-open - cmd = GNOME_OPEN; - - String[] cmdArray = new String[2]; - cmdArray[0] = cmd; - cmdArray[1] = path; - try { - Process exec = getRuntime().exec(cmdArray); - Thread.sleep(300); - exec.getErrorStream().close(); - exec.getInputStream().close(); - exec.getOutputStream().close(); - exec.waitFor(); - if (exec.exitValue() == 0 || isWindows && exec.exitValue() == 1) - // explorer.exe thinks 1 means success - return; - logger.warn("Exit value from " + cmd + " " + path + ": " + exec.exitValue()); - } catch (Exception ex) { - logger.warn("Could not call " + cmd + " " + path, ex); - } - // Fall-back - just show a dialogue with the path - showInputDialog(getMainWindow(), "Copy path from below:", title, - INFORMATION_MESSAGE, null, null, path); - } - - public void setApplicationConfiguration(ApplicationConfiguration applicationConfiguration) { - this.applicationConfiguration = applicationConfiguration; - } -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-menu-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/menu/ViewShowMenuSection.java ---------------------------------------------------------------------- diff --git a/taverna-menu-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/menu/ViewShowMenuSection.java b/taverna-menu-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/menu/ViewShowMenuSection.java deleted file mode 100644 index 2df05e5..0000000 --- a/taverna-menu-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/menu/ViewShowMenuSection.java +++ /dev/null @@ -1,40 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2007 The University of Manchester - * - * Modifications to the initial code base are copyright of their - * respective authors, or their employers as appropriate. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser 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 - ******************************************************************************/ -package net.sf.taverna.t2.workbench.ui.impl.menu; - -import java.net.URI; - -import net.sf.taverna.t2.ui.menu.AbstractMenuSection; - -/** - * @author Alex Nenadic - * @author Alan R Williams - */ -public class ViewShowMenuSection extends AbstractMenuSection { - public static final URI DIAGRAM_MENU = URI - .create("http://taverna.sf.net/2008/t2workbench/menu#diagram"); - public static final URI VIEW_SHOW_MENU_SECTION = URI - .create("http://taverna.sf.net/2008/t2workbench/menu#viewShowMenuSection"); - - public ViewShowMenuSection() { - super(DIAGRAM_MENU, 10, VIEW_SHOW_MENU_SECTION); - } -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-menu-impl/src/main/java/org/apache/taverna/ui/menu/impl/MenuManagerImpl.java ---------------------------------------------------------------------- diff --git a/taverna-menu-impl/src/main/java/org/apache/taverna/ui/menu/impl/MenuManagerImpl.java b/taverna-menu-impl/src/main/java/org/apache/taverna/ui/menu/impl/MenuManagerImpl.java new file mode 100644 index 0000000..826114e --- /dev/null +++ b/taverna-menu-impl/src/main/java/org/apache/taverna/ui/menu/impl/MenuManagerImpl.java @@ -0,0 +1,879 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +package org.apache.taverna.ui.menu.impl; + +import static java.lang.Math.min; +import static javax.help.CSH.setHelpIDString; +import static javax.swing.Action.NAME; +import static javax.swing.Action.SHORT_DESCRIPTION; +import static org.apache.taverna.lang.ui.ShadedLabel.GREEN; +import static org.apache.taverna.ui.menu.AbstractMenuSection.SECTION_COLOR; +import static org.apache.taverna.ui.menu.DefaultContextualMenu.DEFAULT_CONTEXT_MENU; +import static org.apache.taverna.ui.menu.DefaultMenuBar.DEFAULT_MENU_BAR; +import static org.apache.taverna.ui.menu.DefaultToolBar.DEFAULT_TOOL_BAR; + +import java.awt.Color; +import java.awt.Component; +import java.lang.ref.WeakReference; +import java.net.URI; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.WeakHashMap; + +import javax.swing.AbstractButton; +import javax.swing.Action; +import javax.swing.ButtonGroup; +import javax.swing.JButton; +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; +import javax.swing.JRadioButtonMenuItem; +import javax.swing.JToggleButton; +import javax.swing.JToolBar; +import javax.swing.border.EmptyBorder; + +import org.apache.taverna.lang.observer.MultiCaster; +import org.apache.taverna.lang.observer.Observable; +import org.apache.taverna.lang.observer.Observer; +import org.apache.taverna.lang.observer.SwingAwareObserver; +import org.apache.taverna.lang.ui.ShadedLabel; +import org.apache.taverna.ui.menu.AbstractMenuAction; +import org.apache.taverna.ui.menu.AbstractMenuOptionGroup; +import org.apache.taverna.ui.menu.ContextualMenuComponent; +import org.apache.taverna.ui.menu.ContextualSelection; +import org.apache.taverna.ui.menu.DesignOnlyAction; +import org.apache.taverna.ui.menu.DesignOrResultsAction; +import org.apache.taverna.ui.menu.MenuComponent; +import org.apache.taverna.ui.menu.MenuComponent.MenuType; +import org.apache.taverna.ui.menu.MenuManager; +import org.apache.taverna.workbench.selection.SelectionManager; +import org.apache.taverna.workbench.selection.events.PerspectiveSelectionEvent; +import org.apache.taverna.workbench.selection.events.SelectionManagerEvent; + +import org.apache.log4j.Logger; + +/** + * Implementation of {@link MenuManager}. + * + * @author Stian Soiland-Reyes + */ +public class MenuManagerImpl implements MenuManager { + private static Logger logger = Logger.getLogger(MenuManagerImpl.class); + + private boolean needsUpdate; + /** + * Cache used by {@link #getURIByComponent(Component)} + */ + private WeakHashMap<Component, URI> componentToUri; + /** + * {@link MenuElementComparator} used for sorting menu components from the + * SPI registry. + */ + private MenuElementComparator menuElementComparator = new MenuElementComparator(); + /** + * Map of {@link URI} to it's discovered children. Populated by + * {@link #findChildren()}. + */ + private HashMap<URI, List<MenuComponent>> menuElementTree; + /** + * Multicaster to distribute messages to {@link Observer}s of this menu + * manager. + */ + private MultiCaster<MenuManagerEvent> multiCaster; + /** + * Lock for {@link #update()} + */ + private final Object updateLock = new Object(); + /** + * True if {@link #doUpdate()} is running, subsequents call to + * {@link #update()} will return immediately. + */ + private boolean updating; + /** + * Cache used by {@link #getComponentByURI(URI)} + */ + private Map<URI, WeakReference<Component>> uriToComponent; + /** + * Map from {@link URI} to defining {@link MenuComponent}. Children are in + * {@link #menuElementTree}. + */ + private Map<URI, MenuComponent> uriToMenuElement; + // Note: Not reset by #resetCollections() + private Map<URI, List<WeakReference<Component>>> uriToPublishedComponents = new HashMap<>(); + private List<MenuComponent> menuComponents = new ArrayList<>(); + + /** + * Construct the MenuManagerImpl. Observes the SPI registry and does an + * initial {@link #update()}. + */ + public MenuManagerImpl() { + multiCaster = new MultiCaster<>(this); + needsUpdate = true; + } + + /** + * {@inheritDoc} + */ + @Override + public void addMenuItemsWithExpansion(List<JMenuItem> menuItems, + JMenu parentMenu, int maxItemsInMenu, + ComponentFactory headerItemFactory) { + if (menuItems.size() <= maxItemsInMenu) { + // Just add them directly + for (JMenuItem menuItem : menuItems) + parentMenu.add(menuItem); + return; + } + int index = 0; + while (index < menuItems.size()) { + int toIndex = min(menuItems.size(), index + maxItemsInMenu); + if (toIndex == menuItems.size() - 1) + // Don't leave a single item left for the last subMenu + toIndex--; + List<JMenuItem> subList = menuItems.subList(index, toIndex); + JMenuItem firstItem = subList.get(0); + JMenuItem lastItem = subList.get(subList.size() - 1); + JMenu subMenu = new JMenu(firstItem.getText() + " ... " + + lastItem.getText()); + if (headerItemFactory != null) + subMenu.add(headerItemFactory.makeComponent()); + for (JMenuItem menuItem : subList) + subMenu.add(menuItem); + parentMenu.add(subMenu); + index = toIndex; + } + } + + @Override + public void addObserver(Observer<MenuManagerEvent> observer) { + multiCaster.addObserver(observer); + } + + @Override + public JPopupMenu createContextMenu(Object parent, Object selection, + Component relativeToComponent) { + ContextualSelection contextualSelection = new ContextualSelection( + parent, selection, relativeToComponent); + JPopupMenu popupMenu = new JPopupMenu(); + populateContextMenu(popupMenu, DEFAULT_CONTEXT_MENU, + contextualSelection); + registerComponent(DEFAULT_CONTEXT_MENU, popupMenu, true); + return popupMenu; + } + + @Override + public JMenuBar createMenuBar() { + return createMenuBar(DEFAULT_MENU_BAR); + } + + @Override + public JMenuBar createMenuBar(URI id) { + JMenuBar menuBar = new JMenuBar(); + if (needsUpdate) + update(); + populateMenuBar(menuBar, id); + registerComponent(id, menuBar, true); + return menuBar; + } + + @Override + public JToolBar createToolBar() { + return createToolBar(DEFAULT_TOOL_BAR); + } + + @Override + public JToolBar createToolBar(URI id) { + JToolBar toolbar = new JToolBar(); + if (needsUpdate) + update(); + populateToolBar(toolbar, id); + registerComponent(id, toolbar, true); + return toolbar; + } + + @Override + public synchronized Component getComponentByURI(URI id) { + WeakReference<Component> componentRef = uriToComponent.get(id); + if (componentRef == null) + return null; + // Might also be null it reference has gone dead + return componentRef.get(); + } + + @Override + public List<Observer<MenuManagerEvent>> getObservers() { + return multiCaster.getObservers(); + } + + @Override + public synchronized URI getURIByComponent(Component component) { + return componentToUri.get(component); + } + + @Override + public void removeObserver(Observer<MenuManagerEvent> observer) { + multiCaster.removeObserver(observer); + } + + @Override + public void update() { + synchronized (updateLock) { + if (updating && !needsUpdate) + return; + updating = true; + } + try { + doUpdate(); + } finally { + synchronized (updateLock) { + updating = false; + needsUpdate = false; + } + } + } + + public void update(Object service, Map<?, ?> properties) { + needsUpdate = true; + update(); + } + + /** + * Add a {@link JMenu} to the list of components as described by the menu + * component. If there are no children, the menu is not added. + * + * @param components + * List of components where to add the created {@link JMenu} + * @param menuComponent + * The {@link MenuComponent} definition for this menu + * @param isToolbar + * True if the list of components is to be added to a toolbar + */ + private void addMenu(List<Component> components, + MenuComponent menuComponent, MenuOptions menuOptions) { + URI menuId = menuComponent.getId(); + if (menuOptions.isToolbar()) { + logger.warn("Can't have menu " + menuComponent + + " within toolBar element"); + return; + } + MenuOptions childOptions = new MenuOptions(menuOptions); + List<Component> subComponents = makeComponents(menuId, childOptions); + if (subComponents.isEmpty()) { + logger.warn("No sub components found for menu " + menuId); + return; + } + + JMenu menu = new JMenu(menuComponent.getAction()); + for (Component menuItem : subComponents) + if (menuItem == null) + menu.addSeparator(); + else + menu.add(menuItem); + registerComponent(menuId, menu); + components.add(menu); + } + + /** + * Add <code>null</code> to the list of components, meaning that a separator + * is to be created. Subsequent separators are ignored, and if there are no + * components on the list already no separator will be added. + * + * @param components + * List of components + */ + private void addNullSeparator(List<Component> components) { + if (components.isEmpty()) + // Don't start with a separator + return; + if (components.get(components.size() - 1) == null) + // Already a separator in last position + return; + components.add(null); + } + + /** + * Add an {@link AbstractMenuOptionGroup option group} to the list of + * components + * + * @param components + * List of components where to add the created {@link JMenu} + * @param optionGroupId + * The {@link URI} identifying the option group + * @param isToolbar + * True if the option group is to be added to a toolbar + */ + private void addOptionGroup(List<Component> components, URI optionGroupId, + MenuOptions menuOptions) { + MenuOptions childOptions = new MenuOptions(menuOptions); + childOptions.setOptionGroup(true); + + List<Component> buttons = makeComponents(optionGroupId, childOptions); + addNullSeparator(components); + if (buttons.isEmpty()) { + logger.warn("No sub components found for option group " + + optionGroupId); + return; + } + ButtonGroup buttonGroup = new ButtonGroup(); + + for (Component button : buttons) { + if (button instanceof AbstractButton) + buttonGroup.add((AbstractButton) button); + else + logger.warn("Component of button group " + optionGroupId + + " is not an AbstractButton: " + button); + if (button == null) { + logger.warn("Separator found within button group"); + addNullSeparator(components); + } else + components.add(button); + } + addNullSeparator(components); + } + + /** + * Add a section to a list of components. + * + * @param components + * List of components + * @param sectionId + * The {@link URI} identifying the section + * @param menuOptions + * {@link MenuOptions options} for creating the menu + */ + private void addSection(List<Component> components, URI sectionId, + MenuOptions menuOptions) { + List<Component> childComponents = makeComponents(sectionId, menuOptions); + + MenuComponent sectionDef = uriToMenuElement.get(sectionId); + addNullSeparator(components); + if (childComponents.isEmpty()) { + logger.warn("No sub components found for section " + sectionId); + return; + } + Action sectionAction = sectionDef.getAction(); + if (sectionAction != null) { + String sectionLabel = (String) sectionAction.getValue(NAME); + if (sectionLabel != null) { + // No separators before the label + stripTrailingNullSeparator(components); + Color labelColor = (Color) sectionAction.getValue(SECTION_COLOR); + if (labelColor == null) + labelColor = GREEN; + ShadedLabel label = new ShadedLabel(sectionLabel, labelColor); + components.add(label); + } + } + for (Component childComponent : childComponents) + if (childComponent == null) { + logger.warn("Separator found within section " + sectionId); + addNullSeparator(components); + } else + components.add(childComponent); + addNullSeparator(components); + } + + /** + * Remove the last <code>null</code> separator from the list of components + * if it's present. + * + * @param components + * List of components + */ + private void stripTrailingNullSeparator(List<Component> components) { + if (!components.isEmpty()) { + int lastIndex = components.size() - 1; + if (components.get(lastIndex) == null) + components.remove(lastIndex); + } + } + + /** + * Perform the actual update, called by {@link #update()}. Reset all the + * collections, refresh from SPI, modify any previously published components + * and notify any observers. + */ + protected synchronized void doUpdate() { + resetCollections(); + findChildren(); + updatePublishedComponents(); + multiCaster.notify(new UpdatedMenuManagerEvent()); + } + + /** + * Find all children for all known menu components. Populates + * {@link #uriToMenuElement}. + * + */ + protected void findChildren() { + for (MenuComponent menuElement : menuComponents) { + uriToMenuElement.put(menuElement.getId(), menuElement); + logger.debug("Found menu element " + menuElement.getId() + " " + + menuElement); + if (menuElement.getParentId() == null) + continue; + List<MenuComponent> siblings = menuElementTree.get(menuElement + .getParentId()); + if (siblings == null) { + siblings = new ArrayList<>(); + synchronized (menuElementTree) { + menuElementTree.put(menuElement.getParentId(), siblings); + } + } + siblings.add(menuElement); + } +// if (uriToMenuElement.isEmpty()) { +// logger.error("No menu elements found, check classpath/Raven/SPI"); +// } + } + + /** + * Get the children which have the given URI specified as their parent, or + * an empty list if no children exist. + * + * @param id + * The {@link URI} of the parent + * @return The {@link List} of {@link MenuComponent} which have the given + * parent + */ + protected List<MenuComponent> getChildren(URI id) { + List<MenuComponent> children = null; + synchronized (menuElementTree) { + children = menuElementTree.get(id); + if (children != null) + children = new ArrayList<>(children); + } + if (children == null) + children = Collections.<MenuComponent> emptyList(); + else + Collections.sort(children, menuElementComparator); + return children; + } + + /** + * Make the list of Swing {@link Component}s that are the children of the + * given {@link URI}. + * + * @param id + * The {@link URI} of the parent which children are to be made + * @param menuOptions + * Options of the created menu, for instance + * {@link MenuOptions#isToolbar()}. + * @return A {@link List} of {@link Component}s that can be added to a + * {@link JMenuBar}, {@link JMenu} or {@link JToolBar}. + */ + protected List<Component> makeComponents(URI id, MenuOptions menuOptions) { + List<Component> components = new ArrayList<>(); + for (MenuComponent childElement : getChildren(id)) { + if (childElement instanceof ContextualMenuComponent) + ((ContextualMenuComponent) childElement) + .setContextualSelection(menuOptions + .getContextualSelection()); + /* + * Important - check this AFTER setContextualSelection so the item + * can change it's enabled-state if needed. + */ + if (!childElement.isEnabled()) + continue; + MenuType type = childElement.getType(); + Action action = childElement.getAction(); + URI childId = childElement.getId(); + if (type.equals(MenuType.action)) { + if (action == null) { + logger.warn("Skipping invalid action " + childId + " for " + + id); + continue; + } + + Component actionComponent; + if (menuOptions.isOptionGroup()) { + if (menuOptions.isToolbar()) { + actionComponent = new JToggleButton(action); + toolbarizeButton((AbstractButton) actionComponent); + } else + actionComponent = new JRadioButtonMenuItem(action); + } else { + if (menuOptions.isToolbar()) { + actionComponent = new JButton(action); + toolbarizeButton((AbstractButton) actionComponent); + } else + actionComponent = new JMenuItem(action); + } + registerComponent(childId, actionComponent); + components.add(actionComponent); + } else if (type.equals(MenuType.toggle)) { + if (action == null) { + logger.warn("Skipping invalid toggle " + childId + " for " + + id); + continue; + } + Component toggleComponent; + if (menuOptions.isToolbar()) + toggleComponent = new JToggleButton(action); + else + toggleComponent = new JCheckBoxMenuItem(action); + registerComponent(childId, toggleComponent); + components.add(toggleComponent); + } else if (type.equals(MenuType.custom)) { + Component customComponent = childElement.getCustomComponent(); + if (customComponent == null) { + logger.warn("Skipping null custom component " + childId + + " for " + id); + continue; + } + registerComponent(childId, customComponent); + components.add(customComponent); + } else if (type.equals(MenuType.optionGroup)) + addOptionGroup(components, childId, menuOptions); + else if (type.equals(MenuType.section)) + addSection(components, childId, menuOptions); + else if (type.equals(MenuType.menu)) + addMenu(components, childElement, menuOptions); + else { + logger.warn("Skipping invalid/unknown type " + type + " for " + + id); + continue; + } + } + stripTrailingNullSeparator(components); + return components; + } + + /** + * Fill the specified menu bar with the menu elements that have the given + * URI as their parent. + * <p> + * Existing elements on the menu bar will be removed. + * + * @param menuBar + * The {@link JMenuBar} to update + * @param id + * The {@link URI} of the menu bar + */ + protected void populateMenuBar(JMenuBar menuBar, URI id) { + menuBar.removeAll(); + MenuComponent menuDef = uriToMenuElement.get(id); + if (menuDef == null) + throw new IllegalArgumentException("Unknown menuBar " + id); + if (!menuDef.getType().equals(MenuType.menu)) + throw new IllegalArgumentException("Element " + id + + " is not a menu, but a " + menuDef.getType()); + MenuOptions menuOptions = new MenuOptions(); + for (Component component : makeComponents(id, menuOptions)) + if (component == null) + logger.warn("Ignoring separator in menu bar " + id); + else + menuBar.add(component); + } + + /** + * Fill the specified menu bar with the menu elements that have the given + * URI as their parent. + * <p> + * Existing elements on the menu bar will be removed. + * + * @param popupMenu + * The {@link JPopupMenu} to update + * @param id + * The {@link URI} of the menu bar + * @param contextualSelection + * The current selection for the context menu + */ + protected void populateContextMenu(JPopupMenu popupMenu, URI id, + ContextualSelection contextualSelection) { + popupMenu.removeAll(); + MenuComponent menuDef = uriToMenuElement.get(id); + if (menuDef == null) + throw new IllegalArgumentException("Unknown menuBar " + id); + if (!menuDef.getType().equals(MenuType.menu)) + throw new IllegalArgumentException("Element " + id + + " is not a menu, but a " + menuDef.getType()); + MenuOptions menuOptions = new MenuOptions(); + menuOptions.setContextualSelection(contextualSelection); + for (Component component : makeComponents(id, menuOptions)) + if (component == null) + popupMenu.addSeparator(); + else + popupMenu.add(component); + } + + /** + * Fill the specified tool bar with the elements that have the given URI as + * their parent. + * <p> + * Existing elements on the tool bar will be removed. + * + * @param toolbar + * The {@link JToolBar} to update + * @param id + * The {@link URI} of the tool bar + */ + protected void populateToolBar(JToolBar toolbar, URI id) { + toolbar.removeAll(); + MenuComponent toolbarDef = uriToMenuElement.get(id); + if (toolbarDef == null) + throw new IllegalArgumentException("Unknown toolBar " + id); + if (!toolbarDef.getType().equals(MenuType.toolBar)) + throw new IllegalArgumentException("Element " + id + + " is not a toolBar, but a " + toolbarDef.getType()); + if (toolbarDef.getAction() != null) { + String name = (String) toolbarDef.getAction().getValue(Action.NAME); + toolbar.setName(name); + } else + toolbar.setName(""); + MenuOptions menuOptions = new MenuOptions(); + menuOptions.setToolbar(true); + for (Component component : makeComponents(id, menuOptions)) { + if (component == null) { + toolbar.addSeparator(); + continue; + } + if (component instanceof JButton) { + JButton toolbarButton = (JButton) component; + toolbarButton.putClientProperty("hideActionText", true); + } + toolbar.add(component); + } + } + + /** + * Register a component that has been created. Such a component can be + * resolved through {@link #getComponentByURI(URI)}. + * + * @param id + * The {@link URI} that defined the component + * @param component + * The {@link Component} that was created. + */ + protected synchronized void registerComponent(URI id, Component component) { + registerComponent(id, component, false); + } + + /** + * Register a component that has been created. Such a component can be + * resolved through {@link #getComponentByURI(URI)}. + * + * @param id + * The {@link URI} that defined the component + * @param component + * The {@link Component} that was created. + * @param published + * <code>true</code> if the component has been published through + * {@link #createMenuBar()} or similar, and is to be + * automatically updated by later calls to {@link #update()}. + */ + protected synchronized void registerComponent(URI id, Component component, + boolean published) { + uriToComponent.put(id, new WeakReference<>(component)); + componentToUri.put(component, id); + if (published) { + List<WeakReference<Component>> publishedComponents = uriToPublishedComponents + .get(id); + if (publishedComponents == null) { + publishedComponents = new ArrayList<>(); + uriToPublishedComponents.put(id, publishedComponents); + } + publishedComponents.add(new WeakReference<>(component)); + } + setHelpStringForComponent(component, id); + } + + /** + * Reset all collections + * + */ + protected synchronized void resetCollections() { + menuElementTree = new HashMap<>(); + componentToUri = new WeakHashMap<>(); + uriToMenuElement = new HashMap<>(); + uriToComponent = new HashMap<>(); + } + + /** + * Set javax.help string to identify the component for later references to + * the help document. Note that the component (ie. the + * {@link AbstractMenuAction} must have an ID for an registration to take + * place. + * + * @param component + * The {@link Component} to set help string for + * @param componentId + * The {@link URI} to be used as identifier + */ + protected void setHelpStringForComponent(Component component, + URI componentId) { + if (componentId != null) { + String helpId = componentId.toASCIIString(); + setHelpIDString(component, helpId); + } + } + + /** + * Make an {@link AbstractButton} be configured in a "toolbar-like" way, for + * instance showing only the icon. + * + * @param actionButton + * Button to toolbarise + */ + protected void toolbarizeButton(AbstractButton actionButton) { + Action action = actionButton.getAction(); + if (action.getValue(SHORT_DESCRIPTION) == null) + action.putValue(SHORT_DESCRIPTION, action.getValue(NAME)); + actionButton.setBorder(new EmptyBorder(0, 2, 0, 2)); + // actionButton.setHorizontalTextPosition(JButton.CENTER); + // actionButton.setVerticalTextPosition(JButton.BOTTOM); + if (action.getValue(Action.SMALL_ICON) != null) { + // Don't show the text + actionButton.putClientProperty("hideActionText", true); + // Since hideActionText seems to be broken in Java 5 and/or OS X + actionButton.setText(null); + } + } + + /** + * Update all components that have been published using + * {@link #createMenuBar()} and similar. Content of such components will be + * removed and replaced by fresh components. + */ + protected void updatePublishedComponents() { + for (Entry<URI, List<WeakReference<Component>>> entry : uriToPublishedComponents + .entrySet()) + for (WeakReference<Component> reference : entry.getValue()) { + URI id = entry.getKey(); + Component component = reference.get(); + if (component == null) + continue; + if (component instanceof JToolBar) + populateToolBar((JToolBar) component, id); + else if (component instanceof JMenuBar) + populateMenuBar((JMenuBar) component, id); + else + logger.warn("Could not update published component " + id + + ": " + component.getClass()); + } + } + + public void setMenuComponents(List<MenuComponent> menuComponents) { + this.menuComponents = menuComponents; + } + + public void setSelectionManager(SelectionManager selectionManager) { + selectionManager.addObserver(new SelectionManagerObserver()); + } + + /** + * {@link Comparator} that can order {@link MenuComponent}s by their + * {@link MenuComponent#getPositionHint()}. + */ + protected static class MenuElementComparator implements + Comparator<MenuComponent> { + @Override + public int compare(MenuComponent a, MenuComponent b) { + return a.getPositionHint() - b.getPositionHint(); + } + } + + /** + * Various options for + * {@link MenuManagerImpl#makeComponents(URI, MenuOptions)} and friends. + * + * @author Stian Soiland-Reyes + */ + public static class MenuOptions { + private boolean isToolbar = false; + private boolean isOptionGroup = false; + private ContextualSelection contextualSelection = null; + + public ContextualSelection getContextualSelection() { + return contextualSelection; + } + + public void setContextualSelection( + ContextualSelection contextualSelection) { + this.contextualSelection = contextualSelection; + } + + public MenuOptions(MenuOptions original) { + this.isOptionGroup = original.isOptionGroup(); + this.isToolbar = original.isToolbar(); + this.contextualSelection = original.getContextualSelection(); + } + + public MenuOptions() { + } + + @Override + protected MenuOptions clone() { + return new MenuOptions(this); + } + + public boolean isToolbar() { + return isToolbar; + } + + public void setToolbar(boolean isToolbar) { + this.isToolbar = isToolbar; + } + + public boolean isOptionGroup() { + return isOptionGroup; + } + + public void setOptionGroup(boolean isOptionGroup) { + this.isOptionGroup = isOptionGroup; + } + } + + private final class SelectionManagerObserver extends + SwingAwareObserver<SelectionManagerEvent> { + private static final String DESIGN_PERSPECTIVE_ID = "net.sf.taverna.t2.ui.perspectives.design.DesignPerspective"; + private static final String RESULTS_PERSPECTIVE_ID = "net.sf.taverna.t2.ui.perspectives.results.ResultsPerspective"; + + @Override + public void notifySwing(Observable<SelectionManagerEvent> sender, + SelectionManagerEvent message) { + if (!(message instanceof PerspectiveSelectionEvent)) + return; + handlePerspectiveSelect((PerspectiveSelectionEvent) message); + } + + private void handlePerspectiveSelect(PerspectiveSelectionEvent event) { + String perspectiveID = event.getSelectedPerspective().getID(); + boolean isDesign = DESIGN_PERSPECTIVE_ID.equals(perspectiveID); + boolean isResults = RESULTS_PERSPECTIVE_ID.equals(perspectiveID); + + for (MenuComponent menuComponent : menuComponents) + if (!(menuComponent instanceof ContextualMenuComponent)) { + Action action = menuComponent.getAction(); + if (action instanceof DesignOnlyAction) + action.setEnabled(isDesign); + else if (action instanceof DesignOrResultsAction) + action.setEnabled(isDesign || isResults); + } + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-menu-impl/src/main/java/org/apache/taverna/workbench/ui/impl/menu/AdvancedMenu.java ---------------------------------------------------------------------- diff --git a/taverna-menu-impl/src/main/java/org/apache/taverna/workbench/ui/impl/menu/AdvancedMenu.java b/taverna-menu-impl/src/main/java/org/apache/taverna/workbench/ui/impl/menu/AdvancedMenu.java new file mode 100644 index 0000000..50c57e0 --- /dev/null +++ b/taverna-menu-impl/src/main/java/org/apache/taverna/workbench/ui/impl/menu/AdvancedMenu.java @@ -0,0 +1,43 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +package org.apache.taverna.workbench.ui.impl.menu; + +import static java.awt.event.KeyEvent.VK_A; +import static javax.swing.Action.MNEMONIC_KEY; +import static org.apache.taverna.ui.menu.DefaultMenuBar.DEFAULT_MENU_BAR; + +import java.net.URI; + +import org.apache.taverna.ui.menu.AbstractMenu; + +public class AdvancedMenu extends AbstractMenu { + public static final URI ADVANCED_URI = URI + .create("http://taverna.sf.net/2008/t2workbench/menu#advanced"); + + public AdvancedMenu() { + super(DEFAULT_MENU_BAR, 1000, ADVANCED_URI, makeAction()); + } + + public static DummyAction makeAction() { + DummyAction action = new DummyAction("Advanced"); + action.putValue(MNEMONIC_KEY, Integer.valueOf(VK_A)); + return action; + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-menu-impl/src/main/java/org/apache/taverna/workbench/ui/impl/menu/EditMenu.java ---------------------------------------------------------------------- diff --git a/taverna-menu-impl/src/main/java/org/apache/taverna/workbench/ui/impl/menu/EditMenu.java b/taverna-menu-impl/src/main/java/org/apache/taverna/workbench/ui/impl/menu/EditMenu.java new file mode 100644 index 0000000..4d63107 --- /dev/null +++ b/taverna-menu-impl/src/main/java/org/apache/taverna/workbench/ui/impl/menu/EditMenu.java @@ -0,0 +1,42 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +package org.apache.taverna.workbench.ui.impl.menu; + +import static java.awt.event.KeyEvent.VK_E; +import static javax.swing.Action.MNEMONIC_KEY; +import static org.apache.taverna.ui.menu.DefaultMenuBar.DEFAULT_MENU_BAR; + +import java.net.URI; + +import org.apache.taverna.ui.menu.AbstractMenu; + +public class EditMenu extends AbstractMenu { + public EditMenu() { + super(DEFAULT_MENU_BAR, 20, URI + .create("http://taverna.sf.net/2008/t2workbench/menu#edit"), + makeAction()); + } + + public static DummyAction makeAction() { + DummyAction action = new DummyAction("Edit"); + action.putValue(MNEMONIC_KEY, Integer.valueOf(VK_E)); + return action; + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-menu-impl/src/main/java/org/apache/taverna/workbench/ui/impl/menu/FeedbackMenuAction.java ---------------------------------------------------------------------- diff --git a/taverna-menu-impl/src/main/java/org/apache/taverna/workbench/ui/impl/menu/FeedbackMenuAction.java b/taverna-menu-impl/src/main/java/org/apache/taverna/workbench/ui/impl/menu/FeedbackMenuAction.java new file mode 100644 index 0000000..3cb6b7d --- /dev/null +++ b/taverna-menu-impl/src/main/java/org/apache/taverna/workbench/ui/impl/menu/FeedbackMenuAction.java @@ -0,0 +1,74 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +package org.apache.taverna.workbench.ui.impl.menu; + +import static java.awt.Desktop.getDesktop; +import static org.apache.taverna.workbench.ui.impl.menu.HelpMenu.HELP_URI; + +import java.awt.event.ActionEvent; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; + +import javax.swing.AbstractAction; +import javax.swing.Action; + +import org.apache.taverna.ui.menu.AbstractMenuAction; + +import org.apache.log4j.Logger; + +/** + * MenuItem for feedback + * + * @author alanrw + */ +public class FeedbackMenuAction extends AbstractMenuAction { + private static Logger logger = Logger.getLogger(FeedbackMenuAction.class); + + private static String FEEDBACK_URL = "http://www.taverna.org.uk/about/contact-us/feedback/"; + + public FeedbackMenuAction() { + super(HELP_URI, 20); + } + + @Override + protected Action createAction() { + return new FeedbackAction(); + } + + @SuppressWarnings("serial") + private final class FeedbackAction extends AbstractAction { + private FeedbackAction() { + super("Contact us"); + } + + @Override + public void actionPerformed(ActionEvent e) { + try { + getDesktop().browse(new URI(FEEDBACK_URL)); + } catch (IOException e1) { + logger.error("Unable to open URL", e1); + } catch (URISyntaxException e1) { + logger.error("Invalid URL syntax", e1); + } + } + } + +}
