Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/eclipse/ui/internal/PartStack.java


1   /*******************************************************************************
2    * Copyright (c) 2004 IBM Corporation and others.
3    * All rights reserved. This program and the accompanying materials 
4    * are made available under the terms of the Common Public License v1.0
5    * which accompanies this distribution, and is available at
6    * http://www.eclipse.org/legal/cpl-v10.html
7    * 
8    * Contributors:
9    *     IBM Corporation - initial API and implementation
10   *******************************************************************************/
11  package org.eclipse.ui.internal;
12  
13  import java.util.ArrayList;
14  import java.util.Arrays;
15  import java.util.Iterator;
16  import java.util.List;
17  
18  import org.eclipse.core.runtime.IStatus;
19  import org.eclipse.core.runtime.Status;
20  import org.eclipse.jface.action.ContributionItem;
21  import org.eclipse.jface.action.IMenuManager;
22  import org.eclipse.jface.util.Assert;
23  import org.eclipse.jface.util.Geometry;
24  import org.eclipse.jface.window.Window;
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.Display;
31  import org.eclipse.ui.IMemento;
32  import org.eclipse.ui.IWorkbenchPartReference;
33  import org.eclipse.ui.PlatformUI;
34  import org.eclipse.ui.XMLMemento;
35  import org.eclipse.ui.internal.dnd.DragUtil;
36  import org.eclipse.ui.internal.dnd.IDragOverListener;
37  import org.eclipse.ui.internal.dnd.IDropTarget;
38  import org.eclipse.ui.internal.dnd.SwtUtil;
39  import org.eclipse.ui.internal.presentations.PresentationFactoryUtil;
40  import org.eclipse.ui.internal.presentations.PresentationSerializer;
41  import org.eclipse.ui.internal.util.Util;
42  import org.eclipse.ui.presentations.AbstractPresentationFactory;
43  import org.eclipse.ui.presentations.IPresentablePart;
44  import org.eclipse.ui.presentations.IStackPresentationSite;
45  import org.eclipse.ui.presentations.StackDropResult;
46  import org.eclipse.ui.presentations.StackPresentation;
47  
48  /**
49   * Implements the common behavior for stacks of Panes (ie: EditorStack and ViewStack)
50   * This layout container has PartPanes as children and belongs to a PartSashContainer.
51   * 
52   * @since 3.0
53   */
54  public abstract class PartStack extends LayoutPart implements ILayoutContainer {
55  
56      private List children = new ArrayList(3);
57      protected int appearance = PresentationFactoryUtil.ROLE_VIEW;
58  
59      // inactiveCurrent is only used when restoring the persisted state of
60      // perspective on startup.
61      private LayoutPart current;
62      
63      private boolean ignoreSelectionChanges = false;
64      
65      protected IMemento savedPresentationState = null;
66  
67      private DefaultStackPresentationSite presentationSite = new DefaultStackPresentationSite() {
68  
69          public void close(IPresentablePart part) {
70              PartStack.this.close(part);
71          }
72          
73      public void close(IPresentablePart[] parts) {
74        PartStack.this.close(parts);
75      }
76  
77          public void dragStart(IPresentablePart beingDragged, Point initialLocation, boolean keyboard) {
78            PartStack.this.dragStart(beingDragged, initialLocation, keyboard);
79          }
80  
81          public void dragStart(Point initialLocation, boolean keyboard) {
82            PartStack.this.dragStart(null, initialLocation, keyboard);
83          }
84  
85          public boolean isCloseable(IPresentablePart part) {
86            return PartStack.this.isCloseable(part);
87          }
88  
89          public boolean isPartMoveable(IPresentablePart part) {
90            return PartStack.this.isMoveable(part);
91          }
92  
93          public void selectPart(IPresentablePart toSelect) {
94            PartStack.this.presentationSelectionChanged(toSelect);
95          }
96  
97          public boolean supportsState(int state) {
98            return PartStack.this.supportsState(state);
99          }
100         
101         public void setState(int newState) {
102             PartStack.this.setState(newState);
103         }
104 
105     public IPresentablePart getSelectedPart() {
106       return PartStack.this.getSelectedPart();
107     }
108     
109     public void addSystemActions(IMenuManager menuManager) {
110       PartStack.this.addSystemActions(menuManager);
111     }
112 
113     public boolean isStackMoveable() {
114       return canMoveFolder();
115     }
116     };
117     
118     protected abstract boolean isMoveable(IPresentablePart part);
119   protected abstract boolean isCloseable(IPresentablePart part);
120   protected abstract void addSystemActions(IMenuManager menuManager);
121   protected abstract boolean supportsState(int newState);
122     protected abstract boolean canMoveFolder();
123     protected abstract void derefPart(LayoutPart toDeref);
124     protected abstract boolean allowsDrop(PartPane part);
125   
126     protected static void appendToGroupIfPossible(IMenuManager m, String groupId, ContributionItem item) {
127       try {
128         m.appendToGroup(groupId, item);
129       } catch (IllegalArgumentException e) {
130         m.add(item);
131       }
132     }
133     
134     /**
135      * Creates a new PartStack, given a constant determining which presentation to use
136      * 
137      * @param appearance one of the PresentationFactoryUtil.ROLE_* constants
138      */
139     public PartStack(int appearance) {
140         super("PartStack"); //$NON-NLS-1$
141         
142         this.appearance = appearance;
143     }
144 
145     /**
146      * Returns the currently selected IPresentablePart, or null if none
147      * 
148      * @return
149      */
150     protected IPresentablePart getSelectedPart() {
151     if (current == null) {
152       return null;
153     }
154     
155     return current.getPresentablePart();
156     }
157 
158     protected IStackPresentationSite getPresentationSite() {
159       return presentationSite;
160     }
161 
162     /**
163      * Tests the integrity of this object. Throws an exception if the object's state
164      * is invalid. For use in test suites.
165      */
166     public void testInvariants() {
167       Control focusControl = Display.getCurrent().getFocusControl();
168       
169       boolean currentFound = false;
170       
171       LayoutPart[] children = getChildren();
172       
173       for (int idx = 0; idx < children.length; idx++) {
174         LayoutPart child = children[idx];
175         
176         // No null children allowed
177         Assert.isNotNull(child, "null children are not allowed in PartStack"); //$NON-NLS-1$
178         
179         // This object can only contain placeholders or PartPanes
180         Assert.isTrue(child instanceof PartPlaceholder || child instanceof PartPane, 
181             "PartStack can only contain PartPlaceholders or PartPanes"); //$NON-NLS-1$
182         
183         // Ensure that all the PartPanes have an associated presentable part 
184         IPresentablePart part = child.getPresentablePart();
185         if (child instanceof PartPane) {
186           Assert.isNotNull(part, "All PartPanes must have a non-null IPresentablePart"); //$NON-NLS-1$
187         }
188         
189         // Ensure that the child's backpointer points to this stack
190         ILayoutContainer childContainer = child.getContainer();
191 
192       // Disable tests for placeholders -- PartPlaceholder backpointers don't
193       // obey the usual rules -- they sometimes point to a container placeholder
194       // for this stack instead of the real stack.
195       if (!(child instanceof PartPlaceholder)) {
196         
197           if (isDisposed()) {
198   
199             // Currently, we allow null backpointers if the widgetry is disposed.
200             // However, it is never valid for the child to have a parent other than
201             // this object
202             if (childContainer != null) {
203               Assert.isTrue(childContainer == this, 
204                   "PartStack has a child that thinks it has a different parent"); //$NON-NLS-1$
205             }
206           } else {
207             // If the widgetry exists, the child's backpointer must point to us
208             Assert.isTrue(childContainer == this, 
209               "PartStack has a child that thinks it has a different parent"); //$NON-NLS-1$
210             
211               // If this child has focus, then ensure that it is selected and that we have
212               // the active appearance.
213               
214               if (SwtUtil.isChild(child.getControl(), focusControl)) {
215                 Assert.isTrue(child == current, "The part with focus is not the selected part"); //$NON-NLS-1$
216   //  focus check commented out since it fails when focus workaround in LayoutPart.setVisible is not present             
217   //              Assert.isTrue(getActive() == StackPresentation.AS_ACTIVE_FOCUS);
218               }
219           }
220       }
221       
222         // Ensure that "current" points to a valid child
223         if (child == current) {
224           currentFound = true;
225         }
226         
227         // Test the child's internal state
228         child.testInvariants();
229       }
230       
231       // If we have at least one child, ensure that the "current" pointer points to one of them
232       if (!isDisposed() && getPresentableParts().size() > 0) {
233         Assert.isTrue(currentFound);
234         
235         if (!isDisposed()) {
236           StackPresentation presentation = getPresentation();
237           
238           // If the presentation controls have focus, ensure that we have the active appearance
239           if (SwtUtil.isChild(presentation.getControl(), focusControl)) {
240             Assert.isTrue(getActive() == StackPresentation.AS_ACTIVE_FOCUS,
241                 "The presentation has focus but does not have the active appearance"); //$NON-NLS-1$
242           }
243         }
244       }
245     }
246     
247   /* (non-Javadoc)
248    * @see org.eclipse.ui.internal.LayoutPart#describeLayout(java.lang.StringBuffer)
249    */
250   public void describeLayout(StringBuffer buf) {    
251     int activeState = getActive();
252     if (activeState == StackPresentation.AS_ACTIVE_FOCUS) {
253       buf.append("active "); //$NON-NLS-1$
254     } else if (activeState == StackPresentation.AS_ACTIVE_NOFOCUS) {
255       buf.append("active_nofocus "); //$NON-NLS-1$
256     }
257     
258     buf.append("("); //$NON-NLS-1$
259     
260     LayoutPart[] children = ((ILayoutContainer)this).getChildren();
261     
262     int visibleChildren = 0;
263     
264     for (int idx = 0; idx < children.length; idx++) {
265       
266       LayoutPart next = children[idx];
267       if (!(next instanceof PartPlaceholder)) {
268         if (idx > 0) {
269           buf.append(", "); //$NON-NLS-1$
270         }
271         
272         if (next == current) {
273           buf.append("*"); //$NON-NLS-1$
274         }
275         
276         next.describeLayout(buf);
277         
278         visibleChildren++;        
279       }
280     }
281     
282     buf.append(")"); //$NON-NLS-1$
283   }
284   
285     /**
286      * See IVisualContainer#add
287      */
288     public void add(LayoutPart child) {
289         children.add(child);
290         showPart(child, null);
291     }
292     
293     /**
294      * Add a part at a particular position
295      */
296     protected void add(LayoutPart newChild, Object cookie) {
297         children.add(newChild);
298 
299         showPart(newChild, cookie);
300     }
301 
302     /*
303      * (non-Javadoc)
304      * 
305      * @see org.eclipse.ui.internal.ILayoutContainer#allowsAutoFocus()
306      */
307     public boolean allowsAutoFocus() {
308         if (presentationSite.getState() == IStackPresentationSite.STATE_MINIMIZED) { return false; }
309 
310         ILayoutContainer parent = getContainer();
311 
312         if (parent != null && !parent.allowsAutoFocus()) { return false; }
313 
314         return true;
315     }
316 
317     /**
318    * @param parts
319    */
320   protected void close(IPresentablePart[] parts) {
321     for (int idx = 0; idx < parts.length; idx++) {
322       IPresentablePart part = parts[idx];
323       
324       close(part);
325     }
326   }
327     
328     /**
329      * @param part
330      */
331     protected void close(IPresentablePart part) {
332         if (!presentationSite.isCloseable(part)) { return; }
333 
334         LayoutPart layoutPart = getPaneFor(part);
335 
336         if (layoutPart != null && layoutPart instanceof PartPane) {
337             PartPane viewPane = (PartPane) layoutPart;
338             
339             viewPane.doHide();
340         }
341     }
342 
343     public boolean isDisposed() {
344       return getPresentation() == null;
345     }
346 
347     protected AbstractPresentationFactory getFactory() {
348         AbstractPresentationFactory factory = ((WorkbenchWindow) getPage()
349                 .getWorkbenchWindow()).getWindowConfigurer()
350                 .getPresentationFactory();
351 
352         return factory;
353     }
354     
355     public void createControl(Composite parent) {
356       if (!isDisposed()) {
357         return;
358       }
359       
360       AbstractPresentationFactory factory = getFactory();
361         
362         PresentationSerializer serializer = new PresentationSerializer(getPresentableParts());
363         
364         StackPresentation presentation = PresentationFactoryUtil.createPresentation(factory,
365             appearance, parent, presentationSite, serializer, savedPresentationState);
366 
367         createControl(parent, presentation);
368     }
369     
370     public void createControl(Composite parent, StackPresentation presentation) {
371 
372       Assert.isTrue(isDisposed());
373       
374         if (presentationSite.getPresentation() != null) return;
375 
376         presentationSite.setPresentation(presentation);
377 
378         // Add all visible children to the presentation
379         Iterator iter = children.iterator();
380         while (iter.hasNext()) {
381             LayoutPart part = (LayoutPart) iter.next();
382 
383             showPart(part, null);
384         }
385 
386         Control ctrl = getPresentation().getControl();
387 
388         // Add a drop target that lets us drag views directly to a particular
389         // tab
390         DragUtil.addDragTarget(ctrl, new IDragOverListener() {
391 
392             public IDropTarget drag(Control currentControl,
393                     final Object draggedObject, Point position,
394                     Rectangle dragRectangle) {
395 
396                 if (!(draggedObject instanceof PartPane)) { return null; }
397 
398                 final PartPane pane = (PartPane) draggedObject;
399                 if (!allowsDrop(pane)) {
400                   return null;
401                 }
402 
403                 // Don't allow views to be dragged between windows
404                 if (pane.getWorkbenchWindow() != getWorkbenchWindow()) { return null; }
405 
406                 // Regardless of the wishes of the presentation, ignore 4 pixels around the edge of the control.
407                 // This ensures that it will always be possible to dock around the edge of the control.
408                 {
409                   Point controlCoordinates = currentControl.getParent().toControl(position);
410                   Rectangle bounds = currentControl.getBounds();
411                   int closestSide = Geometry.getClosestSide(bounds, controlCoordinates);
412                   
413                   if (Geometry.getDistanceFromEdge(bounds, controlCoordinates, closestSide) < 5) {
414                     return null;
415                   }
416                 }
417                 // End of check for stacking on edge
418                 
419                 final StackDropResult dropResult = getPresentation().dragOver(
420                         currentControl, position);
421 
422                 if (dropResult == null) { return null; }
423 
424                 return new IDropTarget() {
425 
426                     public void drop() {
427                       
428                         // If we're dragging a pane over itself do nothing
429                       //if (dropResult.getInsertionPoint() == pane.getPresentablePart()) { return; };
430                       
431                         // Don't worry about reparenting the view if we're
432                         // simply rearranging tabs within this folder
433                         if (pane.getContainer() != PartStack.this) {
434                           derefPart(pane);
435                             pane.reparent(getParent());
436                         } else {
437                             remove(pane);
438                         }
439 
440                         add(pane, dropResult.getCookie());
441                         setSelection(pane);
442                         pane.setFocus();
443                     }
444 
445                     public Cursor getCursor() {
446                         return DragCursors.getCursor(DragCursors.CENTER);
447                     }
448 
449                     public Rectangle getSnapRectangle() {
450                         return dropResult.getSnapRectangle();
451                     }
452                 };
453             }
454 
455         });
456 
457         ctrl.setData(this);
458         
459         updateActions();
460         
461         // We should not have a placeholder selected once we've created the widgetry
462         if (current instanceof PartPlaceholder) {
463           current = null;
464           updateContainerVisibleTab();
465         }
466         
467         refreshPresentationSelection();
468         
469         Rectangle bounds = presentation.getControl().getBounds();
470         int minimumHeight = getMinimumHeight();
471 
472         if (presentationSite.getState() == IStackPresentationSite.STATE_MINIMIZED
473                 && bounds.height != minimumHeight) {
474             bounds.width = getMinimumWidth();
475             bounds.height = minimumHeight;
476             getPresentation().setBounds(bounds);
477         }
478     }
479 
480     /**
481      * Saves the current state of the presentation to savedPresentationState, if the
482      * presentation exists.
483      */
484     protected void savePresentationState() {
485       if (isDisposed()) {
486         return;
487       }
488       
489         {// Save the presentation's state before disposing it
490           XMLMemento memento = XMLMemento.createWriteRoot(IWorkbenchConstants.TAG_PRESENTATION);
491           memento.putString(IWorkbenchConstants.TAG_ID, getFactory().getId());
492           
493           PresentationSerializer serializer = new PresentationSerializer(getPresentableParts());
494           
495           getPresentation().saveState(serializer, memento);
496         
497           // Store the memento in savedPresentationState
498           savedPresentationState = memento;
499         }
500     }
501     
502     /**
503      * See LayoutPart#dispose
504      */
505     public void dispose() {
506 
507         if (isDisposed()) return;
508 
509         savePresentationState();
510         
511         presentationSite.dispose();
512 
513         Iterator iter = children.iterator();
514         while (iter.hasNext()) {
515             LayoutPart next = (LayoutPart) iter.next();
516 
517             next.setContainer(null);
518         }        
519     }
520     
521     public void findSashes(LayoutPart part, PartPane.Sashes sashes) {
522         ILayoutContainer container = getContainer();
523 
524         if (container != null) {
525             container.findSashes(this, sashes);
526         }
527     }
528 
529     /**
530      * Forces the layout to be recomputed for all parts
531      */
532     private void forceLayout() {
533         PartSashContainer cont = (PartSashContainer) getContainer();
534         if (cont != null) {
535             LayoutTree tree = cont.getLayoutTree();
536             tree.setBounds(getParent().getClientArea());
537         }
538     }
539 
540     /**
541      * Gets the presentation bounds.
542      */
543     public Rectangle getBounds() {
544         if (getPresentation() == null) { return new Rectangle(0, 0, 0, 0); }
545 
546         return getPresentation().getControl().getBounds();
547     }
548 
549     /**
550      * See IVisualContainer#getChildren
551      */
552     public LayoutPart[] getChildren() {
553         return (LayoutPart[]) children.toArray(new LayoutPart[children.size()]);
554     }
555 
556     public Control getControl() {
557         StackPresentation presentation = getPresentation();
558 
559         if (presentation == null) { 
560           return null; 
561         }
562 
563         return presentation.getControl();
564     }
565 
566     /**
567      * Answer the number of children.
568      */
569     public int getItemCount() {
570       if (isDisposed()) {
571         return children.size();
572       }
573         return getPresentableParts().size();
574     }
575 
576     // getMinimumHeight() added by cagatayk@acm.org
577     /**
578      * @see LayoutPart#getMinimumHeight()
579      */
580     public int getMinimumHeight() {
581         if (getPresentation() == null) { return 0; }
582 
583         return getPresentation().computeMinimumSize().y;
584     }
585 
586     /**
587      * Returns the LayoutPart for the given IPresentablePart, or null if the given
588      * IPresentablePart is not in this stack. Returns null if given a null argument.
589      * 
590      * @param part to locate or null
591      * @return
592      */
593     protected LayoutPart getPaneFor(IPresentablePart part) {
594       if (part == null) {
595         return null;
596       }
597       
598         Iterator iter = children.iterator();
599         while (iter.hasNext()) {
600             LayoutPart next = (LayoutPart) iter.next();
601 
602             if (next.getPresentablePart() == part) { return next; }
603         }
604 
605         return null;
606     }
607 
608     /**
609      * Get the parent control.
610      */
611     public Composite getParent() {
612         return getControl().getParent();
613     }
614 
615     private IPresentablePart getPresentablePartAtIndex(int idx) {
616         List presentableParts = getPresentableParts();
617 
618         if (idx >= 0 && idx < presentableParts.size()) { return (IPresentablePart) presentableParts
619                 .get(idx); }
620 
621         return null;
622     }
623 
624     /**
625      * Returns a list of IPresentablePart
626      * 
627      * @return
628      */
629     public List getPresentableParts() {
630         List result = new ArrayList(children.size());
631 
632         Iterator iter = children.iterator();
633         while (iter.hasNext()) {
634             LayoutPart part = (LayoutPart) iter.next();
635 
636             IPresentablePart presentablePart = part.getPresentablePart();
637 
638             if (presentablePart != null) {
639                 result.add(presentablePart);
640             }
641         }
642 
643         return result;
644     }
645 
646     protected StackPresentation getPresentation() {
647         return presentationSite.getPresentation();
648     }
649     
650     /**
651      * Returns the visible child.
652      */
653     public PartPane getVisiblePart() {
654       if (current instanceof PartPane) {
655         return (PartPane)current;
656       }
657         return null;
658     }
659     
660     private void presentationSelectionChanged(IPresentablePart newSelection) {
661       // Ignore selection changes that occur as a result of removing a part
662       if (ignoreSelectionChanges) {
663         return;
664       }
665       LayoutPart newPart = getPaneFor(newSelection); 
666       
667       // This method should only be called on objects that are already in the layout
668       Assert.isNotNull(newPart);
669       
670       if (newPart == current) {
671         return;
672       }
673       
674         setSelection(newPart);
675         
676         if (newPart != null) {
677           newPart.setFocus();
678         }
679 
680         // set the title of the detached window to reflect the active tab
681         Window window = getWindow();
682         if (window instanceof DetachedWindow) {
683             window.getShell().setText(newSelection.getTitle());
684         }
685     }
686 
687     /**
688      * See IVisualContainer#remove
689      */
690     public void remove(LayoutPart child) {
691         IPresentablePart presentablePart = child.getPresentablePart();
692 
693         // Need to remove it from the list of children before notifying the presentation
694         // since it may setVisible(false) on the part, leading to a partHidden notification,
695         // during which findView must not find the view being removed.  See bug 60039. 
696         children.remove(child);
697         
698         StackPresentation presentation = getPresentation();
699         
700         if (presentablePart != null && presentation != null) {
701           ignoreSelectionChanges = true;
702             presentation.removePart(presentablePart);
703             ignoreSelectionChanges = false;
704         }
705 
706         if (!isDisposed()) {
707             child.setContainer(null);
708         }
709         
710         if (child == current) {
711           updateContainerVisibleTab();
712         }      
713     }
714     
715     /**
716      * Reparent a part. Also reparent visible children...
717      */
718     public void reparent(Composite newParent) {
719         if (!newParent.isReparentable()) return;
720 
721         Control control = getControl();
722         if ((control == null) || (control.getParent() == newParent)) return;
723 
724         super.reparent(newParent);
725 
726         Iterator iter = children.iterator();
727         while (iter.hasNext()) {
728             LayoutPart next = (LayoutPart) iter.next();
729             next.reparent(newParent);
730         }
731     }
732 
733     /**
734      * See IVisualContainer#replace
735      */
736     public void replace(LayoutPart oldChild, LayoutPart newChild) {
737     // commented out but left for future reference - we're using this
738     // as the cookie for the part presentation but this will
739     // almost always be null (oldChilds being PartPlaceholders)
740     // even if they aren't null, we don't handle 
741     // IPresentableParts as cookies
742     //
743         // IPresentablePart oldPart = oldChild.getPresentablePart();
744         IPresentablePart newPart = newChild.getPresentablePart();
745 
746         int idx = children.indexOf(oldChild);
747         int numPlaceholders = 0;
748         //subtract the number of placeholders still existing in the list 
749         //before this one - they wont have parts.
750         for (int i = 0; i < idx; i++) {
751           if (children.get(i) instanceof PartPlaceholder)
752             numPlaceholders++;
753     }
754         Integer cookie = new Integer(idx - numPlaceholders);
755         children.add(idx, newChild);
756 
757         showPart(newChild, cookie);
758 
759         if (oldChild == current && !(newChild instanceof PartPlaceholder)) {
760             setSelection(newChild);
761         }
762 
763         remove(oldChild);
764     }
765 
766     public boolean resizesVertically() {
767         return presentationSite.getState() != IStackPresentationSite.STATE_MINIMIZED;
768     }
769 
770     /**
771      * @see IPersistable
772      */
773     public IStatus restoreState(IMemento memento) {
774         // Read the active tab.
775         String activeTabID = memento
776                 .getString(IWorkbenchConstants.TAG_ACTIVE_PAGE_ID);
777 
778         // Read the page elements.
779         IMemento[] children = memento.getChildren(IWorkbenchConstants.TAG_PAGE);
780         if (children != null) {
781             // Loop through the page elements.
782             for (int i = 0; i < children.length; i++) {
783                 // Get the info details.
784                 IMemento childMem = children[i];
785                 String partID = childMem
786                         .getString(IWorkbenchConstants.TAG_CONTENT);
787 
788                 // Create the part.
789                 LayoutPart part = new PartPlaceholder(partID);
790         part.setContainer(this);            
791                 add(part);
792                 //1FUN70C: ITPUI:WIN - Shouldn't set Container when not active
793                 //part.setContainer(this);
794                 if (partID.equals(activeTabID)) {
795                     // Mark this as the active part.
796                     current = part;
797                 }
798             }
799         }
800 
801         Integer expanded = memento.getInteger(IWorkbenchConstants.TAG_EXPANDED);
802         setState((expanded == null || expanded.intValue() != IStackPresentationSite.STATE_MINIMIZED) ? IStackPresentationSite.STATE_RESTORED
803                 : IStackPresentationSite.STATE_MINIMIZED);
804 
805         Integer appearance = memento.getInteger(IWorkbenchConstants.TAG_APPEARANCE);
806         if (appearance != null) {
807           this.appearance = appearance.intValue();
808         }
809         
810         // Determine if the presentation has saved any info here
811         savedPresentationState = null;
812         IMemento[] presentationMementos = memento.getChildren(IWorkbenchConstants.TAG_PRESENTATION);
813         
814         for (int idx = 0; idx < presentationMementos.length; idx++) {
815           IMemento child = presentationMementos[idx];
816           
817           String id = child.getString(IWorkbenchConstants.TAG_ID);
818           
819           if (Util.equals(id, getFactory().getId())) {
820             savedPresentationState = child;
821             break;
822           }
823         }
824         
825         return new Status(IStatus.OK, PlatformUI.PLUGIN_ID, 0, "", null); //$NON-NLS-1$
826     }
827 
828     /**
829      * @see IPersistable
830      */
831     public IStatus saveState(IMemento memento) {
832 
833         // Save the active tab.
834         if (current != null)
835                 memento.putString(IWorkbenchConstants.TAG_ACTIVE_PAGE_ID,
836                         current.getCompoundId());
837 
838         Iterator iter = children.iterator();
839         while (iter.hasNext()) {
840             LayoutPart next = (LayoutPart) iter.next();
841 
842             IMemento childMem = memento
843                     .createChild(IWorkbenchConstants.TAG_PAGE);
844 
845             IPresentablePart part = next.getPresentablePart();
846             String tabText = "LabelNotFound"; //$NON-NLS-1$ 
847             if (part != null) {
848                 tabText = part.getName();
849             }
850             childMem.putString(IWorkbenchConstants.TAG_LABEL, tabText);
851             childMem.putString(IWorkbenchConstants.TAG_CONTENT, next.getCompoundId());
852         }
853 
854         memento
855                 .putInteger(
856                         IWorkbenchConstants.TAG_EXPANDED,
857                         (presentationSite.getState() == IStackPresentationSite.STATE_MINIMIZED) ? IStackPresentationSite.STATE_MINIMIZED
858                                 : IStackPresentationSite.STATE_RESTORED);
859 
860         memento.putInteger(IWorkbenchConstants.TAG_APPEARANCE, appearance);
861         
862         savePresentationState();
863         
864         if (savedPresentationState != null) {
865           IMemento presentationState = memento.createChild(IWorkbenchConstants.TAG_PRESENTATION);
866           presentationState.putMemento(savedPresentationState);
867         }
868         
869         return new Status(IStatus.OK, PlatformUI.PLUGIN_ID, 0, "", null); //$NON-NLS-1$
870     }
871 
872     protected WorkbenchPage getPage() {
873       WorkbenchWindow window = (WorkbenchWindow)getWorkbenchWindow();
874       
875       if (window == null) {
876         return null;
877       }
878       
879       return (WorkbenchPage)window.getActivePage();
880     }
881     
882     /**
883      * Set the active appearence on the tab folder.
884      * 
885      * @param active
886      */
887     public void setActive(int activeState) {
888       
889         if (activeState != StackPresentation.AS_INACTIVE) {
890             if (presentationSite.getState() == IStackPresentationSite.STATE_MINIMIZED) {
891                 setState(IStackPresentationSite.STATE_RESTORED);
892             }            
893         }
894 
895         presentationSite.setActive(activeState);
896     }
897 
898     public int getActive() {
899       return presentationSite.getActive();
900     }
901     
902     /**
903      * Sets the presentation bounds.
904      */
905     public void setBounds(Rectangle r) {
906         if (getPresentation() != null) {
907             getPresentation().setBounds(r);
908         }
909     }
910 
911     public void setSelection(LayoutPart part) {
912     if (current == part) {
913       return;
914     }
915 
916         current = part;
917 
918         if (!isDisposed()) {
919           updateActions();
920         }
921         refreshPresentationSelection();
922     }
923     
924   /**
925    * Subclasses should override this method to update the enablement state of their
926    * actions
927    */
928   protected void updateActions() {
929     
930   }
931     
932     private void refreshPresentationSelection() {
933       if (current != null) {
934           IPresentablePart presentablePart = current.getPresentablePart();
935           StackPresentation presentation = getPresentation();
936   
937           if (presentablePart != null && presentation != null) {
938             
939               current.createControl(getParent());
940               if (current.getControl().getParent() != getControl().getParent()) {
941                 current.reparent(getControl().getParent());
942               }
943             
944               current.moveAbove(getPresentation().getControl());
945               
946               presentation.selectPart(presentablePart);
947           }
948         }
949     }
950 
951     protected void setState(int newState) {      
952         if (!supportsState(newState) || newState == presentationSite.getState()) { return; }
953 
954         int oldState = presentationSite.getState();
955 
956         if (current != null) {
957             if (newState == IStackPresentationSite.STATE_MAXIMIZED) {
958               PartPane pane = getVisiblePart(); 
959               if (pane != null) {
960                 pane.doZoom();
961               }
962             } else {
963                 presentationSite.setPresentationState(newState);
964 
965                 WorkbenchPage page = getPage();
966                 if (page != null) {
967                   if (page.isZoomed()) {
968                       page.zoomOut();
969                   }
970   
971                   updateControlBounds();
972   
973                   if (oldState == IStackPresentationSite.STATE_MINIMIZED) {
974                       forceLayout();
975                   }
976                 }
977             }
978         }
979 
980         if (presentationSite.getState() == IStackPresentationSite.STATE_MINIMIZED) {
981           WorkbenchPage page = getPage();
982           
983           if (page != null) {
984             page.refreshActiveView();
985           }
986         }
987     }
988 
989     public void setZoomed(boolean isZoomed) {
990       super.setZoomed(isZoomed);
991       
992         if (isZoomed) {
993             presentationSite
994                     .setPresentationState(IStackPresentationSite.STATE_MAXIMIZED);
995         } else if (presentationSite.getState() == IStackPresentationSite.STATE_MAXIMIZED) {
996           presentationSite.setPresentationState(IStackPresentationSite.STATE_RESTORED);
997         }
998     }
999 
1000    /**
1001     * Makes the given part visible in the presentation
1002     * 
1003     * @param presentablePart
1004     */
1005    private void showPart(LayoutPart part, Object cookie) {
1006
1007      if (isDisposed()) {
1008        return;
1009      }
1010      
1011        part.setContainer(this);
1012        
1013        IPresentablePart presentablePart = part.getPresentablePart();
1014
1015        if (presentablePart == null) { return; }
1016
1017        presentationSite.getPresentation().addPart(presentablePart, cookie);
1018        
1019        if (current == null) {
1020          setSelection(part);
1021        }
1022    }
1023
1024    /**
1025     * Update the container to show the correct visible tab based on the
1026     * activation list.
1027     * 
1028     * @param org.eclipse.ui.internal.ILayoutContainer
1029     */
1030    private void updateContainerVisibleTab() {
1031        LayoutPart[] parts = getChildren();
1032        
1033        if (parts.length < 1) {
1034            setSelection(null);
1035            return;
1036        }
1037        
1038        PartPane selPart = null;
1039        int topIndex = 0;
1040        WorkbenchPage page = getPage(); 
1041        
1042        if (page != null) {
1043          IWorkbenchPartReference sortedPartsArray[] = page.getSortedParts();
1044          List sortedParts = Arrays.asList(sortedPartsArray);
1045          for (int i = 0; i < parts.length; i++) {
1046              if (parts[i] instanceof PartPane) {
1047                  IWorkbenchPartReference part = ((PartPane) parts[i])
1048                          .getPartReference();
1049                  int index = sortedParts.indexOf(part);
1050                  if (index >= topIndex) {
1051                      topIndex = index;
1052                      selPart = (PartPane) parts[i];
1053                  }
1054              }
1055          }
1056          
1057        }
1058        
1059        if (selPart == null) {
1060          List presentableParts = getPresentableParts();
1061          if (presentableParts.size() != 0) {
1062            IPresentablePart part = (IPresentablePart)getPresentableParts().get(0);
1063            
1064            selPart = (PartPane)getPaneFor(part);
1065          }
1066        }
1067        
1068        setSelection(selPart);
1069    }
1070
1071    private void updateControlBounds() {
1072      StackPresentation presentation = getPresentation();
1073      
1074      if (presentation != null) {
1075          Rectangle bounds = presentation.getControl().getBounds();
1076          int minimumHeight = getMinimumHeight();
1077  
1078          if (presentationSite.getState() == IStackPresentationSite.STATE_MINIMIZED
1079                  && bounds.height != minimumHeight) {
1080              bounds.width = getMinimumWidth();
1081              bounds.height = minimumHeight;
1082              getPresentation().setBounds(bounds);
1083  
1084              forceLayout();
1085          }
1086      }
1087    }
1088
1089  /**
1090   * 
1091   */
1092  public void showSystemMenu() {
1093    getPresentation().showSystemMenu();
1094  }
1095  
1096  public void showPaneMenu() {
1097    getPresentation().showPaneMenu();
1098  }
1099
1100  public void showPartList() {
1101    getPresentation().showPartList();
1102  }
1103  
1104  /**
1105   * @param pane
1106   * @return
1107   */
1108  public Control[] getTabList(LayoutPart part) {
1109    if (part != null) {
1110            IPresentablePart presentablePart = part.getPresentablePart();
1111            StackPresentation presentation = getPresentation();
1112
1113            if (presentablePart != null && presentation != null) {
1114                return presentation.getTabList(presentablePart);
1115            }
1116        }
1117    
1118    return new Control[0];
1119  }
1120  
1121  /**
1122   * 
1123   * @param beingDragged
1124   * @param initialLocation
1125   * @param keyboard
1126   */
1127  public void dragStart(IPresentablePart beingDragged, Point initialLocation, boolean keyboard) {
1128    if (beingDragged == null) {
1129          if (canMoveFolder()) {
1130            if (presentationSite.getState() == IStackPresentationSite.STATE_MAXIMIZED) {
1131              setState(IStackPresentationSite.STATE_RESTORED);
1132            }
1133            
1134              DragUtil.performDrag(PartStack.this, Geometry.toDisplay(
1135                      getParent(), getPresentation().getControl().getBounds()),
1136                      initialLocation, !keyboard);
1137          }
1138    } else {
1139        if (presentationSite.isPartMoveable(beingDragged)) {
1140              LayoutPart pane = getPaneFor(beingDragged);
1141  
1142              if (pane != null) {
1143                if (presentationSite.getState() == IStackPresentationSite.STATE_MAXIMIZED) {
1144                  presentationSite.setState(IStackPresentationSite.STATE_RESTORED);
1145                }
1146                
1147                  DragUtil.performDrag(pane, Geometry.toDisplay(getParent(),
1148                          getPresentation().getControl().getBounds()),
1149                          initialLocation, !keyboard);
1150              }
1151        }
1152    }
1153  }
1154
1155  /**
1156   * @return Returns the savedPresentationState.
1157   */
1158  public IMemento getSavedPresentationState() {
1159    return savedPresentationState;
1160  }
1161}