Package org.eclipse.ui.internal

Source Code of org.eclipse.ui.internal.PartStack$PartStackDropResult

/*******************************************************************************
* Copyright (c) 2004, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*     IBM Corporation - initial API and implementation
*     Chris Gross chris.gross@us.ibm.com Bug 107443
*******************************************************************************/
package org.eclipse.ui.internal;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.action.ContributionItem;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.util.Geometry;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IPersistable;
import org.eclipse.ui.IPropertyListener;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.IWorkbenchPreferenceConstants;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.XMLMemento;
import org.eclipse.ui.internal.StartupThreading.StartupRunnable;
import org.eclipse.ui.internal.dnd.AbstractDropTarget;
import org.eclipse.ui.internal.dnd.DragUtil;
import org.eclipse.ui.internal.dnd.IDropTarget;
import org.eclipse.ui.internal.dnd.SwtUtil;
import org.eclipse.ui.internal.intro.IIntroConstants;
import org.eclipse.ui.internal.layout.ITrimManager;
import org.eclipse.ui.internal.layout.IWindowTrim;
import org.eclipse.ui.internal.presentations.PresentablePart;
import org.eclipse.ui.internal.presentations.PresentationFactoryUtil;
import org.eclipse.ui.internal.presentations.PresentationSerializer;
import org.eclipse.ui.internal.util.PrefUtil;
import org.eclipse.ui.internal.util.Util;
import org.eclipse.ui.presentations.AbstractPresentationFactory;
import org.eclipse.ui.presentations.IPresentablePart;
import org.eclipse.ui.presentations.IStackPresentationSite;
import org.eclipse.ui.presentations.StackDropResult;
import org.eclipse.ui.presentations.StackPresentation;

/**
* Implements the common behavior for stacks of Panes (ie: EditorStack and ViewStack)
* This layout container has PartPanes as children and belongs to a PartSashContainer.
*
* @since 3.0
*/
public abstract class PartStack extends LayoutPart implements ILayoutContainer {

    public static final int PROP_SELECTION = 0x42;
   
    private List children = new ArrayList(3);
    private boolean isActive = true;
    private ArrayList presentableParts = new ArrayList();
   
    private Map properties = new HashMap();
   
    protected int appearance = PresentationFactoryUtil.ROLE_VIEW;
   
    /**
     * Stores the last value passed to setSelection. If UI updates are being deferred,
     * this may be significantly different from the other current pointers. Once UI updates
     * are re-enabled, the stack will update the presentation selection to match the requested
     * current pointer.
     */
    private LayoutPart requestedCurrent;
   
    /**
     * Stores the current part for the stack. Whenever the outside world asks a PartStack
     * for the current part, this is what gets returned. This pointer is only updated after
     * the presentation selection has been restored and the stack has finished updating its
     * internal state. If the stack is still in the process of updating the presentation,
     * it will still point to the previous part until the presentation is up-to-date.
     */
    private LayoutPart current;
   
    /**
     * Stores the presentable part sent to the presentation. Whenever the presentation
     * asks for the current part, this is what gets returned. This is updated before sending
     * the part to the presentation, and it is not updated while UI updates are disabled.
     * When UI updates are enabled, the stack first makes presentationCurrent match
     * requestedCurrent. Once the presentation is displaying the correct part, the "current"
     * pointer on PartStack is updated.
     */
    private PresentablePart presentationCurrent;

    private boolean ignoreSelectionChanges = false;

    protected IMemento savedPresentationState = null;

    protected DefaultStackPresentationSite presentationSite = new DefaultStackPresentationSite() {

        public void close(IPresentablePart part) {
            PartStack.this.close(part);
        }

        public void close(IPresentablePart[] parts) {
            PartStack.this.close(parts);
        }

        public void dragStart(IPresentablePart beingDragged,
                Point initialLocation, boolean keyboard) {
            PartStack.this.dragStart(beingDragged, initialLocation, keyboard);
        }

        public void dragStart(Point initialLocation, boolean keyboard) {
            PartStack.this.dragStart(null, initialLocation, keyboard);
        }

        public boolean isPartMoveable(IPresentablePart part) {
            return PartStack.this.isMoveable(part);
        }

        public void selectPart(IPresentablePart toSelect) {
            PartStack.this.presentationSelectionChanged(toSelect);
        }

        public boolean supportsState(int state) {
            return PartStack.this.supportsState(state);
        }

        public void setState(int newState) {
            PartStack.this.setState(newState);
        }

        public IPresentablePart getSelectedPart() {
            return PartStack.this.getSelectedPart();
        }

        public void addSystemActions(IMenuManager menuManager) {
            PartStack.this.addSystemActions(menuManager);
        }

        public boolean isStackMoveable() {
            return canMoveFolder();
        }
       
        public void flushLayout() {
          PartStack.this.flushLayout();
        }

        public IPresentablePart[] getPartList() {
            List parts = getPresentableParts();
           
            return (IPresentablePart[]) parts.toArray(new IPresentablePart[parts.size()]);
        }

        public String getProperty(String id) {           
            return PartStack.this.getProperty(id);
        }
    };

    private static final class PartStackDropResult extends AbstractDropTarget {
        private PartPane pane;
       
        // Result of the presentation's dragOver method or null if we are stacking over the
        // client area of the pane.
        private StackDropResult dropResult;
        private PartStack stack;
       
        /**
         * Resets the target of this drop result (allows the same drop result object to be
         * reused)
         *
         * @param stack
         * @param pane
         * @param result result of the presentation's dragOver method, or null if we are
         * simply stacking anywhere.
         * @since 3.1
         */
        public void setTarget(PartStack stack, PartPane pane, StackDropResult result) {
            this.pane = pane;
            this.dropResult = result;
            this.stack = stack;
        }
       
        public void drop() {
            // If we're dragging a pane over itself do nothing
            //if (dropResult.getInsertionPoint() == pane.getPresentablePart()) { return; };

            Object cookie = null;
            if (dropResult != null) {
                cookie = dropResult.getCookie();
            }

            // Handle cross window drops by opening a new editor
            if (pane instanceof EditorPane) {
              if (pane.getWorkbenchWindow() != stack.getWorkbenchWindow()) {
                EditorPane editor = (EditorPane) pane;
                try {
            IEditorInput input = editor.getEditorReference().getEditorInput();
           
            // Close the old editor and capture the actual closed state incase of a 'cancel'
            boolean editorClosed = editor.getPage().closeEditor(editor.getEditorReference(), true);
           
            // Only open open the new editor if the old one closed
            if (editorClosed)
              stack.getPage().openEditor(input, editor.getEditorReference().getId());
            return;
          } catch (PartInitException e) {
            e.printStackTrace();
          }
               
              }
            }
           
            if (pane.getContainer() != stack) {
                // Moving from another stack
                stack.derefPart(pane);
                pane.reparent(stack.getParent());
                stack.add(pane, cookie);
                stack.setSelection(pane);
                pane.setFocus();
            } else if (cookie != null) {
                // Rearranging within this stack
                stack.getPresentation().movePart(stack.getPresentablePart(pane), cookie);
            }
        }

        public Cursor getCursor() {
            return DragCursors.getCursor(DragCursors.CENTER);
        }

        public Rectangle getSnapRectangle() {
            if (dropResult == null) {
                return DragUtil.getDisplayBounds(stack.getControl());
            }
            return dropResult.getSnapRectangle();
        }
    }

    private static final PartStackDropResult dropResult = new PartStackDropResult();

    protected boolean isMinimized;

    private ListenerList listeners = new ListenerList();

    /**
     * Custom presentation factory to use for this stack, or null to
     * use the default
     */
    private AbstractPresentationFactory factory;

  private boolean smartZoomed = false;
  private boolean doingUnzoom = false;
           
    protected abstract boolean isMoveable(IPresentablePart part);

    protected abstract void addSystemActions(IMenuManager menuManager);

    protected abstract boolean supportsState(int newState);

    protected abstract boolean canMoveFolder();

    protected abstract void derefPart(LayoutPart toDeref);

    protected abstract boolean allowsDrop(PartPane part);

    protected static void appendToGroupIfPossible(IMenuManager m,
            String groupId, ContributionItem item) {
        try {
            m.appendToGroup(groupId, item);
        } catch (IllegalArgumentException e) {
            m.add(item);
        }
    }
   
    /**
     * Creates a new PartStack, given a constant determining which presentation to use
     *
     * @param appearance one of the PresentationFactoryUtil.ROLE_* constants
     */
    public PartStack(int appearance) {
        this(appearance, null);
    }
   
    /**
     * Creates a new part stack that uses the given custom presentation factory
     * @param appearance
     * @param factory custom factory to use (or null to use the default)
     */
    public PartStack(int appearance, AbstractPresentationFactory factory) {
        super("PartStack"); //$NON-NLS-1$

        this.appearance = appearance;
        this.factory = factory;
    }

    /**
     * Adds a property listener to this stack. The listener will receive a PROP_SELECTION
     * event whenever the result of getSelection changes
     *
     * @param listener
     */
    public void addListener(IPropertyListener listener) {
        listeners.add(listener);
    }
   
    public void removeListener(IPropertyListener listener) {
        listeners.remove(listener);
    }
   
    protected final boolean isStandalone() {
        return (appearance == PresentationFactoryUtil.ROLE_STANDALONE
             || appearance == PresentationFactoryUtil.ROLE_STANDALONE_NOTITLE);
    }
   
    /**
     * Returns the currently selected IPresentablePart, or null if none
     *
     * @return
     */
    protected IPresentablePart getSelectedPart() {
        return presentationCurrent;
    }

    protected IStackPresentationSite getPresentationSite() {
        return presentationSite;
    }

    /**
     * Tests the integrity of this object. Throws an exception if the object's state
     * is invalid. For use in test suites.
     */
    public void testInvariants() {
        Control focusControl = Display.getCurrent().getFocusControl();

        boolean currentFound = false;

        LayoutPart[] children = getChildren();

        for (int idx = 0; idx < children.length; idx++) {
            LayoutPart child = children[idx];

            // No null children allowed
            Assert.isNotNull(child,
                    "null children are not allowed in PartStack"); //$NON-NLS-1$

            // This object can only contain placeholders or PartPanes
            Assert.isTrue(child instanceof PartPlaceholder
                    || child instanceof PartPane,
                    "PartStack can only contain PartPlaceholders or PartPanes"); //$NON-NLS-1$

            // Ensure that all the PartPanes have an associated presentable part
            IPresentablePart part = getPresentablePart(child);
            if (child instanceof PartPane) {
                Assert.isNotNull(part,
                        "All PartPanes must have a non-null IPresentablePart"); //$NON-NLS-1$
            }

            // Ensure that the child's backpointer points to this stack
            ILayoutContainer childContainer = child.getContainer();

            // Disable tests for placeholders -- PartPlaceholder backpointers don't
            // obey the usual rules -- they sometimes point to a container placeholder
            // for this stack instead of the real stack.
            if (!(child instanceof PartPlaceholder)) {

                if (isDisposed()) {

                    // Currently, we allow null backpointers if the widgetry is disposed.
                    // However, it is never valid for the child to have a parent other than
                    // this object
                    if (childContainer != null) {
                        Assert
                                .isTrue(childContainer == this,
                                        "PartStack has a child that thinks it has a different parent"); //$NON-NLS-1$
                    }
                } else {
                    // If the widgetry exists, the child's backpointer must point to us
                    Assert
                            .isTrue(childContainer == this,
                                    "PartStack has a child that thinks it has a different parent"); //$NON-NLS-1$

                    // If this child has focus, then ensure that it is selected and that we have
                    // the active appearance.

                    if (SwtUtil.isChild(child.getControl(), focusControl)) {
                        Assert.isTrue(child == current,
                                "The part with focus is not the selected part"); //$NON-NLS-1$
                        //  focus check commented out since it fails when focus workaround in LayoutPart.setVisible is not present            
                        //              Assert.isTrue(getActive() == StackPresentation.AS_ACTIVE_FOCUS);
                    }
                }
            }

            // Ensure that "current" points to a valid child
            if (child == current) {
                currentFound = true;
            }

            // Test the child's internal state
            child.testInvariants();
        }

        // If we have at least one child, ensure that the "current" pointer points to one of them
        if (!isDisposed() && getPresentableParts().size() > 0) {
            Assert.isTrue(currentFound);

            if (!isDisposed()) {
                StackPresentation presentation = getPresentation();

                // If the presentation controls have focus, ensure that we have the active appearance
                if (SwtUtil.isChild(presentation.getControl(), focusControl)) {
                    Assert
                            .isTrue(
                                    getActive() == StackPresentation.AS_ACTIVE_FOCUS,
                                    "The presentation has focus but does not have the active appearance"); //$NON-NLS-1$
                }
            }
        }
       
        // Check to that we're displaying the zoomed icon iff we're actually maximized
        Assert.isTrue((getState() == IStackPresentationSite.STATE_MAXIMIZED)
                == (getContainer() != null && getContainer().childIsZoomed(this)));

    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.internal.LayoutPart#describeLayout(java.lang.StringBuffer)
     */
    public void describeLayout(StringBuffer buf) {
        int activeState = getActive();
        if (activeState == StackPresentation.AS_ACTIVE_FOCUS) {
            buf.append("active "); //$NON-NLS-1$
        } else if (activeState == StackPresentation.AS_ACTIVE_NOFOCUS) {
            buf.append("active_nofocus "); //$NON-NLS-1$
        }

        buf.append("("); //$NON-NLS-1$

        LayoutPart[] children = ((ILayoutContainer) this).getChildren();

        int visibleChildren = 0;

        for (int idx = 0; idx < children.length; idx++) {

            LayoutPart next = children[idx];
            if (!(next instanceof PartPlaceholder)) {
                if (idx > 0) {
                    buf.append(", "); //$NON-NLS-1$
                }

                if (next == requestedCurrent) {
                    buf.append("*"); //$NON-NLS-1$
                }

                next.describeLayout(buf);

                visibleChildren++;
            }
        }

        buf.append(")"); //$NON-NLS-1$
    }

    /**
     * See IVisualContainer#add
     */
    public void add(LayoutPart child) {
        add(child, null);
    }

    /**
     * Add a part at a particular position
     */
    protected void add(LayoutPart newChild, Object cookie) {
        children.add(newChild);
       
        // Fix for bug 78470:
        if(!(newChild.getContainer() instanceof ContainerPlaceholder)) {
      newChild.setContainer(this);
    }
       
        showPart(newChild, cookie);
    }

    public boolean allowsAdd(LayoutPart toAdd) {
        return !isStandalone();
    }
   
    /*
     * (non-Javadoc)
     *
     * @see org.eclipse.ui.internal.ILayoutContainer#allowsAutoFocus()
     */
    public boolean allowsAutoFocus() {
        if (presentationSite.getState() == IStackPresentationSite.STATE_MINIMIZED) {
            return false;
        }

        return super.allowsAutoFocus();
    }

    /**
     * @param parts
     */
    protected void close(IPresentablePart[] parts) {
        for (int idx = 0; idx < parts.length; idx++) {
            IPresentablePart part = parts[idx];

            close(part);
        }
    }

    /**
     * @param part
     */
    protected void close(IPresentablePart part) {
        if (!presentationSite.isCloseable(part)) {
            return;
        }

        LayoutPart layoutPart = getPaneFor(part);

        if (layoutPart != null && layoutPart instanceof PartPane) {
            PartPane viewPane = (PartPane) layoutPart;

            viewPane.doHide();
        }
    }

    public boolean isDisposed() {
        return getPresentation() == null;
    }

    protected AbstractPresentationFactory getFactory() {
       
        if (factory != null) {
            return factory;
        }
       
        return ((WorkbenchWindow) getPage()
                .getWorkbenchWindow()).getWindowConfigurer()
                .getPresentationFactory();
    }
   
    public void createControl(Composite parent) {
        if (!isDisposed()) {
            return;
        }

        AbstractPresentationFactory factory = getFactory();

        PresentationSerializer serializer = new PresentationSerializer(
                getPresentableParts());

        StackPresentation presentation = PresentationFactoryUtil
                .createPresentation(factory, appearance, parent,
                        presentationSite, serializer, savedPresentationState);

        createControl(parent, presentation);
        getControl().moveBelow(null);
    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.internal.LayoutPart#getDropTarget(java.lang.Object, org.eclipse.swt.graphics.Point)
     */
    public IDropTarget getDropTarget(Object draggedObject, Point position) {

        if (!(draggedObject instanceof PartPane)) {
            return null;
        }

        final PartPane pane = (PartPane) draggedObject;
        if (isStandalone()
                || !allowsDrop(pane)) {
            return null;
        }

        // Don't allow views to be dragged between windows
        boolean differentWindows = pane.getWorkbenchWindow() != getWorkbenchWindow();
        boolean editorDropOK = ((pane instanceof EditorPane) &&
            pane.getWorkbenchWindow().getWorkbench() ==
              getWorkbenchWindow().getWorkbench());
        if (differentWindows && !editorDropOK) {
            return null;
        }

        StackDropResult dropResult = getPresentation().dragOver(
                getControl(), position);
       
        if (dropResult == null) {
          return null;
        }
       
        return createDropTarget(pane, dropResult);
    }
   
    public void setActive(boolean isActive) {
        this.isActive = isActive;
        // Add all visible children to the presentation
        Iterator iter = children.iterator();
        while (iter.hasNext()) {
            LayoutPart part = (LayoutPart) iter.next();
           
            part.setContainer(isActive ? this : null);
        }
       
        for (Iterator iterator = presentableParts.iterator(); iterator.hasNext();) {
            PresentablePart next = (PresentablePart) iterator.next();
           
            next.enableInputs(isActive);
            next.enableOutputs(isActive);
        }
    }
   
    public void createControl(Composite parent, StackPresentation presentation) {

        Assert.isTrue(isDisposed());

        if (presentationSite.getPresentation() != null) {
      return;
    }

        presentationSite.setPresentation(presentation);

        // Add all visible children to the presentation
        // Use a copy of the current set of children to avoid a ConcurrentModificationException
        // if a part is added to the same stack while iterating over the children (bug 78470)
        LayoutPart[] childParts = (LayoutPart[]) children.toArray(new LayoutPart[children.size()]);
        for (int i = 0; i < childParts.length; i++) {
      LayoutPart part = childParts[i];
            showPart(part, null);
        }
       
        if (savedPresentationState!=null) {
      PresentationSerializer serializer = new PresentationSerializer(
          getPresentableParts());
      presentation.restoreState(serializer, savedPresentationState);
    }

        Control ctrl = getPresentation().getControl();

        ctrl.setData(this);

        // We should not have a placeholder selected once we've created the widgetry
        if (requestedCurrent instanceof PartPlaceholder) {
            requestedCurrent = null;
            updateContainerVisibleTab();
        }

        refreshPresentationSelection();
    }

    public IDropTarget createDropTarget(PartPane pane, StackDropResult result) {
        dropResult.setTarget(this, pane, result);
        return dropResult;
    }
   
    /**
     * Saves the current state of the presentation to savedPresentationState, if the
     * presentation exists.
     */
    protected void savePresentationState() {
        if (isDisposed()) {
            return;
        }

        {// Save the presentation's state before disposing it
            XMLMemento memento = XMLMemento
                    .createWriteRoot(IWorkbenchConstants.TAG_PRESENTATION);
            memento.putString(IWorkbenchConstants.TAG_ID, getFactory().getId());

            PresentationSerializer serializer = new PresentationSerializer(
                    getPresentableParts());

            getPresentation().saveState(serializer, memento);

            // Store the memento in savedPresentationState
            savedPresentationState = memento;
        }
    }

    /**
     * See LayoutPart#dispose
     */
    public void dispose() {

        if (isDisposed()) {
      return;
    }

        savePresentationState();

        presentationSite.dispose();
       
        for (Iterator iter = presentableParts.iterator(); iter.hasNext();) {
            PresentablePart part = (PresentablePart) iter.next();
           
            part.dispose();
        }
        presentableParts.clear();
       
        presentationCurrent = null;
        current = null;
        fireInternalPropertyChange(PROP_SELECTION);
    }

    public void findSashes(LayoutPart part, PartPane.Sashes sashes) {
        ILayoutContainer container = getContainer();

        if (container != null) {
            container.findSashes(this, sashes);
        }
    }

    /**
     * Gets the presentation bounds.
     */
    public Rectangle getBounds() {
        if (getPresentation() == null) {
            return new Rectangle(0, 0, 0, 0);
        }

        return getPresentation().getControl().getBounds();
    }

    /**
     * See IVisualContainer#getChildren
     */
    public LayoutPart[] getChildren() {
        return (LayoutPart[]) children.toArray(new LayoutPart[children.size()]);
    }

    public Control getControl() {
        StackPresentation presentation = getPresentation();

        if (presentation == null) {
            return null;
        }

        return presentation.getControl();
    }

    /**
     * Answer the number of children.
     */
    public int getItemCount() {
        if (isDisposed()) {
            return children.size();
        }
        return getPresentableParts().size();
    }
   
    /**
     * Returns the LayoutPart for the given IPresentablePart, or null if the given
     * IPresentablePart is not in this stack. Returns null if given a null argument.
     *
     * @param part to locate or null
     * @return
     */
    protected LayoutPart getPaneFor(IPresentablePart part) {
        if (part == null || !(part instanceof PresentablePart)) {
            return null;
        }

        return ((PresentablePart)part).getPane();
    }

    /**
     * Get the parent control.
     */
    public Composite getParent() {
        return getControl().getParent();
    }

    /**
     * Returns a list of IPresentablePart
     *
     * @return
     */
    public List getPresentableParts() {
        return presentableParts;
    }

    private PresentablePart getPresentablePart(LayoutPart pane) {
        for (Iterator iter = presentableParts.iterator(); iter.hasNext();) {
            PresentablePart part = (PresentablePart) iter.next();
           
            if (part.getPane() == pane) {
                return part;
            }
        }
       
        return null;
    }
   
    protected StackPresentation getPresentation() {
        return presentationSite.getPresentation();
    }

    /**
     * Returns the visible child.
     * @return the currently visible part, or null if none
     */
    public PartPane getSelection() {
        if (current instanceof PartPane) {
            return (PartPane) current;
        }
        return null;
    }

    private void presentationSelectionChanged(IPresentablePart newSelection) {
        // Ignore selection changes that occur as a result of removing a part
        if (ignoreSelectionChanges) {
            return;
        }
        LayoutPart newPart = getPaneFor(newSelection);

        // This method should only be called on objects that are already in the layout
        Assert.isNotNull(newPart);

        if (newPart == requestedCurrent) {
            return;
        }

        setSelection(newPart);

        if (newPart != null) {
            newPart.setFocus();
        }

    }

    /**
     * See IVisualContainer#remove
     */
    public void remove(LayoutPart child) {
        PresentablePart presentablePart = getPresentablePart(child);

        // Need to remove it from the list of children before notifying the presentation
        // since it may setVisible(false) on the part, leading to a partHidden notification,
        // during which findView must not find the view being removed.  See bug 60039.
        children.remove(child);

        StackPresentation presentation = getPresentation();

        if (presentablePart != null && presentation != null) {
            ignoreSelectionChanges = true;
            presentableParts .remove(presentablePart);
            presentation.removePart(presentablePart);
            presentablePart.dispose();
            ignoreSelectionChanges = false;
        }

        if (!isDisposed()) {
            child.setContainer(null);
        }

        if (child == requestedCurrent) {
            updateContainerVisibleTab();
        }
    }

    /**
     * Reparent a part. Also reparent visible children...
     */
    public void reparent(Composite newParent) {

        Control control = getControl();
        if ((control == null) || (control.getParent() == newParent) || !control.isReparentable()) {
      return;
    }

        super.reparent(newParent);

        Iterator iter = children.iterator();
        while (iter.hasNext()) {
            LayoutPart next = (LayoutPart) iter.next();
            next.reparent(newParent);
        }
    }

    /**
     * See IVisualContainer#replace
     */
    public void replace(LayoutPart oldChild, LayoutPart newChild) {
        int idx = children.indexOf(oldChild);
        int numPlaceholders = 0;
        //subtract the number of placeholders still existing in the list
        //before this one - they wont have parts.
        for (int i = 0; i < idx; i++) {
            if (children.get(i) instanceof PartPlaceholder) {
        numPlaceholders++;
      }
        }
        Integer cookie = new Integer(idx - numPlaceholders);
        children.add(idx, newChild);

        showPart(newChild, cookie);

        if (oldChild == requestedCurrent && !(newChild instanceof PartPlaceholder)) {
            setSelection(newChild);
        }

        remove(oldChild);
    }
   
  /* (non-Javadoc)
   * @see org.eclipse.ui.internal.LayoutPart#computePreferredSize(boolean, int, int, int)
   */
  public int computePreferredSize(boolean width, int availableParallel,
      int availablePerpendicular, int preferredParallel) {
   
    return getPresentation().computePreferredSize(width, availableParallel,
        availablePerpendicular, preferredParallel);
  }
   
    /* (non-Javadoc)
     * @see org.eclipse.ui.internal.LayoutPart#getSizeFlags(boolean)
     */
    public int getSizeFlags(boolean horizontal) {
        StackPresentation presentation = getPresentation();
       
        if (presentation != null) {
            return presentation.getSizeFlags(horizontal);
        }
       
        return 0;
    }
   
    /**
     * @see IPersistable
     */
    public IStatus restoreState(IMemento memento) {
        // Read the active tab.
        String activeTabID = memento
                .getString(IWorkbenchConstants.TAG_ACTIVE_PAGE_ID);

        // Read the page elements.
        IMemento[] children = memento.getChildren(IWorkbenchConstants.TAG_PAGE);
        if (children != null) {
            // Loop through the page elements.
            for (int i = 0; i < children.length; i++) {
                // Get the info details.
                IMemento childMem = children[i];
                String partID = childMem
                        .getString(IWorkbenchConstants.TAG_CONTENT);

                // Create the part.
                LayoutPart part = new PartPlaceholder(partID);
                part.setContainer(this);
                add(part);
                //1FUN70C: ITPUI:WIN - Shouldn't set Container when not active
                //part.setContainer(this);
                if (partID.equals(activeTabID)) {
                    setSelection(part);
                    // Mark this as the active part.
                    //current = part;
                }
            }
        }

        IPreferenceStore preferenceStore = PrefUtil.getAPIPreferenceStore();
        boolean useNewMinMax = preferenceStore.getBoolean(IWorkbenchPreferenceConstants.ENABLE_NEW_MIN_MAX);
        final Integer expanded = memento.getInteger(IWorkbenchConstants.TAG_EXPANDED);
        if (useNewMinMax && expanded != null) {
            StartupThreading.runWithoutExceptions(new StartupRunnable() {
          public void runWithException() throws Throwable {               
                setState((expanded == null || expanded.intValue() != IStackPresentationSite.STATE_MINIMIZED) ? IStackPresentationSite.STATE_RESTORED
                        : IStackPresentationSite.STATE_MINIMIZED);
          }
            });
        }
        else {
          setState((expanded == null || expanded.intValue() != IStackPresentationSite.STATE_MINIMIZED) ? IStackPresentationSite.STATE_RESTORED
                  : IStackPresentationSite.STATE_MINIMIZED);
        }

        Integer appearance = memento
                .getInteger(IWorkbenchConstants.TAG_APPEARANCE);
        if (appearance != null) {
            this.appearance = appearance.intValue();
        }

        // Determine if the presentation has saved any info here
        savedPresentationState = null;
        IMemento[] presentationMementos = memento
                .getChildren(IWorkbenchConstants.TAG_PRESENTATION);

        for (int idx = 0; idx < presentationMementos.length; idx++) {
            IMemento child = presentationMementos[idx];

            String id = child.getString(IWorkbenchConstants.TAG_ID);

            if (Util.equals(id, getFactory().getId())) {
                savedPresentationState = child;
                break;
            }
        }

        IMemento propertiesState = memento.getChild(IWorkbenchConstants.TAG_PROPERTIES);
        if (propertiesState != null) {
            IMemento[] props = propertiesState.getChildren(IWorkbenchConstants.TAG_PROPERTY);
            for (int i = 0; i < props.length; i++) {
                properties.put(props[i].getID(), props[i].getTextData());
            }
        }
               
       
        return new Status(IStatus.OK, PlatformUI.PLUGIN_ID, 0, "", null); //$NON-NLS-1$
    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.internal.LayoutPart#setVisible(boolean)
     */
    public void setVisible(boolean makeVisible) {
        Control ctrl = getControl();
       
        boolean useShortcut = makeVisible || !isActive;
       
        if (!SwtUtil.isDisposed(ctrl) && useShortcut) {
            if (makeVisible == ctrl.getVisible()) {
        return;
      }
        }       
       
        if (makeVisible) {
            for (Iterator iterator = presentableParts.iterator(); iterator.hasNext();) {
                PresentablePart next = (PresentablePart) iterator.next();
               
                next.enableInputs(isActive);
                next.enableOutputs(isActive);
            }
        }
       
        super.setVisible(makeVisible);
       
        StackPresentation presentation = getPresentation();
       
        if (presentation != null) {
            presentation.setVisible(makeVisible);
        }
       
        if (!makeVisible) {
            for (Iterator iterator = presentableParts.iterator(); iterator.hasNext();) {
                PresentablePart next = (PresentablePart) iterator.next();
               
                next.enableInputs(false);
            }
        }
    }
   
    /**
     * @see IPersistable
     */
    public IStatus saveState(IMemento memento) {

        // Save the active tab.
        if (requestedCurrent != null) {
      memento.putString(IWorkbenchConstants.TAG_ACTIVE_PAGE_ID, requestedCurrent
                    .getCompoundId());
    }

        // Write out the presentable parts (in order)
        Set cachedIds = new HashSet();
        Iterator ppIter = getPresentableParts().iterator();
        while (ppIter.hasNext()) {
            PresentablePart presPart = (PresentablePart) ppIter.next();

            IMemento childMem = memento
                    .createChild(IWorkbenchConstants.TAG_PAGE);
            PartPane part = presPart.getPane();
            String tabText = part.getPartReference().getPartName();

            childMem.putString(IWorkbenchConstants.TAG_LABEL, tabText);
            childMem.putString(IWorkbenchConstants.TAG_CONTENT, presPart.getPane().getPlaceHolderId());
           
            // Cache the id so we don't write it out later
            cachedIds.add(presPart.getPane().getPlaceHolderId());
        }

        Iterator iter = children.iterator();
        while (iter.hasNext()) {
            LayoutPart next = (LayoutPart) iter.next();

            PartPane part = null;
            if (next instanceof PartPane) {
              // Have we already written it out?
              if (cachedIds.contains(((PartPane)next).getPlaceHolderId()))
                continue;
             
                part = (PartPane)next;
            }

            IMemento childMem = memento
                    .createChild(IWorkbenchConstants.TAG_PAGE);

            String tabText = "LabelNotFound"; //$NON-NLS-1$
            if (part != null) {
                tabText = part.getPartReference().getPartName();
            }
            childMem.putString(IWorkbenchConstants.TAG_LABEL, tabText);
            childMem.putString(IWorkbenchConstants.TAG_CONTENT, next
                    .getCompoundId());
        }

        IPreferenceStore preferenceStore = PrefUtil.getAPIPreferenceStore();
        boolean useNewMinMax = preferenceStore.getBoolean(IWorkbenchPreferenceConstants.ENABLE_NEW_MIN_MAX);
        if (useNewMinMax) {
            memento.putInteger(IWorkbenchConstants.TAG_EXPANDED, presentationSite.getState());
        }
        else {
            memento
            .putInteger(
                    IWorkbenchConstants.TAG_EXPANDED,
                    (presentationSite.getState() == IStackPresentationSite.STATE_MINIMIZED) ? IStackPresentationSite.STATE_MINIMIZED
                            : IStackPresentationSite.STATE_RESTORED);
        }

        memento.putInteger(IWorkbenchConstants.TAG_APPEARANCE, appearance);

        savePresentationState();

        if (savedPresentationState != null) {
            IMemento presentationState = memento
                    .createChild(IWorkbenchConstants.TAG_PRESENTATION);
            presentationState.putMemento(savedPresentationState);
        }
       
        if (!properties.isEmpty()) {
            IMemento propertiesState = memento.createChild(IWorkbenchConstants.TAG_PROPERTIES);
            Set ids = properties.keySet();
            for (Iterator iterator = ids.iterator(); iterator.hasNext();) {  
                String id = (String)iterator.next();
               
                if (properties.get(id) == null) continue;
               
                IMemento prop = propertiesState.createChild(IWorkbenchConstants.TAG_PROPERTY, id);
                prop.putTextData((String)properties.get(id));
            }
        }
       

        return new Status(IStatus.OK, PlatformUI.PLUGIN_ID, 0, "", null); //$NON-NLS-1$
    }

    protected WorkbenchPage getPage() {
        WorkbenchWindow window = (WorkbenchWindow) getWorkbenchWindow();

        if (window == null) {
            return null;
        }

        return (WorkbenchPage) window.getActivePage();
    }

    /**
     * Set the active appearence on the tab folder.
     *
     * @param active
     */
    public void setActive(int activeState) {

        if (activeState == StackPresentation.AS_ACTIVE_FOCUS && isMinimized) {
            setMinimized(false);
        }

        presentationSite.setActive(activeState);
    }

    public int getActive() {
        return presentationSite.getActive();
    }

    /**
     * Sets the presentation bounds.
     */
    public void setBounds(Rectangle r) {
     
        if (getPresentation() != null) {
            getPresentation().setBounds(r);
        }
    }

    public void setSelection(LayoutPart part) {
        if (part == requestedCurrent) {
            return;
        }

        requestedCurrent = part;
       
        refreshPresentationSelection();
    }

    /**
     * Subclasses should override this method to update the enablement state of their
     * actions
     */
    protected abstract void updateActions(PresentablePart current);

    /* (non-Javadoc)
   * @see org.eclipse.ui.internal.LayoutPart#handleDeferredEvents()
   */
  protected void handleDeferredEvents() {
    super.handleDeferredEvents();
   
    refreshPresentationSelection();
  }
   
    private void refreshPresentationSelection() {       
        // If deferring UI updates, exit.
      if (isDeferred()) {
        return;
      }
       
        // If the presentation is already displaying the desired part, then there's nothing
        // to do.
        if (current == requestedCurrent) {
            return;
        }

        StackPresentation presentation = getPresentation();
        if (presentation != null) {
       
            presentationCurrent = getPresentablePart(requestedCurrent);
           
            if (!isDisposed()) {
                updateActions(presentationCurrent);
            }
           
            if (presentationCurrent != null && presentation != null) {
                requestedCurrent.createControl(getParent());
                if (requestedCurrent.getControl().getParent() != getControl()
                        .getParent()) {
                    requestedCurrent.reparent(getControl().getParent());
                }

              
                presentation.selectPart(presentationCurrent);
               
             }
       
            // Update the return value of getVisiblePart
            current = requestedCurrent;
            fireInternalPropertyChange(PROP_SELECTION);
        }
    }

    public int getState() {
      return presentationSite.getState();
    }

  /**
   * Sets the minimized state for this stack. The part may call this method to
   * minimize or restore itself. The minimized state only affects the view
   * when unzoomed in the 3.0 presentation (in 3.3 it's handled by the
   * ViewStack directly and works as expected).
   */
  public void setMinimized(boolean minimized) {
    if (minimized != isMinimized) {
      isMinimized = minimized;

      refreshPresentationState();
    }
  }
   
    /* (non-Javadoc)
     * @see org.eclipse.ui.internal.ILayoutContainer#obscuredByZoom(org.eclipse.ui.internal.LayoutPart)
     */
    public boolean childObscuredByZoom(LayoutPart toTest) {
        return isObscuredByZoom();
    }
   
    /* (non-Javadoc)
     * @see org.eclipse.ui.internal.LayoutPart#requestZoom(org.eclipse.ui.internal.LayoutPart)
     */
    public void childRequestZoomIn(LayoutPart toZoom) {
        super.childRequestZoomIn(toZoom);
       
        requestZoomIn();
    }
    /* (non-Javadoc)
     * @see org.eclipse.ui.internal.LayoutPart#requestZoomOut()
     */
    public void childRequestZoomOut() {
        super.childRequestZoomOut();
       
        requestZoomOut();
    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.internal.ILayoutContainer#isZoomed(org.eclipse.ui.internal.LayoutPart)
     */
    public boolean childIsZoomed(LayoutPart toTest) {
        return isZoomed();
    }
   
    /**
     * This is a hack that allows us to preserve the old
     * min/max behavior for the stack containing the IntroPart.
     * This is required to have the initial Intro (Welcome)
     * pane to show correctly but will induce strange
     * effects should a user re-locate the part to
     * stacks other that its initial one...
     * 
     * @return true if the stack contains the intro
     * as a ViewPane (not if it's only a placeholder)
     */
    private boolean isIntroInStack() {
      LayoutPart[] kids = getChildren();
      for (int i = 0; i < kids.length; i++) {
        if (kids[i] instanceof ViewPane) {
          ViewPane vp = (ViewPane) kids[i];
          if (vp.getID().equals(IIntroConstants.INTRO_VIEW_ID))
            return true;
        }
    }
      return false;
    }

    private void smartZoom() {
    WorkbenchWindow wbw = (WorkbenchWindow) getPage().getWorkbenchWindow();
    if (wbw == null || wbw.getShell() == null)
      return;

    Perspective perspective = getPage().getActivePerspective();
    FastViewManager fvm = perspective.getFastViewManager();

    fvm.deferUpdates(true);

    // Cache the layout bounds
    perspective.getPresentation().updateBoundsMap();
   
    LayoutPart[] children = perspective.getPresentation().getLayout().getChildren();
    for (int i = 0; i < children.length; i++) {
      if (children[i] != this) {
        if (children[i] instanceof ViewStack) {
          ((ViewStack) children[i]).setMinimized(true);
          ViewStackTrimToolBar vstb = fvm
              .getViewStackTrimToolbar(children[i]
                  .getID());
          vstb.setRestoreOnUnzoom(true);
        }
        else if (children[i] instanceof EditorSashContainer && !(this instanceof EditorStack)) {
          perspective.setEditorAreaState(IStackPresentationSite.STATE_MINIMIZED);
          perspective.setEditorAreaRestoreOnUnzoom(true);
        }
      }
    }

    // If the editor area has changed state tell the perspective
    if (this instanceof EditorStack)
      perspective.setEditorAreaState(IStackPresentationSite.STATE_MAXIMIZED);

    // Clear the boundsMap
    perspective.getPresentation().resetBoundsMap();
   
    // We're done batching...
    fvm.deferUpdates(false);
   
    perspective.getPresentation().setMaximizedStack(this);
    smartZoomed = true;
    }

    protected void smartUnzoom() {
      // Prevent recursion through 'setMinimized'
      if (doingUnzoom)
        return;
      doingUnzoom = true;
     
    WorkbenchWindow wbw = (WorkbenchWindow) getPage().getWorkbenchWindow();
    if (wbw == null || wbw.getShell() == null)
      return;

    ITrimManager tbm = wbw.getTrimManager();
    Perspective perspective = getPage().getActivePerspective();
    FastViewManager fvm = perspective.getFastViewManager();

    ILayoutContainer root = getContainer();

    // We go up one more level when maximizing an editor stack
    // so that we 'zoom' the editor area
    boolean restoringEditorArea = false;
    if (root instanceof EditorSashContainer) {
      root = ((EditorSashContainer) root).getContainer();
      restoringEditorArea = true;
    }

    // This is a compound operation
    fvm.deferUpdates(true);
   
    LayoutPart[] children = root.getChildren();
    for (int i = 0; i < children.length; i++) {
      if (children[i] != this) {
        IWindowTrim trim = tbm.getTrim(children[i].getID());
        if (trim == null)
          continue;

        if (trim instanceof ViewStackTrimToolBar) {
          ViewStackTrimToolBar vstb = (ViewStackTrimToolBar) trim;
          if (vstb.restoreOnUnzoom()
              && children[i] instanceof ContainerPlaceholder) {
            // In the current presentation its a
            // container placeholder
            ViewStack realStack = (ViewStack) ((ContainerPlaceholder) children[i])
                .getRealContainer();
            realStack.setMinimized(false);

            vstb.setRestoreOnUnzoom(false);
          }
        } else if (trim instanceof EditorAreaTrimToolBar) {
          if (perspective.getEditorAreaRestoreOnUnzoom())
          perspective.setEditorAreaState(IStackPresentationSite.STATE_RESTORED);
        }
      }
    }

    // If the editor area has changed state tell the perspective
    if (restoringEditorArea)
      perspective.setEditorAreaState(IStackPresentationSite.STATE_RESTORED);

    perspective.getPresentation().setMaximizedStack(null);
   
    fvm.deferUpdates(false);
    smartZoomed = false;
   
    doingUnzoom = false;
    }
   
  protected void setState(final int newState) {
    final int oldState = presentationSite.getState();
    if (!supportsState(newState) || newState == oldState) {
      return;
    }

    final WorkbenchWindow wbw = (WorkbenchWindow) getPage().getWorkbenchWindow();
    if (wbw == null || wbw.getShell() == null || wbw.getActiveWorkbenchPage() == null)
      return;

    WorkbenchPage page = wbw.getActiveWorkbenchPage();
    if (page == null)
      return;
   
    boolean useNewMinMax = Perspective.useNewMinMax(page.getActivePerspective());

    // we have to fiddle with the zoom behavior to satisfy Intro req's
    // by usning the old zoom behavior for its stack
    if (newState == IStackPresentationSite.STATE_MAXIMIZED)
      useNewMinMax = useNewMinMax && !isIntroInStack();
    else if (newState == IStackPresentationSite.STATE_RESTORED) {
      PartStack maxStack = page.getActivePerspective().getPresentation().getMaximizedStack();
      useNewMinMax = useNewMinMax && maxStack == this;
    }

    if (useNewMinMax) {
          StartupThreading.runWithoutExceptions(new StartupRunnable() {
        public void runWithException() throws Throwable {
          wbw.getPageComposite().setRedraw(false);
          try {
            if (newState == IStackPresentationSite.STATE_MAXIMIZED) {
              smartZoom();
            } else if (oldState == IStackPresentationSite.STATE_MAXIMIZED) {
              smartUnzoom();
            }
           
            if (newState == IStackPresentationSite.STATE_MINIMIZED) {
              setMinimized(true);
            }
          } finally {
            wbw.getPageComposite().setRedraw(true);

            // Force a redraw (fixes Mac refresh)
            wbw.getShell().redraw();
          }

          setPresentationState(newState);
        }
      });
    } else {
      boolean minimized = (newState == IStackPresentationSite.STATE_MINIMIZED);
      setMinimized(minimized);

      if (newState == IStackPresentationSite.STATE_MAXIMIZED) {
        requestZoomIn();
      } else if (oldState == IStackPresentationSite.STATE_MAXIMIZED) {
        requestZoomOut();
       
        if (newState == IStackPresentationSite.STATE_MINIMIZED)
          setMinimized(true);
      }
    }
  }
   

    /**
     * Called by the workbench page to notify this part that it has been zoomed or unzoomed.
     * The PartStack should not call this method itself -- it must request zoom changes by
     * talking to the WorkbenchPage.
     */
    public void setZoomed(boolean isZoomed) {
       
        super.setZoomed(isZoomed);
       
        LayoutPart[] children = getChildren();
       
        for (int i = 0; i < children.length; i++) {
            LayoutPart next = children[i];
           
            next.setZoomed(isZoomed);
        }
       
        refreshPresentationState();
    }
   
    public boolean isZoomed() {
        ILayoutContainer container = getContainer();
       
        if (container != null) {
            return container.childIsZoomed(this);
        }
       
        return false;
    }
   
    protected void refreshPresentationState() {
        if (isZoomed() || smartZoomed) {
            presentationSite.setPresentationState(IStackPresentationSite.STATE_MAXIMIZED);
        } else {
           
            boolean wasMinimized = (presentationSite.getState() == IStackPresentationSite.STATE_MINIMIZED);
           
            if (isMinimized) {
                presentationSite.setPresentationState(IStackPresentationSite.STATE_MINIMIZED);
            } else {
                presentationSite.setPresentationState(IStackPresentationSite.STATE_RESTORED);
            }
           
            if (isMinimized != wasMinimized) {
                flushLayout();
               
                if (isMinimized) {
                  WorkbenchPage page = getPage();
 
                  if (page != null) {
                      page.refreshActiveView();
                  }
                }
            }
        }
    }

    /**
     * Makes the given part visible in the presentation.
     * @param part the part to add to the stack
     * @param cookie other information
     */
    private void showPart(LayoutPart part, Object cookie) {

        if (isDisposed()) {
            return;
        }
       
        if ((part instanceof PartPlaceholder)) {
          part.setContainer(this);
          return;
        }

        if (!(part instanceof PartPane)) {
      WorkbenchPlugin.log(NLS.bind(
          WorkbenchMessages.PartStack_incorrectPartInFolder, part
              .getID()));
      return;
    }
       
        PartPane pane = (PartPane)part;
       
        PresentablePart presentablePart = new PresentablePart(pane, getControl().getParent());
        presentableParts.add(presentablePart);
       
        if (isActive) {
            part.setContainer(this);
        }
       
        presentationSite.getPresentation().addPart(presentablePart, cookie);

        if (requestedCurrent == null) {
            setSelection(part);
        }
       
        if (childObscuredByZoom(part)) {
      presentablePart.enableInputs(false);
    }
    }

    /**
   * Update the container to show the correct visible tab based on the
   * activation list.
   */
    private void updateContainerVisibleTab() {
        LayoutPart[] parts = getChildren();

        if (parts.length < 1) {
            setSelection(null);
            return;
        }

        PartPane selPart = null;
        int topIndex = 0;
        WorkbenchPage page = getPage();

        if (page != null) {
            IWorkbenchPartReference sortedPartsArray[] = page.getSortedParts();
            List sortedParts = Arrays.asList(sortedPartsArray);
            for (int i = 0; i < parts.length; i++) {
                if (parts[i] instanceof PartPane) {
                    IWorkbenchPartReference part = ((PartPane) parts[i])
                            .getPartReference();
                    int index = sortedParts.indexOf(part);
                    if (index >= topIndex) {
                        topIndex = index;
                        selPart = (PartPane) parts[i];
                    }
                }
            }

        }

        if (selPart == null) {
            List presentableParts = getPresentableParts();
            if (presentableParts.size() != 0) {
                IPresentablePart part = (IPresentablePart) getPresentableParts()
                        .get(0);

                selPart = (PartPane) getPaneFor(part);
            }
        }

        setSelection(selPart);
    }

    /**
     *
     */
    public void showSystemMenu() {
        getPresentation().showSystemMenu();
    }

    public void showPaneMenu() {
        getPresentation().showPaneMenu();
    }

    public void showPartList() {
        getPresentation().showPartList();
    }
   
    public Control[] getTabList(LayoutPart part) {
        if (part != null) {
            IPresentablePart presentablePart = getPresentablePart(part);
            StackPresentation presentation = getPresentation();

            if (presentablePart != null && presentation != null) {
                return presentation.getTabList(presentablePart);
            }
        }

        return new Control[0];
    }

    /**
     *
     * @param beingDragged
     * @param initialLocation
     * @param keyboard
     */
    private void dragStart(IPresentablePart beingDragged, Point initialLocation,
            boolean keyboard) {
        if (beingDragged == null) {
            paneDragStart((LayoutPart)null, initialLocation, keyboard);
        } else {
            if (presentationSite.isPartMoveable(beingDragged)) {
                LayoutPart pane = getPaneFor(beingDragged);

                if (pane != null) {
                    paneDragStart(pane, initialLocation, keyboard);
                }
            }
        }
    }
   
    public void paneDragStart(LayoutPart pane, Point initialLocation,
            boolean keyboard) {
        if (pane == null) {
            if (canMoveFolder()) {
             
                if (presentationSite.getState() == IStackPresentationSite.STATE_MAXIMIZED) {
                  // Calculate where the initial location was BEFORE the 'restore'...as a percentage
                  Rectangle bounds = Geometry.toDisplay(getParent(), getPresentation().getControl().getBounds());
                  float xpct = (initialLocation.x - bounds.x) / (float)(bounds.width);
                  float ypct = (initialLocation.y - bounds.y) / (float)(bounds.height);

                  setState(IStackPresentationSite.STATE_RESTORED);

                  // Now, adjust the initial location to be within the bounds of the restored rect
                  bounds = Geometry.toDisplay(getParent(), getPresentation().getControl().getBounds());
                  initialLocation.x = (int) (bounds.x + (xpct * bounds.width));
                  initialLocation.y = (int) (bounds.y + (ypct * bounds.height));
                }
   
                DragUtil.performDrag(PartStack.this, Geometry
                        .toDisplay(getParent(), getPresentation().getControl()
                                .getBounds()), initialLocation, !keyboard);
            }
        } else {

            if (presentationSite.getState() == IStackPresentationSite.STATE_MAXIMIZED) {
              // Calculate where the initial location was BEFORE the 'restore'...as a percentage
              Rectangle bounds = Geometry.toDisplay(getParent(), getPresentation().getControl().getBounds());
              float xpct = (initialLocation.x - bounds.x) / (float)(bounds.width);
              float ypct = (initialLocation.y - bounds.y) / (float)(bounds.height);
             
                presentationSite.setState(IStackPresentationSite.STATE_RESTORED);

              // Now, adjust the initial location to be within the bounds of the restored rect
              // See bug 100908
              bounds = Geometry.toDisplay(getParent(), getPresentation().getControl().getBounds());
              initialLocation.x = (int) (bounds.x + (xpct * bounds.width));
              initialLocation.y = (int) (bounds.y + (ypct * bounds.height));
            }
   
            DragUtil.performDrag(pane, Geometry.toDisplay(getParent(),
                    getPresentation().getControl().getBounds()),
                    initialLocation, !keyboard);
        }
    }

    /**
     * @return Returns the savedPresentationState.
     */
    public IMemento getSavedPresentationState() {
        return savedPresentationState;
    }
   
    private void fireInternalPropertyChange(int id) {
        Object listeners[] = this.listeners.getListeners();
        for (int i = 0; i < listeners.length; i++) {
            ((IPropertyListener) listeners[i]).propertyChanged(this, id);
        }
    }
   
    // TrimStack Support
   
    /**
     * Explicitly sets the presentation state. This is used by the
     * new min/max code to force the CTabFolder to show the proper
     * state without going through the 'setState' code (which causes
     * nasty side-effects.
     * @param newState The state to set the presentation to
     */
    public void setPresentationState(int newState) {
      presentationSite.setPresentationState(newState);
    }

    //
    // Support for passing perspective layout properties to the presentation

   
    public String getProperty(String id)  {
        return (String)properties.get(id);
    }
   
    public void setProperty(String id, String value) {
      if (value==null) {
        properties.remove(id);
      } else {
        properties.put(id, value);
      }
    }
   
    /**
     * Copies all appearance related data from this stack to the given stack.
     */
    public void copyAppearanceProperties(PartStack copyTo) {
        copyTo.appearance = this.appearance;
        if (!properties.isEmpty()) {
            Set ids = properties.keySet();
            for (Iterator iterator = ids.iterator(); iterator.hasNext();) {
                String id = (String)iterator.next();
                copyTo.setProperty(id, (String)properties.get(id));
            }
        }
    }
}
TOP

Related Classes of org.eclipse.ui.internal.PartStack$PartStackDropResult

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.