KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > team > internal > ui > synchronize > StructuredViewerAdvisor


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 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.internal.ui.synchronize;
12
13 import org.eclipse.core.resources.IResource;
14 import org.eclipse.jface.action.*;
15 import org.eclipse.jface.util.IPropertyChangeListener;
16 import org.eclipse.jface.util.PropertyChangeEvent;
17 import org.eclipse.jface.viewers.*;
18 import org.eclipse.swt.events.*;
19 import org.eclipse.swt.widgets.Menu;
20 import org.eclipse.team.core.synchronize.SyncInfoSet;
21 import org.eclipse.team.internal.ui.IPreferenceIds;
22 import org.eclipse.team.internal.ui.TeamUIPlugin;
23 import org.eclipse.team.internal.ui.mapping.DiffTreeStatusLineContributionGroup;
24 import org.eclipse.team.ui.synchronize.*;
25 import org.eclipse.ui.*;
26 import org.eclipse.ui.actions.ActionContext;
27 import org.eclipse.ui.actions.ActionGroup;
28
29 /**
30  * A <code>StructuredViewerAdvisor</code> controls various UI
31  * aspects of viewers that show {@link SyncInfoSet} like the context menu, toolbar,
32  * content provider, label provider, navigation, and model provider. The
33  * advisor allows decoupling viewer behavior from the viewers presentation. This
34  * allows viewers that aren't in the same class hierarchy to re-use basic
35  * behavior.
36  * <p>
37  * This advisor allows viewer contributions made in a plug-in manifest to
38  * be scoped to a particular unique id. As a result the context menu for the
39  * viewer can be configured to show object contributions for random id schemes.
40  * To enable declarative action contributions for a configuration there are two
41  * steps required:
42  * <ul>
43  * <li>Create a viewer contribution with a <code>targetID</code> that groups
44  * sets of actions that are related. A common pratice for synchronize view
45  * configurations is to use the participant id as the targetID.
46  *
47  * <pre>
48  * &lt;viewerContribution
49  * id=&quot;org.eclipse.team.ccvs.ui.CVSCompareSubscriberContributions&quot;
50  * targetID=&quot;org.eclipse.team.cvs.ui.compare-participant&quot;&gt;
51  * ...
52  * </pre>
53  *
54  * <li>Create a configuration instance with a <code>menuID</code> that
55  * matches the targetID in the viewer contribution.
56  * </ul>
57  * </p><p>
58  * Clients may subclass to add behavior for concrete structured viewers.
59  * </p>
60  *
61  * @see TreeViewerAdvisor
62  * @since 3.0
63  */

64 public abstract class StructuredViewerAdvisor extends AbstractViewerAdvisor {
65     
66     // Property change listener which responds to:
67
// - working set selection by the user
68
// - decorator format change selected by the user
69
private IPropertyChangeListener propertyListener = new IPropertyChangeListener() {
70         public void propertyChange(PropertyChangeEvent event) {
71             // Change to showing of sync state in text labels preference
72
if(event.getProperty().equals(IPreferenceIds.SYNCVIEW_VIEW_SYNCINFO_IN_LABEL)) {
73                 StructuredViewer viewer = getViewer();
74                 if(viewer != null && !viewer.getControl().isDisposed()) {
75                     viewer.refresh(true /* update labels */);
76                 }
77             }
78         }
79     };
80     private DiffTreeStatusLineContributionGroup statusLine;
81
82     /**
83      * Create an advisor that will allow viewer contributions with the given <code>targetID</code>. This
84      * advisor will provide a presentation model based on the given sync info set. The model is disposed
85      * when the viewer is disposed.
86      *
87      * @param configuration
88      */

89     public StructuredViewerAdvisor(ISynchronizePageConfiguration configuration) {
90         super(configuration);
91     }
92     
93     /**
94      * Install a viewer to be configured with this advisor. An advisor can only be installed with
95      * one viewer at a time. When this method completes the viewer is considered initialized and
96      * can be shown to the user.
97      * @param viewer the viewer being installed
98      */

99     public void initializeViewer(final StructuredViewer viewer) {
100         super.initializeViewer(viewer);
101         initializeListeners(viewer);
102         hookContextMenu(viewer);
103     }
104     
105     /**
106      * Must be called when an advisor is no longer needed.
107      */

108     public void dispose() {
109         if (getActionGroup() != null) {
110             getActionGroup().dispose();
111         }
112         if (statusLine != null)
113             statusLine.dispose();
114         TeamUIPlugin.getPlugin().getPreferenceStore().removePropertyChangeListener(propertyListener);
115     }
116     
117     /**
118      * Method invoked from <code>initializeViewer(Composite, StructuredViewer)</code>
119      * in order to initialize any listeners for the viewer.
120      *
121      * @param viewer the viewer being initialize
122      */

123     protected void initializeListeners(final StructuredViewer viewer) {
124         viewer.getControl().addDisposeListener(new DisposeListener() {
125             public void widgetDisposed(DisposeEvent e) {
126                 StructuredViewerAdvisor.this.dispose();
127             }
128         });
129         viewer.addOpenListener(new IOpenListener() {
130             public void open(OpenEvent event) {
131                 handleOpen();
132             }
133         });
134         viewer.addDoubleClickListener(new IDoubleClickListener() {
135             public void doubleClick(DoubleClickEvent event) {
136                 handleDoubleClick(viewer, event);
137             }
138         });
139         viewer.addSelectionChangedListener(new ISelectionChangedListener() {
140             public void selectionChanged(SelectionChangedEvent event) {
141                 // Update the action bars enablement for any contributed action groups
142
updateActionBars((IStructuredSelection)viewer.getSelection());
143             }
144         });
145         TeamUIPlugin.getPlugin().getPreferenceStore().addPropertyChangeListener(propertyListener);
146     }
147     
148     /**
149      * Handles a double-click event. If <code>false</code> is returned,
150      * subclasses may handle the double click.
151      */

152     protected boolean handleDoubleClick(StructuredViewer viewer, DoubleClickEvent event) {
153         IStructuredSelection selection = (IStructuredSelection) event.getSelection();
154         Object JavaDoc node = selection.getFirstElement();
155         if (node != null && node instanceof SyncInfoModelElement) {
156             SyncInfoModelElement syncNode = (SyncInfoModelElement) node;
157             IResource resource = syncNode.getResource();
158             if (syncNode != null && resource != null && resource.getType() == IResource.FILE) {
159                 // The open is handled by the open strategy but say we handled
160
// it so that overriding methods will not do anything
161
return true;
162             }
163         }
164         return false;
165     }
166     
167     private void handleOpen() {
168         Object JavaDoc o = getConfiguration().getProperty(SynchronizePageConfiguration.P_OPEN_ACTION);
169         if (o instanceof IAction) {
170             IAction action = (IAction)o;
171             action.run();
172         }
173     }
174     
175     /**
176      * Method invoked from the synchronize page when the action
177      * bars are set. The advisor uses the configuration to determine
178      * which groups appear in the action bar menus and allows all
179      * action groups registered with the configuration to fill the action bars.
180      * @param actionBars the Action bars for the page
181      */

182     public final void setActionBars(IActionBars actionBars) {
183         if(actionBars != null) {
184             IToolBarManager manager = actionBars.getToolBarManager();
185             
186             // Populate the toobar menu with the configured groups
187
Object JavaDoc o = getConfiguration().getProperty(ISynchronizePageConfiguration.P_TOOLBAR_MENU);
188             if (!(o instanceof String JavaDoc[])) {
189                 o = ISynchronizePageConfiguration.DEFAULT_TOOLBAR_MENU;
190             }
191             String JavaDoc[] groups = (String JavaDoc[])o;
192             for (int i = 0; i < groups.length; i++) {
193                 String JavaDoc group = groups[i];
194                 // The groupIds must be converted to be unique since the toolbar is shared
195
manager.add(new Separator(getGroupId(group)));
196             }
197
198             // view menu
199
IMenuManager menu = actionBars.getMenuManager();
200             if (menu != null) {
201                 // Populate the view dropdown menu with the configured groups
202
o = getConfiguration().getProperty(ISynchronizePageConfiguration.P_VIEW_MENU);
203                 if (!(o instanceof String JavaDoc[])) {
204                     o = ISynchronizePageConfiguration.DEFAULT_VIEW_MENU;
205                 }
206                 groups = (String JavaDoc[]) o;
207                 initializeStatusLine(actionBars);
208                 for (int i = 0; i < groups.length; i++) {
209                     String JavaDoc group = groups[i];
210                     // The groupIds must be converted to be unique since the
211
// view menu is shared
212
menu.add(new Separator(getGroupId(group)));
213                 }
214             }
215             
216             fillActionBars(actionBars);
217         }
218     }
219     
220     /**
221      * Initialize the status line
222      * @param actionBars the action bars
223      */

224     protected void initializeStatusLine(IActionBars actionBars) {
225         statusLine = new DiffTreeStatusLineContributionGroup(
226                 getConfiguration().getSite().getShell(),
227                 getConfiguration());
228         IStatusLineManager statusLineMgr = actionBars.getStatusLineManager();
229         if (statusLineMgr != null && statusLine != null) {
230             statusLine.fillActionBars(actionBars);
231         }
232     }
233
234     /*
235      * Method invoked from <code>initializeViewer(StructuredViewer)</code>
236      * in order to configure the viewer to call <code>fillContextMenu(StructuredViewer, IMenuManager)</code>
237      * when a context menu is being displayed in viewer.
238      *
239      * @param viewer the viewer being initialized
240      * @see fillContextMenu(StructuredViewer, IMenuManager)
241      */

242     private void hookContextMenu(final StructuredViewer viewer) {
243         String JavaDoc targetID = getContextMenuId(viewer);
244         final MenuManager menuMgr = createContextMenuManager(targetID);
245         
246         menuMgr.setRemoveAllWhenShown(true);
247         menuMgr.addMenuListener(new IMenuListener() {
248             public void menuAboutToShow(IMenuManager manager) {
249                 fillContextMenu(viewer, manager);
250             }
251         });
252         Menu menu = menuMgr.createContextMenu(viewer.getControl());
253         menu.addMenuListener(new MenuListener() {
254     
255             public void menuHidden(MenuEvent e) {
256             }
257     
258             // Hack to allow action contributions to update their
259
// state before the menu is shown. This is required when
260
// the state of the selection changes and the contributions
261
// need to update enablement based on this.
262
// TODO: Is this hack still needed
263
public void menuShown(MenuEvent e) {
264                 IContributionItem[] items = menuMgr.getItems();
265                 for (int i = 0; i < items.length; i++) {
266                     IContributionItem item = items[i];
267                     if (item instanceof ActionContributionItem) {
268                         IAction actionItem = ((ActionContributionItem) item).getAction();
269                         if (actionItem instanceof SynchronizeModelAction) {
270                             ((SynchronizeModelAction) actionItem).selectionChanged(viewer.getSelection());
271                         }
272                     }
273                 }
274             }
275         });
276         viewer.getControl().setMenu(menu);
277         registerContextMenu(viewer, menuMgr);
278     }
279
280     /**
281      * Create the menu manager to be used to manage the context
282      * menu of the viewer.
283      * @param targetID the context menu id
284      * @return the menu manager to be used to manage the context
285      * menu of the viewer
286      */

287     protected MenuManager createContextMenuManager(String JavaDoc targetID) {
288         return new MenuManager(targetID);
289     }
290
291     /**
292      * Register the context menu with the platform if apropriate.
293      * @param viewer the viewer
294      * @param menuMgr the context menu manager
295      */

296     protected void registerContextMenu(final StructuredViewer viewer, MenuManager menuMgr) {
297         String JavaDoc targetID = getContextMenuId(viewer);
298         if (targetID != null) {
299             IWorkbenchSite workbenchSite = getConfiguration().getSite().getWorkbenchSite();
300             IWorkbenchPartSite ws = null;
301             if (workbenchSite instanceof IWorkbenchPartSite)
302                 ws = (IWorkbenchPartSite)workbenchSite;
303             if (ws != null) {
304                 ws.registerContextMenu(targetID, menuMgr, viewer);
305             }
306         }
307     }
308
309     /**
310      * Return the context menu id.
311      * @param viewer the viewer
312      * @return the context menu id
313      */

314     protected String JavaDoc getContextMenuId(StructuredViewer viewer) {
315         String JavaDoc targetID;
316         Object JavaDoc o = getConfiguration().getProperty(ISynchronizePageConfiguration.P_OBJECT_CONTRIBUTION_ID);
317         if (o instanceof String JavaDoc) {
318             targetID = (String JavaDoc)o;
319         } else {
320             targetID = null;
321         }
322         return targetID;
323     }
324     
325     /**
326      * Callback that is invoked when a context menu is about to be shown in the
327      * viewer. Subsclasses must implement to contribute menus. Also, menus can
328      * contributed by creating a viewer contribution with a <code>targetID</code>
329      * that groups sets of actions that are related.
330      *
331      * @param viewer the viewer in which the context menu is being shown.
332      * @param manager the menu manager to which actions can be added.
333      */

334     protected void fillContextMenu(StructuredViewer viewer, final IMenuManager manager) {
335         addContextMenuGroups(manager);
336         getActionGroup().setContext(new ActionContext(viewer.getSelection()));
337         getActionGroup().fillContextMenu(manager);
338     }
339
340     /**
341      * Add the context menu groups to the context menu.
342      * @param manager the menu manager
343      */

344     protected void addContextMenuGroups(final IMenuManager manager) {
345         // Populate the menu with the configured groups
346
Object JavaDoc o = getConfiguration().getProperty(ISynchronizePageConfiguration.P_CONTEXT_MENU);
347         if (!(o instanceof String JavaDoc[])) {
348             o = ISynchronizePageConfiguration.DEFAULT_CONTEXT_MENU;
349         }
350         String JavaDoc[] groups = (String JavaDoc[])o;
351         for (int i = 0; i < groups.length; i++) {
352             String JavaDoc group = groups[i];
353             // There is no need to adjust the group ids in a contetx menu (see setActionBars)
354
manager.add(new Separator(group));
355         }
356     }
357     
358     /**
359      * Invoked once when the action bars are set.
360      * @param actionBars the action bars
361      */

362     protected void fillActionBars(IActionBars actionBars) {
363         getActionGroup().fillActionBars(actionBars);
364         updateActionBars((IStructuredSelection) getViewer().getSelection());
365         Object JavaDoc input = getViewer().getInput();
366         if (input instanceof ISynchronizeModelElement) {
367             getActionGroup().modelChanged((ISynchronizeModelElement) input);
368         }
369     }
370     
371     /**
372      * Invoked each time the selection in the view changes in order
373      * to update the ction bars.
374      * @param selection the selection from the viewer
375      */

376     protected void updateActionBars(IStructuredSelection selection) {
377         ActionGroup group = getActionGroup();
378         if (group != null) {
379             group.setContext(new ActionContext(selection));
380             group.updateActionBars();
381         }
382     }
383     
384     protected SynchronizePageActionGroup getActionGroup() {
385         return (SynchronizePageActionGroup)getConfiguration();
386     }
387     
388     private String JavaDoc getGroupId(String JavaDoc group) {
389         return ((SynchronizePageConfiguration)getConfiguration()).getGroupId(group);
390     }
391 }
392
Popular Tags