KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > internal > layout > TrimLayout


1 /*******************************************************************************
2  * Copyright (c) 2004, 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.internal.layout;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.Collections 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.jface.preference.IPreferenceStore;
21 import org.eclipse.jface.util.Geometry;
22 import org.eclipse.swt.SWT;
23 import org.eclipse.swt.custom.CBanner;
24 import org.eclipse.swt.events.DisposeEvent;
25 import org.eclipse.swt.events.DisposeListener;
26 import org.eclipse.swt.graphics.Point;
27 import org.eclipse.swt.graphics.Rectangle;
28 import org.eclipse.swt.widgets.Composite;
29 import org.eclipse.swt.widgets.Control;
30 import org.eclipse.swt.widgets.Layout;
31 import org.eclipse.ui.IWorkbenchPreferenceConstants;
32 import org.eclipse.ui.PlatformUI;
33 import org.eclipse.ui.internal.TrimDragPreferences;
34
35 /**
36  * Lays out the children of a Composite. One control occupies the center of the
37  * composite, and any number of controls may be attached to the top, bottom, and
38  * sides. This is a common layout for application windows, which typically have
39  * a central work area and a number of small widgets (toolbars, status lines,
40  * etc.) attached to the edge.
41  *
42  * <p>
43  * Unlike most other SWT layouts, this layout does not require layout data to be
44  * attached to each child control. Instead, member functions on the Layout are
45  * used to control the positioning of controls within the layout.
46  * </p>
47  *
48  * <p>
49  * The interface to this layout is intended to easily support drag-and-drop.
50  * Trim widgets can be added, removed, or inserted between other existing
51  * widgets and the layout will adjust accordingly. If one side of the layout
52  * contains no trim widgets, the central area will expand to reclaim the unused
53  * space.
54  * </p>
55  *
56  * <p>
57  * This layout must be told about every widget that it is supposed to arrange.
58  * If the composite contains additional widgets, they will not be moved by the
59  * layout and may be arranged through other means.
60  * </p>
61  *
62  * @since 3.0
63  */

64 public class TrimLayout extends Layout implements ICachingLayout, ITrimManager {
65
66     /**
67      * Trim area ID.
68      */

69     public static final Integer JavaDoc TOP_ID = new Integer JavaDoc(TOP);
70
71     /**
72      * Trim area ID.
73      */

74     public static final Integer JavaDoc BOTTOM_ID = new Integer JavaDoc(BOTTOM);
75
76     /**
77      * Trim area ID.
78      */

79     public static final Integer JavaDoc LEFT_ID = new Integer JavaDoc(LEFT);
80
81     /**
82      * Trim area ID.
83      */

84     public static final Integer JavaDoc RIGHT_ID = new Integer JavaDoc(RIGHT);
85
86     /**
87      * Trim area ID.
88      */

89     public static final Integer JavaDoc NONTRIM_ID = new Integer JavaDoc(NONTRIM);
90
91     /**
92      * IDs for the current trim areas we support.
93      */

94     private static final int[] TRIM_ID_INFO = { LEFT, RIGHT, TOP, BOTTOM };
95
96     private SizeCache centerArea = new SizeCache();
97
98     /**
99      * Map of TrimAreas by IDs.
100      */

101     private Map JavaDoc fTrimArea = new HashMap JavaDoc();
102
103     /**
104      * Map of TrimDescriptors by IDs.
105      */

106     private Map JavaDoc fTrimDescriptors = new HashMap JavaDoc();
107
108     private int marginWidth;
109
110     private int marginHeight;
111
112     private int topSpacing;
113
114     private int bottomSpacing;
115
116     private int leftSpacing;
117
118     private int rightSpacing;
119
120     private int spacing = 3;
121     
122     private boolean trimLocked;
123
124     private HashMap JavaDoc preferredLocationMap = new HashMap JavaDoc();
125
126     /**
127      * Creates a new (initially empty) trim layout.
128      */

129     public TrimLayout() {
130         // Determine whether or not the trim is 'locked'
131
final IPreferenceStore store = PlatformUI.getPreferenceStore();
132         trimLocked = store.getBoolean(IWorkbenchPreferenceConstants.LOCK_TRIM);
133         
134         createTrimArea(TOP_ID, TOP_ID.toString(), SWT.DEFAULT, SWT.TOP);
135         createTrimArea(BOTTOM_ID, BOTTOM_ID.toString(), SWT.DEFAULT, SWT.BOTTOM);
136         createTrimArea(LEFT_ID, LEFT_ID.toString(), SWT.DEFAULT, SWT.LEFT);
137         createTrimArea(RIGHT_ID, RIGHT_ID.toString(), SWT.DEFAULT, SWT.RIGHT);
138     }
139
140     private void createTrimArea(Integer JavaDoc id, String JavaDoc displayName, int trimSize,
141             int trimMods) {
142         TrimArea top = new TrimArea(id.intValue(), displayName);
143         top.setTrimSize(trimSize);
144         top.setControlModifiers(trimMods);
145         fTrimArea.put(id, top);
146     }
147
148     /**
149      * Sets the empty space surrounding the center area. This whitespace is
150      * located between the trim and the central widget.
151      *
152      * @param left
153      * pixel width
154      * @param right
155      * pixel width
156      * @param top
157      * pixel width
158      * @param bottom
159      * pixel width
160      */

161     public void setSpacing(int left, int right, int top, int bottom) {
162         leftSpacing = left;
163         rightSpacing = right;
164         topSpacing = top;
165         bottomSpacing = bottom;
166     }
167
168     /**
169      * Sets the empty space around the outside of the layout. This whitespace is
170      * located outside the trim widgets.
171      *
172      * @param marginWidth
173      * @param marginHeight
174      */

175     public void setMargins(int marginWidth, int marginHeight) {
176         this.marginWidth = marginWidth;
177         this.marginHeight = marginHeight;
178     }
179
180     /**
181      * Sets the trimSize (pixels) for the given side of the layout. If
182      * SWT.DEFAULT, then the trim size will be computed from child controls.
183      *
184      * @param areaId
185      * the area ID
186      * @param size
187      * in pixels
188      * @see #getAreaIds()
189      */

190     public void setTrimSize(int areaId, int size) {
191         TrimArea area = (TrimArea) fTrimArea.get(new Integer JavaDoc(areaId));
192         if (area != null) {
193             area.setTrimSize(size);
194         }
195     }
196
197     /**
198      * Returns the location of the given trim control. For example, returns
199      * SWT.LEFT if the control is docked on the left, SWT.RIGHT if docked on the
200      * right, etc. Returns SWT.DEFAULT if the given control is not a trim
201      * control.
202      *
203      * @param trimControl
204      * control to query
205      * @return The area ID of this control. If the control is not part of our
206      * trim, return SWT.DEFAULT.
207      * @see #getAreaIds()
208      */

209     public int getTrimAreaId(Control trimControl) {
210         TrimDescriptor desc = findTrimDescription(trimControl);
211         if (desc != null) {
212             return desc.getAreaId();
213         }
214         return SWT.DEFAULT;
215     }
216
217     /**
218      * @param control
219      * new window trim to be added
220      * @param areaId
221      * the area ID
222      * @see #getAreaIds()
223      * @deprecated
224      */

225     public void addTrim(IWindowTrim control, int areaId) {
226         addTrim(areaId, control, null);
227     }
228
229     /**
230      *
231      * @param trim
232      * new window trim to be added
233      * @param areaId
234      * the area ID
235      * @param beforeMe
236      * if null, the control will be inserted as the last trim widget
237      * on this side of the layout. Otherwise, the control will be
238      * inserted before the given widget.
239      * @see #getAreaIds()
240      * @deprecated
241      */

242     public void addTrim(IWindowTrim trim, int areaId, IWindowTrim beforeMe) {
243         addTrim(areaId, trim, beforeMe);
244     }
245
246     /*
247      * (non-Javadoc)
248      *
249      * @see org.eclipse.ui.internal.layout.ITrimManager#addTrim(int,
250      * org.eclipse.ui.internal.IWindowTrim)
251      */

252     public void addTrim(int areaId, IWindowTrim trim) {
253         // If we're adding trim to the same side that it's
254
// already on then don't change its order
255
IWindowTrim insertBefore = null;
256         List JavaDoc trimDescs = getAreaTrim(areaId);
257         for (Iterator JavaDoc trimIter = trimDescs.iterator(); trimIter.hasNext();) {
258             IWindowTrim curTrim = (IWindowTrim) trimIter.next();
259             if (curTrim.getId().equals(trim.getId())) {
260                 if (trimIter.hasNext()) {
261                     insertBefore = (IWindowTrim) trimIter.next();
262                 }
263             }
264         }
265         
266         addTrim(areaId, trim, insertBefore);
267     }
268
269     /*
270      * (non-Javadoc)
271      *
272      * @see org.eclipse.ui.internal.layout.ITrimManager#addTrim(int,
273      * org.eclipse.ui.internal.IWindowTrim,
274      * org.eclipse.ui.internal.IWindowTrim)
275      */

276     public void addTrim(int areaId, IWindowTrim trim, IWindowTrim beforeMe) {
277         TrimArea area = (TrimArea) fTrimArea.get(new Integer JavaDoc(areaId));
278         if (area == null) {
279             return;
280         }
281
282         // remove the trim from the current layout
283
removeTrim(trim);
284
285         // Create a new trim descriptor for the new area...
286
TrimDescriptor desc = new TrimDescriptor(trim, areaId);
287
288         // If the trim can be relocated then add a docking handle
289
boolean isAlreadyAHandle = trim instanceof TrimToolBarBase;
290         if (!trimLocked && trim.getValidSides() != SWT.NONE && !isAlreadyAHandle) {
291             // Create a 'docking' handle to allow dragging the trim
292
Composite dockingHandle = new TrimCommonUIHandle(this, trim, areaId);
293             desc.setDockingCache(new SizeCache(dockingHandle));
294         }
295
296         // Add the trim control
297
SizeCache cache = new SizeCache(trim.getControl());
298         trim.getControl().setLayoutData(trim);
299         desc.setCache(cache);
300         
301         // Add a dispose listener so we can clean up if the Client disposes the trim
302
trim.getControl().addDisposeListener(new DisposeListener() {
303             public void widgetDisposed(DisposeEvent e) {
304                 Control control = (Control) e.widget;
305                 if (control.getLayoutData() instanceof IWindowTrim) {
306                     IWindowTrim trim = (IWindowTrim) control.getLayoutData();
307                     removeTrim(trim);
308                     //forceLayout();
309
}
310             }
311         });
312
313         // Add the new descriptor to the map
314
fTrimDescriptors.put(desc.getId(), desc);
315
316         // insert before behaviour, revisited
317
if (beforeMe != null) {
318             TrimDescriptor beforeDesc = (TrimDescriptor) fTrimDescriptors
319                     .get(beforeMe.getId());
320             if (beforeDesc != null && beforeDesc.getAreaId() == areaId) {
321                 area.addTrim(desc, beforeDesc);
322             } else {
323                 area.addTrim(desc);
324             }
325         } else {
326             area.addTrim(desc);
327         }
328     }
329
330     /**
331      * Force a layout of the trim
332      */

333     public void forceLayout() {
334         removeDisposed();
335
336         // we hack this by calling the LayoutUtil with the
337
// first piece of trim that we find...(kludge!!)
338
Iterator JavaDoc d = fTrimDescriptors.values().iterator();
339         while (d.hasNext()) {
340             TrimDescriptor desc = (TrimDescriptor) d.next();
341             if (desc.getTrim().getControl() != null) {
342                 LayoutUtil.resize(desc.getTrim().getControl());
343                 return;
344             }
345         }
346     }
347
348     /*
349      * (non-Javadoc)
350      *
351      * @see org.eclipse.ui.internal.layout.ITrimManager#removeTrim(org.eclipse.ui.internal.IWindowTrim)
352      */

353     public void removeTrim(IWindowTrim toRemove) {
354         TrimDescriptor desc = (TrimDescriptor) fTrimDescriptors.remove(toRemove
355                 .getId());
356         if (desc == null) {
357             return;
358         }
359
360         TrimArea area = (TrimArea) fTrimArea.get(new Integer JavaDoc(desc.getAreaId()));
361         if (area != null) {
362             area.removeTrim(desc);
363             desc.getCache().getControl().setLayoutData(null);
364         }
365
366         // If we had a trim UI handle then dispose it
367
if (desc.getDockingCache() != null) {
368             Control ctrl = desc.getDockingCache().getControl();
369             
370             // KLUDGE!! we'll leak a handle rather than losing the
371
// mouse capture (for now...)
372
ctrl.setVisible(false);
373             //ctrl.dispose();
374
desc.setDockingCache(null);
375         }
376     }
377
378     /*
379      * (non-Javadoc)
380      *
381      * @see org.eclipse.ui.internal.layout.ITrimManager#getTrim(java.lang.String)
382      */

383     public IWindowTrim getTrim(String JavaDoc id) {
384         TrimDescriptor desc = (TrimDescriptor) fTrimDescriptors.get(id);
385         if (desc != null) {
386             return desc.getTrim();
387         }
388         return null;
389     }
390
391     /**
392      * Removes any disposed widgets from this layout. This is still experimental
393      * code.
394      */

395     private void removeDisposed() {
396         Iterator JavaDoc a = fTrimArea.values().iterator();
397         while (a.hasNext()) {
398             TrimArea area = (TrimArea) a.next();
399             Iterator JavaDoc d = area.getDescriptors().iterator();
400             while (d.hasNext()) {
401                 TrimDescriptor desc = (TrimDescriptor) d.next();
402                 Control nextControl = desc.getTrim().getControl();
403                 if (nextControl == null || nextControl.isDisposed()) {
404                     // Remvoe the trim from the area's list (not the local copy)
405
area.removeTrim(desc);
406                     
407                     // Remove it from the map
408
fTrimDescriptors.remove(desc.getId());
409                 }
410             }
411         }
412     }
413
414     /*
415      * (non-Javadoc)
416      *
417      * @see org.eclipse.swt.widgets.Layout#computeSize(org.eclipse.swt.widgets.Composite,
418      * int, int, boolean)
419      */

420     protected Point computeSize(Composite composite, int wHint, int hHint,
421             boolean flushCache) {
422         Point result = new Point(wHint, hHint);
423
424         TrimArea top = (TrimArea) fTrimArea.get(TOP_ID);
425         TrimArea bottom = (TrimArea) fTrimArea.get(BOTTOM_ID);
426         TrimArea left = (TrimArea) fTrimArea.get(LEFT_ID);
427         TrimArea right = (TrimArea) fTrimArea.get(RIGHT_ID);
428
429         int horizontalTrim = left.calculateTrimSize(wHint, hHint)
430                 + right.calculateTrimSize(wHint, hHint) + (2 * marginWidth)
431                 + leftSpacing + rightSpacing;
432         int verticalTrim = top.calculateTrimSize(wHint, hHint)
433                 + bottom.calculateTrimSize(wHint, hHint) + (2 * marginHeight)
434                 + topSpacing + bottomSpacing;
435
436         Point innerSize = centerArea.computeSize(wHint == SWT.DEFAULT ? wHint
437                 : wHint - horizontalTrim, hHint == SWT.DEFAULT ? hHint : hHint
438                 - verticalTrim);
439
440         if (wHint == SWT.DEFAULT) {
441             result.x = innerSize.x + horizontalTrim;
442         } else if (hHint == SWT.DEFAULT) {
443             result.y = innerSize.y + verticalTrim;
444         }
445
446         /*
447          * We -can't- determine the correct size for the shell because
448          * of it's underlying 'big lie' structure and the fact that most of the
449          * UI elements don't really exist until shown (meaning that
450          * the normal 'computeSize' mechanism won't work).
451          *
452          * See bug 166619 for details but we'll keep returning the
453          * current value (and the code above for legacy reasons...
454          */

455         return new Point(0, 0);
456     }
457
458     /*
459      * (non-Javadoc)
460      *
461      * @see org.eclipse.swt.widgets.Layout#layout(org.eclipse.swt.widgets.Composite,
462      * boolean)
463      */

464     protected void layout(Composite composite, boolean flushCache) {
465         removeDisposed();
466
467         TrimArea top = (TrimArea) fTrimArea.get(TOP_ID);
468         TrimArea bottom = (TrimArea) fTrimArea.get(BOTTOM_ID);
469         TrimArea left = (TrimArea) fTrimArea.get(LEFT_ID);
470         TrimArea right = (TrimArea) fTrimArea.get(RIGHT_ID);
471
472         Rectangle clientArea = composite.getClientArea();
473
474         clientArea.x += marginWidth;
475         clientArea.width -= 2 * marginWidth;
476         clientArea.y += marginHeight;
477         clientArea.height -= 2 * marginHeight;
478
479         // Get the max of the trim's preferred size for each side
480
int trim_top = top.calculateTrimSize(clientArea.width,
481                 clientArea.height);
482         int trim_bottom = bottom.calculateTrimSize(clientArea.width,
483                 clientArea.height);
484         int trim_left = left.calculateTrimSize(clientArea.width,
485                 clientArea.height);
486         int trim_right = right.calculateTrimSize(clientArea.width,
487                 clientArea.height);
488
489         // Determine the amount of 'useable' space for the trim
490
int leftOfLayout = clientArea.x;
491         int leftOfCenterPane = leftOfLayout + trim_left + leftSpacing;
492         int widthOfCenterPane = clientArea.width - trim_left - trim_right
493                 - leftSpacing - rightSpacing;
494         int rightOfCenterPane = clientArea.x + clientArea.width - trim_right;
495
496         // HACK!! Surgical Fix: Ideally the fix would handle 'wrapping' trim
497
// on any side. The following code is in place specifically to
498
// handle the CBanner's CoolBar wrapping. The code that calculates 'trim_top'
499
// above won't pick up if the CoolBar wraps and uses extra height
500
// So we have to re-calc the value based on the actual trim height
501
// as laid out.
502

503         // Do the layout of the top and update the height to match the actual
504
// height used
505
int topOfLayout = clientArea.y;
506         trim_top = arrange(new Rectangle(leftOfLayout, topOfLayout, clientArea.width,
507                 trim_top), top.getCaches(), !top.isVertical(), spacing);
508
509         // Now that we have an accurate value for the top's height we can
510
// proceed with the rest of the layout 'normally'.
511
int topOfCenterPane = topOfLayout + trim_top + topSpacing;
512         int heightOfCenterPane = clientArea.height - trim_top - trim_bottom
513                 - topSpacing - bottomSpacing;
514         int bottomOfCenterPane = clientArea.y + clientArea.height - trim_bottom;
515
516         arrange(new Rectangle(leftOfCenterPane, bottomOfCenterPane,
517                 widthOfCenterPane, trim_bottom), bottom.getCaches(), !bottom
518                 .isVertical(), spacing);
519         arrange(new Rectangle(leftOfLayout, topOfCenterPane, trim_left,
520                 clientArea.height - trim_top), left.getCaches(), !left
521                 .isVertical(), spacing);
522         arrange(new Rectangle(rightOfCenterPane, topOfCenterPane, trim_right,
523                 clientArea.height - trim_top), right.getCaches(), !right
524                 .isVertical(), spacing);
525
526         if (centerArea.getControl() != null) {
527             centerArea.getControl().setBounds(leftOfCenterPane,
528                     topOfCenterPane, widthOfCenterPane, heightOfCenterPane);
529         }
530     }
531
532     /**
533      * Arranges all the given controls in a horizontal row that fills the given
534      * rectangle.
535      *
536      * @param area
537      * area to be filled by the controls
538      * @param caches
539      * a list of SizeCaches for controls that will span the rectangle
540      * @param horizontally
541      * how we are filling the rectangle
542      * @param spacing
543      * in pixels
544      */

545     private static int arrange(Rectangle area, List JavaDoc caches,
546             boolean horizontally, int spacing) {
547         Point currentPosition = new Point(area.x, area.y);
548
549         List JavaDoc resizable = new ArrayList JavaDoc(caches.size());
550         List JavaDoc nonResizable = new ArrayList JavaDoc(caches.size());
551
552         TrimArea.filterResizable(caches, resizable, nonResizable, horizontally);
553
554         int[] sizes = new int[nonResizable.size()];
555
556         int idx = 0;
557         int used = 0;
558         int hint = Geometry.getDimension(area, !horizontally);
559
560         // Compute the sizes of non-resizable controls
561
Iterator JavaDoc iter = nonResizable.iterator();
562
563         while (iter.hasNext()) {
564             SizeCache next = (SizeCache) iter.next();
565
566             sizes[idx] = TrimArea.getSize(next, hint, horizontally);
567             used += sizes[idx];
568             idx++;
569         }
570
571         int available = Geometry.getDimension(area, horizontally) - used
572                 - spacing * (caches.size() - 1);
573         idx = 0;
574         int remainingResizable = resizable.size();
575
576         iter = caches.iterator();
577
578         while (iter.hasNext()) {
579             SizeCache next = (SizeCache) iter.next();
580             if (next.getControl().isVisible()) {
581
582                 int thisSize;
583                 if (TrimArea.isResizable(next.getControl(), horizontally)) {
584                     thisSize = available / remainingResizable;
585                     available -= thisSize;
586                     remainingResizable--;
587                 } else {
588                     thisSize = sizes[idx];
589                     idx++;
590                 }
591
592                 if (TrimDragPreferences.showRaggedTrim()) {
593                     Point prefSize = next.computeSize(SWT.DEFAULT, SWT.DEFAULT);
594                     if (horizontally) {
595                         // HACK!! Surgical Fix: Ideally the fix would handle 'wrapping' trim
596
// on any side. The following code is in place specifically to
597
// handle the CBanner's CoolBar wrapping. We need to pick up
598
// if the CoolBar wraps and uses extra height
599
// So we have to re-calc the value based on the actual trim height
600
// as laid out.
601
if (next.getControl() instanceof CBanner) {
602                             prefSize = next.getControl().computeSize(thisSize, SWT.DEFAULT);
603                             if (prefSize.y > hint)
604                                 hint = prefSize.y;
605                         }
606                         
607                         next.getControl().setBounds(currentPosition.x,
608                                 currentPosition.y, thisSize, prefSize.y);
609                         currentPosition.x += thisSize + spacing;
610                     } else {
611                         next.getControl().setBounds(currentPosition.x,
612                                 currentPosition.y, prefSize.x, thisSize);
613                         currentPosition.y += thisSize + spacing;
614                     }
615                 }
616                 else {
617                     if (horizontally) {
618                         next.getControl().setBounds(currentPosition.x,
619                                 currentPosition.y, thisSize, hint);
620                         currentPosition.x += thisSize + spacing;
621                     } else {
622                         next.getControl().setBounds(currentPosition.x,
623                                 currentPosition.y, hint, thisSize);
624                         currentPosition.y += thisSize + spacing;
625                     }
626                 }
627             }
628         }
629         
630         return hint;
631     }
632
633     /**
634      * Sets the widget that will occupy the central area of the layout.
635      * Typically, this will be a composite that contains the main widgetry of
636      * the application.
637      *
638      * @param center
639      * control that will occupy the center of the layout, or null if
640      * none
641      */

642     public void setCenterControl(Control center) {
643         centerArea.setControl(center);
644     }
645
646     /**
647      * Returns the control in the center of this layout
648      *
649      * @return the center area control.
650      */

651     public Control getCenterControl() {
652         return centerArea.getControl();
653     }
654
655     /*
656      * (non-Javadoc)
657      *
658      * @see org.eclipse.ui.internal.layout.ICachingLayout#flush(org.eclipse.swt.widgets.Control)
659      */

660     public void flush(Control dirtyControl) {
661         if (dirtyControl == centerArea.getControl()) {
662             centerArea.flush();
663         } else {
664             TrimDescriptor desc = findTrimDescription(dirtyControl);
665             if (desc != null) {
666                 desc.flush();
667             }
668         }
669     }
670
671     /*
672      * (non-Javadoc)
673      *
674      * @see org.eclipse.ui.internal.layout.ITrimManager#getAreaIds()
675      */

676     public int[] getAreaIds() {
677         return (int[]) TRIM_ID_INFO.clone();
678     }
679
680     /*
681      * (non-Javadoc)
682      *
683      * @see org.eclipse.ui.internal.layout.ITrimManager#getAreaTrim(int)
684      */

685     public List JavaDoc getAreaTrim(int areaId) {
686         TrimArea area = (TrimArea) fTrimArea.get(new Integer JavaDoc(areaId));
687         if (area == null) {
688             return Collections.EMPTY_LIST;
689         }
690         return area.getTrims();
691     }
692
693     /*
694      * (non-Javadoc)
695      *
696      * @see org.eclipse.ui.internal.layout.ITrimManager#updateAreaTrim(int,
697      * java.util.List, boolean)
698      */

699     public void updateAreaTrim(int id, List JavaDoc trim, boolean removeExtra) {
700         TrimArea area = (TrimArea) fTrimArea.get(new Integer JavaDoc(id));
701         if (area == null) {
702             return;
703         }
704         List JavaDoc current = area.getTrims();
705
706         // add back the trim ... this takes care of moving it
707
// from one trim area to another.
708
Iterator JavaDoc i = trim.iterator();
709         while (i.hasNext()) {
710             IWindowTrim t = (IWindowTrim) i.next();
711             t.dock(id); // Ensure that the trim is properly oriented
712
addTrim(id, t, null);
713             current.remove(t);
714         }
715
716         if (removeExtra) {
717             // if it wasn't removed from the current list, then it's extra
718
// trim we don't need.
719
i = current.iterator();
720             while (i.hasNext()) {
721                 IWindowTrim t = (IWindowTrim) i.next();
722                 removeTrim(t);
723             }
724         }
725     }
726
727     /**
728      * Return a trim area rectangle.
729      *
730      * @param window
731      * the window that has the trim
732      * @param areaId
733      * the side it's on
734      * @return the area rectangle.
735      * @since 3.2
736      * @see #getAreaIds()
737      */

738     public Rectangle getTrimRect(Composite window, int areaId) {
739         Rectangle bb = window.getBounds();
740
741         Rectangle cr = window.getClientArea();
742         Rectangle tr = window.computeTrim(cr.x, cr.y, cr.width, cr.height);
743
744         // Place the Client Area 'within' its window
745
Geometry.moveRectangle(cr, new Point(bb.x - tr.x, bb.y - tr.y));
746
747         TrimArea top = (TrimArea) fTrimArea.get(TOP_ID);
748         TrimArea bottom = (TrimArea) fTrimArea.get(BOTTOM_ID);
749         TrimArea left = (TrimArea) fTrimArea.get(LEFT_ID);
750         TrimArea right = (TrimArea) fTrimArea.get(RIGHT_ID);
751
752         int trim_top = top.calculateTrimSize(cr.width, cr.height);
753         int trim_bottom = bottom.calculateTrimSize(cr.width, cr.height);
754         int trim_left = left.calculateTrimSize(cr.width, cr.height);
755         int trim_right = right.calculateTrimSize(cr.width, cr.height);
756
757         // Adjust the trim sizes to incorporate the margins for sides that
758
// don't currently have trim
759
if (trim_top == 0) {
760             trim_top = marginHeight;
761         }
762         if (trim_bottom == 0) {
763             trim_bottom = marginHeight;
764         }
765         if (trim_left == 0) {
766             trim_left = marginWidth;
767         }
768         if (trim_right == 0) {
769             trim_right = marginWidth;
770         }
771
772         Rectangle trimRect = new Rectangle(0, 0, 0, 0);
773         switch (areaId) {
774         case TOP:
775             trimRect.x = cr.x;
776             trimRect.width = cr.width;
777             trimRect.y = cr.y;
778             trimRect.height = trim_top;
779             break;
780         case BOTTOM:
781             trimRect.x = cr.x;
782             trimRect.width = cr.width;
783             trimRect.y = (cr.y + cr.height) - trim_bottom;
784             trimRect.height = trim_bottom;
785             break;
786         case LEFT:
787             trimRect.x = cr.x;
788             trimRect.width = trim_left;
789             trimRect.y = cr.y + trim_top;
790             trimRect.height = cr.height - (trim_top + trim_bottom);
791             break;
792         case RIGHT:
793             trimRect.x = (cr.x + cr.width) - trim_right;
794             trimRect.width = trim_right;
795             trimRect.y = cr.y + trim_top;
796             trimRect.height = cr.height - (trim_top + trim_bottom);
797             break;
798         }
799
800         return trimRect;
801     }
802
803     /*
804      * (non-Javadoc)
805      *
806      * @see org.eclipse.ui.internal.layout.ITrimManager#getAllTrim()
807      */

808     public List JavaDoc getAllTrim() {
809         List JavaDoc trimList = new ArrayList JavaDoc(fTrimDescriptors.size());
810
811         Iterator JavaDoc d = fTrimDescriptors.values().iterator();
812         while (d.hasNext()) {
813             TrimDescriptor desc = (TrimDescriptor) d.next();
814             trimList.add(desc.getTrim());
815         }
816
817         return trimList;
818     }
819
820     /*
821      * (non-Javadoc)
822      *
823      * @see org.eclipse.ui.internal.layout.ITrimManager#setTrimVisible(org.eclipse.ui.internal.IWindowTrim,
824      * boolean)
825      */

826     public void setTrimVisible(IWindowTrim trim, boolean visible) {
827         TrimDescriptor desc = findTrimDescription(trim.getControl());
828
829         if (desc != null) {
830             desc.setVisible(visible);
831         }
832     }
833
834     /**
835      * Find the trim descriptor for this control.
836      *
837      * @param trim
838      * the Control to find.
839      * @return the trim descriptor, or <code>null</code> if not found.
840      * @since 3.2
841      */

842     private TrimDescriptor findTrimDescription(Control trim) {
843         Iterator JavaDoc d = fTrimDescriptors.values().iterator();
844         while (d.hasNext()) {
845             TrimDescriptor desc = (TrimDescriptor) d.next();
846             if (desc.getTrim().getControl() == trim) {
847                 return desc;
848             }
849             if (desc.getDockingCache() != null
850                     && desc.getDockingCache().getControl() == trim) {
851                 return desc;
852             }
853         }
854         return null;
855     }
856
857     /**
858      * Return the trim area associated with the given id
859      *
860      * @param areaId
861      * The id of the trim area to get
862      * @return The TrimArea or <code>null</code> if the id is not found
863      */

864     public TrimArea getTrimArea(int areaId) {
865         return (TrimArea) fTrimArea.get(new Integer JavaDoc(areaId));
866     }
867
868     /**
869      * Remember the persisted locations for the trim. This allows the code
870      * to site the trim in its preferred (i.e. cached) location on creation
871      *
872      * @param areaId The id of the trim area being defined
873      * @param preferredLocations A list of trim ID's
874      */

875     public void setPreferredLocations(int areaId, List JavaDoc preferredLocations) {
876         preferredLocationMap.put(new Integer JavaDoc(areaId), preferredLocations);
877     }
878     
879     /**
880      * If the given id has a cached location return its preferred side
881      *
882      * @param trimId The id of the trim to be tested
883      * @return The areaId of a cached id or -1 if no cache info exists
884      */

885     public int getPreferredArea(String JavaDoc trimId) {
886         Iterator JavaDoc keyIter = preferredLocationMap.keySet().iterator();
887         while (keyIter.hasNext()) {
888             Integer JavaDoc key = (Integer JavaDoc) keyIter.next();
889             List JavaDoc areaList = (List JavaDoc) preferredLocationMap.get(key);
890             if (areaList.contains(trimId))
891                 return key.intValue();
892         }
893         
894         return -1;
895     }
896     
897     /**
898      * If the given id has a cached location return an existing trim
899      * element that it should be placed before (if any)
900      *
901      * @param trimId The id of the trim to be tested
902      * @return The trim to be inserted before or <code>null</code>
903      * if no cached info exists
904      */

905     public IWindowTrim getPreferredLocation(String JavaDoc trimId) {
906         Iterator JavaDoc keyIter = preferredLocationMap.keySet().iterator();
907         while (keyIter.hasNext()) {
908             Integer JavaDoc key = (Integer JavaDoc) keyIter.next();
909             List JavaDoc areaList = (List JavaDoc) preferredLocationMap.get(key);
910             int index = areaList.indexOf(trimId);
911             if (index != -1) {
912                 // OK, find the first 'real' trim after this one
913
// This will be used as the 'beforeMe' parameter
914
// in the 'addTrim' call
915
for (int i = index+1; i < areaList.size(); i++) {
916                     String JavaDoc id = (String JavaDoc) areaList.get(i);
917                     IWindowTrim trim = getTrim(id);
918                     if (trim != null)
919                         return trim;
920                 }
921             }
922         }
923         
924         return null;
925     }
926
927     /**
928      * Disables the controls associated with visible trim elements. This
929      * is only used during long-running WorkbenchWindow operations to prevent users
930      * from changing the environment while the operation (i.e. a long-running editor
931      * 'save') is in progress.
932      *
933      * The expected life-cycle is to first call this this method to disable any visible
934      * trim (and caching the elements that had to be disabled) followed by a call to
935      * 'enableTrim' passing in the list returned from this method.
936      *
937      * @param ignoreMe Since the current UI has a disable button in the StatusLine
938      * we allow the caller to designate one piece of trim to ignore
939      *
940      * @return The list of trim controls that were disabled during this call
941      */

942     public List JavaDoc disableTrim(IWindowTrim ignoreMe) {
943         List JavaDoc disabledControls = new ArrayList JavaDoc();
944
945         // Disable all the trim -except- for 'ignoreMe'
946
List JavaDoc allTrim = getAllTrim();
947         for (Iterator JavaDoc trimIter = allTrim.iterator(); trimIter.hasNext();) {
948             IWindowTrim trim = (IWindowTrim) trimIter.next();
949             if (ignoreMe == trim)
950                 continue;
951             
952             Control ctrl = trim.getControl();
953             if (ctrl == null || ctrl.isDisposed() || !ctrl.isVisible() || !ctrl.isEnabled())
954                 continue;
955             
956             ctrl.setEnabled(false);
957             disabledControls.add(ctrl);
958         }
959         
960         return disabledControls;
961     }
962     
963     /**
964      * Enables the controls in the list. This list is expected to be a non-modified
965      * List as returned from a call to 'disableTrim'.
966      * @param disabledControls The list of controls to enable
967      */

968     public void enableTrim(List JavaDoc disabledControls) {
969         // Simply re-enable any controls in the list
970
for (Iterator JavaDoc dcIter = disabledControls.iterator(); dcIter.hasNext();) {
971             Control ctrl = (Control) dcIter.next();
972             
973             if (!ctrl.isDisposed() && !ctrl.isEnabled())
974                 ctrl.setEnabled(true);
975         }
976     }
977 }
978
Popular Tags