KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > internal > handlers > ActionDelegateHandlerProxy


1 /*******************************************************************************
2  * Copyright (c) 2005, 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
12 package org.eclipse.ui.internal.handlers;
13
14 import org.eclipse.core.commands.ExecutionEvent;
15 import org.eclipse.core.commands.IHandler;
16 import org.eclipse.core.commands.IHandlerListener;
17 import org.eclipse.core.commands.IObjectWithState;
18 import org.eclipse.core.commands.ParameterizedCommand;
19 import org.eclipse.core.commands.State;
20 import org.eclipse.core.expressions.EvaluationResult;
21 import org.eclipse.core.expressions.Expression;
22 import org.eclipse.core.expressions.IEvaluationContext;
23 import org.eclipse.core.runtime.CoreException;
24 import org.eclipse.core.runtime.IConfigurationElement;
25 import org.eclipse.core.runtime.ISafeRunnable;
26 import org.eclipse.core.runtime.IStatus;
27 import org.eclipse.core.runtime.InvalidRegistryObjectException;
28 import org.eclipse.core.runtime.ListenerList;
29 import org.eclipse.core.runtime.SafeRunner;
30 import org.eclipse.core.runtime.Status;
31 import org.eclipse.jface.action.IAction;
32 import org.eclipse.jface.util.IPropertyChangeListener;
33 import org.eclipse.jface.util.PropertyChangeEvent;
34 import org.eclipse.jface.viewers.ISelection;
35 import org.eclipse.jface.viewers.ISelectionChangedListener;
36 import org.eclipse.jface.viewers.SelectionChangedEvent;
37 import org.eclipse.jface.viewers.StructuredSelection;
38 import org.eclipse.swt.widgets.Event;
39 import org.eclipse.ui.IActionDelegate;
40 import org.eclipse.ui.IActionDelegate2;
41 import org.eclipse.ui.IActionDelegateWithEvent;
42 import org.eclipse.ui.IEditorActionDelegate;
43 import org.eclipse.ui.IEditorPart;
44 import org.eclipse.ui.INullSelectionListener;
45 import org.eclipse.ui.IObjectActionDelegate;
46 import org.eclipse.ui.ISelectionListener;
47 import org.eclipse.ui.ISources;
48 import org.eclipse.ui.IViewActionDelegate;
49 import org.eclipse.ui.IViewPart;
50 import org.eclipse.ui.IWorkbenchPage;
51 import org.eclipse.ui.IWorkbenchPart;
52 import org.eclipse.ui.IWorkbenchWindow;
53 import org.eclipse.ui.IWorkbenchWindowActionDelegate;
54 import org.eclipse.ui.handlers.IHandlerService;
55 import org.eclipse.ui.internal.WorkbenchPlugin;
56
57 /**
58  * <p>
59  * This proxies an {@link IActionDelegate} so that it can impersonate an
60  * {@link IHandler}.
61  * </p>
62  * <p>
63  * This class is not intended for use outside of the
64  * <code>org.eclipse.ui.workbench</code> plug-in.
65  * </p>
66  *
67  * @since 3.2
68  */

69 public final class ActionDelegateHandlerProxy implements ISelectionListener,
70         ISelectionChangedListener, INullSelectionListener, IHandler,
71         IObjectWithState {
72
73     /**
74      * The fake action that proxies all of the command-based services. This
75      * value is never <code>null</code>.
76      */

77     private CommandLegacyActionWrapper action;
78
79     /**
80      * The identifier of the actions to create as a wrapper to the command
81      * architecture. This value may be <code>null</code>.
82      */

83     private String JavaDoc actionId;
84
85     /**
86      * The command that will back the dummy actions exposed to this delegate.
87      * This value is never <code>null</code>.
88      */

89     private ParameterizedCommand command;
90
91     /**
92      * This is the current selection, as seen by this proxy.
93      */

94     private ISelection currentSelection;
95
96     /**
97      * The delegate, if it has been created yet.
98      */

99     private IActionDelegate delegate;
100
101     //
102
// instead of casting, which is unreliable, pick
103
// a delegate type based on the IConfigurationElement
104
//
105
private IEditorActionDelegate editorDelegate = null;
106     private IViewActionDelegate viewDelegate = null;
107     private IObjectActionDelegate objectDelegate = null;
108     private IWorkbenchWindowActionDelegate windowDelegate = null;
109
110     /**
111      * The name of the configuration element attribute which contains the
112      * information necessary to instantiate the real handler.
113      */

114     private String JavaDoc delegateAttributeName;
115
116     /**
117      * The configuration element from which the handler can be created. This
118      * value will exist until the element is converted into a real class -- at
119      * which point this value will be set to <code>null</code>.
120      */

121     private IConfigurationElement element;
122
123     /**
124      * The <code>enabledWhen</code> expression for the handler. Only if this
125      * expression evaluates to <code>true</code> (or the value is
126      * <code>null</code>) should we consult the handler.
127      */

128     private final Expression enabledWhenExpression;
129
130     /**
131      * A collection of objects listening to changes to this manager. This
132      * collection is <code>null</code> if there are no listeners.
133      */

134     private transient ListenerList listenerList = null;
135
136     /**
137      * The image style to use when selecting the images to display for this
138      * delegate. This value may be <code>null</code>, if the default style
139      * should be used.
140      */

141     private final String JavaDoc style;
142
143     /**
144      * The identifier of the view with which this delegate must be associated.
145      * This value is not <code>null</code> iff the delegate is an
146      * {@link IViewActionDelegate}.
147      */

148     private final String JavaDoc viewId;
149
150     /**
151      * The workbench window in which this delegate is active. This value is
152      * never <code>null</code>.
153      */

154     private final IWorkbenchWindow window;
155
156     /**
157      * Constructs a new instance of <code>ActionDelegateHandlerProxy</code>
158      * with all the information it needs to try to avoid loading until it is
159      * needed.
160      *
161      * @param element
162      * The configuration element from which the real class can be
163      * loaded at run-time; must not be <code>null</code>.
164      * @param delegateAttributeName
165      * The name of the attibute or element containing the action
166      * delegate; must not be <code>null</code>.
167      * @param actionId
168      * The identifier of the underlying action; may be
169      * <code>null</code>.
170      * @param command
171      * The command with which the action delegate will be associated;
172      * must not be <code>null</code>.
173      * @param window
174      * The workbench window in which this delegate will be active;
175      * must not be <code>null</code>.
176      * @param style
177      * The image style with which the icons are associated; may be
178      * <code>null</code>.
179      * @param enabledWhenExpression
180      * The name of the element containing the enabledWhen expression.
181      * This should be a child of the
182      * <code>configurationElement</code>. If this value is
183      * <code>null</code>, then there is no enablement expression
184      * (i.e., enablement will be delegated to the handler when
185      * possible).
186      * @param viewId
187      * The identifier of the view to which this proxy is bound; may
188      * be <code>null</code> if this proxy is not for an
189      * {@link IViewActionDelegate}.
190      */

191     public ActionDelegateHandlerProxy(final IConfigurationElement element,
192             final String JavaDoc delegateAttributeName, final String JavaDoc actionId,
193             final ParameterizedCommand command, final IWorkbenchWindow window,
194             final String JavaDoc style, final Expression enabledWhenExpression,
195             final String JavaDoc viewId) {
196         if (element == null) {
197             throw new NullPointerException JavaDoc(
198                     "The configuration element backing a handler proxy cannot be null"); //$NON-NLS-1$
199
}
200
201         if (delegateAttributeName == null) {
202             throw new NullPointerException JavaDoc(
203                     "The attribute containing the action delegate must be known"); //$NON-NLS-1$
204
}
205
206         if (window == null) {
207             throw new NullPointerException JavaDoc(
208                     "The workbench window for a delegate must not be null"); //$NON-NLS-1$
209
}
210
211         this.element = element;
212         this.enabledWhenExpression = enabledWhenExpression;
213         this.delegateAttributeName = delegateAttributeName;
214         this.window = window;
215         this.command = command;
216         this.actionId = actionId;
217         this.style = style;
218         this.viewId = viewId;
219     }
220
221     public final void addHandlerListener(final IHandlerListener handlerListener) {
222         if (listenerList == null) {
223             listenerList = new ListenerList(ListenerList.IDENTITY);
224         }
225
226         listenerList.add(handlerListener);
227     }
228
229     public void addState(String JavaDoc id, State state) {
230         // TODO Auto-generated method stub
231

232     }
233
234     public final void dispose() {
235         final IActionDelegate delegate = getDelegate();
236         if (delegate instanceof IWorkbenchWindowActionDelegate) {
237             final IWorkbenchWindowActionDelegate workbenchWindowDelegate = (IWorkbenchWindowActionDelegate) delegate;
238             workbenchWindowDelegate.dispose();
239         } else if (delegate instanceof IActionDelegate2) {
240             final IActionDelegate2 delegate2 = (IActionDelegate2) delegate;
241             delegate2.dispose();
242         }
243     }
244
245     public final Object JavaDoc execute(final ExecutionEvent event) {
246         final IAction action = getAction();
247         if (loadDelegate() && (action != null)) {
248             final Object JavaDoc trigger = event.getTrigger();
249
250             // Attempt to update the selection.
251
final Object JavaDoc applicationContext = event.getApplicationContext();
252             if (applicationContext instanceof IEvaluationContext) {
253                 final IEvaluationContext context = (IEvaluationContext) applicationContext;
254                 updateDelegate(action, context);
255             }
256
257             // Decide what type of delegate we have.
258
if ((delegate instanceof IActionDelegate2)
259                     && (trigger instanceof Event)) {
260                 // This supports Eclipse 2.1 to Eclipse 3.1.
261
final IActionDelegate2 delegate2 = (IActionDelegate2) delegate;
262                 final Event triggeringEvent = (Event) trigger;
263                 delegate2.runWithEvent(action, triggeringEvent);
264             } else if ((delegate instanceof IActionDelegateWithEvent)
265                     && (trigger instanceof Event)) {
266                 // This supports Eclipse 2.0
267
final IActionDelegateWithEvent delegateWithEvent = (IActionDelegateWithEvent) delegate;
268                 final Event triggeringEvent = (Event) trigger;
269                 delegateWithEvent.runWithEvent(action, triggeringEvent);
270             } else {
271                 delegate.run(action);
272             }
273         }
274
275         return null;
276     }
277
278     /**
279      * @param action
280      * @param context
281      */

282     private void updateDelegate(final IAction action,
283             final IEvaluationContext context) {
284         if (action == null || delegate == null) {
285             return;
286         }
287
288         if (editorDelegate != null) {
289             final Object JavaDoc activeEditor = context
290                     .getVariable(ISources.ACTIVE_EDITOR_NAME);
291             if (activeEditor != null) {
292                 editorDelegate.setActiveEditor(action,
293                         (IEditorPart) activeEditor);
294             }
295         } else if (objectDelegate != null) {
296             final Object JavaDoc activePart = context
297                     .getVariable(ISources.ACTIVE_PART_NAME);
298             if (activePart != null) {
299                 objectDelegate.setActivePart(action,
300                         (IWorkbenchPart) activePart);
301             }
302         }
303
304         final Object JavaDoc selectionObject = getCurrentSelection(context);
305         if (selectionObject instanceof ISelection) {
306             currentSelection = (ISelection) selectionObject;
307             delegate.selectionChanged(action, currentSelection);
308         } else {
309             currentSelection = null;
310             delegate.selectionChanged(action, null);
311         }
312     }
313
314     /**
315      * @param context
316      * @return
317      */

318     private Object JavaDoc getCurrentSelection(final IEvaluationContext context) {
319         Object JavaDoc obj = context
320                 .getVariable(ISources.ACTIVE_MENU_EDITOR_INPUT_NAME);
321         if (obj == null) {
322             obj = context.getVariable(ISources.ACTIVE_MENU_SELECTION_NAME);
323             if (obj == null) {
324                 obj = context
325                         .getVariable(ISources.ACTIVE_CURRENT_SELECTION_NAME);
326             }
327         }
328         return obj;
329     }
330
331     /**
332      * Retrieves the action corresponding to the currently active workbench
333      * window, if any.
334      *
335      * @return The current action; <code>null</code> if there is no currently
336      * active workbench window.
337      */

338     private final CommandLegacyActionWrapper getAction() {
339         if (action == null) {
340             action = new CommandLegacyActionWrapper(actionId, command, style,
341                     window);
342             action.addPropertyChangeListener(new IPropertyChangeListener() {
343                 public final void propertyChange(final PropertyChangeEvent event) {
344                     // TODO Update the state somehow.
345
}
346             });
347         }
348         return action;
349     }
350
351     /**
352      * Retrieves the delegate corresponding to the currently active workbench
353      * window, if any. This does not trigger loading of the delegate.
354      *
355      * @return The current delegate; or <code>null</code> if none.
356      */

357     private final IActionDelegate getDelegate() {
358         return delegate;
359     }
360
361     public State getState(String JavaDoc stateId) {
362         // TODO Auto-generated method stub
363
return null;
364     }
365
366     public String JavaDoc[] getStateIds() {
367         // TODO Auto-generated method stub
368
return null;
369     }
370
371     public final void handleStateChange(final State state, final Object JavaDoc oldValue) {
372         // TODO What should we do here?
373
}
374
375     /**
376      * Initialize the action delegate by calling its lifecycle method.
377      */

378     private final boolean initDelegate() {
379         final IWorkbenchPage page = window.getActivePage();
380         final IWorkbenchPart activePart;
381         final IEditorPart activeEditor;
382         if (page == null) {
383             activePart = null;
384             activeEditor = null;
385         } else {
386             activePart = page.getActivePart();
387             activeEditor = page.getActiveEditor();
388         }
389         final IActionDelegate delegate = getDelegate();
390         final IAction action = getAction();
391
392         // Check to see if the view delegate should be initialized.
393
if ((viewId != null) && (page != null) && (viewDelegate != null)) {
394             final IViewPart viewPart = page.findView(viewId);
395             if (viewPart == null) {
396                 return false;
397             }
398         }
399
400         // Initialize the delegate.
401
final ISafeRunnable runnable = new ISafeRunnable() {
402             public final void handleException(final Throwable JavaDoc exception) {
403                 // Do nothing.
404
}
405
406             public final void run() {
407                 // Handle IActionDelegate2
408
if (delegate instanceof IActionDelegate2) {
409                     final IActionDelegate2 delegate2 = (IActionDelegate2) delegate;
410                     delegate2.init(action);
411                 }
412
413                 // Handle IObjectActionDelegates
414
if ((objectDelegate != null) && (activePart != null)) {
415                     objectDelegate.setActivePart(action, activePart);
416                 } else if (editorDelegate != null) {
417                     editorDelegate.setActiveEditor(action, activeEditor);
418                 } else if ((viewId != null) && (page != null)
419                         && (viewDelegate != null)) {
420                     final IViewPart viewPart = page.findView(viewId);
421                     viewDelegate.init(viewPart);
422                 } else if (windowDelegate != null) {
423                     windowDelegate.init(window);
424                 }
425             }
426         };
427         SafeRunner.run(runnable);
428         return true;
429     }
430
431     public final boolean isEnabled() {
432         final IHandlerService service = (IHandlerService) window
433                 .getService(IHandlerService.class);
434         IEvaluationContext context = service.getCurrentState();
435         return isEnabled(context);
436     }
437
438     public final boolean isEnabled(IEvaluationContext context) {
439         final CommandLegacyActionWrapper action = getAction();
440         if (enabledWhenExpression != null) {
441             try {
442                 final EvaluationResult result = enabledWhenExpression
443                         .evaluate(context);
444                 if (result == EvaluationResult.TRUE) {
445                     updateDelegate(action, context);
446                     return (action == null)
447                             || action.isEnabledDisregardingCommand();
448                 }
449             } catch (final CoreException e) {
450                 // We will just fall through an let it return false.
451
final StringBuffer JavaDoc message = new StringBuffer JavaDoc(
452                         "An exception occurred while evaluating the enabledWhen expression for "); //$NON-NLS-1$
453
if (element == null) {
454                     message.append(delegate);
455                 } else {
456                     message.append(element.getAttribute(delegateAttributeName));
457                 }
458                 message.append("' could not be loaded"); //$NON-NLS-1$
459
final IStatus status = new Status(IStatus.WARNING,
460                         WorkbenchPlugin.PI_WORKBENCH, 0, e.getMessage(), e);
461                 WorkbenchPlugin.log(message.toString(), status);
462             }
463
464             return false;
465         }
466
467         updateDelegate(action, context);
468         return (action == null) || action.isEnabledDisregardingCommand();
469     }
470
471     public final boolean isHandled() {
472         return true;
473     }
474
475     /**
476      * Checks if the declaring plugin has been loaded. This means that there
477      * will be no need to delay creating the delegate.
478      *
479      * @return <code>true</code> if the bundle containing the delegate is
480      * already loaded -- making it safe to load the delegate.
481      */

482     private final boolean isSafeToLoadDelegate() {
483         return false;
484         // TODO This causes problem because some people expect their selections
485
// to be a particular class.
486
// final String bundleId = element.getNamespace();
487
// return BundleUtility.isActive(bundleId);
488
}
489
490     /**
491      * Loads the delegate, if possible. If the delegate is loaded, then the
492      * member variables are updated accordingly.
493      *
494      * @return <code>true</code> if the delegate is now non-null;
495      * <code>false</code> otherwise.
496      */

497     private final boolean loadDelegate() {
498         // Try to load the delegate, if it hasn't been loaded already.
499
if (delegate == null) {
500             /*
501              * If this is an IViewActionDelegate, then check to see if we have a
502              * view ready yet. If not, then we'll have to wait.
503              */

504             if (viewId != null) {
505                 final IWorkbenchPage activePage = window.getActivePage();
506                 if (activePage != null) {
507                     final IViewPart part = activePage.findView(viewId);
508                     if (part == null) {
509                         return false;
510                     }
511                 } else {
512                     return false;
513                 }
514             }
515
516             // Load the delegate.
517
try {
518                 delegate = (IActionDelegate) element
519                         .createExecutableExtension(delegateAttributeName);
520                 String JavaDoc name = element.getDeclaringExtension()
521                         .getExtensionPointUniqueIdentifier();
522                 if ("org.eclipse.ui.actionSets".equals(name) //$NON-NLS-1$
523
&& delegate instanceof IWorkbenchWindowActionDelegate) {
524                     windowDelegate = (IWorkbenchWindowActionDelegate) delegate;
525                 } else if ("org.eclipse.ui.editorActions".equals(name) //$NON-NLS-1$
526
&& delegate instanceof IEditorActionDelegate) {
527                     editorDelegate = (IEditorActionDelegate) delegate;
528                 } else if ("org.eclipse.ui.viewActions".equals(name) //$NON-NLS-1$
529
&& delegate instanceof IViewActionDelegate) {
530                     viewDelegate = (IViewActionDelegate) delegate;
531                 } else if ("org.eclipse.ui.popupMenus".equals(name)) { //$NON-NLS-1$
532
IConfigurationElement parent = (IConfigurationElement) element
533                             .getParent();
534                     if ("objectContribution".equals(parent.getName()) //$NON-NLS-1$
535
&& delegate instanceof IObjectActionDelegate) {
536                         objectDelegate = (IObjectActionDelegate) delegate;
537                     } else if (viewId == null
538                             && delegate instanceof IEditorActionDelegate) {
539                         editorDelegate = (IEditorActionDelegate) delegate;
540                     } else if (viewId != null
541                             && delegate instanceof IViewActionDelegate) {
542                         viewDelegate = (IViewActionDelegate) delegate;
543                     }
544                 }
545                 if (initDelegate()) {
546                     element = null;
547                     delegateAttributeName = null;
548                     return true;
549                 }
550
551                 delegate = null;
552                 objectDelegate = null;
553                 viewDelegate = null;
554                 editorDelegate = null;
555                 windowDelegate = null;
556                 return false;
557
558             } catch (final ClassCastException JavaDoc e) {
559                 final String JavaDoc message = "The proxied delegate was the wrong class"; //$NON-NLS-1$
560
final IStatus status = new Status(IStatus.ERROR,
561                         WorkbenchPlugin.PI_WORKBENCH, 0, message, e);
562                 WorkbenchPlugin.log(message, status);
563                 return false;
564
565             } catch (final CoreException e) {
566                 final String JavaDoc message = "The proxied delegate for '" //$NON-NLS-1$
567
+ element.getAttribute(delegateAttributeName)
568                         + "' could not be loaded"; //$NON-NLS-1$
569
IStatus status = new Status(IStatus.ERROR,
570                         WorkbenchPlugin.PI_WORKBENCH, 0, message, e);
571                 WorkbenchPlugin.log(message, status);
572                 return false;
573             }
574         }
575
576         return true;
577     }
578
579     /**
580      * Refresh the action enablement.
581      */

582     private final void refreshEnablement() {
583         final IActionDelegate delegate = getDelegate();
584         final IAction action = getAction();
585         if ((delegate != null) && (action != null)) {
586             delegate.selectionChanged(action, currentSelection);
587         }
588     }
589
590     public void removeHandlerListener(IHandlerListener handlerListener) {
591         if (listenerList != null) {
592             listenerList.remove(handlerListener);
593
594             if (listenerList.isEmpty()) {
595                 listenerList = null;
596             }
597         }
598     }
599
600     public void removeState(String JavaDoc stateId) {
601         // TODO Auto-generated method stub
602

603     }
604
605     private final void selectionChanged(final ISelection selection) {
606         // Update selection.
607
currentSelection = selection;
608         if (currentSelection == null) {
609             currentSelection = StructuredSelection.EMPTY;
610         }
611
612         // The selection is passed to the delegate as-is without
613
// modification. If the selection needs to be modified
614
// the action contributors should do so.
615

616         // If the delegate can be loaded, do so.
617
// Otherwise, just update the enablement.
618
final IActionDelegate delegate = getDelegate();
619         if (delegate == null && isSafeToLoadDelegate()) {
620             loadDelegate();
621         }
622         refreshEnablement();
623     }
624
625     public final void selectionChanged(final IWorkbenchPart part,
626             final ISelection selection) {
627         selectionChanged(selection);
628
629     }
630
631     public final void selectionChanged(final SelectionChangedEvent event) {
632         final ISelection selection = event.getSelection();
633         selectionChanged(selection);
634     }
635
636     public final String JavaDoc toString() {
637         final StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
638         buffer.append("ActionDelegateHandlerProxy("); //$NON-NLS-1$
639
buffer.append(getDelegate());
640         if (element != null) {
641             buffer.append(',');
642             try {
643                 final String JavaDoc className = element
644                         .getAttribute(delegateAttributeName);
645                 buffer.append(className);
646             } catch (InvalidRegistryObjectException e) {
647                 buffer.append(actionId);
648             }
649         }
650         buffer.append(')');
651         return buffer.toString();
652     }
653 }
654
Popular Tags