KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > internal > PerspectiveHelper


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
12 package org.eclipse.ui.internal;
13
14 import java.util.ArrayList JavaDoc;
15 import java.util.Collections JavaDoc;
16 import java.util.Enumeration JavaDoc;
17 import java.util.HashMap JavaDoc;
18 import java.util.List JavaDoc;
19 import java.util.Map JavaDoc;
20 import java.util.Vector JavaDoc;
21
22 import org.eclipse.core.runtime.IStatus;
23 import org.eclipse.jface.preference.IPreferenceStore;
24 import org.eclipse.swt.SWT;
25 import org.eclipse.swt.graphics.Cursor;
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.Shell;
31 import org.eclipse.ui.IMemento;
32 import org.eclipse.ui.IViewReference;
33 import org.eclipse.ui.IWorkbenchPartReference;
34 import org.eclipse.ui.IWorkbenchPreferenceConstants;
35 import org.eclipse.ui.PlatformUI;
36 import org.eclipse.ui.internal.dnd.AbstractDropTarget;
37 import org.eclipse.ui.internal.dnd.DragUtil;
38 import org.eclipse.ui.internal.dnd.IDragOverListener;
39 import org.eclipse.ui.internal.dnd.IDropTarget;
40 import org.eclipse.ui.internal.misc.StringMatcher;
41 import org.eclipse.ui.presentations.IStackPresentationSite;
42
43 /**
44  * A perspective presentation is a collection of parts with a layout. Each part
45  * is parented to a main window, so you can create more than one presentation
46  * on a set of parts and change the layout just by activating / deactivating a
47  * presentation.
48  *
49  * In addition, the user can change the position of any part by mouse
50  * manipulation (drag & drop). If a part is removed, we leave a placeholder
51  * behind to indicate where it goes should the part be added back.
52  */

53 public class PerspectiveHelper {
54     private WorkbenchPage page;
55     
56     private Perspective perspective;
57
58     private Composite parentWidget;
59
60     private ViewSashContainer mainLayout;
61     
62     private PartStack maximizedStack;
63
64     /**
65      * If there is a ViewStack maximized on shutdown the id is
66      * cached and restored into this field on 'restoreState'.
67      * This is then used to bash the ViewStack's presentation state
68      * into the correct value on activation (the startup life-cycle
69      * is such that we have to use this 'latch' because the window
70      * state isn't valid until the activate happens.
71      */

72     private String JavaDoc maximizedStackId;
73
74     private ArrayList JavaDoc detachedWindowList = new ArrayList JavaDoc(1);
75
76     private ArrayList JavaDoc detachedPlaceHolderList = new ArrayList JavaDoc(1);
77
78     /**
79      * Maps a stack's id to its current bounds
80      * this is used to capture the current bounds of all
81      * stacks -before- starting a maximize (since the
82      * iterative 'minimize' calls cause the intial stack's
83      * bounds to change.
84      */

85     private Map JavaDoc boundsMap = new HashMap JavaDoc();
86
87     private boolean detachable = false;
88
89     private boolean active = false;
90
91     // key is the LayoutPart object, value is the PartDragDrop object
92
//private IPartDropListener partDropListener;
93

94     private static final int MIN_DETACH_WIDTH = 150;
95
96     private static final int MIN_DETACH_HEIGHT = 250;
97
98     protected ActualDropTarget dropTarget;
99     
100     private IDragOverListener dragTarget = new IDragOverListener() {
101
102         public IDropTarget drag(Control currentControl, Object JavaDoc draggedObject,
103                 Point position, final Rectangle dragRectangle) {
104             
105             if (!(draggedObject instanceof ViewPane || draggedObject instanceof ViewStack)) {
106                 return null;
107             }
108             final LayoutPart part = (LayoutPart) draggedObject;
109
110             if (part.getWorkbenchWindow() != page.getWorkbenchWindow()) {
111                 return null;
112             }
113
114             if (dropTarget == null) {
115                 dropTarget = new ActualDropTarget(part, dragRectangle);
116             } else {
117                 dropTarget.setTarget(part, dragRectangle);
118             }
119             
120             return dropTarget;
121         }
122
123     };
124
125     private final class ActualDropTarget extends AbstractDropTarget {
126         private LayoutPart part;
127
128         private Rectangle dragRectangle;
129
130         private ActualDropTarget(LayoutPart part, Rectangle dragRectangle) {
131             super();
132             setTarget(part, dragRectangle);
133         }
134
135         /**
136          * @param part
137          * @param dragRectangle
138          * @since 3.1
139          */

140         private void setTarget(LayoutPart part, Rectangle dragRectangle) {
141             this.part = part;
142             this.dragRectangle = dragRectangle;
143         }
144
145         public void drop() {
146
147             Shell shell = part.getShell();
148             if (shell.getData() instanceof DetachedWindow) {
149                 // only one tab folder in a detach window, so do window
150
// move
151
if (part instanceof ViewStack) {
152                     shell.setLocation(dragRectangle.x,
153                             dragRectangle.y);
154                     return;
155                 }
156                 // if only one view in tab folder then do a window move
157
ILayoutContainer container = part.getContainer();
158                 if (container instanceof ViewStack) {
159                     if (((ViewStack) container).getItemCount() == 1) {
160                         shell.setLocation(dragRectangle.x,
161                                 dragRectangle.y);
162                         return;
163                     }
164                 }
165             }
166
167             // If layout is modified always zoom out.
168
if (isZoomed()) {
169                 zoomOut();
170             }
171             // do a normal part detach
172
detach(part, dragRectangle.x, dragRectangle.y);
173         }
174
175         public Cursor getCursor() {
176             return DragCursors.getCursor(DragCursors.OFFSCREEN);
177         }
178     }
179
180     private class MatchingPart implements Comparable JavaDoc {
181         String JavaDoc pid;
182
183         String JavaDoc sid;
184
185         LayoutPart part;
186
187         boolean hasWildcard;
188
189         int len;
190
191         MatchingPart(String JavaDoc pid, String JavaDoc sid, LayoutPart part) {
192             this.pid = pid;
193             this.sid = sid;
194             this.part = part;
195             this.len = (pid == null ? 0 : pid.length())
196                     + (sid == null ? 0 : sid.length());
197             this.hasWildcard = (pid != null && pid
198                     .indexOf(PartPlaceholder.WILD_CARD) != -1)
199                     || (sid != null && sid.indexOf(PartPlaceholder.WILD_CARD) != -1);
200         }
201
202         public int compareTo(Object JavaDoc a) {
203             // specific ids always outweigh ids with wildcards
204
MatchingPart ma = (MatchingPart) a;
205             if (this.hasWildcard && !ma.hasWildcard) {
206                 return -1;
207             }
208             if (!this.hasWildcard && ma.hasWildcard) {
209                 return 1;
210             }
211             // if both are specific or both have wildcards, simply compare based on length
212
return ma.len - this.len;
213         }
214     }
215
216     
217     /**
218      * Constructs a new object.
219      */

220     public PerspectiveHelper(WorkbenchPage workbenchPage,
221             ViewSashContainer mainLayout, Perspective perspective) {
222         this.page = workbenchPage;
223         this.mainLayout = mainLayout;
224         this.perspective = perspective;
225         
226         // Views can be detached if the feature is enabled (true by default,
227
// use the plug-in customization file to disable), and if the platform
228
// supports detaching.
229

230         final IPreferenceStore store = PlatformUI.getPreferenceStore();
231         this.detachable = store.getBoolean(IWorkbenchPreferenceConstants.ENABLE_DETACHED_VIEWS);
232
233         if (this.detachable) {
234             // Check if some arbitrary Composite supports reparenting. If it
235
// doesn't, views cannot be detached.
236

237             Composite client = workbenchPage.getClientComposite();
238             if (client == null) {
239                 // The workbench page is not initialized. I don't think this can happen,
240
// but if it does, silently set detachable to false.
241
this.detachable = false;
242             } else {
243                 Composite testChild = new Composite(client, SWT.NONE);
244                 this.detachable = testChild.isReparentable();
245                 testChild.dispose();
246             }
247         }
248     }
249
250     /**
251      * Show the presentation.
252      */

253     public void activate(Composite parent) {
254
255         if (active) {
256             return;
257         }
258
259         parentWidget = parent;
260
261         // Activate main layout
262
// make sure all the views have been properly parented
263
Vector JavaDoc children = new Vector JavaDoc();
264         collectViewPanes(children, mainLayout.getChildren());
265         Enumeration JavaDoc itr = children.elements();
266         while (itr.hasMoreElements()) {
267             LayoutPart part = (LayoutPart) itr.nextElement();
268             part.reparent(parent);
269         }
270         mainLayout.createControl(parent);
271         mainLayout.setActive(true);
272
273         // Open the detached windows.
274
for (int i = 0, length = detachedWindowList.size(); i < length; i++) {
275             DetachedWindow dwindow = (DetachedWindow) detachedWindowList.get(i);
276             dwindow.open();
277         }
278
279         enableAllDrag();
280
281         // Ensure that the maximized stack's presentation state is correct
282
if (maximizedStackId != null) {
283             LayoutPart part = findPart(maximizedStackId);
284             if (part instanceof PartStack) {
285                 maximizedStack = (PartStack) part;
286                 maximizedStackId = null;
287             }
288         }
289         
290         // NOTE: we only handle ViewStacks here; Editor Stacks are handled by the
291
// perspective
292
if (maximizedStack instanceof ViewStack) {
293             maximizedStack.setPresentationState(IStackPresentationSite.STATE_MAXIMIZED);
294         }
295         
296         active = true;
297     }
298
299     /**
300      * Adds a part to the presentation. If a placeholder exists for the part
301      * then swap the part in. Otherwise, add the part in the bottom right
302      * corner of the presentation.
303      */

304     public void addPart(LayoutPart part) {
305         
306         // Look for a placeholder.
307
PartPlaceholder placeholder = null;
308         LayoutPart testPart = null;
309         String JavaDoc primaryId = part.getID();
310         String JavaDoc secondaryId = null;
311
312         IViewReference ref = null;
313         if (part instanceof ViewPane) {
314             ViewPane pane = (ViewPane) part;
315             ref = (IViewReference) pane.getPartReference();
316             secondaryId = ref.getSecondaryId();
317         }
318         if (secondaryId != null) {
319             testPart = findPart(primaryId, secondaryId);
320         } else {
321             testPart = findPart(primaryId);
322         }
323
324         // validate the testPart
325
if (testPart != null && testPart instanceof PartPlaceholder) {
326             placeholder = (PartPlaceholder) testPart;
327         }
328
329         // If there is no placeholder do a simple add. Otherwise, replace the
330
// placeholder if its not a pattern matching placholder
331
if (placeholder == null) {
332             part.reparent(mainLayout.getParent());
333             LayoutPart relative = mainLayout.findBottomRight();
334             if (relative != null && relative instanceof ILayoutContainer) {
335                 ILayoutContainer stack = (ILayoutContainer)relative;
336                 if (stack.allowsAdd(part)) {
337                     mainLayout.stack(part, stack);
338                 } else {
339                     mainLayout.add(part);
340                 }
341             } else {
342                 mainLayout.add(part);
343             }
344         } else {
345             ILayoutContainer container = placeholder.getContainer();
346             if (container != null) {
347                 if (container instanceof DetachedPlaceHolder) {
348                     //Create a detached window add the part on it.
349
DetachedPlaceHolder holder = (DetachedPlaceHolder) container;
350                     detachedPlaceHolderList.remove(holder);
351                     container.remove(testPart);
352                     DetachedWindow window = new DetachedWindow(page);
353                     detachedWindowList.add(window);
354                     window.create();
355                     part.createControl(window.getShell());
356                     // Open window.
357
window.getShell().setBounds(holder.getBounds());
358                     window.open();
359                     // add part to detached window.
360
ViewPane pane = (ViewPane) part;
361                     window.add(pane);
362                     LayoutPart otherChildren[] = holder.getChildren();
363                     for (int i = 0; i < otherChildren.length; i++) {
364                         part.getContainer().add(otherChildren[i]);
365                     }
366                 } else {
367                     // show parent if necessary
368
if (container instanceof ContainerPlaceholder) {
369                         ContainerPlaceholder containerPlaceholder = (ContainerPlaceholder) container;
370                         ILayoutContainer parentContainer = containerPlaceholder
371                                 .getContainer();
372                         container = (ILayoutContainer) containerPlaceholder
373                                 .getRealContainer();
374                         if (container instanceof LayoutPart) {
375                             parentContainer.replace(containerPlaceholder,
376                                     (LayoutPart) container);
377                         }
378                         containerPlaceholder.setRealContainer(null);
379                     }
380
381                     // reparent part.
382
if (!(container instanceof ViewStack)) {
383                         // We don't need to reparent children of PartTabFolders since they will automatically
384
// reparent their children when they become visible. This if statement used to be
385
// part of an else branch. Investigate if it is still necessary.
386
part.reparent(mainLayout.getParent());
387                     }
388
389                     // see if we should replace the placeholder
390
if (placeholder.hasWildCard()) {
391                         if (container instanceof PartSashContainer) {
392                             ((PartSashContainer) container)
393                                     .addChildForPlaceholder(part, placeholder);
394                         } else {
395                             container.add(part);
396                         }
397                     } else {
398                         container.replace(placeholder, part);
399                     }
400                 }
401             }
402         }
403     }
404     
405     /**
406      * Attaches a part that was previously detached to the mainLayout.
407      *
408      * @param ref
409      */

410     public void attachPart(IViewReference ref) {
411         ViewPane pane = (ViewPane)((WorkbenchPartReference)ref).getPane();
412         
413         // Restore any maximized part before re-attaching.
414
// Note that 'getMaximizedStack != null' implies 'useNewMinMax'
415
if (getMaximizedStack() != null) {
416             getMaximizedStack().setState(IStackPresentationSite.STATE_RESTORED);
417         }
418         
419         derefPart(pane);
420         addPart(pane);
421         bringPartToTop(pane);
422         pane.setFocus();
423     }
424
425     /**
426      * Return whether detachable parts can be supported.
427      */

428     public boolean canDetach() {
429         return detachable;
430     }
431
432     /**
433      * Bring a part forward so it is visible.
434      *
435      * @return true if the part was brought to top, false if not.
436      */

437     public boolean bringPartToTop(LayoutPart part) {
438         ILayoutContainer container = part.getContainer();
439         if (container != null && container instanceof PartStack) {
440             PartStack folder = (PartStack) container;
441             if (folder.getSelection() != part) {
442                 folder.setSelection(part);
443                 return true;
444             }
445         }
446         return false;
447     }
448
449     /**
450      * Returns true if the given part is visible.
451      * A part is visible if it's top-level (not in a tab folder) or if it is the top one
452      * in a tab folder.
453      */

454     public boolean isPartVisible(IWorkbenchPartReference partRef) {
455         LayoutPart foundPart;
456         if (partRef instanceof IViewReference) {
457             foundPart = findPart(partRef.getId(), ((IViewReference) partRef).getSecondaryId());
458         } else {
459             foundPart = findPart(partRef.getId());
460         }
461         if (foundPart == null) {
462             return false;
463         }
464         if (foundPart instanceof PartPlaceholder) {
465             return false;
466         }
467
468         ILayoutContainer container = foundPart.getContainer();
469         
470         if (container instanceof ContainerPlaceholder) {
471             return false;
472         }
473
474         if (container instanceof ViewStack) {
475             ViewStack folder = (ViewStack) container;
476             PartPane visiblePart = folder.getSelection();
477             if (visiblePart == null) {
478                 return false;
479             }
480             return partRef.equals(visiblePart.getPartReference());
481         }
482         return true;
483     }
484
485     /**
486      * Returns true is not in a tab folder or if it is the top one in a tab
487      * folder.
488      */

489     public boolean willPartBeVisible(String JavaDoc partId) {
490         return willPartBeVisible(partId, null);
491     }
492
493     public boolean willPartBeVisible(String JavaDoc partId, String JavaDoc secondaryId) {
494         LayoutPart part = findPart(partId, secondaryId);
495         if (part == null) {
496             return false;
497         }
498         ILayoutContainer container = part.getContainer();
499         if (container != null && container instanceof ContainerPlaceholder) {
500             container = (ILayoutContainer) ((ContainerPlaceholder) container)
501                     .getRealContainer();
502         }
503
504         if (container != null && container instanceof ViewStack) {
505             ViewStack folder = (ViewStack) container;
506             if (folder.getSelection() == null) {
507                 return false;
508             }
509             return part.getCompoundId().equals(
510                     folder.getSelection().getCompoundId());
511         }
512         return true;
513     }
514
515     /**
516      * Answer a list of the PartPlaceholder objects.
517      */

518     private PartPlaceholder[] collectPlaceholders() {
519         // Scan the main window.
520
PartPlaceholder[] results = collectPlaceholders(mainLayout
521                 .getChildren());
522
523         // Scan each detached window.
524
if (detachable) {
525             for (int i = 0, length = detachedWindowList.size(); i < length; i++) {
526                 DetachedWindow win = (DetachedWindow) detachedWindowList.get(i);
527                 PartPlaceholder[] moreResults = collectPlaceholders(win
528                         .getChildren());
529                 if (moreResults.length > 0) {
530                     int newLength = results.length + moreResults.length;
531                     PartPlaceholder[] newResults = new PartPlaceholder[newLength];
532                     System.arraycopy(results, 0, newResults, 0, results.length);
533                     System.arraycopy(moreResults, 0, newResults,
534                             results.length, moreResults.length);
535                     results = newResults;
536                 }
537             }
538         }
539         return results;
540     }
541
542     /**
543      * Answer a list of the PartPlaceholder objects.
544      */

545     private PartPlaceholder[] collectPlaceholders(LayoutPart[] parts) {
546         PartPlaceholder[] result = new PartPlaceholder[0];
547
548         for (int i = 0, length = parts.length; i < length; i++) {
549             LayoutPart part = parts[i];
550             if (part instanceof ILayoutContainer) {
551                 // iterate through sub containers to find sub-parts
552
PartPlaceholder[] newParts = collectPlaceholders(((ILayoutContainer) part)
553                         .getChildren());
554                 PartPlaceholder[] newResult = new PartPlaceholder[result.length
555                         + newParts.length];
556                 System.arraycopy(result, 0, newResult, 0, result.length);
557                 System.arraycopy(newParts, 0, newResult, result.length,
558                         newParts.length);
559                 result = newResult;
560             } else if (part instanceof PartPlaceholder) {
561                 PartPlaceholder[] newResult = new PartPlaceholder[result.length + 1];
562                 System.arraycopy(result, 0, newResult, 0, result.length);
563                 newResult[result.length] = (PartPlaceholder) part;
564                 result = newResult;
565             }
566         }
567
568         return result;
569     }
570
571     /**
572      * Answer a list of the view panes.
573      */

574     public void collectViewPanes(List JavaDoc result) {
575         // Scan the main window.
576
collectViewPanes(result, mainLayout.getChildren());
577
578         // Scan each detached window.
579
if (detachable) {
580             for (int i = 0, length = detachedWindowList.size(); i < length; i++) {
581                 DetachedWindow win = (DetachedWindow) detachedWindowList.get(i);
582                 collectViewPanes(result, win.getChildren());
583             }
584         }
585     }
586
587     /**
588      * Answer a list of the view panes.
589      */

590     private void collectViewPanes(List JavaDoc result, LayoutPart[] parts) {
591         for (int i = 0, length = parts.length; i < length; i++) {
592             LayoutPart part = parts[i];
593             if (part instanceof ViewPane) {
594                 result.add(part);
595             } else if (part instanceof ILayoutContainer) {
596                 collectViewPanes(result, ((ILayoutContainer) part)
597                         .getChildren());
598             }
599         }
600     }
601
602     /**
603      * Hide the presentation.
604      */

605     public void deactivate() {
606         if (!active) {
607             return;
608         }
609
610         disableAllDrag();
611
612         // Reparent all views to the main window
613
Composite parent = mainLayout.getParent();
614         Vector JavaDoc children = new Vector JavaDoc();
615         collectViewPanes(children, mainLayout.getChildren());
616
617         for (int i = 0, length = detachedWindowList.size(); i < length; i++) {
618             DetachedWindow window = (DetachedWindow) detachedWindowList.get(i);
619             collectViewPanes(children, window.getChildren());
620         }
621
622         // *** Do we even need to do this if detached windows not supported?
623
Enumeration JavaDoc itr = children.elements();
624         while (itr.hasMoreElements()) {
625             LayoutPart part = (LayoutPart) itr.nextElement();
626             part.reparent(parent);
627         }
628         
629         // Dispose main layout.
630

631         mainLayout.setActive(false);
632         
633         // Dispose the detached windows
634
for (int i = 0, length = detachedWindowList.size(); i < length; i++) {
635             DetachedWindow window = (DetachedWindow) detachedWindowList.get(i);
636             window.close();
637         }
638         
639         active = false;
640     }
641     
642     public void dispose() {
643         mainLayout.dispose();
644         mainLayout.disposeSashes();
645     }
646     
647     /**
648      * Writes a description of the layout to the given string buffer.
649      * This is used for drag-drop test suites to determine if two layouts are the
650      * same. Like a hash code, the description should compare as equal iff the
651      * layouts are the same. However, it should be user-readable in order to
652      * help debug failed tests. Although these are english readable strings,
653      * they should not be translated or equality tests will fail.
654      * <p>
655      * This is only intended for use by test suites.
656      * </p>
657      *
658      * @param buf
659      */

660     public void describeLayout(StringBuffer JavaDoc buf) {
661
662         if (detachable) {
663             if(detachedWindowList.size() != 0){
664                 buf.append("detachedWindows ("); //$NON-NLS-1$
665

666                 for (int i = 0, length = detachedWindowList.size(); i < length; i++) {
667                     DetachedWindow window = (DetachedWindow) detachedWindowList.get(i);
668                     LayoutPart[] children = window.getChildren();
669                     if(children.length != 0){
670                         buf.append("dWindow ("); //$NON-NLS-1$
671
for(int j = 0; j < children.length; j++){
672                             buf.append(((ViewPane)children[j]).getViewReference().getPartName());
673                             if(j < (children.length - 1)) {
674                                 buf.append(", "); //$NON-NLS-1$
675
}
676                         }
677                         buf.append(")"); //$NON-NLS-1$
678
}
679                     
680                 }
681                 buf.append("), "); //$NON-NLS-1$
682
}
683         }
684             
685         getLayout().describeLayout(buf);
686     }
687
688     /**
689      * Deref a given part. Deconstruct its container as required. Do not remove
690      * drag listeners.
691      */

692     /* package */void derefPart(LayoutPart part) {
693         if (part instanceof ViewPane) {
694             IViewReference ref = ((ViewPane) part).getViewReference();
695             if (perspective.isFastView(ref)) {
696                 // Special check: if it's a fast view then it's actual ViewStack
697
// may only contain placeholders and the stack is represented in
698
// the presentation by a container placeholder...make sure the
699
// PartPlaceHolder for 'ref' is removed from the ViewStack
700
String JavaDoc id = perspective.getFastViewManager().getIdForRef(ref);
701                 LayoutPart parentPart = findPart(id, null);
702                 if (parentPart instanceof ContainerPlaceholder) {
703                     ViewStack vs = (ViewStack) ((ContainerPlaceholder)parentPart).getRealContainer();
704                     LayoutPart[] kids = vs.getChildren();
705                     for (int i = 0; i < kids.length; i++) {
706                         if (kids[i] instanceof PartPlaceholder) {
707                             if (ref.getId().equals(kids[i].id))
708                                 vs.remove(kids[i]);
709                         }
710                     }
711                 }
712                 perspective.getFastViewManager().removeViewReference(ref, true, true);
713             }
714         }
715
716         // Get vital part stats before reparenting.
717
ILayoutContainer oldContainer = part.getContainer();
718         boolean wasDocked = part.isDocked();
719         Shell oldShell = part.getShell();
720
721         // Reparent the part back to the main window
722
part.reparent(mainLayout.getParent());
723
724         // Update container.
725
if (oldContainer == null) {
726             return;
727         }
728
729         oldContainer.remove(part);
730
731         LayoutPart[] children = oldContainer.getChildren();
732         if (wasDocked) {
733             boolean hasChildren = (children != null) && (children.length > 0);
734             if (hasChildren) {
735                 // make sure one is at least visible
736
int childVisible = 0;
737                 for (int i = 0; i < children.length; i++) {
738                     if (children[i].getControl() != null) {
739                         childVisible++;
740                     }
741                 }
742
743                 // none visible, then reprarent and remove container
744
if (oldContainer instanceof ViewStack) {
745                     ViewStack folder = (ViewStack) oldContainer;
746                     
747                     // Is the part in the trim?
748
boolean inTrim = false;
749                     // Safety check...there may be no FastViewManager
750
if (perspective.getFastViewManager() != null)
751                         inTrim = perspective.getFastViewManager().getFastViews(folder.getID()).size() > 0;
752                         
753                     if (childVisible == 0 && !inTrim) {
754                         ILayoutContainer parentContainer = folder
755                                 .getContainer();
756                         for (int i = 0; i < children.length; i++) {
757                             folder.remove(children[i]);
758                             parentContainer.add(children[i]);
759                         }
760                         hasChildren = false;
761                     } else if (childVisible == 1) {
762                         LayoutTree layout = mainLayout.getLayoutTree();
763                         layout = layout.find(folder);
764                         layout.setBounds(layout.getBounds());
765                     }
766                 }
767             }
768
769             if (!hasChildren) {
770                 // There are no more children in this container, so get rid of
771
// it
772
if (oldContainer instanceof LayoutPart) {
773                     LayoutPart parent = (LayoutPart) oldContainer;
774                     ILayoutContainer parentContainer = parent.getContainer();
775                     if (parentContainer != null) {
776                         parentContainer.remove(parent);
777                         parent.dispose();
778                     }
779                 }
780             }
781         } else if (!wasDocked) {
782             if (children == null || children.length == 0) {
783                 // There are no more children in this container, so get rid of
784
// it
785
// Turn on redraw again just in case it was off.
786
//oldShell.setRedraw(true);
787
DetachedWindow w = (DetachedWindow)oldShell.getData();
788                 oldShell.close();
789                 detachedWindowList.remove(w);
790             } else {
791                 // There are children. If none are visible hide detached
792
// window.
793
boolean allInvisible = true;
794                 for (int i = 0, length = children.length; i < length; i++) {
795                     if (!(children[i] instanceof PartPlaceholder)) {
796                         allInvisible = false;
797                         break;
798                     }
799                 }
800                 if (allInvisible) {
801                     DetachedPlaceHolder placeholder = new DetachedPlaceHolder(
802                             "", //$NON-NLS-1$
803
oldShell.getBounds());
804                     for (int i = 0, length = children.length; i < length; i++) {
805                         oldContainer.remove(children[i]);
806                         children[i].setContainer(placeholder);
807                         placeholder.add(children[i]);
808                     }
809                     detachedPlaceHolderList.add(placeholder);
810                     DetachedWindow w = (DetachedWindow)oldShell.getData();
811                     oldShell.close();
812                     detachedWindowList.remove(w);
813                 }
814             }
815         }
816
817     }
818
819     /**
820      * Create a detached window containing a part.
821      */

822     private void detach(LayoutPart source, int x, int y) {
823
824         // Detaching is disabled on some platforms ..
825
if (!detachable) {
826             return;
827         }
828
829         LayoutPart part = source.getPart();
830         // Calculate detached window size.
831
Point size = part.getSize();
832         if (size.x == 0 || size.y == 0) {
833             ILayoutContainer container = part.getContainer();
834             if (container instanceof LayoutPart) {
835                 size = ((LayoutPart) container).getSize();
836             }
837         }
838         int width = Math.max(size.x, MIN_DETACH_WIDTH);
839         int height = Math.max(size.y, MIN_DETACH_HEIGHT);
840
841         // Create detached window.
842
DetachedWindow window = new DetachedWindow(page);
843         detachedWindowList.add(window);
844
845         // Open window.
846
window.create();
847         window.getShell().setBounds(x, y, width, height);
848         window.open();
849
850         if (part instanceof ViewStack) {
851             window.getShell().setRedraw(false);
852             parentWidget.setRedraw(false);
853             LayoutPart visiblePart = ((ViewStack) part).getSelection();
854             LayoutPart children[] = ((ViewStack) part).getChildren();
855             for (int i = 0; i < children.length; i++) {
856                 if (children[i] instanceof ViewPane) {
857                     // remove the part from its current container
858
derefPart(children[i]);
859                     // add part to detached window.
860
ViewPane pane = (ViewPane) children[i];
861                     window.add(pane);
862                 }
863             }
864             if (visiblePart != null) {
865                 bringPartToTop(visiblePart);
866                 visiblePart.setFocus();
867             }
868             window.getShell().setRedraw(true);
869             parentWidget.setRedraw(true);
870         } else {
871             // remove the part from its current container
872
derefPart(part);
873             // add part to detached window.
874
ViewPane pane = (ViewPane) part;
875             window.add(pane);
876             part.setFocus();
877         }
878
879     }
880     
881     /**
882      * Detached a part from the mainLayout. Presently this does not use placeholders
883      * since the current implementation is not robust enough to remember a view's position
884      * in more than one root container. For now the view is simply derefed and will dock
885      * in the default position when attachPart is called.
886      *
887      * By default parts detached this way are set to float on top of the workbench
888      * without docking. It is assumed that people that want to drag a part back onto
889      * the WorkbenchWindow will detach it via drag and drop.
890      *
891      * @param ref
892      */

893     public void detachPart(IViewReference ref) {
894         ViewPane pane = (ViewPane)((WorkbenchPartReference)ref).getPane();
895         if (canDetach() && pane != null) {
896             Rectangle bounds = pane.getParentBounds();
897             detach(pane, bounds.x ,bounds.y);
898         }
899     }
900
901     /**
902      * Create a detached window containing a part.
903      */

904     public void addDetachedPart(LayoutPart part) {
905         // Calculate detached window size.
906
Rectangle bounds = parentWidget.getShell().getBounds();
907         bounds.x = bounds.x + (bounds.width - 300) / 2;
908         bounds.y = bounds.y + (bounds.height - 300) / 2;
909         
910         addDetachedPart(part, bounds);
911     }
912     
913     public void addDetachedPart(LayoutPart part, Rectangle bounds) {
914         // Detaching is disabled on some platforms ..
915
if (!detachable) {
916             addPart(part);
917             return;
918         }
919         
920         // Create detached window.
921
DetachedWindow window = new DetachedWindow(page);
922         detachedWindowList.add(window);
923         window.create();
924
925         // add part to detached window.
926
part.createControl(window.getShell());
927         ViewPane pane = (ViewPane) part;
928         window.add(pane);
929
930         // Open window.
931
window.getShell().setBounds(bounds.x, bounds.y, bounds.width, bounds.height);
932         window.open();
933
934         part.setFocus();
935         
936     }
937
938     /**
939      * disableDragging.
940      */

941     private void disableAllDrag() {
942         DragUtil.removeDragTarget(null, dragTarget);
943     }
944
945     /**
946      * enableDragging.
947      */

948     private void enableAllDrag() {
949         DragUtil.addDragTarget(null, dragTarget);
950     }
951
952     /**
953      * Find the first part with a given ID in the presentation.
954      * Wild cards now supported.
955      */

956     private LayoutPart findPart(String JavaDoc id) {
957         return findPart(id, null);
958     }
959
960     /**
961      * Find the first part that matches the specified
962      * primary and secondary id pair. Wild cards
963      * are supported.
964      */

965     public LayoutPart findPart(String JavaDoc primaryId, String JavaDoc secondaryId) {
966         // check main window.
967
ArrayList JavaDoc matchingParts = new ArrayList JavaDoc();
968         LayoutPart part = (secondaryId != null) ? findPart(primaryId,
969                 secondaryId, mainLayout.getChildren(), matchingParts)
970                 : findPart(primaryId, mainLayout.getChildren(), matchingParts);
971         if (part != null) {
972             return part;
973         }
974
975         // check each detached windows.
976
for (int i = 0, length = detachedWindowList.size(); i < length; i++) {
977             DetachedWindow window = (DetachedWindow) detachedWindowList.get(i);
978             part = (secondaryId != null) ? findPart(primaryId, secondaryId,
979                     window.getChildren(), matchingParts) : findPart(primaryId,
980                     window.getChildren(), matchingParts);
981             if (part != null) {
982                 return part;
983             }
984         }
985         for (int i = 0; i < detachedPlaceHolderList.size(); i++) {
986             DetachedPlaceHolder holder = (DetachedPlaceHolder) detachedPlaceHolderList
987                     .get(i);
988             part = (secondaryId != null) ? findPart(primaryId, secondaryId,
989                     holder.getChildren(), matchingParts) : findPart(primaryId,
990                     holder.getChildren(), matchingParts);
991             if (part != null) {
992                 return part;
993             }
994         }
995
996         // sort the matching parts
997
if (matchingParts.size() > 0) {
998             Collections.sort(matchingParts);
999             MatchingPart mostSignificantPart = (MatchingPart) matchingParts
1000                    .get(0);
1001            if (mostSignificantPart != null) {
1002                return mostSignificantPart.part;
1003            }
1004        }
1005
1006        // Not found.
1007
return null;
1008    }
1009
1010    /**
1011     * Find the first part with a given ID in the presentation.
1012     */

1013    private LayoutPart findPart(String JavaDoc id, LayoutPart[] parts,
1014            ArrayList JavaDoc matchingParts) {
1015        for (int i = 0, length = parts.length; i < length; i++) {
1016            LayoutPart part = parts[i];
1017            // check for part equality, parts with secondary ids fail
1018
if (part.getID().equals(id)) {
1019                if (part instanceof ViewPane) {
1020                    ViewPane pane = (ViewPane) part;
1021                    IViewReference ref = (IViewReference) pane
1022                            .getPartReference();
1023                    if (ref.getSecondaryId() != null) {
1024                        continue;
1025                    }
1026                }
1027                return part;
1028            }
1029            // check pattern matching placeholders
1030
else if (part instanceof PartPlaceholder
1031                    && ((PartPlaceholder) part).hasWildCard()) {
1032                StringMatcher sm = new StringMatcher(part.getID(), true, false);
1033                if (sm.match(id)) {
1034                    matchingParts
1035                            .add(new MatchingPart(part.getID(), null, part));
1036                }
1037            } else if (part instanceof EditorSashContainer) {
1038                // Skip.
1039
} else if (part instanceof ILayoutContainer) {
1040                part = findPart(id, ((ILayoutContainer) part).getChildren(),
1041                        matchingParts);
1042                if (part != null) {
1043                    return part;
1044                }
1045            }
1046        }
1047        return null;
1048    }
1049
1050    /**
1051     * Find the first part that matches the specified
1052     * primary and secondary id pair. Wild cards
1053     * are supported.
1054     */

1055    private LayoutPart findPart(String JavaDoc primaryId, String JavaDoc secondaryId,
1056            LayoutPart[] parts, ArrayList JavaDoc matchingParts) {
1057        for (int i = 0, length = parts.length; i < length; i++) {
1058            LayoutPart part = parts[i];
1059            // check containers first
1060
if (part instanceof ILayoutContainer) {
1061                LayoutPart testPart = findPart(primaryId, secondaryId,
1062                        ((ILayoutContainer) part).getChildren(), matchingParts);
1063                if (testPart != null) {
1064                    return testPart;
1065                }
1066            }
1067            // check for view part equality
1068
if (part instanceof ViewPane) {
1069                ViewPane pane = (ViewPane) part;
1070                IViewReference ref = (IViewReference) pane.getPartReference();
1071                if (ref.getId().equals(primaryId)
1072                        && ref.getSecondaryId() != null
1073                        && ref.getSecondaryId().equals(secondaryId)) {
1074                    return part;
1075                }
1076            }
1077            // check placeholders
1078
else if ((parts[i] instanceof PartPlaceholder)) {
1079                String JavaDoc id = part.getID();
1080
1081                // optimization: don't bother parsing id if it has no separator -- it can't match
1082
String JavaDoc phSecondaryId = ViewFactory.extractSecondaryId(id);
1083                if (phSecondaryId == null) {
1084                    // but still need to check for wildcard case
1085
if (id.equals(PartPlaceholder.WILD_CARD)) {
1086                        matchingParts.add(new MatchingPart(id, null, part));
1087                    }
1088                    continue;
1089                }
1090
1091                String JavaDoc phPrimaryId = ViewFactory.extractPrimaryId(id);
1092                // perfect matching pair
1093
if (phPrimaryId.equals(primaryId)
1094                        && phSecondaryId.equals(secondaryId)) {
1095                    return part;
1096                }
1097                // check for partial matching pair
1098
StringMatcher sm = new StringMatcher(phPrimaryId, true, false);
1099                if (sm.match(primaryId)) {
1100                    sm = new StringMatcher(phSecondaryId, true, false);
1101                    if (sm.match(secondaryId)) {
1102                        matchingParts.add(new MatchingPart(phPrimaryId,
1103                                phSecondaryId, part));
1104                    }
1105                }
1106            } else if (part instanceof EditorSashContainer) {
1107                // Skip.
1108
}
1109        }
1110        return null;
1111    }
1112
1113    /**
1114     * Returns true if a placeholder exists for a given ID.
1115     */

1116    public boolean hasPlaceholder(String JavaDoc id) {
1117        return hasPlaceholder(id, null);
1118    }
1119
1120    /**
1121     * Returns true if a placeholder exists for a given ID.
1122     * @since 3.0
1123     */

1124    public boolean hasPlaceholder(String JavaDoc primaryId, String JavaDoc secondaryId) {
1125        LayoutPart testPart;
1126        if (secondaryId == null) {
1127            testPart = findPart(primaryId);
1128        } else {
1129            testPart = findPart(primaryId, secondaryId);
1130        }
1131        return (testPart != null && testPart instanceof PartPlaceholder);
1132    }
1133
1134    /**
1135     * Returns the layout container.
1136     */

1137    public ViewSashContainer getLayout() {
1138        return mainLayout;
1139    }
1140
1141    /**
1142     * Gets the active state.
1143     */

1144    public boolean isActive() {
1145        return active;
1146    }
1147
1148    /**
1149     * Returns whether the presentation is zoomed.
1150     *
1151     * <strong>NOTE:</strong> As of 3.3 this method should always return 'false'
1152     * when using the new min/max behavior. It is only used for
1153     * legacy 'zoom' handling.
1154     */

1155    public boolean isZoomed() {
1156        return mainLayout.getZoomedPart() != null;
1157    }
1158
1159    /**
1160     * @return The currently maxmized stack (if any)
1161     */

1162    public PartStack getMaximizedStack() {
1163        return maximizedStack;
1164    }
1165
1166    /**
1167     * Sets the currently maximized stack. Used for query
1168     * and 'unZoom' purposes in the 3.3 presentation.
1169     *
1170     * @param stack The newly maximized stack
1171     */

1172    public void setMaximizedStack(PartStack stack) {
1173        if (stack == maximizedStack)
1174            return;
1175        
1176        maximizedStack = stack;
1177    }
1178    
1179    /**
1180     * Returns the ratio that should be used when docking the given source
1181     * part onto the given target
1182     *
1183     * @param source newly added part
1184     * @param target existing part being dragged over
1185     * @return the final size of the source part (wrt the current size of target)
1186     * after it is docked
1187     */

1188    public static float getDockingRatio(LayoutPart source, LayoutPart target) {
1189        if ((source instanceof ViewPane || source instanceof ViewStack)
1190                && target instanceof EditorSashContainer) {
1191            return 0.25f;
1192        }
1193        return 0.5f;
1194    }
1195
1196    /**
1197     * Returns whether changes to a part will affect zoom. There are a few
1198     * conditions for this .. - we are zoomed. - the part is contained in the
1199     * main window. - the part is not the zoom part - the part is not a fast
1200     * view - the part and the zoom part are not in the same editor workbook
1201     * - the part and the zoom part are not in the same view stack.
1202     */

1203    public boolean partChangeAffectsZoom(LayoutPart pane) {
1204        return pane.isObscuredByZoom();
1205    }
1206    
1207    /**
1208     * Remove all references to a part.
1209     */

1210    public void removePart(LayoutPart part) {
1211
1212        // Reparent the part back to the main window
1213
Composite parent = mainLayout.getParent();
1214        part.reparent(parent);
1215
1216        // Replace part with a placeholder
1217
ILayoutContainer container = part.getContainer();
1218        if (container != null) {
1219            String JavaDoc placeHolderId = part.getPlaceHolderId();
1220            container.replace(part, new PartPlaceholder(placeHolderId));
1221
1222            // If the parent is root we're done. Do not try to replace
1223
// it with placeholder.
1224
if (container == mainLayout) {
1225                return;
1226            }
1227
1228            // If the parent is empty replace it with a placeholder.
1229
LayoutPart[] children = container.getChildren();
1230            if (children != null) {
1231                boolean allInvisible = true;
1232                for (int i = 0, length = children.length; i < length; i++) {
1233                    if (!(children[i] instanceof PartPlaceholder)) {
1234                        allInvisible = false;
1235                        break;
1236                    }
1237                }
1238                if (allInvisible && (container instanceof LayoutPart)) {
1239                    // what type of window are we in?
1240
LayoutPart cPart = (LayoutPart) container;
1241                    //Window oldWindow = cPart.getWindow();
1242
boolean wasDocked = cPart.isDocked();
1243                    Shell oldShell = cPart.getShell();
1244                    if (wasDocked) {
1245                        
1246                        // PR 1GDFVBY: ViewStack not disposed when page
1247
// closed.
1248
if (container instanceof ViewStack) {
1249                            ((ViewStack) container).dispose();
1250                        }
1251                        
1252                        // replace the real container with a
1253
// ContainerPlaceholder
1254
ILayoutContainer parentContainer = cPart.getContainer();
1255                        ContainerPlaceholder placeholder = new ContainerPlaceholder(
1256                                cPart.getID());
1257                        placeholder.setRealContainer(container);
1258                        parentContainer.replace(cPart, placeholder);
1259                        
1260                    } else {
1261                        DetachedPlaceHolder placeholder = new DetachedPlaceHolder(
1262                                "", oldShell.getBounds()); //$NON-NLS-1$
1263
for (int i = 0, length = children.length; i < length; i++) {
1264                            children[i].getContainer().remove(children[i]);
1265                            children[i].setContainer(placeholder);
1266                            placeholder.add(children[i]);
1267                        }
1268                        detachedPlaceHolderList.add(placeholder);
1269                        DetachedWindow w = (DetachedWindow)oldShell.getData();
1270                        oldShell.close();
1271                        detachedWindowList.remove(w);
1272                    }
1273                }
1274            }
1275        }
1276    }
1277
1278    /**
1279     * Add a part to the presentation.
1280     *
1281     * Note: unlike all other LayoutParts, PartPlaceholders will still point to
1282     * their parent container even when it is inactive. This method relies on this
1283     * fact to locate the parent.
1284     */

1285    public void replacePlaceholderWithPart(LayoutPart part) {
1286        
1287        // Look for a PartPlaceholder that will tell us how to position this
1288
// object
1289
PartPlaceholder[] placeholders = collectPlaceholders();
1290        for (int i = 0, length = placeholders.length; i < length; i++) {
1291            if (placeholders[i].getCompoundId().equals(part.getCompoundId())) {
1292                // found a matching placeholder which we can replace with the
1293
// new View
1294
ILayoutContainer container = placeholders[i].getContainer();
1295                if (container != null) {
1296                    if (container instanceof ContainerPlaceholder) {
1297                        // One of the children is now visible so replace the
1298
// ContainerPlaceholder with the real container
1299
ContainerPlaceholder containerPlaceholder = (ContainerPlaceholder) container;
1300                        ILayoutContainer parentContainer = containerPlaceholder
1301                                .getContainer();
1302                        container = (ILayoutContainer) containerPlaceholder
1303                                .getRealContainer();
1304                        if (container instanceof LayoutPart) {
1305                            parentContainer.replace(containerPlaceholder,
1306                                    (LayoutPart) container);
1307                        }
1308                        containerPlaceholder.setRealContainer(null);
1309                    }
1310                    container.replace(placeholders[i], part);
1311                    return;
1312                }
1313            }
1314        }
1315
1316    }
1317
1318    /**
1319     * @see org.eclipse.ui.IPersistable
1320     */

1321    public IStatus restoreState(IMemento memento) {
1322        // Restore main window.
1323
IMemento childMem = memento
1324                .getChild(IWorkbenchConstants.TAG_MAIN_WINDOW);
1325        IStatus r = mainLayout.restoreState(childMem);
1326
1327        // Restore each floating window.
1328
if (detachable) {
1329            IMemento detachedWindows[] = memento
1330                    .getChildren(IWorkbenchConstants.TAG_DETACHED_WINDOW);
1331            for (int nX = 0; nX < detachedWindows.length; nX++) {
1332                DetachedWindow win = new DetachedWindow(page);
1333                detachedWindowList.add(win);
1334                win.restoreState(detachedWindows[nX]);
1335            }
1336            IMemento childrenMem[] = memento
1337                    .getChildren(IWorkbenchConstants.TAG_HIDDEN_WINDOW);
1338            for (int i = 0, length = childrenMem.length; i < length; i++) {
1339                DetachedPlaceHolder holder = new DetachedPlaceHolder(
1340                        "", new Rectangle(0, 0, 0, 0)); //$NON-NLS-1$
1341
holder.restoreState(childrenMem[i]);
1342                detachedPlaceHolderList.add(holder);
1343            }
1344        }
1345        
1346        // Get the cached id of the currently maximized stack
1347
maximizedStackId = childMem.getString(IWorkbenchConstants.TAG_MAXIMIZED);
1348        
1349        return r;
1350    }
1351
1352    /**
1353     * @see org.eclipse.ui.IPersistable
1354     */

1355    public IStatus saveState(IMemento memento) {
1356        // Persist main window.
1357
IMemento childMem = memento
1358                .createChild(IWorkbenchConstants.TAG_MAIN_WINDOW);
1359        IStatus r = mainLayout.saveState(childMem);
1360
1361        if (detachable) {
1362            // Persist each detached window.
1363
for (int i = 0, length = detachedWindowList.size(); i < length; i++) {
1364                DetachedWindow window = (DetachedWindow) detachedWindowList
1365                        .get(i);
1366                childMem = memento
1367                        .createChild(IWorkbenchConstants.TAG_DETACHED_WINDOW);
1368                window.saveState(childMem);
1369            }
1370            for (int i = 0, length = detachedPlaceHolderList.size(); i < length; i++) {
1371                DetachedPlaceHolder holder = (DetachedPlaceHolder) detachedPlaceHolderList
1372                        .get(i);
1373                childMem = memento
1374                        .createChild(IWorkbenchConstants.TAG_HIDDEN_WINDOW);
1375                holder.saveState(childMem);
1376            }
1377        }
1378        
1379        // Write out the id of the maximized (View) stack (if any)
1380
// NOTE: we only write this out if it's a ViewStack since the
1381
// Editor Area is handled by the perspective
1382
if (maximizedStack instanceof ViewStack) {
1383            childMem.putString(IWorkbenchConstants.TAG_MAXIMIZED, maximizedStack.getID());
1384        }
1385        else if (maximizedStackId != null) {
1386            // Maintain the cache if the perspective has never been activated
1387
childMem.putString(IWorkbenchConstants.TAG_MAXIMIZED, maximizedStackId);
1388        }
1389        
1390        return r;
1391    }
1392
1393    /**
1394     * Zoom in on a particular layout part.
1395     */

1396    public void zoomIn(IWorkbenchPartReference ref) {
1397        PartPane pane = ((WorkbenchPartReference) ref).getPane();
1398
1399
1400        parentWidget.setRedraw(false);
1401        try {
1402            pane.requestZoomIn();
1403        } finally {
1404            parentWidget.setRedraw(true);
1405        }
1406    }
1407
1408    /**
1409     * Zoom out.
1410     */

1411    public void zoomOut() {
1412        // New 3.3 behavior
1413
if (Perspective.useNewMinMax(perspective)) {
1414             if (maximizedStack != null)
1415                 maximizedStack.setState(IStackPresentationSite.STATE_RESTORED);
1416             return;
1417        }
1418        
1419        LayoutPart zoomPart = mainLayout.getZoomedPart();
1420        if (zoomPart != null) {
1421            zoomPart.requestZoomOut();
1422        }
1423    }
1424
1425    /**
1426     * Forces the perspective to have no zoomed or minimized parts.
1427     * This is used when switching to the 3.3 presentation...
1428     */

1429    public void forceNoZoom() {
1430        // Ensure that nobody's zoomed
1431
zoomOut();
1432        
1433        // Now, walk the layout ensuring that nothing is minimized
1434
LayoutPart[] kids = mainLayout.getChildren();
1435        for (int i = 0; i < kids.length; i++) {
1436            if (kids[i] instanceof ViewStack) {
1437                ((ViewStack)kids[i]).setMinimized(false);
1438            }
1439            else if (kids[i] instanceof EditorSashContainer) {
1440                LayoutPart[] editorStacks = ((EditorSashContainer)kids[i]).getChildren();
1441                for (int j = 0; j < editorStacks.length; j++) {
1442                    if (editorStacks[j] instanceof EditorStack) {
1443                        ((EditorStack)editorStacks[j]).setMinimized(false);
1444                    }
1445                }
1446            }
1447        }
1448    }
1449
1450    /**
1451     * Captures the current bounds of all ViewStacks and the editor
1452     * area and puts them into an ID -> Rectangle map. This info is
1453     * used to cache the bounds so that we can correctly place minimized
1454     * stacks during a 'maximized' operation (where the iterative min's
1455     * affect the current layout while being performed.
1456     */

1457    public void updateBoundsMap() {
1458        boundsMap.clear();
1459        
1460        // Walk the layout gathering the current bounds of each stack
1461
// and the editor area
1462
LayoutPart[] kids = mainLayout.getChildren();
1463        for (int i = 0; i < kids.length; i++) {
1464            if (kids[i] instanceof ViewStack) {
1465                ViewStack vs = (ViewStack)kids[i];
1466                boundsMap.put(vs.getID(), vs.getBounds());
1467            }
1468            else if (kids[i] instanceof EditorSashContainer) {
1469                EditorSashContainer esc = (EditorSashContainer)kids[i];
1470                boundsMap.put(esc.getID(), esc.getBounds());
1471            }
1472        }
1473    }
1474
1475    /**
1476     * Resets the bounds map so that it won't interfere with normal minimize
1477     * operayions
1478     */

1479    public void resetBoundsMap() {
1480        boundsMap.clear();
1481    }
1482    
1483    public Rectangle getCachedBoundsFor(String JavaDoc id) {
1484        return (Rectangle) boundsMap.get(id);
1485    }
1486}
1487
Popular Tags