| /******************************************************************************* |
| * Copyright (c) 2000, 2009 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| * Tonny Madsen, RCP Company - bug 201055 |
| *******************************************************************************/ |
| package org.eclipse.ui.actions; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.Comparator; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| |
| import com.ibm.icu.text.Collator; |
| |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.SelectionEvent; |
| import org.eclipse.swt.widgets.Event; |
| import org.eclipse.swt.widgets.Menu; |
| import org.eclipse.swt.widgets.MenuItem; |
| |
| import org.eclipse.core.commands.ExecutionException; |
| import org.eclipse.core.commands.NotEnabledException; |
| import org.eclipse.core.commands.NotHandledException; |
| import org.eclipse.core.commands.common.NotDefinedException; |
| |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Status; |
| |
| import org.eclipse.jface.action.Action; |
| import org.eclipse.jface.action.ContributionItem; |
| import org.eclipse.jface.action.IAction; |
| import org.eclipse.jface.action.IContributionItem; |
| import org.eclipse.jface.action.IMenuListener; |
| import org.eclipse.jface.action.IMenuManager; |
| import org.eclipse.jface.action.MenuManager; |
| import org.eclipse.jface.action.Separator; |
| |
| import org.eclipse.ui.IPerspectiveDescriptor; |
| import org.eclipse.ui.IPerspectiveRegistry; |
| import org.eclipse.ui.IWorkbenchCommandConstants; |
| import org.eclipse.ui.IWorkbenchPage; |
| import org.eclipse.ui.IWorkbenchPreferenceConstants; |
| import org.eclipse.ui.IWorkbenchWindow; |
| import org.eclipse.ui.activities.WorkbenchActivityHelper; |
| import org.eclipse.ui.handlers.IHandlerService; |
| import org.eclipse.ui.internal.WorkbenchMessages; |
| import org.eclipse.ui.internal.WorkbenchPlugin; |
| import org.eclipse.ui.internal.util.PrefUtil; |
| import org.eclipse.ui.statushandlers.StatusManager; |
| |
| /** |
| * A menu for perspective selection. |
| * <p> |
| * A <code>PerspectiveMenu</code> is used to populate a menu with |
| * perspective shortcut items. If the user selects one of these items |
| * an action is performed for the selected perspective. |
| * </p><p> |
| * The visible perspective items within the menu are dynamic and reflect the |
| * available set generated by each subclass. The default available set consists |
| * of the perspective shortcut list of the current perspective. |
| * </p><p> |
| * This class is abstract. Subclasses must implement the <code>run</code> method, |
| * which performs a specialized action for the selected perspective. |
| * </p> |
| * @since 1.0 |
| */ |
| public abstract class PerspectiveMenu extends ContributionItem { |
| /** |
| * @deprecated Replaced by {@link IWorkbenchCommandConstants#PERSPECTIVES_SHOW_PERSPECTIVE} |
| */ |
| protected static final String SHOW_PERSP_ID = IWorkbenchCommandConstants.PERSPECTIVES_SHOW_PERSPECTIVE; |
| |
| private IPerspectiveRegistry reg; |
| |
| private IWorkbenchWindow window; |
| |
| private boolean showActive = false; |
| |
| private boolean dirty = true; |
| |
| private IMenuListener menuListener = new IMenuListener() { |
| public void menuAboutToShow(IMenuManager manager) { |
| manager.markDirty(); |
| dirty = true; |
| } |
| }; |
| |
| private Comparator comparator = new Comparator() { |
| private Collator collator = Collator.getInstance(); |
| |
| public int compare(Object ob1, Object ob2) { |
| IPerspectiveDescriptor d1 = (IPerspectiveDescriptor) ob1; |
| IPerspectiveDescriptor d2 = (IPerspectiveDescriptor) ob2; |
| return collator.compare(d1.getLabel(), d2.getLabel()); |
| } |
| }; |
| |
| /** |
| * The translatable message to show when there are no perspectives. |
| */ |
| private static final String NO_TARGETS_MSG = WorkbenchMessages.get().Workbench_showInNoPerspectives; |
| |
| /** |
| * The map of perspective identifiers (String) to actions |
| * (OpenPerspectiveAction). This map may be empty, but it is never |
| * <code>null</code>. |
| */ |
| private Map actions = new HashMap(); |
| |
| /** |
| * The action for that allows the user to choose any perspective to open. |
| */ |
| private Action openOtherAction = new Action(WorkbenchMessages.get().PerspectiveMenu_otherItem) { |
| public final void runWithEvent(final Event event) { |
| runOther(new SelectionEvent(event)); |
| } |
| }; |
| |
| |
| /** |
| * Constructs a new instance of <code>PerspectiveMenu</code>. |
| * |
| * @param window the window containing this menu |
| * @param id the menu id |
| */ |
| public PerspectiveMenu(IWorkbenchWindow window, String id) { |
| super(id); |
| this.window = window; |
| reg = window.getWorkbench().getPerspectiveRegistry(); |
| openOtherAction |
| .setActionDefinitionId(IWorkbenchCommandConstants.PERSPECTIVES_SHOW_PERSPECTIVE); |
| } |
| |
| /* |
| * (non-Javadoc) Fills the menu with perspective items. |
| */ |
| public void fill(Menu menu, int index) { |
| if (getParent() instanceof MenuManager) { |
| ((MenuManager) getParent()).addMenuListener(menuListener); |
| } |
| |
| if (!dirty) { |
| return; |
| } |
| |
| final MenuManager manager = new MenuManager(); |
| fillMenu(manager); |
| final IContributionItem items[] = manager.getItems(); |
| if (items.length == 0) { |
| MenuItem item = new MenuItem(menu, SWT.NONE, index++); |
| item.setText(NO_TARGETS_MSG); |
| item.setEnabled(false); |
| } else { |
| for (int i = 0; i < items.length; i++) { |
| items[i].fill(menu, index++); |
| } |
| } |
| dirty = false; |
| } |
| |
| /** |
| * Fills the given menu manager with all the open perspective actions |
| * appropriate for the currently active perspective. Filtering is applied to |
| * the actions based on the activities and capabilities mechanism. |
| * |
| * @param manager |
| * The menu manager that should receive the menu items; must not |
| * be <code>null</code>. |
| */ |
| private final void fillMenu(final MenuManager manager) { |
| // Clear out the manager so that we have a blank slate. |
| manager.removeAll(); |
| |
| // Collect and sort perspective descriptors. |
| final List persps = getPerspectiveItems(); |
| Collections.sort(persps, comparator); |
| |
| /* |
| * Convert the perspective descriptors to actions, and filter out |
| * actions using the activity/capability mechanism. |
| */ |
| final List actions = new ArrayList(persps.size()); |
| for (Iterator i = persps.iterator(); i.hasNext();) { |
| final IPerspectiveDescriptor descriptor = (IPerspectiveDescriptor) i |
| .next(); |
| final IAction action = getAction(descriptor.getId()); |
| if (action != null) { |
| if (WorkbenchActivityHelper.filterItem(action)) { |
| continue; |
| } |
| actions.add(action); |
| } |
| } |
| |
| // Go through and add each of the actions to the menu manager. |
| for (Iterator i = actions.iterator(); i.hasNext();) { |
| manager.add((IAction) i.next()); |
| } |
| |
| if (PrefUtil |
| .getAPIPreferenceStore() |
| .getBoolean( |
| IWorkbenchPreferenceConstants.SHOW_OTHER_IN_PERSPECTIVE_MENU)) { |
| // Add a separator and then "Other..." |
| if (actions.size() > 0) { |
| manager.add(new Separator()); |
| } |
| manager.add(openOtherAction); |
| } |
| } |
| |
| /** |
| * Returns the action for the given perspective id. This is a lazy cache. If |
| * the action does not already exist, then it is created. If there is no |
| * perspective with the given identifier, then the action is not created. |
| * |
| * @param id |
| * The identifier of the perspective for which the action should |
| * be retrieved. |
| * @return The action for the given identifier; or <code>null</code> if |
| * there is no perspective with the given identifier. |
| */ |
| private final IAction getAction(final String id) { |
| IAction action = (IAction) actions.get(id); |
| if (action == null) { |
| IPerspectiveDescriptor descriptor = reg.findPerspectiveWithId(id); |
| if (descriptor != null) { |
| action = new OpenPerspectiveAction(window, descriptor, this); |
| action.setActionDefinitionId(id); |
| actions.put(id, action); |
| } |
| } |
| return action; |
| } |
| |
| /* (non-Javadoc) |
| * Returns the perspective shortcut items for the active perspective. |
| * |
| * @return a list of <code>IPerspectiveDescriptor</code> items |
| */ |
| private ArrayList getPerspectiveShortcuts() { |
| ArrayList list = new ArrayList(); |
| |
| IWorkbenchPage page = window.getActivePage(); |
| if (page == null) { |
| return list; |
| } |
| |
| String[] ids = page.getPerspectiveShortcuts(); |
| |
| for (int i = 0; i < ids.length; i++) { |
| IPerspectiveDescriptor desc = reg.findPerspectiveWithId(ids[i]); |
| if (desc != null && !list.contains(desc)) { |
| if (WorkbenchActivityHelper.filterItem(desc)) { |
| continue; |
| } |
| list.add(desc); |
| } |
| } |
| |
| return list; |
| } |
| |
| /** |
| * Returns the available list of perspectives to display in the menu. |
| * <p> |
| * By default, the list contains the perspective shortcuts |
| * for the current perspective. |
| * </p><p> |
| * Subclasses can override this method to return a different list. |
| * </p> |
| * |
| * @return an <code>ArrayList<code> of perspective items <code>IPerspectiveDescriptor</code> |
| */ |
| protected ArrayList getPerspectiveItems() { |
| /* Allow the user to see all the perspectives they have |
| * selected via Customize Perspective. Bugzilla bug #23445 */ |
| ArrayList shortcuts = getPerspectiveShortcuts(); |
| ArrayList list = new ArrayList(shortcuts.size()); |
| |
| // Add perspective shortcuts from the active perspective |
| int size = shortcuts.size(); |
| for (int i = 0; i < size; i++) { |
| if (!list.contains(shortcuts.get(i))) { |
| list.add(shortcuts.get(i)); |
| } |
| } |
| |
| return list; |
| } |
| |
| /** |
| * Returns whether the menu item representing the active perspective |
| * will have a check mark. |
| * |
| * @return <code>true</code> if a check mark is shown, <code>false</code> otherwise |
| */ |
| protected boolean getShowActive() { |
| return showActive; |
| } |
| |
| /** |
| * Returns the window for this menu. |
| * |
| * @return the window |
| */ |
| protected IWorkbenchWindow getWindow() { |
| return window; |
| } |
| |
| /* (non-Javadoc) |
| * Returns whether this menu is dynamic. |
| */ |
| public boolean isDirty() { |
| return dirty; |
| } |
| |
| /* (non-Javadoc) |
| * Returns whether this menu is dynamic. |
| */ |
| public boolean isDynamic() { |
| return true; |
| } |
| |
| /** |
| * Runs an action for a particular perspective. The behavior of the |
| * action is defined by the subclass. |
| * |
| * @param desc the selected perspective |
| */ |
| protected abstract void run(IPerspectiveDescriptor desc); |
| |
| /** |
| * Runs an action for a particular perspective. The behavior of the action |
| * is defined by the subclass. By default, this just calls |
| * <code>run(IPerspectiveDescriptor)</code>. |
| * |
| * @param desc |
| * the selected perspective |
| * @param event |
| * SelectionEvent - the event send along with the selection |
| * callback |
| */ |
| protected void run(IPerspectiveDescriptor desc, SelectionEvent event) { |
| //Do a run without the event by default |
| run(desc); |
| } |
| |
| /** |
| * Show the "other" dialog, select a perspective, and run it. Pass on the selection event should |
| * the menu need it. |
| * |
| * @param event the selection event |
| */ |
| void runOther(SelectionEvent event) { |
| IHandlerService handlerService = (IHandlerService) window |
| .getService(IHandlerService.class); |
| try { |
| handlerService.executeCommand(IWorkbenchCommandConstants.PERSPECTIVES_SHOW_PERSPECTIVE, null); |
| } catch (ExecutionException e) { |
| StatusManager.getManager().handle( |
| new Status(IStatus.WARNING, WorkbenchPlugin.PI_WORKBENCH, |
| "Failed to execute " + IWorkbenchCommandConstants.PERSPECTIVES_SHOW_PERSPECTIVE, e)); //$NON-NLS-1$ |
| } catch (NotDefinedException e) { |
| StatusManager.getManager().handle( |
| new Status(IStatus.WARNING, WorkbenchPlugin.PI_WORKBENCH, |
| "Failed to execute " + IWorkbenchCommandConstants.PERSPECTIVES_SHOW_PERSPECTIVE, e)); //$NON-NLS-1$ |
| } catch (NotEnabledException e) { |
| StatusManager.getManager().handle( |
| new Status(IStatus.WARNING, WorkbenchPlugin.PI_WORKBENCH, |
| "Failed to execute " + IWorkbenchCommandConstants.PERSPECTIVES_SHOW_PERSPECTIVE, e)); //$NON-NLS-1$ |
| } catch (NotHandledException e) { |
| StatusManager.getManager().handle( |
| new Status(IStatus.WARNING, WorkbenchPlugin.PI_WORKBENCH, |
| "Failed to execute " + IWorkbenchCommandConstants.PERSPECTIVES_SHOW_PERSPECTIVE, e)); //$NON-NLS-1$ |
| } |
| } |
| |
| /** |
| * Sets the showActive flag. If <code>showActive == true</code> then the |
| * active perspective is hilighted with a check mark. |
| * |
| * @param b the new showActive flag |
| */ |
| protected void showActive(boolean b) { |
| showActive = b; |
| } |
| } |