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.internal;
011:
012: import org.eclipse.core.runtime.IConfigurationElement;
013: import org.eclipse.jface.action.Action;
014: import org.eclipse.jface.action.IAction;
015: import org.eclipse.ui.IEditorPart;
016: import org.eclipse.ui.IPluginContribution;
017: import org.eclipse.ui.IViewPart;
018: import org.eclipse.ui.IWorkbenchActionConstants;
019: import org.eclipse.ui.IWorkbenchWindow;
020: import org.eclipse.ui.PlatformUI;
021: import org.eclipse.ui.internal.registry.IWorkbenchRegistryConstants;
022: import org.eclipse.ui.plugin.AbstractUIPlugin;
023:
024: /**
025: * When 'action' tag is found in the registry, an object of this
026: * class is created. It creates the appropriate action object
027: * and captures information that is later used to add this action
028: * object into menu/tool bar. This class is reused for
029: * global (workbench) menu/tool bar, popup menu actions,
030: * as well as view's pulldown and local tool bar.
031: */
032: public class ActionDescriptor implements IPluginContribution {
033: private PluginAction action;
034:
035: private String toolbarId;
036:
037: private String menuPath;
038:
039: private String id;
040:
041: private String pluginId;
042:
043: private String menuGroup;
044:
045: private String toolbarGroupId;
046:
047: /**
048: * Popup constant. Value <code>0x1</code>.
049: */
050: public static final int T_POPUP = 0x1;
051:
052: /**
053: * View constant. Value <code>0x2</code>.
054: */
055: public static final int T_VIEW = 0x2;
056:
057: /**
058: * Workbench constant. Value <code>0x3</code>.
059: */
060: public static final int T_WORKBENCH = 0x3;
061:
062: /**
063: * Editor constant. Value <code>0x4</code>.
064: */
065: public static final int T_EDITOR = 0x4;
066:
067: /**
068: * Workbench pulldown constant. Value <code>0x5</code>.
069: */
070: public static final int T_WORKBENCH_PULLDOWN = 0x5;
071:
072: /**
073: * Push style constant. Value <code>push</code>.
074: */
075: public static final String STYLE_PUSH = "push"; //$NON-NLS-1$
076:
077: /**
078: * Radio style constant. Value <code>radio</code>.
079: */
080: public static final String STYLE_RADIO = "radio"; //$NON-NLS-1$
081:
082: /***
083: * Toggle style constant. Value <code>toggle</code>.
084: */
085: public static final String STYLE_TOGGLE = "toggle"; //$NON-NLS-1$
086:
087: /**
088: * Pulldown style constant. Value <code>pulldown</code>.
089: */
090: public static final String STYLE_PULLDOWN = "pulldown"; //$NON-NLS-1$
091:
092: /**
093: * Creates a new descriptor with the specified target.
094: *
095: * @param actionElement the configuration element
096: * @param targetType the type of action
097: */
098: public ActionDescriptor(IConfigurationElement actionElement,
099: int targetType) {
100: this (actionElement, targetType, null);
101: }
102:
103: /**
104: * Creates a new descriptor with the target and destination workbench part
105: * it will go into.
106: *
107: * @param actionElement the configuration element
108: * @param targetType the type of action
109: * @param target the target object
110: */
111: public ActionDescriptor(IConfigurationElement actionElement,
112: int targetType, Object target) {
113: // Load attributes.
114: id = actionElement
115: .getAttribute(IWorkbenchRegistryConstants.ATT_ID);
116: pluginId = actionElement.getNamespace();
117: String label = actionElement
118: .getAttribute(IWorkbenchRegistryConstants.ATT_LABEL);
119: String tooltip = actionElement
120: .getAttribute(IWorkbenchRegistryConstants.ATT_TOOLTIP);
121: String helpContextId = actionElement
122: .getAttribute(IWorkbenchRegistryConstants.ATT_HELP_CONTEXT_ID);
123: String mpath = actionElement
124: .getAttribute(IWorkbenchRegistryConstants.ATT_MENUBAR_PATH);
125: String tpath = actionElement
126: .getAttribute(IWorkbenchRegistryConstants.ATT_TOOLBAR_PATH);
127: String style = actionElement
128: .getAttribute(IWorkbenchRegistryConstants.ATT_STYLE);
129: String icon = actionElement
130: .getAttribute(IWorkbenchRegistryConstants.ATT_ICON);
131: String hoverIcon = actionElement
132: .getAttribute(IWorkbenchRegistryConstants.ATT_HOVERICON);
133: String disabledIcon = actionElement
134: .getAttribute(IWorkbenchRegistryConstants.ATT_DISABLEDICON);
135: String description = actionElement
136: .getAttribute(IWorkbenchRegistryConstants.TAG_DESCRIPTION);
137: String accelerator = actionElement
138: .getAttribute(IWorkbenchRegistryConstants.ATT_ACCELERATOR);
139:
140: // Verify input.
141: if (label == null) {
142: WorkbenchPlugin
143: .log("Invalid action declaration (label == null): " + id); //$NON-NLS-1$
144: label = WorkbenchMessages.ActionDescriptor_invalidLabel;
145: }
146:
147: // Calculate menu and toolbar paths.
148: String mgroup = null;
149: String tgroup = null;
150: if (mpath != null) {
151: int loc = mpath.lastIndexOf('/');
152: if (loc != -1) {
153: mgroup = mpath.substring(loc + 1);
154: mpath = mpath.substring(0, loc);
155: } else {
156: mgroup = mpath;
157: mpath = null;
158: }
159: }
160: if (targetType == T_POPUP && mgroup == null) {
161: mgroup = IWorkbenchActionConstants.MB_ADDITIONS;
162: }
163: if (tpath != null) {
164: int loc = tpath.lastIndexOf('/');
165: if (loc != -1) {
166: tgroup = tpath.substring(loc + 1);
167: tpath = tpath.substring(0, loc);
168: } else {
169: tgroup = tpath;
170: tpath = null;
171: }
172: }
173: menuPath = mpath;
174: menuGroup = mgroup;
175: if ((tpath != null) && tpath.equals("Normal")) { //$NON-NLS-1$
176: tpath = ""; //$NON-NLS-1$
177: }
178: toolbarId = tpath;
179: toolbarGroupId = tgroup;
180:
181: // Create action.
182: action = createAction(targetType, actionElement, target, style);
183: if (action.getText() == null) {
184: action.setText(label);
185: }
186: if (action.getToolTipText() == null && tooltip != null) {
187: action.setToolTipText(tooltip);
188: }
189: if (helpContextId != null) {
190: String fullID = helpContextId;
191: if (helpContextId.indexOf(".") == -1) { //$NON-NLS-1$
192: // For backward compatibility we auto qualify the id if it is not
193: // qualified)
194: fullID = actionElement.getNamespace()
195: + "." + helpContextId;//$NON-NLS-1$
196: }
197: PlatformUI.getWorkbench().getHelpSystem().setHelp(action,
198: fullID);
199: }
200: if (description != null) {
201: action.setDescription(description);
202: }
203:
204: if (style != null) {
205: // Since 2.1, the "state" and "pulldown" attributes means something different
206: // when the new "style" attribute has been set. See doc for more info.
207: String state = actionElement
208: .getAttribute(IWorkbenchRegistryConstants.ATT_STATE);
209: if (state != null) {
210: if (style.equals(STYLE_RADIO)
211: || style.equals(STYLE_TOGGLE)) {
212: action.setChecked(state.equals("true"));//$NON-NLS-1$
213: }
214: }
215: } else {
216: // Keep for backward compatibility for actions not using the
217: // new style attribute.
218: String state = actionElement
219: .getAttribute(IWorkbenchRegistryConstants.ATT_STATE);
220: if (state != null) {
221: action.setChecked(state.equals("true"));//$NON-NLS-1$
222: }
223: }
224:
225: String extendingPluginId = actionElement
226: .getDeclaringExtension().getNamespace();
227:
228: if (icon != null) {
229: action
230: .setImageDescriptor(AbstractUIPlugin
231: .imageDescriptorFromPlugin(
232: extendingPluginId, icon));
233: }
234: if (hoverIcon != null) {
235: action.setHoverImageDescriptor(AbstractUIPlugin
236: .imageDescriptorFromPlugin(extendingPluginId,
237: hoverIcon));
238: }
239: if (disabledIcon != null) {
240: action.setDisabledImageDescriptor(AbstractUIPlugin
241: .imageDescriptorFromPlugin(extendingPluginId,
242: disabledIcon));
243: }
244:
245: if (accelerator != null) {
246: processAccelerator(action, accelerator);
247: }
248: }
249:
250: /**
251: * Creates an instance of PluginAction. Depending on the target part,
252: * subclasses of this class may be created.
253: */
254: private PluginAction createAction(int targetType,
255: IConfigurationElement actionElement, Object target,
256: String style) {
257: int actionStyle = IAction.AS_UNSPECIFIED;
258: if (style != null) {
259: if (style.equals(STYLE_RADIO)) {
260: actionStyle = IAction.AS_RADIO_BUTTON;
261: } else if (style.equals(STYLE_TOGGLE)) {
262: actionStyle = IAction.AS_CHECK_BOX;
263: } else if (style.equals(STYLE_PULLDOWN)) {
264: actionStyle = IAction.AS_DROP_DOWN_MENU;
265: } else if (style.equals(STYLE_PUSH)) {
266: actionStyle = IAction.AS_PUSH_BUTTON;
267: }
268: }
269:
270: switch (targetType) {
271: case T_VIEW:
272: return new ViewPluginAction(actionElement,
273: (IViewPart) target, id, actionStyle);
274: case T_EDITOR:
275: return new EditorPluginAction(actionElement,
276: (IEditorPart) target, id, actionStyle);
277: case T_WORKBENCH:
278: return new WWinPluginAction(actionElement,
279: (IWorkbenchWindow) target, id, actionStyle);
280: case T_WORKBENCH_PULLDOWN:
281: actionStyle = IAction.AS_DROP_DOWN_MENU;
282: return new WWinPluginPulldown(actionElement,
283: (IWorkbenchWindow) target, id, actionStyle);
284: case T_POPUP:
285: return new ObjectPluginAction(actionElement, id,
286: actionStyle);
287: default:
288: WorkbenchPlugin.log("Unknown Action Type: " + targetType);//$NON-NLS-1$
289: return null;
290: }
291: }
292:
293: /**
294: * Returns the action object held in this descriptor.
295: *
296: * @return the action
297: */
298: public PluginAction getAction() {
299: return action;
300: }
301:
302: /**
303: * Returns action's id as defined in the registry.
304: *
305: * @return the id
306: */
307: public String getId() {
308: return id;
309: }
310:
311: /**
312: * Returns named slot (group) in the menu where this action
313: * should be added.
314: *
315: * @return the menu group
316: */
317: public String getMenuGroup() {
318: return menuGroup;
319: }
320:
321: /**
322: * Returns menu path where this action should be added. If null,
323: * the action will not be added into the menu.
324: *
325: * @return the menubar path
326: */
327: public String getMenuPath() {
328: return menuPath;
329: }
330:
331: /**
332: * Returns the named slot (group) in the tool bar where this
333: * action should be added.
334: *
335: * @return the toolbar group id
336: */
337: public String getToolbarGroupId() {
338: return toolbarGroupId;
339: }
340:
341: /**
342: * Returns id of the tool bar where this action should be added.
343: * If null, action will not be added to the tool bar.
344: *
345: * @return the toolbar id
346: */
347: public String getToolbarId() {
348: return toolbarId;
349: }
350:
351: /**
352: * For debugging only.
353: */
354: public String toString() {
355: return "ActionDescriptor(" + id + ")";//$NON-NLS-2$//$NON-NLS-1$
356: }
357:
358: /**
359: * Process the accelerator definition. If it is a number
360: * then process the code directly - if not then parse it
361: * and create the code
362: */
363: private void processAccelerator(IAction action,
364: String acceleratorText) {
365:
366: if (acceleratorText.length() == 0) {
367: return;
368: }
369:
370: //Is it a numeric definition?
371: if (Character.isDigit(acceleratorText.charAt(0))) {
372: try {
373: action.setAccelerator(Integer.valueOf(acceleratorText)
374: .intValue());
375: } catch (NumberFormatException e) {
376: WorkbenchPlugin
377: .log(
378: "Invalid accelerator declaration for action: " + id, e); //$NON-NLS-1$
379: }
380: } else {
381: action.setAccelerator(Action
382: .convertAccelerator(acceleratorText));
383: }
384: }
385:
386: /* (non-Javadoc)
387: * @see org.eclipse.ui.IPluginContribution#getLocalId()
388: */
389: public String getLocalId() {
390: return getId();
391: }
392:
393: /* (non-Javadoc)
394: * @see org.eclipse.ui.IPluginContribution#getPluginId()
395: */
396: public String getPluginId() {
397: return pluginId;
398: }
399: }
|