KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > team > ui > synchronize > SynchronizePageActionGroup


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.team.ui.synchronize;
12
13 import java.util.*;
14
15 import org.eclipse.core.runtime.ListenerList;
16 import org.eclipse.core.runtime.SafeRunner;
17 import org.eclipse.jface.action.*;
18 import org.eclipse.jface.util.SafeRunnable;
19 import org.eclipse.jface.viewers.*;
20 import org.eclipse.team.internal.ui.synchronize.SynchronizePageConfiguration;
21 import org.eclipse.ui.IActionBars;
22 import org.eclipse.ui.IKeyBindingService;
23 import org.eclipse.ui.actions.ActionGroup;
24
25 /**
26  * Used to add one or more actions to the context menu, toolbar or view menu
27  * of an {@link ISynchronizePage}. An action group is added to a synchronize
28  * page by adding the group to the {@link ISynchronizePageConfiguration} after
29  * configuration has been created by the page but before the page is created.
30  * <p>
31  * The life cycle of an action group is:
32  * <ul>
33  * <li>the <code>initialize(ISynchronizePageConfiguration}</code> method is
34  * invoked before the methods to populate menus. This is done to give clients
35  * a change to create and initialize the actions of the action group.
36  * <li>The <code>fillActionBars(IActionBars)</code> method is invoked
37  * to populate the page's action bars (view menu and toolbar). It is
38  * possible for the action bars to be missing one or more components
39  * so clients are expected to check for <code>null</code> when accessing
40  * the menus from the action bars.
41  * <li>The <code>fillContextMenu(IMenuManager)</code> method is invoked each time
42  * the context menu is shown. Before this method is called, the
43  * action group will be provided with an <code>ActionContext</code>
44  * containing the view selection. Clients can access the context using
45  * <code>getContext()</code>.
46  * <li>The <code>updateActionBars()</code> method is invoked whenever the
47  * page's selection changes. Before this method is called, the
48  * action group will be provided with an <code>ActionContext</code>
49  * containing the view selection. Clients can access the context using
50  * <code>getContext()</code>.
51  * <li>The <code>modelChanged(ISynchronizeModelElement)</code> method is
52  * invoked whenever the model being displayed is changed. This gives clients
53  * a chance to adjust the input to actions that operate on all visible elements.
54  * <li>The <code>dispose()</code> method is called when the page is disposed.
55  * </ul>
56  * </p>
57  * @since 3.0
58  */

59 public abstract class SynchronizePageActionGroup extends ActionGroup {
60
61     private ISynchronizePageConfiguration configuration;
62     
63     private Map menuContributions = new HashMap();
64     
65     private VisibleRootsSelectionProvider visibleRootSelectionProvider;
66
67     /*
68      * A selection provider whose selection is the root elements visible in the
69      * page. Selection changed events are sent out when the model roots change
70      * or their visible children change
71      */

72     private class VisibleRootsSelectionProvider extends SynchronizePageActionGroup implements ISelectionProvider {
73
74         private ListenerList selectionChangedListeners = new ListenerList(ListenerList.IDENTITY);
75         private ISelection selection;
76
77         protected VisibleRootsSelectionProvider(ISynchronizeModelElement element) {
78             modelChanged(element);
79         }
80         
81         /* (non-Javadoc)
82          * @see org.eclipse.team.ui.synchronize.SynchronizePageActionGroup#modelChanged(org.eclipse.team.ui.synchronize.ISynchronizeModelElement)
83          */

84         public void modelChanged(ISynchronizeModelElement root) {
85             if (root == null) {
86                 setSelection(StructuredSelection.EMPTY);
87             } else {
88                 setSelection(new StructuredSelection(root));
89             }
90         }
91         
92         /* (non-Javadoc)
93          * Method declared on ISelectionProvider.
94          */

95         public void addSelectionChangedListener(ISelectionChangedListener listener) {
96             selectionChangedListeners.add(listener);
97         }
98         
99         /* (non-Javadoc)
100          * Method declared on ISelectionProvider.
101          */

102         public void removeSelectionChangedListener(ISelectionChangedListener listener) {
103             selectionChangedListeners.remove(listener);
104         }
105         
106         /* (non-Javadoc)
107          * Method declared on ISelectionProvider.
108          */

109         public ISelection getSelection() {
110             return selection;
111         }
112         
113         /* (non-Javadoc)
114          * Method declared on ISelectionProvider.
115          */

116         public void setSelection(ISelection selection) {
117             this.selection = selection;
118             selectionChanged(new SelectionChangedEvent(this, getSelection()));
119         }
120         
121         private void selectionChanged(final SelectionChangedEvent event) {
122             // pass on the notification to listeners
123
Object JavaDoc[] listeners = selectionChangedListeners.getListeners();
124             for (int i = 0; i < listeners.length; ++i) {
125                 final ISelectionChangedListener l = (ISelectionChangedListener)listeners[i];
126                 SafeRunner.run(new SafeRunnable() {
127                     public void run() {
128                         l.selectionChanged(event);
129                     }
130                 });
131             }
132         }
133     }
134     
135     /**
136      * Initialize the actions of this contribution. This method will be invoked
137      * once before any calls are made to <code>filleContextMenu</code> or
138      * <code>setActionBars</code> but after the control for the page has been
139      * created. As a result of this, the site of the configuration can be
140      * accessed. Subclasses may override this method but must invoke the
141      * overridden method.
142      *
143      * @param configuration the configuration for the part to which the
144      * contribution is associated
145      */

146     public void initialize(ISynchronizePageConfiguration configuration) {
147         this.configuration = configuration;
148         if (visibleRootSelectionProvider != null) {
149             configuration.addActionContribution(visibleRootSelectionProvider);
150         }
151     }
152     
153     /**
154      * This method is invoked whenever the model being displayed in the view
155      * changes. This includes when the input to the view changes and when the
156      * children of the input change. The default implementation of this method
157      * does nothing. Subclasses may override.
158      *
159      * @param root the root of the model being viewed
160      */

161     public void modelChanged(ISynchronizeModelElement root) {
162         // Do nothing by default
163
}
164     
165     /**
166      * Dispose of the action group. Subclasses may override but must
167      * invoke the overridden method.
168      */

169     public void dispose() {
170         super.dispose();
171         if (configuration != null) {
172             configuration.removeActionContribution(this);
173         }
174     }
175
176     /**
177      * Helper method to find the group of the given id for the page associated
178      * with the configuration of this action group. The id of the returned group
179      * will not match that of the provided id since the group must be modified
180      * to ensure that groups are unique across pages.
181      *
182      * @param menu the menu
183      * @param groupId the id of the group being searched for
184      * @return the group for the given id or <code>null</code>
185      */

186     protected IContributionItem findGroup(IContributionManager menu, String JavaDoc groupId) {
187         if(menu == null) return null;
188         IContributionItem item = menu.find(((SynchronizePageConfiguration)configuration).getGroupId(groupId));
189         if (item == null) {
190             // Context menus do not change the id
191
item = menu.find(groupId);
192         }
193         return item;
194     }
195     
196     /**
197      * Helper method to add an action to a group in a menu. The action is only
198      * added to the menu if the group exists in the menu. Calling this method
199      * also has no effect if either the menu or action are <code>null</code>.
200      *
201      * @param manager the menu manager
202      * @param groupId the group to append the action to
203      * @param action the action to add
204      * @return <code>true</code> if the group exists and the action was added
205      * and <code>false</code> if the action was not added
206      */

207     protected boolean appendToGroup(IContributionManager manager, String JavaDoc groupId, IAction action) {
208         if (internalAppendToGroup(manager, groupId, action)) {
209             registerActionWithWorkbench(action);
210             return true;
211         }
212         return false;
213     }
214     
215     private boolean internalAppendToGroup(IContributionManager manager, String JavaDoc groupId, IAction action) {
216         if (manager == null || action == null) return false;
217         IContributionItem group = findGroup(manager, groupId);
218         if (group != null) {
219             manager.appendToGroup(group.getId(), action);
220             return true;
221         }
222         return false;
223     }
224     
225     /**
226      * Helper method to add a contribution item to a group in a menu. The item
227      * is only added to the menu if the group exists in the menu. Calling this
228      * method also has no effect if either the menu or item are
229      * <code>null</code>.
230      *
231      * @param manager the menu manager
232      * @param groupId the group to append the action to
233      * @param item the item to add
234      * @return <code>true</code> if the group exists and the action was added
235      * and <code>false</code> if the action was not added
236      */

237     protected boolean appendToGroup(IContributionManager manager, String JavaDoc groupId, IContributionItem item) {
238         if (manager == null || item == null) return false;
239         IContributionItem group = findGroup(manager, groupId);
240         if (group != null) {
241             manager.appendToGroup(group.getId(), item);
242             return true;
243         }
244         return false;
245     }
246     
247     /**
248      * Helper method that can be invoked during initialization to add an action
249      * to a particular menu (one of P_TOOLBAR_MENU, P_VIEW_MENU, P_CONTEXT_MENU
250      * from ISynchronizePageConfiguration). The action is added to the given
251      * group if it is present. Otherwise the action is not added to the menu.
252      *
253      * @param menuId the menu id (one of P_TOOLBAR_MENU, P_VIEW_MENU,
254      * P_CONTEXT_MENU from ISynchronizePageConfiguration)
255      * @param groupId the group id in the menu to which the action is to be
256      * added
257      * @param action the action to be added
258      */

259     protected void appendToGroup(String JavaDoc menuId, String JavaDoc groupId, IAction action) {
260         registerActionWithWorkbench(action);
261         internalAppendToGroup(menuId, groupId, action);
262     }
263     
264     /**
265      * Register this action with the workbench so that it can participate in keybindings and
266      * retargetable actions.
267      *
268      * @param action the action to register
269      */

270     private void registerActionWithWorkbench(IAction action) {
271         ISynchronizePageSite site = configuration.getSite();
272         String JavaDoc id = action.getId();
273         if (id != null) {
274             site.getActionBars().setGlobalActionHandler(id, action);
275             IKeyBindingService keyBindingService = site.getKeyBindingService();
276             if(keyBindingService != null)
277                 keyBindingService.registerAction(action);
278         }
279     }
280
281     /**
282      * Helper method that can be invoked during initialization to add an item to
283      * a particular menu (one of P_TOOLBAR_MENU, P_VIEW_MENU, P_CONTEXT_MENU
284      * from ISynchronizePageConfiguration). The item is added to the given group
285      * if it is present. Otherwise the item is not added to the menu.
286      *
287      * @param menuId the menu id (one of P_TOOLBAR_MENU, P_VIEW_MENU,
288      * P_CONTEXT_MENU from ISynchronizePageConfiguration)
289      * @param groupId the group id in the menu to which the item is to be added
290      * @param item the item to be added
291      */

292     protected void appendToGroup(String JavaDoc menuId, String JavaDoc groupId, IContributionItem item) {
293         internalAppendToGroup(menuId, groupId, item);
294     }
295     
296     /**
297      * Return a selection provider whose selection includes all roots of the
298      * elements visible in the page. Selection change events are fired when the
299      * elements visible in the view change.
300      *
301      * @return a selection provider whose selection is the roots of all
302      * elements visible in the page
303      */

304     protected ISelectionProvider getVisibleRootsSelectionProvider() {
305         if (visibleRootSelectionProvider == null) {
306             ISynchronizeModelElement root = null;
307             if (configuration != null) {
308                 root = (ISynchronizeModelElement)configuration.getProperty(SynchronizePageConfiguration.P_MODEL);
309             }
310             visibleRootSelectionProvider = new VisibleRootsSelectionProvider(root);
311             if (configuration != null) {
312                 configuration.addActionContribution(visibleRootSelectionProvider);
313             }
314         }
315         return visibleRootSelectionProvider;
316     }
317     
318     /* (non-Javadoc)
319      * @see org.eclipse.ui.actions.ActionGroup#fillContextMenu(org.eclipse.jface.action.IMenuManager)
320      */

321     public void fillContextMenu(IMenuManager menu) {
322         super.fillContextMenu(menu);
323         fillMenu(menu, ISynchronizePageConfiguration.P_CONTEXT_MENU);
324     }
325     
326     /* (non-Javadoc)
327      * @see org.eclipse.ui.actions.ActionGroup#fillActionBars(org.eclipse.ui.IActionBars)
328      */

329     public void fillActionBars(IActionBars actionBars) {
330         super.fillActionBars(actionBars);
331         if (actionBars != null) {
332             fillMenu(actionBars.getMenuManager(), ISynchronizePageConfiguration.P_VIEW_MENU);
333             fillMenu(actionBars.getToolBarManager(), ISynchronizePageConfiguration.P_TOOLBAR_MENU);
334         }
335     }
336     
337     private void fillMenu(IContributionManager menu, String JavaDoc menuId) {
338         Map groups = (Map)menuContributions.get(menuId);
339         if (menu != null && groups != null) {
340             for (Iterator iter = groups.keySet().iterator(); iter.hasNext(); ) {
341                 String JavaDoc groupId = (String JavaDoc) iter.next();
342                 List actions = (List)groups.get(groupId);
343                 if (actions != null) {
344                     for (Iterator iter2 = actions.iterator(); iter2.hasNext();) {
345                         Object JavaDoc element = iter2.next();
346                         if (element instanceof IAction) {
347                             // Call the internal method to avoid registering the action
348
// as a global handler since it would have been registered
349
// when the action was added to the menuContributions
350
internalAppendToGroup(menu, groupId, (IAction)element);
351                         } else if (element instanceof IContributionItem) {
352                             appendToGroup(menu, groupId, (IContributionItem)element);
353                         }
354                     }
355                 }
356             }
357         }
358     }
359
360     private void internalAppendToGroup(String JavaDoc menuId, String JavaDoc groupId, Object JavaDoc action) {
361         Map groups = (Map)menuContributions.get(menuId);
362         if (groups == null) {
363             groups = new HashMap();
364             menuContributions.put(menuId, groups);
365         }
366         List actions = (List)groups.get(groupId);
367         if (actions == null) {
368             actions = new ArrayList();
369             groups.put(groupId, actions);
370         }
371         actions.add(action);
372     }
373     
374     /**
375      * Return the configuration for the page to which the action group
376      * is associated.
377      * @return the configuration for the page to which the action group
378      * is associated
379      *
380      * @since 3.1
381      */

382     public ISynchronizePageConfiguration getConfiguration() {
383         return configuration;
384     }
385 }
386
Popular Tags