blob: f1223379693d6a33730055265986a8031f701ee6 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2006 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
*******************************************************************************/
package org.eclipse.ui.actions;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IRegistryChangeEvent;
import org.eclipse.core.runtime.IRegistryChangeListener;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.dynamichelpers.IExtensionChangeHandler;
import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.Separator;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.activities.WorkbenchActivityHelper;
import org.eclipse.ui.internal.WorkbenchMessages;
import org.eclipse.ui.internal.WorkbenchPlugin;
import org.eclipse.ui.internal.WorkbenchWindow;
import org.eclipse.ui.internal.actions.NewWizardShortcutAction;
import org.eclipse.ui.internal.util.Util;
import org.eclipse.ui.wizards.IWizardDescriptor;
/**
* A <code>BaseNewWizardMenu</code> is used to populate a menu manager with
* New Wizard actions for the current perspective's new wizard shortcuts,
* including an Other... action to open the new wizard dialog.
*
* @since 3.1
*/
public class BaseNewWizardMenu extends CompoundContributionItem {
/*
* @issue Should be possible to implement this class entirely using public
* API. Cases to be fixed: WorkbenchWindow, NewWizardShortcutAction
* Suggestions:
* - add the ability to update the submenus of a window
*/
private final Map actions = new HashMap(21);
private final IExtensionChangeHandler configListener = new IExtensionChangeHandler() {
/* (non-Javadoc)
* @see org.eclipse.core.runtime.dynamicHelpers.IExtensionChangeHandler#removeExtension(org.eclipse.core.runtime.IExtension, java.lang.Object[])
*/
public void removeExtension(IExtension source, Object[] objects) {
for (int i = 0; i < objects.length; i++) {
if (objects[i] instanceof NewWizardShortcutAction) {
actions.values().remove(objects[i]);
}
}
}
/* (non-Javadoc)
* @see org.eclipse.core.runtime.dynamicHelpers.IExtensionChangeHandler#addExtension(org.eclipse.core.runtime.dynamicHelpers.IExtensionTracker, org.eclipse.core.runtime.IExtension)
*/
public void addExtension(IExtensionTracker tracker, IExtension extension) {
// Do nothing
}
};
/**
* TODO: should this be done with an addition listener?
*/
private final IRegistryChangeListener registryListener = new IRegistryChangeListener() {
public void registryChanged(IRegistryChangeEvent event) {
// reset the reader.
// TODO This is expensive. Can we be more selective?
if (getParent() != null) {
getParent().markDirty();
}
}
};
private final IAction showDlgAction;
private IWorkbenchWindow workbenchWindow;
/**
* Creates a new wizard shortcut menu for the IDE.
*
* @param window
* the window containing the menu
* @param id
* the contribution item identifier, or <code>null</code>
*/
public BaseNewWizardMenu(IWorkbenchWindow window, String id) {
super(id);
Assert.isNotNull(window);
this.workbenchWindow = window;
showDlgAction = ActionFactory.NEW.create(window);
registerListeners();
// indicate that a new wizards submenu has been created
((WorkbenchWindow) window)
.addSubmenu(WorkbenchWindow.NEW_WIZARD_SUBMENU);
}
/**
* Adds the items to show to the given list.
*
* @param list the list to add items to
*/
protected void addItems(List list) {
if (addShortcuts(list)) {
list.add(new Separator());
}
list.add(new ActionContributionItem(getShowDialogAction()));
}
/**
* Adds the new wizard shortcuts for the current perspective to the given list.
*
* @param list the list to add items to
* @return <code>true</code> if any items were added, <code>false</code> if none were added
*/
protected boolean addShortcuts(List list) {
boolean added = false;
IWorkbenchPage page = workbenchWindow.getActivePage();
if (page != null) {
String[] wizardIds = page.getNewWizardShortcuts();
for (int i = 0; i < wizardIds.length; i++) {
IAction action = getAction(wizardIds[i]);
if (action != null) {
if (!WorkbenchActivityHelper.filterItem(action)) {
list.add(new ActionContributionItem(action));
added = true;
}
}
}
}
return added;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.action.IContributionItem#dispose()
*/
public void dispose() {
if (workbenchWindow != null) {
super.dispose();
unregisterListeners();
workbenchWindow = null;
}
}
/*
* (non-Javadoc) Returns the action for the given wizard id, or null if not
* found.
*/
private IAction getAction(String id) {
// Keep a cache, rather than creating a new action each time,
// so that image caching in ActionContributionItem works.
IAction action = (IAction) actions.get(id);
if (action == null) {
IWizardDescriptor wizardDesc = WorkbenchPlugin.getDefault()
.getNewWizardRegistry().findWizard(id);
if (wizardDesc != null) {
action = new NewWizardShortcutAction(workbenchWindow,
wizardDesc);
actions.put(id, action);
IConfigurationElement element = (IConfigurationElement) Util
.getAdapter(wizardDesc, IConfigurationElement.class);
if (element != null) {
workbenchWindow.getExtensionTracker().registerObject(
element.getDeclaringExtension(), action,
IExtensionTracker.REF_WEAK);
}
}
}
return action;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.actions.CompoundContributionItem#getContributionItems()
*/
protected IContributionItem[] getContributionItems() {
ArrayList list = new ArrayList();
if (workbenchWindow != null && workbenchWindow.getActivePage() != null
&& workbenchWindow.getActivePage().getPerspective() != null) {
addItems(list);
} else {
String text = WorkbenchMessages.Workbench_noApplicableItems;
Action dummyAction = new Action(text) {
// dummy inner class; no methods
};
dummyAction.setEnabled(false);
list.add(new ActionContributionItem(dummyAction));
}
return (IContributionItem[]) list.toArray(new IContributionItem[list.size()]);
}
/**
* Returns the "Other..." action, used to show the new wizards dialog.
*
* @return the action used to show the new wizards dialog
*/
protected IAction getShowDialogAction() {
return showDlgAction;
}
/**
* Returns the window in which this menu appears.
*
* @return the window in which this menu appears
*/
protected IWorkbenchWindow getWindow() {
return workbenchWindow;
}
/**
* Registers listeners.
*
* @since 3.1
*/
private void registerListeners() {
Platform.getExtensionRegistry().addRegistryChangeListener(
registryListener);
workbenchWindow.getExtensionTracker().registerHandler(
configListener, null);
}
/**
* Returns whether the new wizards registry has a non-empty category with
* the given identifier.
*
* @param categoryId
* the identifier for the category
* @return <code>true</code> if there is a non-empty category with the
* given identifier, <code>false</code> otherwise
*/
protected boolean registryHasCategory(String categoryId) {
return WorkbenchPlugin.getDefault().getNewWizardRegistry()
.findCategory(categoryId) != null;
}
/**
* Unregisters listeners.
*
* @since 3.1
*/
private void unregisterListeners() {
Platform.getExtensionRegistry().removeRegistryChangeListener(
registryListener);
workbenchWindow.getExtensionTracker().unregisterHandler(configListener);
}
}