001: /*******************************************************************************
002: * Copyright (c) 2003, 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.navigator;
011:
012: import java.util.Collections;
013: import java.util.Comparator;
014: import java.util.HashMap;
015: import java.util.Iterator;
016: import java.util.Map;
017: import java.util.SortedSet;
018: import java.util.TreeMap;
019: import java.util.TreeSet;
020:
021: import org.eclipse.core.runtime.Assert;
022: import org.eclipse.jface.action.IAction;
023: import org.eclipse.jface.action.IMenuManager;
024: import org.eclipse.jface.action.Separator;
025: import org.eclipse.jface.viewers.ISelection;
026: import org.eclipse.jface.viewers.IStructuredSelection;
027: import org.eclipse.ui.IWorkbench;
028: import org.eclipse.ui.IWorkbenchWindow;
029: import org.eclipse.ui.PlatformUI;
030: import org.eclipse.ui.actions.ActionContext;
031: import org.eclipse.ui.actions.ActionGroup;
032: import org.eclipse.ui.internal.navigator.wizards.CommonWizardDescriptor;
033: import org.eclipse.ui.internal.navigator.wizards.CommonWizardDescriptorManager;
034: import org.eclipse.ui.internal.navigator.wizards.WizardShortcutAction;
035: import org.eclipse.ui.wizards.IWizardDescriptor;
036: import org.eclipse.ui.wizards.IWizardRegistry;
037:
038: /**
039: *
040: * Populates context menus with shortcut actions for defined wizards. Wizards
041: * may be defined by any of the following extension points:
042: * <p>
043: * <ul>
044: * <li><b>org.eclipse.ui.newWizards</b></li>
045: * <li><b>org.eclipse.ui.importWizards</b></li>
046: * <li><b>org.eclipse.ui.exportWizards</b></li>
047: * </ul>
048: * </p>
049: * <p>
050: * Here are the required steps for using this feature correctly:
051: * <ol>
052: * <li>Declare all new/import/export wizards from the extension points above,
053: * or locate the existing wizards that you intend to reuse.</li>
054: * <li>Declare <b>org.eclipse.ui.navigator.navigatorContent/commonWizard</b>
055: * elements to identify which wizards should be associated with what items in
056: * your viewer or navigator.</li>
057: * <li>If you are using Resources in your viewer and have bound the resource
058: * extension declared in <b>org.eclipse.ui.navigator.resources</b>, then you
059: * will get most of this functionality for free.</li>
060: * <li>Otherwise, you may choose to build your own custom menu. In which case,
061: * you may instantiate this class, and hand it the menu or submenu that you want
062: * to list out the available wizard shortcuts via
063: * {@link WizardActionGroup#fillContextMenu(IMenuManager)}.</li>
064: * </ol>
065: * </p>
066: * <p>
067: * Clients may instantiate, but not subclass WizardActionGroup.
068: * </p>
069: *
070: * @see PlatformUI#getWorkbench()
071: * @see IWorkbench#getNewWizardRegistry()
072: * @see IWorkbench#getImportWizardRegistry()
073: * @see IWorkbench#getExportWizardRegistry()
074: * @since 3.2
075: *
076: */
077: public final class WizardActionGroup extends ActionGroup {
078:
079: /**
080: * The type for commonWizard extensions with the value "new" for their type
081: * attribute.
082: */
083: public static final String TYPE_NEW = "new"; //$NON-NLS-1$
084:
085: /**
086: * The type for commonWizard extensions with the value "new" for their type
087: * attribute.
088: */
089: public static final String TYPE_IMPORT = "import"; //$NON-NLS-1$
090:
091: /**
092: * The type for commonWizard extensions with the value "new" for their type
093: * attribute.
094: */
095: public static final String TYPE_EXPORT = "export"; //$NON-NLS-1$
096:
097: private static final CommonWizardDescriptor[] NO_DESCRIPTORS = new CommonWizardDescriptor[0];
098:
099: private static final String[] NO_IDS = new String[0];
100:
101: private CommonWizardDescriptor[] descriptors;
102:
103: /* a map of (id, IAction)-pairs. */
104: private Map actions;
105:
106: /*
107: * the window is passed to created WizardShortcutActions for the shell and
108: * selection service.
109: */
110: private IWorkbenchWindow window;
111:
112: /* the correct wizard registry for this action group (getRegistry()) */
113: private IWizardRegistry wizardRegistry;
114:
115: private boolean disposed = false;
116:
117: private String type;
118:
119: private INavigatorContentService contentService;
120:
121: /**
122: *
123: * @param aWindow
124: * The window that will be used to acquire a Shell and a
125: * Selection Service
126: * @param aWizardRegistry
127: * The wizard registry will be used to locate the correct wizard
128: * descriptions.
129: * @param aType
130: * Indicates the value of the type attribute of the commonWizard
131: * extension point. Use any of the TYPE_XXX constants defined on
132: * this class.
133: * @see PlatformUI#getWorkbench()
134: * @see IWorkbench#getNewWizardRegistry()
135: * @see IWorkbench#getImportWizardRegistry()
136: * @see IWorkbench#getExportWizardRegistry()
137: */
138: public WizardActionGroup(IWorkbenchWindow aWindow,
139: IWizardRegistry aWizardRegistry, String aType) {
140: super ();
141: Assert.isNotNull(aWindow);
142: Assert.isNotNull(aWizardRegistry);
143: Assert
144: .isTrue(aType != null
145: && (TYPE_NEW.equals(aType)
146: || TYPE_IMPORT.equals(aType) || TYPE_EXPORT
147: .equals(aType)));
148: window = aWindow;
149: wizardRegistry = aWizardRegistry;
150: type = aType;
151:
152: }
153:
154: /**
155: *
156: * @param aWindow
157: * The window that will be used to acquire a Shell and a
158: * Selection Service
159: * @param aWizardRegistry
160: * The wizard registry will be used to locate the correct wizard
161: * descriptions.
162: * @param aType
163: * Indicates the value of the type attribute of the commonWizard
164: * extension point. Use any of the TYPE_XXX constants defined on
165: * this class.
166: * @param aContentService
167: * The content service to use when deciding visibility.
168: * @see PlatformUI#getWorkbench()
169: * @see IWorkbench#getNewWizardRegistry()
170: * @see IWorkbench#getImportWizardRegistry()
171: * @see IWorkbench#getExportWizardRegistry()
172: */
173: public WizardActionGroup(IWorkbenchWindow aWindow,
174: IWizardRegistry aWizardRegistry, String aType,
175: INavigatorContentService aContentService) {
176: this (aWindow, aWizardRegistry, aType);
177: contentService = aContentService;
178:
179: }
180:
181: public void setContext(ActionContext aContext) {
182: Assert.isTrue(!disposed);
183:
184: super .setContext(aContext);
185: if (aContext != null) {
186: ISelection selection = aContext.getSelection();
187: Object element = null;
188: if (selection instanceof IStructuredSelection) {
189: element = ((IStructuredSelection) selection)
190: .getFirstElement();
191: }
192: if (element == null) {
193: element = Collections.EMPTY_LIST;
194: }
195: // null should be okay here
196: setWizardActionDescriptors(CommonWizardDescriptorManager
197: .getInstance().getEnabledCommonWizardDescriptors(
198: element, type, contentService));
199: } else {
200: setWizardActionDescriptors(NO_DESCRIPTORS);
201: }
202: }
203:
204: /*
205: * (non-Javadoc)
206: *
207: * @see org.eclipse.ui.actions.ActionGroup#fillContextMenu(org.eclipse.jface.action.IMenuManager)
208: */
209: public void fillContextMenu(IMenuManager menu) {
210: Assert.isTrue(!disposed);
211:
212: if (descriptors != null) {
213: Map groups = findGroups();
214: SortedSet sortedWizards = null;
215: String menuGroupId = null;
216: for (Iterator menuGroupItr = groups.keySet().iterator(); menuGroupItr
217: .hasNext();) {
218: menuGroupId = (String) menuGroupItr.next();
219: sortedWizards = (SortedSet) groups.get(menuGroupId);
220: menu.add(new Separator(menuGroupId));
221: for (Iterator wizardItr = sortedWizards.iterator(); wizardItr
222: .hasNext();) {
223: menu.add((IAction) wizardItr.next());
224: }
225: }
226: }
227: }
228:
229: /**
230: * @return A Map of menuGroupIds to SortedSets of IActions.
231: */
232: private synchronized Map/*<String, SortedSet<IAction>>*/findGroups() {
233: IAction action = null;
234: Map groups = new TreeMap();
235: SortedSet sortedWizards = null;
236: String menuGroupId = null;
237: for (int i = 0; i < descriptors.length; i++) {
238: menuGroupId = descriptors[i].getMenuGroupId() != null ? descriptors[i]
239: .getMenuGroupId()
240: : CommonWizardDescriptor.DEFAULT_MENU_GROUP_ID;
241: sortedWizards = (SortedSet) groups.get(menuGroupId);
242: if (sortedWizards == null) {
243: groups.put(descriptors[i].getMenuGroupId(),
244: sortedWizards = new TreeSet(
245: ActionComparator.INSTANCE));
246: }
247: if ((action = getAction(descriptors[i].getWizardId())) != null) {
248: sortedWizards.add(action);
249: }
250: }
251: return groups;
252: }
253:
254: public void dispose() {
255: super .dispose();
256: actions = null;
257: window = null;
258: descriptors = null;
259: wizardRegistry = null;
260: disposed = true;
261: }
262:
263: /*
264: * (non-Javadoc) Returns the action for the given wizard id, or null if not
265: * found.
266: */
267: protected IAction getAction(String id) {
268: if (id == null || id.length() == 0) {
269: return null;
270: }
271:
272: // Keep a cache, rather than creating a new action each time,
273: // so that image caching in ActionContributionItem works.
274: IAction action = (IAction) getActions().get(id);
275: if (action == null) {
276: IWizardDescriptor descriptor = wizardRegistry
277: .findWizard(id);
278: if (descriptor != null) {
279: action = new WizardShortcutAction(window, descriptor);
280: getActions().put(id, action);
281: }
282: }
283:
284: return action;
285: }
286:
287: /**
288: * @return a map of (id, IAction)-pairs.
289: */
290: protected Map getActions() {
291: if (actions == null) {
292: actions = new HashMap();
293: }
294: return actions;
295: }
296:
297: /**
298: * @return Returns the wizardActionIds.
299: */
300: public synchronized String[] getWizardActionIds() {
301: if (descriptors != null && descriptors.length > 0) {
302: String[] wizardActionIds = new String[descriptors.length];
303: for (int i = 0; i < descriptors.length; i++) {
304: wizardActionIds[i] = descriptors[i].getWizardId();
305: }
306: return wizardActionIds;
307: }
308: return NO_IDS;
309: }
310:
311: /**
312: * @param theWizardDescriptors
313: * The wizard action ids to set. These should be defined through
314: * <b>org.eclipse.ui.xxxWizards</b>
315: */
316: protected synchronized void setWizardActionDescriptors(
317: CommonWizardDescriptor[] theWizardDescriptors) {
318: descriptors = theWizardDescriptors;
319: }
320:
321: private static class ActionComparator implements Comparator {
322:
323: private static final ActionComparator INSTANCE = new ActionComparator();
324:
325: /* (non-Javadoc)
326: * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
327: */
328: public int compare(Object arg0, Object arg1) {
329: return ((IAction) arg0).getText().compareTo(
330: ((IAction) arg1).getText());
331: }
332: }
333: }
|