org.eclipse.ui.internal.PartStack Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of workbench Show documentation
Show all versions of workbench Show documentation
This plug-in contains the bulk of the Workbench implementation, and depends on JFace, SWT, and Core Runtime. It cannot be used independently from org.eclipse.ui. Workbench client plug-ins should not depend directly on this plug-in.
The newest version!
/*******************************************************************************
* 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 [email protected] 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));
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy