KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > internal > menus > TrimBarManager2


1 /*******************************************************************************
2  * Copyright (c) 2006, 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.menus;
13
14 import java.util.ArrayList JavaDoc;
15 import java.util.HashMap JavaDoc;
16 import java.util.Iterator JavaDoc;
17 import java.util.List JavaDoc;
18 import java.util.Map JavaDoc;
19
20 import org.eclipse.core.runtime.CoreException;
21 import org.eclipse.core.runtime.IConfigurationElement;
22 import org.eclipse.core.runtime.IStatus;
23 import org.eclipse.jface.menus.IWidget;
24 import org.eclipse.swt.SWT;
25 import org.eclipse.swt.layout.RowLayout;
26 import org.eclipse.swt.widgets.Composite;
27 import org.eclipse.ui.internal.WindowTrimProxy;
28 import org.eclipse.ui.internal.WorkbenchWindow;
29 import org.eclipse.ui.internal.layout.IWindowTrim;
30 import org.eclipse.ui.internal.layout.TrimLayout;
31 import org.eclipse.ui.internal.misc.StatusUtil;
32 import org.eclipse.ui.menus.AbstractWorkbenchTrimWidget;
33 import org.eclipse.ui.menus.IMenuService;
34 import org.eclipse.ui.menus.IWorkbenchWidget;
35 import org.eclipse.ui.statushandlers.StatusManager;
36
37 /**
38  * <p>
39  * An implementation that supports 'trim' elements defined in using the
40  * <code>org.eclipse.ui.menus</code> extension point.
41  * </p>
42  * <p>
43  * This class is not intended to be used outside of the
44  * <code>org.eclipse.ui.workbench</code> plug-in.
45  * </p>
46  *
47  * @since 3.2
48  */

49 public class TrimBarManager2 {
50
51     /**
52      * A List of the URI's representing the trim areas
53      */

54     private MenuLocationURI[] trimAreaURIs = {
55             new MenuLocationURI("toolbar:command1"), //$NON-NLS-1$
56
new MenuLocationURI("toolbar:command2"), //$NON-NLS-1$
57
new MenuLocationURI("toolbar:vertical1"), //$NON-NLS-1$
58
new MenuLocationURI("toolbar:vertical2"), //$NON-NLS-1$
59
new MenuLocationURI("toolbar:status"), //$NON-NLS-1$
60
};
61
62     /**
63      * The SWT 'side' corresponding to a URI
64      */

65     int[] swtSides = { SWT.TOP, SWT.TOP, SWT.LEFT, SWT.RIGHT, SWT.BOTTOM };
66     /**
67      * The window on which this menu manager exists; never <code>null</code>.
68      */

69     private STrimBuilder fTrimBuilder;
70
71     private WorkbenchMenuService fMenuService;
72
73     private boolean fDirty;
74
75     /**
76      * Constructs a new instance of <code>TrimBarManager</code>.
77      *
78      * @param window
79      * The window on which this menu manager exists; must not be
80      * <code>null</code>.
81      */

82     public TrimBarManager2(final WorkbenchWindow window) {
83         if (window == null) {
84             throw new IllegalArgumentException JavaDoc("The window cannot be null"); //$NON-NLS-1$
85
}
86
87         // Remember the parameters
88
fMenuService = (WorkbenchMenuService) window.getWorkbench().getService(
89                 IMenuService.class);
90         fTrimBuilder = new STrimBuilder(window);
91
92         // New layouts are always 'dirty'
93
fDirty = true;
94     }
95
96     /**
97      * Hacked version of the update method that allows the hiding of any trim
98      * sited at SWT.TOP. This is because the Intro management wants there to be
99      * no trim at the top but can only currently indicate this by using the
100      * CoolBar's visibility...
101      *
102      * @param force
103      * @param recursive
104      * @param hideTopTrim
105      */

106     public void update(boolean force, boolean recursive, boolean hideTopTrim) {
107         if (force || isDirty()) {
108             // Re-render the trim based on the new layout
109
fTrimBuilder.build(hideTopTrim);
110             setDirty(false);
111         }
112     }
113
114     /**
115      * Copied from the <code>MenuManager</code> method...
116      *
117      * @param force
118      * If true then do the update even if not 'dirty'
119      * @param recursive
120      * Update recursively
121      *
122      * @see org.eclipse.jface.action.MenuManager#update(boolean, boolean)
123      */

124     public void update(boolean force, boolean recursive) {
125         update(force, recursive, false);
126     }
127
128     /**
129      * Set the dirty state of the layout
130      *
131      * @param isDirty
132      */

133     private void setDirty(boolean isDirty) {
134         fDirty = isDirty;
135     }
136
137     /**
138      * Returns the 'dirty' state of the layout
139      *
140      * @return Always returns 'true' for now
141      */

142     private boolean isDirty() {
143         return fDirty;
144     }
145
146     /**
147      * This is a convenience class that maintains the list of the widgets in the
148      * group. This allows any position / orientation changes to the group to be
149      * passed on to all the widgets for that group.
150      *
151      * @since 3.2
152      *
153      */

154     private class TrimWidgetProxy extends WindowTrimProxy {
155
156         private List JavaDoc widgets;
157         private TrimAdditionCacheEntry cacheEntry;
158         private int originalSide;
159         private int curSide;
160
161         private Composite parent;
162
163         /**
164          * Constructor that takes in any information necessary to implement an
165          * IWindowTrim and also has enough state to manage a group with multiple
166          * IWidget contributions.
167          *
168          */

169         public TrimWidgetProxy(List JavaDoc widgets, int side, Composite parent,
170                 TrimAdditionCacheEntry entry, boolean resizeable) {
171             super(parent, entry.getId(), entry.getId(), SWT.TOP | SWT.BOTTOM | SWT.LEFT
172                     | SWT.RIGHT, resizeable);
173
174             // Remember our widget structure
175
this.widgets = widgets;
176             this.curSide = side;
177             this.originalSide = side;
178             this.parent = parent;
179             this.cacheEntry = entry;
180         }
181
182         /*
183          * (non-Javadoc)
184          *
185          * @see org.eclipse.ui.internal.WindowTrimProxy#dock(int)
186          */

187         public void dock(int newSide) {
188             // out with the old...
189
for (Iterator JavaDoc iter = widgets.iterator(); iter.hasNext();) {
190                 IWidget widget = (IWidget) iter.next();
191                 widget.dispose();
192                 
193                 cacheEntry.removeWidget(widget);
194             }
195
196             // ...in with the new
197
for (Iterator JavaDoc iter = widgets.iterator(); iter.hasNext();) {
198                 IWorkbenchWidget widget = (IWorkbenchWidget) iter.next();
199                 if (widget instanceof AbstractWorkbenchTrimWidget)
200                     ((AbstractWorkbenchTrimWidget)widget).fill(parent, curSide, newSide);
201                 else
202                     widget.fill(parent);
203             }
204
205             curSide = newSide;
206             parent.layout();
207         }
208
209         /**
210          * Disposes all the widgets contributed into this group and then
211          * disposes the group's 'proxy' control
212          */

213         public void dispose() {
214             for (Iterator JavaDoc iter = widgets.iterator(); iter.hasNext();) {
215                 IWidget widget = (IWidget) iter.next();
216                 widget.dispose();
217
218                 // Remove the IWidget from the entry's cache
219
cacheEntry.removeWidget(widget);
220             }
221
222             getControl().dispose();
223         }
224
225         /**
226          * @return The side that the trim was declared to be on
227          */

228         public int getSide() {
229             return originalSide;
230         }
231
232         /**
233          * @return Whether this addition is at the start or end of the
234          * containing trim area
235          */

236         public boolean isAtStart() {
237             //Delegate to the cache entry
238
return cacheEntry.isAtStart();
239         }
240     }
241
242     /**
243      * A convenience class that implements the 'rendering' code necessary to
244      * turn the contributions to the 'trim' bar into actual SWT controls.
245      *
246      * @since 3.2
247      *
248      */

249     private class STrimBuilder {
250         /**
251          * The WorkbenchWindow that this builder is for
252          */

253         private WorkbenchWindow fWindow;
254
255         /**
256          * The list of <code>WindowTrimProxy</code> elements currently
257          * rendered in the WorkbenchWindow. Used to support the update mechanism
258          * (specifically, it's needed to implement the <code>tearDown</code>
259          * method).
260          */

261         private List JavaDoc curGroups = new ArrayList JavaDoc();
262
263         /**
264          * Map to cache which trim has already been initialized
265          */

266         private Map JavaDoc initializedTrim = new HashMap JavaDoc();
267         
268         /**
269          * Construct a trim builder for the given WorkbenchWindow
270          *
271          * @param window
272          * The WorkbenchWindow to render the trim on
273          */

274         public STrimBuilder(WorkbenchWindow window) {
275             fWindow = window;
276         }
277
278         /**
279          * Remove any rendered trim. This method will always be directly
280          * followed by a call to the 'build' method to update the contents.
281          */

282         public void tearDown() {
283             // First, remove all trim
284
for (Iterator JavaDoc iter = curGroups.iterator(); iter.hasNext();) {
285                 TrimWidgetProxy proxy = (TrimWidgetProxy) iter.next();
286                 fWindow.getTrimManager().removeTrim(proxy);
287
288                 try {
289                     proxy.dispose();
290                 } catch (Throwable JavaDoc e) {
291                     IStatus status = null;
292                     if (e instanceof CoreException) {
293                         status = ((CoreException) e).getStatus();
294                     } else {
295                         status = StatusUtil
296                                 .newStatus(
297                                         IStatus.ERROR,
298                                         "Internal plug-in widget delegate error on dispose.", e); //$NON-NLS-1$
299
}
300                     StatusUtil
301                             .handleStatus(
302                                     status,
303                                     "widget delegate failed on dispose: id = " + proxy.getId(), StatusManager.LOG); //$NON-NLS-1$
304
}
305             }
306
307             // Clear out the old list
308
curGroups.clear();
309         }
310
311         /**
312          * Construct the trim based on the contributions.
313          *
314          * @param layout
315          * The new layout information
316          * @param hideTopTrim
317          * <code>true</code> iff we don't want to display trim
318          * contributed into the SWT.TOP area. This is because the
319          * 'Intro' View hides the CBanner (and so, presumably, also
320          * wants to not show any other trim at the top.
321          *
322          * @param window
323          * The widnow to 'render' the trim into
324          *
325          */

326         public void build(boolean hideTopTrim) {
327             tearDown();
328             
329             for (int i = 0; i < trimAreaURIs.length; i++) {
330                 processAdditions(trimAreaURIs[i], hideTopTrim);
331             }
332         }
333
334         /**
335          * @param menuLocationURI
336          * @param hideTopTrim
337          */

338         private void processAdditions(MenuLocationURI trimURI, boolean hideTopTrim) {
339             List JavaDoc additions = fMenuService.getAdditionsForURI(trimURI);
340             if (additions.size() == 0)
341                 return;
342             
343             int swtSide = getSide(trimURI);
344             
345             // Dont show trim on the top if it's 'hidden'
346
if (swtSide == SWT.TOP && hideTopTrim)
347                 return;
348
349             // Each trim addition represents a 'group' into which one or more
350
// widgets can be placed...
351
for (Iterator JavaDoc iterator = additions.iterator(); iterator.hasNext();) {
352                 TrimAdditionCacheEntry trimEntry = (TrimAdditionCacheEntry) iterator.next();
353                 String JavaDoc groupId = trimEntry.getId();
354                 
355                 // Get the list of IConfgurationElements representing
356
// widgets in this group
357
List JavaDoc widgets = trimEntry.getWidgets();
358                 if (widgets.size() == 0)
359                     continue;
360                 
361                 // Create a 'container' composite for the group
362
Composite grpComposite = new Composite(fWindow.getShell(), SWT.NONE);
363                 grpComposite.setToolTipText(groupId);
364                 
365                 // Create the layout for the 'group' container...-no- border margins
366
RowLayout rl = new RowLayout();
367                 rl.marginBottom = rl.marginHeight = rl.marginLeft = rl.marginRight = rl.marginTop = rl.marginWidth = 0;
368                 grpComposite.setLayout(rl);
369                 
370                 // keep track of whether -any- of the widgets are resizeable
371
boolean resizeable = false;
372
373                 for (Iterator JavaDoc widgetIter = widgets.iterator(); widgetIter.hasNext();) {
374                     IWorkbenchWidget widget = (IWorkbenchWidget) widgetIter.next();
375                     IConfigurationElement widgetElement = trimEntry.getElement(widget);
376                     if (widget != null) {
377                         resizeable |= trimEntry.fillMajor(widgetElement);
378                         renderTrim(grpComposite, widget, swtSide);
379                     }
380                 }
381
382                 // Create the trim proxy for this group
383
TrimWidgetProxy groupTrimProxy = new TrimWidgetProxy(widgets,
384                         swtSide, grpComposite, trimEntry, resizeable);
385                 curGroups.add(groupTrimProxy);
386
387                 // 'Site' the group in its default location
388
placeGroup(groupTrimProxy);
389             }
390         }
391
392         private void placeGroup(final TrimWidgetProxy proxy) {
393             // Get the placement parameters
394
final int side = proxy.getSide();
395             boolean atStart = proxy.isAtStart();
396
397             // Place the trim before any other trim if it's
398
// at the 'start'; otherwise place it at the end
399
IWindowTrim beforeMe = null;
400             if (atStart) {
401                 List JavaDoc trim = fWindow.getTrimManager().getAreaTrim(side);
402                 if (trim.size() > 0)
403                     beforeMe = (IWindowTrim) trim.get(0);
404             }
405
406             // Add the group into trim...safely
407
try {
408                 proxy.dock(side); // ensure that the widgets are properly oriented
409
TrimLayout tl = (TrimLayout) fWindow.getShell().getLayout();
410                 tl.addTrim(side, proxy, beforeMe);
411             } catch (Throwable JavaDoc e) {
412                 IStatus status = null;
413                 if (e instanceof CoreException) {
414                     status = ((CoreException) e).getStatus();
415                 } else {
416                     status = StatusUtil
417                             .newStatus(
418                                     IStatus.ERROR,
419                                     "Internal plug-in widget delegate error on dock.", e); //$NON-NLS-1$
420
}
421                 StatusUtil.handleStatus(status, "widget delegate failed on dock: id = " + proxy.getId(), //$NON-NLS-1$
422
StatusManager.LOG);
423             }
424         }
425
426         /**
427          * Render a particular SWidget into a given group
428          *
429          * @param groupComposite
430          * The parent to create the widgets under
431          * @param widget
432          * The SWidget to render
433          * @param side
434          */

435         private void renderTrim(final Composite groupComposite, IWidget iw,
436                 final int side) {
437             // OK, fill the widget
438
if (iw != null) {
439                 // The -first- time trim is displayed we'll initialize it
440
if (iw instanceof IWorkbenchWidget && initializedTrim.get(iw) == null) {
441                     IWorkbenchWidget iww = (IWorkbenchWidget) iw;
442                     iww.init(fWindow);
443                     initializedTrim.put(iw, iw);
444                 }
445
446                 if (iw instanceof AbstractWorkbenchTrimWidget)
447                     ((AbstractWorkbenchTrimWidget)iw).fill(groupComposite, SWT.DEFAULT, side);
448                 else
449                     iw.fill(groupComposite);
450             }
451         }
452
453         private int getSide(MenuLocationURI uri) {
454             for (int i = 0; i < trimAreaURIs.length; i++) {
455                 if (trimAreaURIs[i].getRawString().equals(uri.getRawString()))
456                     return swtSides[i];
457             }
458             return SWT.BOTTOM;
459         }
460
461
462         /**
463          * Reposition any contributed trim whose id is -not- a 'knownId'. If the
464          * id is known then the trim has already been positioned from the stored
465          * workbench state. If it isn't then it's a new contribution whose
466          * default position may have been trashed by the WorkbenchWindow's
467          * 'restoreState' handling.
468          *
469          * @param knownIds
470          * A List of strings containing the ids of any trim that was
471          * explicitly positioned during the restore state.
472          */

473         public void updateLocations(List JavaDoc knownIds) {
474             for (Iterator JavaDoc iter = curGroups.iterator(); iter.hasNext();) {
475                 TrimWidgetProxy proxy = (TrimWidgetProxy) iter.next();
476                 if (!knownIds.contains(proxy.getId())) {
477                     placeGroup(proxy);
478                 }
479             }
480         }
481     }
482
483     /**
484      * Updates the placement of any contributed trim that is -not- in the
485      * 'knownIds' list (which indicates that it has already been placed using
486      * cached workspace data.
487      *
488      * Forward on to the bulder for implementation
489      */

490     public void updateLocations(List JavaDoc knownIds) {
491         fTrimBuilder.updateLocations(knownIds);
492     }
493     
494     /**
495      * unhook the menu service.
496      */

497     public void dispose() {
498         fMenuService = null;
499         fTrimBuilder = null;
500     }
501 }
502
503
Popular Tags