001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.ui.actions;
011:
012: import java.util.ArrayList;
013: import java.util.HashMap;
014: import java.util.List;
015: import java.util.Map;
016:
017: import org.eclipse.core.runtime.Assert;
018: import org.eclipse.core.runtime.IConfigurationElement;
019: import org.eclipse.core.runtime.IExtension;
020: import org.eclipse.core.runtime.IRegistryChangeEvent;
021: import org.eclipse.core.runtime.IRegistryChangeListener;
022: import org.eclipse.core.runtime.Platform;
023: import org.eclipse.core.runtime.dynamichelpers.IExtensionChangeHandler;
024: import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker;
025: import org.eclipse.jface.action.Action;
026: import org.eclipse.jface.action.ActionContributionItem;
027: import org.eclipse.jface.action.IAction;
028: import org.eclipse.jface.action.IContributionItem;
029: import org.eclipse.jface.action.Separator;
030: import org.eclipse.ui.IWorkbenchPage;
031: import org.eclipse.ui.IWorkbenchWindow;
032: import org.eclipse.ui.activities.WorkbenchActivityHelper;
033: import org.eclipse.ui.internal.WorkbenchMessages;
034: import org.eclipse.ui.internal.WorkbenchPlugin;
035: import org.eclipse.ui.internal.WorkbenchWindow;
036: import org.eclipse.ui.internal.actions.NewWizardShortcutAction;
037: import org.eclipse.ui.internal.util.Util;
038: import org.eclipse.ui.wizards.IWizardDescriptor;
039:
040: /**
041: * A <code>BaseNewWizardMenu</code> is used to populate a menu manager with
042: * New Wizard actions for the current perspective's new wizard shortcuts,
043: * including an Other... action to open the new wizard dialog.
044: *
045: * @since 3.1
046: */
047: public class BaseNewWizardMenu extends CompoundContributionItem {
048: /*
049: * @issue Should be possible to implement this class entirely using public
050: * API. Cases to be fixed: WorkbenchWindow, NewWizardShortcutAction
051: * Suggestions:
052: * - add the ability to update the submenus of a window
053: */
054:
055: private final Map actions = new HashMap(21);
056:
057: private final IExtensionChangeHandler configListener = new IExtensionChangeHandler() {
058:
059: /* (non-Javadoc)
060: * @see org.eclipse.core.runtime.dynamicHelpers.IExtensionChangeHandler#removeExtension(org.eclipse.core.runtime.IExtension, java.lang.Object[])
061: */
062: public void removeExtension(IExtension source, Object[] objects) {
063: for (int i = 0; i < objects.length; i++) {
064: if (objects[i] instanceof NewWizardShortcutAction) {
065: actions.values().remove(objects[i]);
066: }
067: }
068: }
069:
070: /* (non-Javadoc)
071: * @see org.eclipse.core.runtime.dynamicHelpers.IExtensionChangeHandler#addExtension(org.eclipse.core.runtime.dynamicHelpers.IExtensionTracker, org.eclipse.core.runtime.IExtension)
072: */
073: public void addExtension(IExtensionTracker tracker,
074: IExtension extension) {
075: // Do nothing
076: }
077: };
078:
079: /**
080: * TODO: should this be done with an addition listener?
081: */
082: private final IRegistryChangeListener registryListener = new IRegistryChangeListener() {
083:
084: public void registryChanged(IRegistryChangeEvent event) {
085: // reset the reader.
086: // TODO This is expensive. Can we be more selective?
087: if (getParent() != null) {
088: getParent().markDirty();
089: }
090: }
091:
092: };
093:
094: private final IAction showDlgAction;
095:
096: private IWorkbenchWindow workbenchWindow;
097:
098: /**
099: * Creates a new wizard shortcut menu for the IDE.
100: *
101: * @param window
102: * the window containing the menu
103: * @param id
104: * the contribution item identifier, or <code>null</code>
105: */
106: public BaseNewWizardMenu(IWorkbenchWindow window, String id) {
107: super (id);
108: Assert.isNotNull(window);
109: this .workbenchWindow = window;
110: showDlgAction = ActionFactory.NEW.create(window);
111: registerListeners();
112: // indicate that a new wizards submenu has been created
113: ((WorkbenchWindow) window)
114: .addSubmenu(WorkbenchWindow.NEW_WIZARD_SUBMENU);
115: }
116:
117: /**
118: * Adds the items to show to the given list.
119: *
120: * @param list the list to add items to
121: */
122: protected void addItems(List list) {
123: if (addShortcuts(list)) {
124: list.add(new Separator());
125: }
126: list.add(new ActionContributionItem(getShowDialogAction()));
127: }
128:
129: /**
130: * Adds the new wizard shortcuts for the current perspective to the given list.
131: *
132: * @param list the list to add items to
133: * @return <code>true</code> if any items were added, <code>false</code> if none were added
134: */
135: protected boolean addShortcuts(List list) {
136: boolean added = false;
137: IWorkbenchPage page = workbenchWindow.getActivePage();
138: if (page != null) {
139: String[] wizardIds = page.getNewWizardShortcuts();
140: for (int i = 0; i < wizardIds.length; i++) {
141: IAction action = getAction(wizardIds[i]);
142: if (action != null) {
143: if (!WorkbenchActivityHelper.filterItem(action)) {
144: list.add(new ActionContributionItem(action));
145: added = true;
146: }
147: }
148: }
149: }
150: return added;
151: }
152:
153: /*
154: * (non-Javadoc)
155: *
156: * @see org.eclipse.jface.action.IContributionItem#dispose()
157: */
158: public void dispose() {
159: if (workbenchWindow != null) {
160: super .dispose();
161: unregisterListeners();
162: workbenchWindow = null;
163: }
164: }
165:
166: /*
167: * (non-Javadoc) Returns the action for the given wizard id, or null if not
168: * found.
169: */
170: private IAction getAction(String id) {
171: // Keep a cache, rather than creating a new action each time,
172: // so that image caching in ActionContributionItem works.
173: IAction action = (IAction) actions.get(id);
174: if (action == null) {
175: IWizardDescriptor wizardDesc = WorkbenchPlugin.getDefault()
176: .getNewWizardRegistry().findWizard(id);
177: if (wizardDesc != null) {
178: action = new NewWizardShortcutAction(workbenchWindow,
179: wizardDesc);
180: actions.put(id, action);
181: IConfigurationElement element = (IConfigurationElement) Util
182: .getAdapter(wizardDesc,
183: IConfigurationElement.class);
184: if (element != null) {
185: workbenchWindow.getExtensionTracker()
186: .registerObject(
187: element.getDeclaringExtension(),
188: action, IExtensionTracker.REF_WEAK);
189: }
190: }
191: }
192: return action;
193: }
194:
195: /*
196: * (non-Javadoc)
197: *
198: * @see org.eclipse.ui.actions.CompoundContributionItem#getContributionItems()
199: */
200: protected IContributionItem[] getContributionItems() {
201: ArrayList list = new ArrayList();
202: if (workbenchWindow != null
203: && workbenchWindow.getActivePage() != null
204: && workbenchWindow.getActivePage().getPerspective() != null) {
205: addItems(list);
206: } else {
207: String text = WorkbenchMessages.Workbench_noApplicableItems;
208: Action dummyAction = new Action(text) {
209: // dummy inner class; no methods
210: };
211: dummyAction.setEnabled(false);
212: list.add(new ActionContributionItem(dummyAction));
213: }
214: return (IContributionItem[]) list
215: .toArray(new IContributionItem[list.size()]);
216: }
217:
218: /**
219: * Returns the "Other..." action, used to show the new wizards dialog.
220: *
221: * @return the action used to show the new wizards dialog
222: */
223: protected IAction getShowDialogAction() {
224: return showDlgAction;
225: }
226:
227: /**
228: * Returns the window in which this menu appears.
229: *
230: * @return the window in which this menu appears
231: */
232: protected IWorkbenchWindow getWindow() {
233: return workbenchWindow;
234: }
235:
236: /**
237: * Registers listeners.
238: *
239: * @since 3.1
240: */
241: private void registerListeners() {
242: Platform.getExtensionRegistry().addRegistryChangeListener(
243: registryListener);
244: workbenchWindow.getExtensionTracker().registerHandler(
245: configListener, null);
246: }
247:
248: /**
249: * Returns whether the new wizards registry has a non-empty category with
250: * the given identifier.
251: *
252: * @param categoryId
253: * the identifier for the category
254: * @return <code>true</code> if there is a non-empty category with the
255: * given identifier, <code>false</code> otherwise
256: */
257: protected boolean registryHasCategory(String categoryId) {
258: return WorkbenchPlugin.getDefault().getNewWizardRegistry()
259: .findCategory(categoryId) != null;
260: }
261:
262: /**
263: * Unregisters listeners.
264: *
265: * @since 3.1
266: */
267: private void unregisterListeners() {
268: Platform.getExtensionRegistry().removeRegistryChangeListener(
269: registryListener);
270: workbenchWindow.getExtensionTracker().unregisterHandler(
271: configListener);
272: }
273: }
|