KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > internal > PluginAction


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.ui.internal;
12
13 import org.eclipse.core.runtime.CoreException;
14 import org.eclipse.core.runtime.IConfigurationElement;
15 import org.eclipse.core.runtime.IStatus;
16 import org.eclipse.jface.action.Action;
17 import org.eclipse.jface.action.IAction;
18 import org.eclipse.jface.dialogs.MessageDialog;
19 import org.eclipse.jface.viewers.ISelection;
20 import org.eclipse.jface.viewers.ISelectionChangedListener;
21 import org.eclipse.jface.viewers.SelectionChangedEvent;
22 import org.eclipse.jface.viewers.StructuredSelection;
23 import org.eclipse.swt.widgets.Event;
24 import org.eclipse.ui.IActionDelegate;
25 import org.eclipse.ui.IActionDelegate2;
26 import org.eclipse.ui.IActionDelegateWithEvent;
27 import org.eclipse.ui.INullSelectionListener;
28 import org.eclipse.ui.IPluginContribution;
29 import org.eclipse.ui.ISelectionListener;
30 import org.eclipse.ui.IWorkbenchPart;
31 import org.eclipse.ui.IWorkbenchWindowActionDelegate;
32 import org.eclipse.ui.SelectionEnabler;
33 import org.eclipse.ui.WorkbenchException;
34 import org.eclipse.ui.internal.misc.StatusUtil;
35 import org.eclipse.ui.internal.registry.IWorkbenchRegistryConstants;
36 import org.eclipse.ui.internal.util.BundleUtility;
37 import org.eclipse.ui.internal.util.Util;
38
39 /**
40  * A PluginAction is a proxy for an action extension.
41  *
42  * At startup we read the registry and create a PluginAction for each action extension.
43  * This plugin action looks like the real action ( label, icon, etc ) and acts as
44  * a proxy for the action until invoked. At that point the proxy will instantiate
45  * the real action and delegate the run method to the real action.
46  * This makes it possible to load the action extension lazily.
47  *
48  * Occasionally the class will ask if it is OK to
49  * load the delegate (on selection changes). If the plugin containing
50  * the action extension has been loaded then the action extension itself
51  * will be instantiated.
52  */

53
54 public abstract class PluginAction extends Action implements
55         ISelectionListener, ISelectionChangedListener, INullSelectionListener,
56         IPluginContribution {
57     private IActionDelegate delegate;
58
59     private SelectionEnabler enabler;
60
61     private ISelection selection;
62
63     private IConfigurationElement configElement;
64
65     private String JavaDoc pluginId;
66
67     private String JavaDoc runAttribute = IWorkbenchRegistryConstants.ATT_CLASS;
68
69     private static int actionCount = 0;
70
71     /**
72      * PluginAction constructor.
73      *
74      * @param actionElement the element
75      * @param id the identifier
76      * @param style the style bits
77      */

78     public PluginAction(IConfigurationElement actionElement, String JavaDoc id,
79             int style) {
80         super(null, style);
81
82         this.configElement = actionElement;
83
84         if (id != null) {
85             setId(id);
86         } else {
87             // Create unique action id.
88
setId("PluginAction." + Integer.toString(actionCount)); //$NON-NLS-1$
89
++actionCount;
90         }
91
92         String JavaDoc defId = actionElement
93                 .getAttribute(IWorkbenchRegistryConstants.ATT_DEFINITION_ID);
94         setActionDefinitionId(defId);
95
96         pluginId = configElement.getNamespace();
97
98         // Read enablement declaration.
99
if (configElement.getAttribute(IWorkbenchRegistryConstants.ATT_ENABLES_FOR) != null) {
100             enabler = new SelectionEnabler(configElement);
101         } else {
102             IConfigurationElement[] kids = configElement
103                     .getChildren(IWorkbenchRegistryConstants.TAG_ENABLEMENT);
104             IConfigurationElement[] kids2 = configElement
105                     .getChildren(IWorkbenchRegistryConstants.TAG_SELECTION);
106             if (kids.length > 0 || kids2.length>0) {
107                 enabler = new SelectionEnabler(configElement);
108             }
109         }
110
111         // Give enabler or delegate a chance to adjust enable state
112
selectionChanged(new StructuredSelection());
113     }
114
115     /**
116      * Creates the delegate and refreshes its enablement.
117      */

118     protected final void createDelegate() {
119         // The runAttribute is null if delegate creation failed previously...
120
if (delegate == null && runAttribute != null) {
121             try {
122                 Object JavaDoc obj = WorkbenchPlugin.createExtension(configElement,
123                         runAttribute);
124                 delegate = validateDelegate(obj);
125                 initDelegate();
126                 refreshEnablement();
127             } catch (Throwable JavaDoc e) {
128                 runAttribute = null;
129                 IStatus status = null;
130                 if (e instanceof CoreException) {
131                     status = ((CoreException) e).getStatus();
132                 } else {
133                     status = StatusUtil
134                             .newStatus(
135                                     IStatus.ERROR,
136                                     "Internal plug-in action delegate error on creation.", e); //$NON-NLS-1$
137
}
138                 String JavaDoc id = configElement.getAttribute(IWorkbenchRegistryConstants.ATT_ID);
139                 WorkbenchPlugin
140                         .log(
141                                 "Could not create action delegate for id: " + id, status); //$NON-NLS-1$
142
return;
143             }
144         }
145     }
146
147     /**
148      * Validates the object is a delegate of the expected type. Subclasses can
149      * override to check for specific delegate types.
150      * <p>
151      * <b>Note:</b> Calls to the object are not allowed during this method.
152      * </p>
153      *
154      * @param obj a possible action delegate implementation
155      * @return the <code>IActionDelegate</code> implementation for the object
156      * @throws WorkbenchException if not of the expected delegate type
157      */

158     protected IActionDelegate validateDelegate(Object JavaDoc obj)
159             throws WorkbenchException {
160         if (obj instanceof IActionDelegate) {
161             return (IActionDelegate) obj;
162         }
163         
164         throw new WorkbenchException(
165                 "Action must implement IActionDelegate"); //$NON-NLS-1$
166
}
167
168     /**
169      * Initialize the action delegate by calling its lifecycle method.
170      * Subclasses may override but must call this implementation first.
171      */

172     protected void initDelegate() {
173         if (delegate instanceof IActionDelegate2) {
174             ((IActionDelegate2) delegate).init(this);
175         }
176     }
177
178     /**
179      * Returns the action delegate if created. Can be <code>null</code>
180      * if the delegate is not created yet or if previous delegate
181      * creation failed.
182      */

183     protected IActionDelegate getDelegate() {
184         return delegate;
185     }
186
187     /**
188      * Returns true if the declaring plugin has been loaded
189      * and there is no need to delay creating the delegate
190      * any more.
191      */

192     protected boolean isOkToCreateDelegate() {
193         if (getStyle() == IAction.AS_DROP_DOWN_MENU
194                 && !WWinPluginPulldown.class.isInstance(this)) {
195             return true;
196         }
197         
198         // test if the plugin has loaded
199
String JavaDoc bundleId = configElement.getNamespace();
200         return BundleUtility.isActive(bundleId);
201     }
202
203     /**
204      * Refresh the action enablement.
205      */

206     protected void refreshEnablement() {
207         if (enabler != null) {
208             setEnabled(enabler.isEnabledForSelection(selection));
209         }
210         if (delegate != null) {
211             delegate.selectionChanged(this, selection);
212         }
213     }
214
215     /* (non-Javadoc)
216      * Method declared on IAction.
217      */

218     public void run() {
219         runWithEvent(null);
220     }
221
222     /* (non-Javadoc)
223      * Method declared on IAction.
224      */

225     public void runWithEvent(Event event) {
226         // this message dialog is problematic.
227
if (delegate == null) {
228             createDelegate();
229             if (delegate == null) {
230                 MessageDialog
231                         .openInformation(
232                                 Util.getShellToParentOn(),
233                                 WorkbenchMessages.Information,
234                                 WorkbenchMessages.PluginAction_operationNotAvailableMessage);
235                 return;
236             }
237             if (!isEnabled()) {
238                 MessageDialog.openInformation(Util.getShellToParentOn(), WorkbenchMessages.Information,
239                         WorkbenchMessages.PluginAction_disabledMessage);
240                 return;
241             }
242         }
243
244         if (event != null) {
245             if (delegate instanceof IActionDelegate2) {
246                 ((IActionDelegate2) delegate).runWithEvent(this, event);
247                 return;
248             }
249             // Keep for backward compatibility with R2.0
250
if (delegate instanceof IActionDelegateWithEvent) {
251                 ((IActionDelegateWithEvent) delegate).runWithEvent(this, event);
252                 return;
253             }
254         }
255
256         delegate.run(this);
257     }
258
259     /**
260      * Handles selection change. If rule-based enabled is
261      * defined, it will be first to call it. If the delegate
262      * is loaded, it will also be given a chance.
263      *
264      * @param newSelection the new selection
265      */

266     public void selectionChanged(ISelection newSelection) {
267         // Update selection.
268
selection = newSelection;
269         if (selection == null) {
270             selection = StructuredSelection.EMPTY;
271         }
272
273         // The selection is passed to the delegate as-is without
274
// modification. If the selection needs to be modified
275
// the action contributors should do so.
276

277         // If the delegate can be loaded, do so.
278
// Otherwise, just update the enablement.
279
if (delegate == null && isOkToCreateDelegate()) {
280             createDelegate();
281         } else {
282             refreshEnablement();
283         }
284     }
285
286     /**
287      * The <code>SelectionChangedEventAction</code> implementation of this
288      * <code>ISelectionChangedListener</code> method calls
289      * <code>selectionChanged(IStructuredSelection)</code> when the selection is
290      * a structured one.
291      */

292     public void selectionChanged(SelectionChangedEvent event) {
293         ISelection sel = event.getSelection();
294         selectionChanged(sel);
295     }
296
297     /**
298      * The <code>SelectionChangedEventAction</code> implementation of this
299      * <code>ISelectionListener</code> method calls
300      * <code>selectionChanged(IStructuredSelection)</code> when the selection is
301      * a structured one. Subclasses may extend this method to react to the change.
302      */

303     public void selectionChanged(IWorkbenchPart part, ISelection sel) {
304         selectionChanged(sel);
305     }
306
307     /**
308      * For testing purposes only.
309      *
310      * @return the selection
311      * @since 3.1
312      */

313     public ISelection getSelection() {
314         return selection;
315     }
316
317     /**
318      * Returns the action identifier this action overrides.
319      * Default implementation returns <code>null</code>.
320      *
321      * @return the action identifier to override or <code>null</code>
322      */

323     public String JavaDoc getOverrideActionId() {
324         return null;
325     }
326
327     /**
328      * @return the IConfigurationElement used to create this PluginAction.
329      *
330      * @since 3.0
331      */

332     protected IConfigurationElement getConfigElement() {
333         return configElement;
334     }
335
336     /* (non-Javadoc)
337      * @see org.eclipse.ui.IPluginContribution#getLocalId()
338      */

339     public String JavaDoc getLocalId() {
340         return getId();
341     }
342
343     /* (non-Javadoc)
344      * @see org.eclipse.ui.IPluginContribution#getPluginId()
345      */

346     public String JavaDoc getPluginId() {
347         return pluginId;
348     }
349
350     /**
351      * Disposes the delegate, if created.
352      *
353      * @since 3.1
354      */

355     public void disposeDelegate() {
356         // avoid calling dispose() twice if the delegate implements
357
// both IActionDelegate2 and IWorkbenchWindowActionDelegate
358
if (getDelegate() instanceof IActionDelegate2) {
359             ((IActionDelegate2) getDelegate()).dispose();
360         }
361         else if (getDelegate() instanceof IWorkbenchWindowActionDelegate) {
362             ((IWorkbenchWindowActionDelegate) getDelegate()).dispose();
363         }
364         delegate = null;
365     }
366
367     /**
368      * Disposes this plugin action.
369      *
370      * @since 3.1
371      */

372     public void dispose() {
373         disposeDelegate();
374     }
375 }
376
Popular Tags