| /******************************************************************************* |
| * Copyright (c) 2004 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Common Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/cpl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.ui.internal; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.jface.action.ContributionItem; |
| import org.eclipse.jface.action.IMenuManager; |
| import org.eclipse.jface.util.Assert; |
| import org.eclipse.jface.util.Geometry; |
| import org.eclipse.jface.window.Window; |
| 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.IMemento; |
| import org.eclipse.ui.IWorkbenchPartReference; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.XMLMemento; |
| import org.eclipse.ui.internal.dnd.DragUtil; |
| import org.eclipse.ui.internal.dnd.IDragOverListener; |
| import org.eclipse.ui.internal.dnd.IDropTarget; |
| import org.eclipse.ui.internal.dnd.SwtUtil; |
| import org.eclipse.ui.internal.presentations.PresentationFactoryUtil; |
| import org.eclipse.ui.internal.presentations.PresentationSerializer; |
| 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 { |
| |
| private List children = new ArrayList(3); |
| private int appearance = PresentationFactoryUtil.ROLE_VIEW; |
| |
| // inactiveCurrent is only used when restoring the persisted state of |
| // perspective on startup. |
| private LayoutPart current; |
| |
| private boolean ignoreSelectionChanges = false; |
| |
| private IMemento savedPresentationState = null; |
| |
| private 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 isCloseable(IPresentablePart part) { |
| return PartStack.this.isCloseable(part); |
| } |
| |
| 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(); |
| } |
| }; |
| |
| protected abstract boolean isMoveable(IPresentablePart part); |
| protected abstract boolean isCloseable(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) { |
| super("PartStack"); //$NON-NLS-1$ |
| |
| this.appearance = appearance; |
| } |
| |
| /** |
| * Returns the currently selected IPresentablePart, or null if none |
| * |
| * @return |
| */ |
| protected IPresentablePart getSelectedPart() { |
| if (current == null) { |
| return null; |
| } |
| |
| return current.getPresentablePart(); |
| } |
| |
| 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); |
| |
| // This object can only contain placeholders or PartPanes |
| Assert.isTrue(child instanceof PartPlaceholder || child instanceof PartPane); |
| |
| // Ensure that all the PartPanes have an associated presentable part |
| IPresentablePart part = child.getPresentablePart(); |
| if (child instanceof PartPane) { |
| Assert.isNotNull(part); |
| } |
| |
| // Ensure that the child's backpointer points to this stack |
| ILayoutContainer childContainer = child.getContainer(); |
| |
| 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); |
| } |
| } else { |
| // If the widgetry exists, the child's backpointer must point to us |
| Assert.isTrue(childContainer == this); |
| |
| // 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); |
| 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 (children.length > 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); |
| } |
| } |
| } else { |
| // Ensure that we have the inactive appearance if we don't have any children |
| Assert.isTrue(getActive() == StackPresentation.AS_INACTIVE); |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ui.internal.LayoutPart#describeLayout(java.lang.StringBuffer) |
| */ |
| public void describeLayout(StringBuffer buf) { |
| |
| testInvariants(); |
| |
| super.describeLayout(buf); |
| // |
| // int activeState = getActive(); |
| // if (activeState == StackPresentation.AS_ACTIVE_FOCUS) { |
| // buf.append("active "); |
| // } else if (activeState == StackPresentation.AS_ACTIVE_NOFOCUS) { |
| // buf.append("active_nofocus "); |
| // } |
| // |
| // 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 (visibleChildren > 0) { |
| // buf.append(", "); //$NON-NLS-1$ |
| // } |
| // |
| // if (next == current) { |
| // buf.append("*"); |
| // } |
| // |
| // next.describeLayout(buf); |
| // |
| // visibleChildren++; |
| // } |
| // } |
| } |
| |
| /** |
| * See IVisualContainer#add |
| */ |
| public void add(LayoutPart child) { |
| children.add(child); |
| showPart(child, null); |
| |
| if (children.size() == 1 && child instanceof PartPane) { |
| setSelection(child); |
| } |
| } |
| |
| /** |
| * Add a part at a particular position |
| */ |
| protected void add(LayoutPart newChild, Object cookie) { |
| children.add(newChild); |
| |
| showPart(newChild, cookie); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.ui.internal.ILayoutContainer#allowsAutoFocus() |
| */ |
| public boolean allowsAutoFocus() { |
| if (presentationSite.getState() == IStackPresentationSite.STATE_MINIMIZED) { return false; } |
| |
| ILayoutContainer parent = getContainer(); |
| |
| if (parent != null && !parent.allowsAutoFocus()) { return false; } |
| |
| return true; |
| } |
| |
| /** |
| * @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; |
| } |
| |
| private AbstractPresentationFactory getFactory() { |
| AbstractPresentationFactory factory = ((WorkbenchWindow) getPage() |
| .getWorkbenchWindow()).getWindowConfigurer() |
| .getPresentationFactory(); |
| |
| return factory; |
| } |
| |
| 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); |
| } |
| |
| 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 |
| Iterator iter = children.iterator(); |
| while (iter.hasNext()) { |
| LayoutPart part = (LayoutPart) iter.next(); |
| |
| showPart(part, null); |
| } |
| |
| Control ctrl = getPresentation().getControl(); |
| |
| // Add a drop target that lets us drag views directly to a particular |
| // tab |
| DragUtil.addDragTarget(ctrl, new IDragOverListener() { |
| |
| public IDropTarget drag(Control currentControl, |
| final Object draggedObject, Point position, |
| Rectangle dragRectangle) { |
| |
| if (!(draggedObject instanceof PartPane)) { return null; } |
| |
| final PartPane pane = (PartPane) draggedObject; |
| if (!allowsDrop(pane)) { |
| return null; |
| } |
| |
| // Don't allow views to be dragged between windows |
| if (pane.getWorkbenchWindow() != getWorkbenchWindow()) { return null; } |
| |
| // Regardless of the wishes of the presentation, ignore 4 pixels around the edge of the control. |
| // This ensures that it will always be possible to dock around the edge of the control. |
| { |
| Point controlCoordinates = currentControl.getParent().toControl(position); |
| Rectangle bounds = currentControl.getBounds(); |
| int closestSide = Geometry.getClosestSide(bounds, controlCoordinates); |
| |
| if (Geometry.getDistanceFromEdge(bounds, controlCoordinates, closestSide) < 5) { |
| return null; |
| } |
| } |
| // End of check for stacking on edge |
| |
| final StackDropResult dropResult = getPresentation().dragOver( |
| currentControl, position); |
| |
| if (dropResult == null) { return null; } |
| |
| //if (dropResult.getInsertionPoint() == pane.getPresentablePart()) { return null; }; |
| |
| return new IDropTarget() { |
| |
| public void drop() { |
| |
| // If we're dragging a pane over itself do nothing |
| //if (dropResult.getInsertionPoint() == pane.getPresentablePart()) { return; }; |
| |
| // Don't worry about reparenting the view if we're |
| // simply rearranging tabs within this folder |
| if (pane.getContainer() != PartStack.this) { |
| derefPart(pane); |
| pane.reparent(getParent()); |
| } else { |
| remove(pane); |
| } |
| |
| add(pane, dropResult.getCookie()); |
| setSelection(pane); |
| pane.setFocus(); |
| } |
| |
| public Cursor getCursor() { |
| return DragCursors.getCursor(DragCursors.CENTER); |
| } |
| |
| public Rectangle getSnapRectangle() { |
| return dropResult.getSnapRectangle(); |
| } |
| }; |
| } |
| |
| }); |
| |
| ctrl.setData(this); |
| |
| if (getVisiblePart() == null) { |
| updateContainerVisibleTab(); |
| } |
| |
| updateActions(); |
| |
| refreshPresentationSelection(); |
| } |
| |
| /** |
| * Saves the current state of the presentation to savedPresentationState, if the |
| * presentation exists. |
| */ |
| private 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(); |
| |
| Iterator iter = children.iterator(); |
| while (iter.hasNext()) { |
| LayoutPart next = (LayoutPart) iter.next(); |
| |
| next.setContainer(null); |
| } |
| } |
| |
| public void findSashes(LayoutPart part, PartPane.Sashes sashes) { |
| ILayoutContainer container = getContainer(); |
| |
| if (container != null) { |
| container.findSashes(this, sashes); |
| } |
| } |
| |
| /** |
| * Forces the layout to be recomputed for all parts |
| */ |
| private void forceLayout() { |
| PartSashContainer cont = (PartSashContainer) getContainer(); |
| if (cont != null) { |
| LayoutTree tree = cont.getLayoutTree(); |
| tree.setBounds(getParent().getClientArea()); |
| } |
| } |
| |
| /** |
| * 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(); |
| } |
| |
| // getMinimumHeight() added by cagatayk@acm.org |
| /** |
| * @see LayoutPart#getMinimumHeight() |
| */ |
| public int getMinimumHeight() { |
| if (getPresentation() == null) { return 0; } |
| |
| return getPresentation().computeMinimumSize().y; |
| } |
| |
| /** |
| * 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) { |
| return null; |
| } |
| |
| Iterator iter = children.iterator(); |
| while (iter.hasNext()) { |
| LayoutPart next = (LayoutPart) iter.next(); |
| |
| if (next.getPresentablePart() == part) { return next; } |
| } |
| |
| return null; |
| } |
| |
| /** |
| * Get the parent control. |
| */ |
| public Composite getParent() { |
| return getControl().getParent(); |
| } |
| |
| private IPresentablePart getPresentablePartAtIndex(int idx) { |
| List presentableParts = getPresentableParts(); |
| |
| if (idx >= 0 && idx < presentableParts.size()) { return (IPresentablePart) presentableParts |
| .get(idx); } |
| |
| return null; |
| } |
| |
| /** |
| * Returns a list of IPresentablePart |
| * |
| * @return |
| */ |
| private List getPresentableParts() { |
| List result = new ArrayList(children.size()); |
| |
| Iterator iter = children.iterator(); |
| while (iter.hasNext()) { |
| LayoutPart part = (LayoutPart) iter.next(); |
| |
| IPresentablePart presentablePart = part.getPresentablePart(); |
| |
| if (presentablePart != null) { |
| result.add(presentablePart); |
| } |
| } |
| |
| return result; |
| } |
| |
| protected StackPresentation getPresentation() { |
| return presentationSite.getPresentation(); |
| } |
| |
| /** |
| * Returns the visible child. |
| */ |
| public PartPane getVisiblePart() { |
| 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 == current) { |
| return; |
| } |
| |
| setSelection(newPart); |
| |
| if (newPart != null) { |
| newPart.setFocus(); |
| } |
| |
| // set the title of the detached window to reflect the active tab |
| Window window = getWindow(); |
| if (window instanceof DetachedWindow) { |
| window.getShell().setText(newSelection.getTitle()); |
| } |
| } |
| |
| /** |
| * See IVisualContainer#remove |
| */ |
| public void remove(LayoutPart child) { |
| IPresentablePart presentablePart = child.getPresentablePart(); |
| |
| // 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; |
| presentation.removePart(presentablePart); |
| ignoreSelectionChanges = false; |
| } |
| |
| if (!isDisposed()) { |
| child.setContainer(null); |
| } |
| |
| if (child == current) { |
| updateContainerVisibleTab(); |
| } |
| } |
| |
| /** |
| * Reparent a part. Also reparent visible children... |
| */ |
| public void reparent(Composite newParent) { |
| if (!newParent.isReparentable()) return; |
| |
| Control control = getControl(); |
| if ((control == null) || (control.getParent() == newParent)) 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) { |
| IPresentablePart oldPart = oldChild.getPresentablePart(); |
| IPresentablePart newPart = newChild.getPresentablePart(); |
| |
| int idx = children.indexOf(oldChild); |
| children.add(idx, newChild); |
| |
| showPart(newChild, oldPart); |
| |
| if (oldChild == current) { |
| setSelection(newChild); |
| } |
| |
| remove(oldChild); |
| } |
| |
| public boolean resizesVertically() { |
| return presentationSite.getState() != IStackPresentationSite.STATE_MINIMIZED; |
| } |
| |
| /** |
| * @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)) { |
| // Mark this as the active part. |
| current = part; |
| } |
| } |
| } |
| |
| Integer expanded = memento.getInteger(IWorkbenchConstants.TAG_EXPANDED); |
| 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; |
| } |
| } |
| |
| return new Status(IStatus.OK, PlatformUI.PLUGIN_ID, 0, "", null); //$NON-NLS-1$ |
| } |
| |
| /** |
| * @see IPersistable |
| */ |
| public IStatus saveState(IMemento memento) { |
| |
| // Save the active tab. |
| if (current != null) |
| memento.putString(IWorkbenchConstants.TAG_ACTIVE_PAGE_ID, |
| current.getID()); |
| |
| Iterator iter = children.iterator(); |
| while (iter.hasNext()) { |
| LayoutPart next = (LayoutPart) iter.next(); |
| |
| IMemento childMem = memento |
| .createChild(IWorkbenchConstants.TAG_PAGE); |
| |
| IPresentablePart part = next.getPresentablePart(); |
| String tabText = "LabelNotFound"; //$NON-NLS-1$ |
| if (part != null) { |
| tabText = part.getName(); |
| } |
| childMem.putString(IWorkbenchConstants.TAG_LABEL, tabText); |
| childMem.putString(IWorkbenchConstants.TAG_CONTENT, next.getID()); |
| } |
| |
| 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); |
| } |
| |
| 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_INACTIVE) { |
| if (presentationSite.getState() == IStackPresentationSite.STATE_MINIMIZED) { |
| setState(IStackPresentationSite.STATE_RESTORED); |
| } |
| } |
| |
| 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 (current == part) { |
| return; |
| } |
| |
| current = part; |
| |
| if (!isDisposed()) { |
| updateActions(); |
| } |
| refreshPresentationSelection(); |
| } |
| |
| /** |
| * Subclasses should override this method to update the enablement state of their |
| * actions |
| */ |
| protected void updateActions() { |
| |
| } |
| |
| private void refreshPresentationSelection() { |
| if (current != null) { |
| IPresentablePart presentablePart = current.getPresentablePart(); |
| StackPresentation presentation = getPresentation(); |
| |
| if (presentablePart != null && presentation != null) { |
| |
| current.createControl(getParent()); |
| if (current.getControl().getParent() != getControl().getParent()) { |
| current.reparent(getControl().getParent()); |
| } |
| |
| current.moveAbove(getPresentation().getControl()); |
| |
| presentation.selectPart(presentablePart); |
| } |
| } |
| } |
| |
| private void setState(int newState) { |
| if (!supportsState(newState) || newState == presentationSite.getState()) { return; } |
| |
| int oldState = presentationSite.getState(); |
| |
| if (current != null) { |
| if (newState == IStackPresentationSite.STATE_MAXIMIZED) { |
| PartPane pane = getVisiblePart(); |
| if (pane != null) { |
| pane.doZoom(); |
| } |
| } else { |
| presentationSite.setPresentationState(newState); |
| |
| WorkbenchPage page = getPage(); |
| if (page != null) { |
| if (page.isZoomed()) { |
| page.zoomOut(); |
| } |
| |
| updateControlBounds(); |
| |
| if (oldState == IStackPresentationSite.STATE_MINIMIZED) { |
| forceLayout(); |
| } |
| } |
| } |
| } |
| |
| if (presentationSite.getState() == IStackPresentationSite.STATE_MINIMIZED) { |
| WorkbenchPage page = getPage(); |
| |
| if (page != null) { |
| page.refreshActiveView(); |
| } |
| } |
| } |
| |
| public void setZoomed(boolean isZoomed) { |
| super.setZoomed(isZoomed); |
| |
| if (isZoomed) { |
| presentationSite |
| .setPresentationState(IStackPresentationSite.STATE_MAXIMIZED); |
| } else if (presentationSite.getState() == IStackPresentationSite.STATE_MAXIMIZED) { |
| presentationSite.setPresentationState(IStackPresentationSite.STATE_RESTORED); |
| } |
| } |
| |
| /** |
| * Makes the given part visible in the presentation |
| * |
| * @param presentablePart |
| */ |
| private void showPart(LayoutPart part, Object cookie) { |
| |
| if (isDisposed()) { |
| return; |
| } |
| |
| part.setContainer(this); |
| |
| IPresentablePart presentablePart = part.getPresentablePart(); |
| |
| if (presentablePart == null) { return; } |
| |
| presentationSite.getPresentation().addPart(presentablePart, cookie); |
| } |
| |
| /** |
| * Update the container to show the correct visible tab based on the |
| * activation list. |
| * |
| * @param org.eclipse.ui.internal.ILayoutContainer |
| */ |
| 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); |
| } |
| |
| private void updateControlBounds() { |
| StackPresentation presentation = getPresentation(); |
| |
| if (presentation != null) { |
| Rectangle bounds = presentation.getControl().getBounds(); |
| int minimumHeight = getMinimumHeight(); |
| |
| if (presentationSite.getState() == IStackPresentationSite.STATE_MINIMIZED |
| && bounds.height != minimumHeight) { |
| bounds.width = getMinimumWidth(); |
| bounds.height = minimumHeight; |
| getPresentation().setBounds(bounds); |
| |
| forceLayout(); |
| } |
| } |
| } |
| |
| /** |
| * |
| */ |
| public void showSystemMenu() { |
| getPresentation().showSystemMenu(); |
| } |
| |
| public void showPaneMenu() { |
| getPresentation().showPaneMenu(); |
| } |
| |
| public void showPartList() { |
| getPresentation().showPartList(); |
| } |
| |
| /** |
| * @param pane |
| * @return |
| */ |
| public Control[] getTabList(LayoutPart part) { |
| if (part != null) { |
| IPresentablePart presentablePart = part.getPresentablePart(); |
| StackPresentation presentation = getPresentation(); |
| |
| if (presentablePart != null && presentation != null) { |
| return presentation.getTabList(presentablePart); |
| } |
| } |
| |
| return new Control[0]; |
| } |
| |
| /** |
| * |
| * @param beingDragged |
| * @param initialLocation |
| * @param keyboard |
| */ |
| public void dragStart(IPresentablePart beingDragged, Point initialLocation, boolean keyboard) { |
| if (beingDragged == null) { |
| if (canMoveFolder()) { |
| if (presentationSite.getState() == IStackPresentationSite.STATE_MAXIMIZED) { |
| setState(IStackPresentationSite.STATE_RESTORED); |
| } |
| |
| DragUtil.performDrag(PartStack.this, Geometry.toDisplay( |
| getParent(), getPresentation().getControl().getBounds()), |
| initialLocation, !keyboard); |
| } |
| } else { |
| if (presentationSite.isPartMoveable(beingDragged)) { |
| LayoutPart pane = getPaneFor(beingDragged); |
| |
| if (pane != null) { |
| if (presentationSite.getState() == IStackPresentationSite.STATE_MAXIMIZED) { |
| presentationSite.setState(IStackPresentationSite.STATE_RESTORED); |
| } |
| |
| DragUtil.performDrag(pane, Geometry.toDisplay(getParent(), |
| getPresentation().getControl().getBounds()), |
| initialLocation, !keyboard); |
| } |
| } |
| } |
| } |
| } |