KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > SubActionBars


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;
12
13 import java.util.HashMap JavaDoc;
14 import java.util.Iterator JavaDoc;
15 import java.util.Map JavaDoc;
16 import java.util.WeakHashMap JavaDoc;
17
18 import org.eclipse.core.commands.IHandler;
19 import org.eclipse.core.commands.common.EventManager;
20 import org.eclipse.core.expressions.EvaluationResult;
21 import org.eclipse.core.expressions.Expression;
22 import org.eclipse.core.expressions.ExpressionInfo;
23 import org.eclipse.core.expressions.IEvaluationContext;
24 import org.eclipse.jface.action.IAction;
25 import org.eclipse.jface.action.IMenuManager;
26 import org.eclipse.jface.action.IStatusLineManager;
27 import org.eclipse.jface.action.IToolBarManager;
28 import org.eclipse.jface.action.SubMenuManager;
29 import org.eclipse.jface.action.SubStatusLineManager;
30 import org.eclipse.jface.action.SubToolBarManager;
31 import org.eclipse.jface.commands.ActionHandler;
32 import org.eclipse.jface.util.IPropertyChangeListener;
33 import org.eclipse.jface.util.PropertyChangeEvent;
34 import org.eclipse.ui.handlers.IHandlerActivation;
35 import org.eclipse.ui.handlers.IHandlerService;
36 import org.eclipse.ui.internal.EditorActionBars;
37 import org.eclipse.ui.internal.WorkbenchPlugin;
38 import org.eclipse.ui.internal.actions.CommandAction;
39 import org.eclipse.ui.internal.handlers.CommandLegacyActionWrapper;
40 import org.eclipse.ui.internal.handlers.IActionCommandMappingService;
41 import org.eclipse.ui.internal.services.SourcePriorityNameMapping;
42 import org.eclipse.ui.services.IServiceLocator;
43
44 /**
45  * Generic implementation of the <code>IActionBars</code> interface.
46  */

47 public class SubActionBars extends EventManager implements IActionBars {
48
49     /**
50      * The expression to use when contributing handlers through
51      * {@link #setGlobalActionHandler(String, IAction)}}. This ensures that
52      * handlers contributed through {@link SubActionBars} are given priority
53      * over handlers contributed to the {@link IHandlerService}.
54      */

55     private static final Expression EXPRESSION = new Expression() {
56         public final EvaluationResult evaluate(final IEvaluationContext context) {
57             return EvaluationResult.TRUE;
58         }
59
60         public final void collectExpressionInfo(final ExpressionInfo info) {
61             info
62                     .addVariableNameAccess(SourcePriorityNameMapping.LEGACY_LEGACY_NAME);
63         }
64     };
65
66     /**
67      * Property constant for changes to action handlers.
68      */

69     public static final String JavaDoc P_ACTION_HANDLERS = "org.eclipse.ui.internal.actionHandlers"; //$NON-NLS-1$
70

71     private Map JavaDoc actionHandlers;
72
73     private boolean actionHandlersChanged;
74
75     /**
76      * A map of handler activations ({@link IHandlerActivation} indexed by
77      * action id ({@link String}) indexed by service locator ({@link IServiceLocator}).
78      * This value is <code>null</code> if there are no activations.
79      */

80     private Map JavaDoc activationsByActionIdByServiceLocator;
81
82     private boolean active = false;
83
84     private SubMenuManager menuMgr;
85
86     private IActionBars parent;
87
88     /**
89      * A service locator appropriate for this action bar. This value is never
90      * <code>null</code>. It must be capable of providing a
91      * {@link IHandlerService}.
92      */

93     private IServiceLocator serviceLocator;
94
95     private SubStatusLineManager statusLineMgr;
96
97     private SubToolBarManager toolBarMgr;
98
99     private Map JavaDoc actionIdByCommandId = new HashMap JavaDoc();
100
101     /**
102      * Construct a new <code>SubActionBars</code> object. The service locator
103      * will simply be the service locator of the parent.
104      *
105      * @param parent
106      * The parent of this action bar; must not be <code>null</code>.
107      */

108     public SubActionBars(final IActionBars parent) {
109         this(parent, null);
110     }
111
112     /**
113      * Constructs a new instance of <code>SubActionBars</code>.
114      *
115      * @param parent
116      * The parent of this action bar; must not be <code>null</code>.
117      * @param serviceLocator
118      * The service locator for this action bar; should not be
119      * <code>null</code>.
120      *
121      * @since 3.2
122      */

123     public SubActionBars(final IActionBars parent,
124             final IServiceLocator serviceLocator) {
125         if (parent == null) {
126             throw new NullPointerException JavaDoc("The parent cannot be null"); //$NON-NLS-1$
127
}
128
129         this.parent = parent;
130         this.serviceLocator = serviceLocator;
131     }
132
133     /**
134      * Activate the contributions.
135      */

136     public void activate() {
137         activate(true);
138     }
139
140     /**
141      * Activate the contributions.
142      * <p>
143      * Workaround for toolbar layout flashing when editors contribute large
144      * amounts of items. In this case we want to force the items to be
145      * visible/hidden only when required, otherwise just change the enablement
146      * state.
147      * </p>
148      */

149     public void activate(boolean forceVisibility) {
150         setActive(true);
151     }
152
153     /**
154      * Adds a property change listener. Has no effect if an identical listener
155      * is already registered.
156      *
157      * @param listener
158      * a property change listener
159      */

160     public void addPropertyChangeListener(IPropertyChangeListener listener) {
161         addListenerObject(listener);
162     }
163
164     /**
165      * Sets the active flag. Clients should not call this method directly unless
166      * they are overriding the setActive() method.
167      */

168     protected final void basicSetActive(boolean active) {
169         this.active = active;
170     }
171
172     /**
173      * Clear the global action handlers.
174      */

175     public void clearGlobalActionHandlers() {
176         if (actionHandlers != null) {
177             actionHandlers.clear();
178             actionHandlersChanged = true;
179         }
180
181         if (activationsByActionIdByServiceLocator != null) {
182             // Clean up the activations.
183
final Iterator JavaDoc activationItr = activationsByActionIdByServiceLocator
184                     .entrySet().iterator();
185             while (activationItr.hasNext()) {
186                 final Map.Entry JavaDoc value = (Map.Entry JavaDoc) activationItr.next();
187                 final IServiceLocator locator = (IServiceLocator) value
188                         .getKey();
189                 final IHandlerService service = (IHandlerService) locator
190                         .getService(IHandlerService.class);
191                 final Map JavaDoc activationsByActionId = (Map JavaDoc) value.getValue();
192                 final Iterator JavaDoc iterator = activationsByActionId.values()
193                         .iterator();
194                 while (iterator.hasNext()) {
195                     final IHandlerActivation activation = (IHandlerActivation) iterator
196                             .next();
197                     service.deactivateHandler(activation);
198                     activation.getHandler().dispose();
199                 }
200             }
201             activationsByActionIdByServiceLocator.clear();
202         }
203     }
204
205     /**
206      * Returns a new sub menu manager.
207      *
208      * @param parent
209      * the parent menu manager
210      * @return the menu manager
211      */

212     protected SubMenuManager createSubMenuManager(IMenuManager parent) {
213         return new SubMenuManager(parent);
214     }
215
216     /**
217      * Returns a new sub toolbar manager.
218      *
219      * @param parent
220      * the parent toolbar manager
221      * @return the tool bar manager
222      */

223     protected SubToolBarManager createSubToolBarManager(IToolBarManager parent) {
224         return new SubToolBarManager(parent);
225     }
226
227     /**
228      * Deactivate the contributions.
229      */

230     public void deactivate() {
231         deactivate(true);
232     }
233
234     /**
235      * Deactivate the contributions.
236      * <p>
237      * Workaround for menubar/toolbar layout flashing when editors have many
238      * contributions. In this case we want to force the contributions to be
239      * visible/hidden only when required, otherwise just change the enablement
240      * state.
241      * </p>
242      */

243     public void deactivate(boolean forceHide) {
244         setActive(false);
245     }
246
247     /**
248      * Dispose the contributions.
249      */

250     public void dispose() {
251         clearGlobalActionHandlers();
252         if (menuMgr != null) {
253             menuMgr.dispose();
254             menuMgr.disposeManager();
255         }
256         if (statusLineMgr != null) {
257             statusLineMgr.disposeManager();
258         }
259         if (toolBarMgr != null) {
260             toolBarMgr.disposeManager();
261         }
262         clearListeners();
263     }
264
265     /**
266      * Notifies any property change listeners if the global action handlers have
267      * changed
268      */

269     protected void fireActionHandlersChanged() {
270         if (actionHandlersChanged) {
271             // Doesn't actually pass the old and new values
272
firePropertyChange(new PropertyChangeEvent(this, P_ACTION_HANDLERS,
273                     null, null));
274             actionHandlersChanged = false;
275         }
276     }
277
278     /**
279      * Notifies any property change listeners that a property has changed. Only
280      * listeners registered at the time this method is called are notified.
281      *
282      * @param event
283      * the property change event
284      *
285      * @see IPropertyChangeListener#propertyChange
286      */

287     protected void firePropertyChange(PropertyChangeEvent event) {
288         Object JavaDoc[] listeners = getListeners();
289         for (int i = 0; i < listeners.length; ++i) {
290             ((IPropertyChangeListener) listeners[i]).propertyChange(event);
291         }
292     }
293
294     /**
295      * Return whether the manager is currently active or not.
296      */

297     protected final boolean getActive() {
298         return active;
299     }
300
301     /**
302      * Get the handler for a window action.
303      *
304      * @param actionID
305      * an action ID declared in the registry
306      * @return an action handler which implements the action ID, or
307      * <code>null</code> if none is registered.
308      */

309     public IAction getGlobalActionHandler(String JavaDoc actionID) {
310         if (actionHandlers == null) {
311             return null;
312         }
313         return (IAction) actionHandlers.get(actionID);
314     }
315
316     /**
317      * Returns the complete list of active global action handlers. If there are
318      * no global action handlers registered return null.
319      */

320     public Map JavaDoc getGlobalActionHandlers() {
321         return actionHandlers;
322     }
323
324     /**
325      * Returns the abstract menu manager. If items are added or removed from the
326      * manager be sure to call <code>updateActionBars</code>.
327      *
328      * @return the menu manager
329      */

330     public IMenuManager getMenuManager() {
331         if (menuMgr == null) {
332             menuMgr = createSubMenuManager(parent.getMenuManager());
333             menuMgr.setVisible(active);
334         }
335         return menuMgr;
336     }
337
338     /**
339      * Return the parent action bar manager.
340      */

341     protected final IActionBars getParent() {
342         return parent;
343     }
344
345     /**
346      * Answer the service locator for this action bar.
347      *
348      * @return an <code>IServiceLocater</code> or the parents if
349      * the receiver does not have one
350      *
351      * @since 3.2
352      */

353     public final IServiceLocator getServiceLocator() {
354         if (serviceLocator != null) {
355             return serviceLocator;
356         }
357
358         return parent.getServiceLocator();
359     }
360
361     /**
362      * Returns the status line manager. If items are added or removed from the
363      * manager be sure to call <code>updateActionBars</code>.
364      *
365      * @return the status line manager
366      */

367     public IStatusLineManager getStatusLineManager() {
368         if (statusLineMgr == null) {
369             statusLineMgr = new SubStatusLineManager(parent
370                     .getStatusLineManager());
371             statusLineMgr.setVisible(active);
372         }
373         return statusLineMgr;
374     }
375
376     /**
377      * Returns the tool bar manager. If items are added or removed from the
378      * manager be sure to call <code>updateActionBars</code>.
379      *
380      * @return the tool bar manager
381      */

382     public IToolBarManager getToolBarManager() {
383         if (toolBarMgr == null) {
384             toolBarMgr = createSubToolBarManager(parent.getToolBarManager());
385             toolBarMgr.setVisible(active);
386         }
387         return toolBarMgr;
388     }
389
390     /**
391      * Return whether the sub menu manager has been created yet.
392      */

393     protected final boolean isSubMenuManagerCreated() {
394         return menuMgr != null;
395     }
396
397     /**
398      * Return whether the sub status line manager has been created yet.
399      */

400     protected final boolean isSubStatusLineManagerCreated() {
401         return statusLineMgr != null;
402     }
403
404     /**
405      * Return whether the sub toolbar manager has been created yet.
406      */

407     protected final boolean isSubToolBarManagerCreated() {
408         return toolBarMgr != null;
409     }
410
411     /**
412      * Notification that the target part for the action bars has changed.
413      */

414     public void partChanged(IWorkbenchPart part) {
415     }
416
417     /**
418      * Removes the given property change listener. Has no effect if an identical
419      * listener is not registered.
420      *
421      * @param listener
422      * a property change listener
423      */

424     public void removePropertyChangeListener(IPropertyChangeListener listener) {
425         removeListenerObject(listener);
426     }
427
428     /**
429      * Activate / deactivate the contributions.
430      */

431     protected void setActive(boolean set) {
432         active = set;
433         if (menuMgr != null) {
434             menuMgr.setVisible(set);
435         }
436
437         if (statusLineMgr != null) {
438             statusLineMgr.setVisible(set);
439         }
440
441         if (toolBarMgr != null) {
442             toolBarMgr.setVisible(set);
443         }
444     }
445
446     /**
447      * Add a handler for a window action.
448      *
449      * @param actionID
450      * an action ID declared in the registry
451      * @param handler
452      * an action which implements the action ID. <code>null</code>
453      * may be passed to deregister a handler.
454      */

455     public void setGlobalActionHandler(String JavaDoc actionID, IAction handler) {
456         if (actionID == null) {
457             /*
458              * Bug 124061. It used to be invalid to pass null as an action id,
459              * but some people still did it. Handle this case by trapping the
460              * exception and logging it.
461              */

462             WorkbenchPlugin
463                     .log("Cannot set the global action handler for a null action id"); //$NON-NLS-1$
464
return;
465         }
466         
467         if (handler instanceof CommandLegacyActionWrapper) {
468             // this is a registration of a fake action for an already
469
// registered handler
470
WorkbenchPlugin
471                     .log("Cannot feed a CommandLegacyActionWrapper back into the system"); //$NON-NLS-1$
472
return;
473         }
474         
475         if (handler instanceof CommandAction) {
476             // we unfortunately had to allow these out into the wild, but they
477
// still must not feed back into the system
478
return;
479         }
480         
481         if (handler != null) {
482             // Update the action handlers.
483
if (actionHandlers == null) {
484                 actionHandlers = new HashMap JavaDoc(11);
485             }
486             actionHandlers.put(actionID, handler);
487
488             // Add a mapping from this action id to the command id.
489
if (serviceLocator != null) {
490                 final IActionCommandMappingService mappingService = (IActionCommandMappingService) serviceLocator
491                         .getService(IActionCommandMappingService.class);
492                 final String JavaDoc commandId = mappingService.getCommandId(actionID);
493
494                 // Update the handler activations.
495
final IHandlerService service = (IHandlerService) serviceLocator
496                         .getService(IHandlerService.class);
497                 Map JavaDoc activationsByActionId = null;
498                 if (activationsByActionIdByServiceLocator == null) {
499                     activationsByActionIdByServiceLocator = new WeakHashMap JavaDoc();
500                     activationsByActionId = new HashMap JavaDoc();
501                     activationsByActionIdByServiceLocator.put(serviceLocator,
502                             activationsByActionId);
503                 } else {
504                     activationsByActionId = (Map JavaDoc) activationsByActionIdByServiceLocator
505                             .get(serviceLocator);
506                     if (activationsByActionId == null) {
507                         activationsByActionId = new HashMap JavaDoc();
508                         activationsByActionIdByServiceLocator.put(
509                                 serviceLocator, activationsByActionId);
510                     } else if (activationsByActionId.containsKey(actionID)) {
511                         final Object JavaDoc value = activationsByActionId
512                                 .remove(actionID);
513                         if (value instanceof IHandlerActivation) {
514                             final IHandlerActivation activation = (IHandlerActivation) value;
515                             actionIdByCommandId.remove(activation.getCommandId());
516                             service.deactivateHandler(activation);
517                             activation.getHandler().dispose();
518                         }
519                     } else if (commandId != null
520                             && actionIdByCommandId.containsKey(commandId)) {
521                         final Object JavaDoc value = activationsByActionId
522                                 .remove(actionIdByCommandId.remove(commandId));
523                         if (value instanceof IHandlerActivation) {
524                             final IHandlerActivation activation = (IHandlerActivation) value;
525                             service.deactivateHandler(activation);
526                             activation.getHandler().dispose();
527                         }
528                     }
529                 }
530
531                 if (commandId != null) {
532                     actionIdByCommandId.put(commandId, actionID);
533                     // Register this as a handler with the given definition id.
534
// the expression gives the setGlobalActionHandler() a
535
// priority.
536
final IHandler actionHandler = new ActionHandler(handler);
537                     Expression handlerExpression = EXPRESSION;
538                     //XXX add new API in next release to avoid down-casting (bug 137091)
539
if (this instanceof EditorActionBars) {
540                         handlerExpression = ((EditorActionBars)this).getHandlerExpression();
541                     }
542                     final IHandlerActivation activation = service
543                             .activateHandler(commandId, actionHandler,
544                                     handlerExpression);
545                     activationsByActionId.put(actionID, activation);
546                 }
547             }
548
549         } else {
550             if (actionHandlers != null) {
551                 actionHandlers.remove(actionID);
552             }
553
554             // Remove the handler activation.
555
if (serviceLocator != null) {
556                 final IHandlerService service = (IHandlerService) serviceLocator
557                         .getService(IHandlerService.class);
558                 if (activationsByActionIdByServiceLocator != null) {
559                     final Map JavaDoc activationsByActionId = (Map JavaDoc) activationsByActionIdByServiceLocator
560                             .get(serviceLocator);
561                     if ((activationsByActionId != null)
562                             && (activationsByActionId.containsKey(actionID))) {
563                         final Object JavaDoc value = activationsByActionId
564                                 .remove(actionID);
565                         if (value instanceof IHandlerActivation) {
566                             final IHandlerActivation activation = (IHandlerActivation) value;
567                             actionIdByCommandId.remove(activation.getCommandId());
568                             service.deactivateHandler(activation);
569                             activation.getHandler().dispose();
570                         }
571                     }
572                 }
573             }
574         }
575         actionHandlersChanged = true;
576     }
577
578     /**
579      * Sets the service locator for this action bar.
580      *
581      * @param locator
582      * The new locator; must not be <code>null</code>.
583      *
584      * @since 3.2
585      */

586     protected final void setServiceLocator(final IServiceLocator locator) {
587         if (locator == null) {
588             throw new NullPointerException JavaDoc("The service locator cannot be null"); //$NON-NLS-1$
589
}
590         this.serviceLocator = locator;
591     }
592
593     /**
594      * Commits all UI changes. This should be called after additions or
595      * subtractions have been made to a menu, status line, or toolbar.
596      */

597     public void updateActionBars() {
598         parent.updateActionBars();
599         fireActionHandlersChanged();
600     }
601 }
602
Popular Tags