| /******************************************************************************* |
| * Copyright (c) 2000, 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 |
| *******************************************************************************/ |
| package org.eclipse.ui.internal; |
| |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.Map; |
| |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.MultiStatus; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.dnd.DND; |
| import org.eclipse.swt.dnd.DropTarget; |
| import org.eclipse.swt.graphics.Rectangle; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.ui.IMemento; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.internal.StartupThreading.StartupRunnable; |
| import org.eclipse.ui.internal.presentations.PresentationSerializer; |
| import org.eclipse.ui.presentations.IStackPresentationSite; |
| import org.eclipse.ui.presentations.StackPresentation; |
| |
| /** |
| * Represents the area set aside for editor workbooks. |
| * This container only accepts EditorStack and PartSash |
| * as layout parts. |
| * |
| * Note no views are allowed within this container. |
| */ |
| public class EditorSashContainer extends PartSashContainer { |
| |
| static final String DEFAULT_WORKBOOK_ID = "DefaultEditorWorkbook";//$NON-NLS-1$ |
| |
| private ArrayList editorWorkbooks = new ArrayList(3); |
| |
| private EditorStack activeEditorWorkbook; |
| |
| private DropTarget dropTarget; |
| |
| public EditorSashContainer(String editorId, WorkbenchPage page, Composite parent) { |
| super(editorId, page, parent); |
| |
| createDefaultWorkbook(); |
| } |
| |
| |
| /** |
| * Add an editor to the active workbook. |
| */ |
| public void addEditor(EditorPane pane, EditorStack stack) { |
| //EditorStack workbook = getActiveWorkbook(); |
| stack.add(pane); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ui.internal.PartSashContainer#addChild(org.eclipse.ui.internal.PartSashContainer.RelationshipInfo) |
| */ |
| protected void addChild(RelationshipInfo info) { |
| super.addChild(info); |
| |
| updateStackButtons(); |
| } |
| |
| /** |
| * Hides the min/max buttons for all editor stacks |
| * -except- for the upper/left one. |
| */ |
| public void updateStackButtons() { |
| // This is applicable only when the new |
| // min/max behaviour is being used |
| Perspective persp = getPage().getActivePerspective(); |
| if (!Perspective.useNewMinMax(persp)) |
| return; |
| |
| // Find the upper Right editor stack |
| LayoutPart[] stacks = getChildren(); |
| EditorStack winner = getUpperRightEditorStack(stacks); |
| |
| // Now hide the buttons for all but the upper right stack |
| for (int i = 0; i < stacks.length; i++) { |
| if (!(stacks[i] instanceof EditorStack)) |
| continue; |
| ((EditorStack)stacks[i]).showMinMax(stacks[i] == winner); |
| } |
| |
| // Force the stack's presentation state to match its perspective |
| persp.refreshEditorAreaVisibility(); |
| } |
| |
| /** |
| * @param stacks |
| * @return the EditorStack in the upper right position |
| */ |
| public EditorStack getUpperRightEditorStack(LayoutPart[] stacks) { |
| if (stacks == null) |
| stacks = getChildren(); |
| |
| // Find the upper Right editor stack |
| EditorStack winner = null; |
| Rectangle winnerRect = null; |
| |
| for (int i = 0; i < stacks.length; i++) { |
| if (!(stacks[i] instanceof EditorStack)) |
| continue; |
| |
| EditorStack stack = (EditorStack) stacks[i]; |
| Rectangle bb = stack.getBounds(); |
| if (winnerRect == null || |
| bb.y < winnerRect.y || |
| (bb.y == winnerRect.y && bb.x > winnerRect.x)) { |
| winner = stack; |
| winnerRect = bb; |
| } |
| } |
| |
| return winner; |
| } |
| |
| /** |
| * Notification that a child layout part has been |
| * added to the container. Subclasses may override |
| * this method to perform any container specific |
| * work. |
| */ |
| protected void childAdded(LayoutPart child) { |
| super.childAdded(child); |
| |
| if (child instanceof EditorStack) { |
| editorWorkbooks.add(child); |
| } |
| } |
| |
| /** |
| * Notification that a child layout part has been |
| * removed from the container. Subclasses may override |
| * this method to perform any container specific |
| * work. |
| */ |
| protected void childRemoved(LayoutPart child) { |
| super.childRemoved(child); |
| |
| if (child instanceof EditorStack) { |
| editorWorkbooks.remove(child); |
| if (activeEditorWorkbook == child) { |
| setActiveWorkbook(null, false); |
| } |
| |
| updateStackButtons(); |
| } |
| } |
| |
| protected EditorStack createDefaultWorkbook() { |
| EditorStack newWorkbook = EditorStack.newEditorWorkbook(this, page); |
| newWorkbook.setID(DEFAULT_WORKBOOK_ID); |
| add(newWorkbook); |
| return newWorkbook; |
| } |
| |
| /** |
| * Subclasses override this method to specify |
| * the composite to use to parent all children |
| * layout parts it contains. |
| */ |
| protected Composite createParent(Composite parentWidget) { |
| return new Composite(parentWidget, SWT.NONE); |
| } |
| |
| /** |
| * Dispose of the editor area. |
| */ |
| public void dispose() { |
| // Free editor workbooks. |
| editorWorkbooks.clear(); |
| |
| // Free rest. |
| super.dispose(); |
| } |
| |
| /** |
| * Subclasses override this method to dispose |
| * of any swt resources created during createParent. |
| */ |
| protected void disposeParent() { |
| this.parent.dispose(); |
| } |
| |
| /** |
| * Return the editor workbook which is active. |
| */ |
| public EditorStack getActiveWorkbook() { |
| if (activeEditorWorkbook == null) { |
| if (editorWorkbooks.size() < 1) { |
| setActiveWorkbook(createDefaultWorkbook(), false); |
| } else { |
| setActiveWorkbook((EditorStack) editorWorkbooks.get(0), false); |
| } |
| } |
| |
| return activeEditorWorkbook; |
| } |
| |
| /** |
| * Return the editor workbook id which is active. |
| */ |
| public String getActiveWorkbookID() { |
| return getActiveWorkbook().getID(); |
| } |
| |
| /** |
| * Return the all the editor workbooks. |
| */ |
| public ArrayList getEditorWorkbooks() { |
| return (ArrayList) editorWorkbooks.clone(); |
| } |
| |
| /** |
| * Return the all the editor workbooks. |
| */ |
| public int getEditorWorkbookCount() { |
| return editorWorkbooks.size(); |
| } |
| |
| /** |
| * Return true is the workbook specified |
| * is the active one. |
| */ |
| protected boolean isActiveWorkbook(EditorStack workbook) { |
| return activeEditorWorkbook == workbook; |
| } |
| |
| /** |
| * Find the sashs around the specified part. |
| */ |
| public void findSashes(LayoutPart pane, PartPane.Sashes sashes) { |
| //Find the sashes around the current editor and |
| //then the sashes around the editor area. |
| super.findSashes(pane, sashes); |
| |
| ILayoutContainer container = getContainer(); |
| if (container != null) { |
| container.findSashes(this, sashes); |
| } |
| } |
| |
| /** |
| * Remove all the editors |
| */ |
| public void removeAllEditors() { |
| EditorStack currentWorkbook = getActiveWorkbook(); |
| |
| // Iterate over a copy so the original can be modified. |
| Iterator workbooks = ((ArrayList) editorWorkbooks.clone()).iterator(); |
| while (workbooks.hasNext()) { |
| EditorStack workbook = (EditorStack) workbooks.next(); |
| workbook.removeAll(); |
| if (workbook != currentWorkbook) { |
| remove(workbook); |
| workbook.dispose(); |
| } |
| } |
| } |
| |
| /** |
| * Remove an editor from its' workbook. |
| */ |
| public void removeEditor(EditorPane pane) { |
| EditorStack workbook = pane.getWorkbook(); |
| if (workbook == null) { |
| return; |
| } |
| workbook.remove(pane); |
| |
| // remove the editor workbook if empty |
| if (workbook.getItemCount() < 1 /* && editorWorkbooks.size() > 1*/) { |
| // If the user closes the last editor and the editor area |
| // is maximized, restore it |
| Perspective persp = getPage().getActivePerspective(); |
| if (Perspective.useNewMinMax(persp)) { |
| if (persp.getPresentation().getMaximizedStack() instanceof EditorStack) |
| persp.getPresentation().getMaximizedStack(). |
| setState(IStackPresentationSite.STATE_RESTORED); |
| } |
| |
| remove(workbook); |
| workbook.dispose(); |
| } |
| } |
| |
| /** |
| * @see IPersistablePart |
| */ |
| public IStatus restoreState(IMemento memento) { |
| MultiStatus result = new MultiStatus( |
| PlatformUI.PLUGIN_ID, |
| IStatus.OK, |
| WorkbenchMessages.RootLayoutContainer_problemsRestoringPerspective, null); |
| |
| // Remove the default editor workbook that is |
| // initialy created with the editor area. |
| if (children != null) { |
| StartupThreading.runWithoutExceptions(new StartupRunnable() { |
| |
| public void runWithException() throws Throwable { |
| EditorStack defaultWorkbook = null; |
| for (int i = 0; i < children.size(); i++) { |
| LayoutPart child = (LayoutPart) children.get(i); |
| if (child.getID() == DEFAULT_WORKBOOK_ID) { |
| defaultWorkbook = (EditorStack) child; |
| if (defaultWorkbook.getItemCount() > 0) { |
| defaultWorkbook = null; |
| } |
| } |
| } |
| if (defaultWorkbook != null) { |
| remove(defaultWorkbook); |
| } |
| }}); |
| |
| } |
| |
| // Restore the relationship/layout |
| IMemento[] infos = memento.getChildren(IWorkbenchConstants.TAG_INFO); |
| final Map mapIDtoPart = new HashMap(infos.length); |
| |
| for (int i = 0; i < infos.length; i++) { |
| // Get the info details. |
| IMemento childMem = infos[i]; |
| final String partID = childMem.getString(IWorkbenchConstants.TAG_PART); |
| final String relativeID = childMem |
| .getString(IWorkbenchConstants.TAG_RELATIVE); |
| int relationship = 0; |
| int left = 0, right = 0; |
| float ratio = 0.5f; |
| if (relativeID != null) { |
| relationship = childMem.getInteger( |
| IWorkbenchConstants.TAG_RELATIONSHIP).intValue(); |
| Float ratioFloat = childMem |
| .getFloat(IWorkbenchConstants.TAG_RATIO); |
| Integer leftInt = childMem |
| .getInteger(IWorkbenchConstants.TAG_RATIO_LEFT); |
| Integer rightInt = childMem |
| .getInteger(IWorkbenchConstants.TAG_RATIO_RIGHT); |
| if (leftInt != null && rightInt != null) { |
| left = leftInt.intValue(); |
| right = rightInt.intValue(); |
| } else if (ratioFloat != null) { |
| ratio = ratioFloat.floatValue(); |
| } |
| } |
| |
| final EditorStack workbook [] = new EditorStack[1]; |
| StartupThreading.runWithoutExceptions(new StartupRunnable() { |
| |
| public void runWithException() throws Throwable { |
| // Create the part. |
| workbook[0] = EditorStack.newEditorWorkbook(EditorSashContainer.this, page); |
| workbook[0].setID(partID); |
| // 1FUN70C: ITPUI:WIN - Shouldn't set Container when not active |
| workbook[0].setContainer(EditorSashContainer.this); |
| }}); |
| |
| |
| IMemento workbookMemento = childMem |
| .getChild(IWorkbenchConstants.TAG_FOLDER); |
| if (workbookMemento != null) { |
| result.add(workbook[0].restoreState(workbookMemento)); |
| } |
| |
| final int myLeft = left, myRight = right, myRelationship = relationship; |
| final float myRatio = ratio; |
| StartupThreading.runWithoutExceptions(new StartupRunnable() { |
| |
| public void runWithException() throws Throwable { |
| // Add the part to the layout |
| if (relativeID == null) { |
| add(workbook[0]); |
| } else { |
| LayoutPart refPart = (LayoutPart) mapIDtoPart.get(relativeID); |
| if (refPart != null) { |
| //$TODO pass in left and right |
| if (myLeft == 0 || myRight == 0) { |
| add(workbook[0], myRelationship, myRatio, refPart); |
| } else { |
| add(workbook[0], myRelationship, myLeft, myRight, refPart); |
| } |
| } else { |
| WorkbenchPlugin |
| .log("Unable to find part for ID: " + relativeID);//$NON-NLS-1$ |
| } |
| } |
| }}); |
| |
| mapIDtoPart.put(partID, workbook[0]); |
| } |
| |
| return result; |
| } |
| |
| /** |
| * @see IPersistablePart |
| */ |
| public IStatus saveState(IMemento memento) { |
| RelationshipInfo[] relationships = computeRelation(); |
| MultiStatus result = new MultiStatus( |
| PlatformUI.PLUGIN_ID, |
| IStatus.OK, |
| WorkbenchMessages.RootLayoutContainer_problemsSavingPerspective, null); |
| |
| for (int i = 0; i < relationships.length; i++) { |
| // Save the relationship info .. |
| // private LayoutPart part; |
| // private int relationship; |
| // private float ratio; |
| // private LayoutPart relative; |
| RelationshipInfo info = relationships[i]; |
| IMemento childMem = memento |
| .createChild(IWorkbenchConstants.TAG_INFO); |
| childMem.putString(IWorkbenchConstants.TAG_PART, info.part.getID()); |
| |
| EditorStack stack = (EditorStack) info.part; |
| if (stack != null) { |
| IMemento folderMem = childMem |
| .createChild(IWorkbenchConstants.TAG_FOLDER); |
| result.add(stack.saveState(folderMem)); |
| } |
| |
| if (info.relative != null) { |
| childMem.putString(IWorkbenchConstants.TAG_RELATIVE, |
| info.relative.getID()); |
| childMem.putInteger(IWorkbenchConstants.TAG_RELATIONSHIP, |
| info.relationship); |
| childMem.putInteger(IWorkbenchConstants.TAG_RATIO_LEFT, |
| info.left); |
| childMem.putInteger(IWorkbenchConstants.TAG_RATIO_RIGHT, |
| info.right); |
| // Note: "ratio" is not used in newer versions of Eclipse, which use "left" |
| // and "right" (above) instead |
| childMem.putFloat(IWorkbenchConstants.TAG_RATIO, info |
| .getRatio()); |
| } |
| } |
| |
| return result; |
| } |
| |
| /** |
| * Set the editor workbook which is active. |
| */ |
| public void setActiveWorkbook(EditorStack newWorkbook, boolean hasFocus) { |
| if (newWorkbook != null) { |
| if (newWorkbook.isDisposed()) { |
| return; |
| } |
| if (!editorWorkbooks.contains(newWorkbook)) { |
| return; |
| } |
| } |
| EditorStack oldWorkbook = activeEditorWorkbook; |
| activeEditorWorkbook = newWorkbook; |
| |
| if (oldWorkbook != null && oldWorkbook != newWorkbook) { |
| oldWorkbook.setActive(StackPresentation.AS_INACTIVE); |
| } |
| |
| if (newWorkbook != null) { |
| if (hasFocus) { |
| newWorkbook.setActive(StackPresentation.AS_ACTIVE_FOCUS); |
| } else { |
| newWorkbook.setActive(StackPresentation.AS_ACTIVE_NOFOCUS); |
| } |
| } |
| |
| updateTabList(); |
| } |
| |
| /** |
| * Set the editor workbook which is active. |
| */ |
| public void setActiveWorkbookFromID(String id) { |
| for (int i = 0; i < editorWorkbooks.size(); i++) { |
| EditorStack workbook = (EditorStack) editorWorkbooks.get(i); |
| if (workbook.getID().equals(id)) { |
| setActiveWorkbook(workbook, false); |
| } |
| } |
| } |
| |
| public EditorStack getWorkbookFromID(String id) { |
| for (int i = 0; i < editorWorkbooks.size(); i++) { |
| EditorStack workbook = (EditorStack) editorWorkbooks.get(i); |
| if (workbook.getID().equals(id)) { |
| return workbook; |
| } |
| } |
| |
| return null; |
| } |
| |
| /** |
| * Updates the editor area's tab list to include the active |
| * editor and its tab. |
| */ |
| public void updateTabList() { |
| Composite parent = getParent(); |
| if (parent != null) { // parent may be null on startup |
| EditorStack wb = getActiveWorkbook(); |
| if (wb == null) { |
| parent.setTabList(new Control[0]); |
| } else { |
| parent.setTabList(wb.getTabList()); |
| } |
| } |
| } |
| |
| /** |
| * @see org.eclipse.ui.internal.LayoutPart#createControl(org.eclipse.swt.widgets.Composite) |
| */ |
| public void createControl(Composite parent) { |
| super.createControl(parent); |
| |
| //let the user drop files/editor input on the editor area |
| addDropSupport(); |
| } |
| |
| private void addDropSupport() { |
| if (dropTarget == null) { |
| WorkbenchWindowConfigurer winConfigurer = ((WorkbenchWindow) page |
| .getWorkbenchWindow()).getWindowConfigurer(); |
| |
| dropTarget = new DropTarget(getControl(), DND.DROP_DEFAULT |
| | DND.DROP_COPY | DND.DROP_LINK); |
| dropTarget.setTransfer(winConfigurer.getTransfers()); |
| if (winConfigurer.getDropTargetListener() != null) { |
| dropTarget.addDropListener(winConfigurer |
| .getDropTargetListener()); |
| } |
| } |
| } |
| |
| /* package */DropTarget getDropTarget() { |
| return dropTarget; |
| } |
| |
| /** |
| * @see org.eclipse.ui.internal.LayoutPart#getImportance() |
| */ |
| public boolean isCompressible() { |
| //Added for bug 19524 |
| return true; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ui.internal.PartSashContainer#isStackType(org.eclipse.ui.internal.LayoutPart) |
| */ |
| public boolean isStackType(LayoutPart toTest) { |
| return (toTest instanceof EditorStack); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ui.internal.PartSashContainer#isPaneType(org.eclipse.ui.internal.LayoutPart) |
| */ |
| public boolean isPaneType(LayoutPart toTest) { |
| return (toTest instanceof EditorPane); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ui.internal.PartSashContainer#createStack(org.eclipse.ui.internal.LayoutPart) |
| */ |
| protected PartStack createStack() { |
| EditorStack newWorkbook = EditorStack.newEditorWorkbook(this, page); |
| |
| return newWorkbook; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ui.internal.PartSashContainer#setVisiblePart(org.eclipse.ui.internal.ILayoutContainer, org.eclipse.ui.internal.LayoutPart) |
| */ |
| protected void setVisiblePart(ILayoutContainer container, |
| LayoutPart visiblePart) { |
| EditorStack refPart = (EditorStack) container; |
| |
| refPart.becomeActiveWorkbook(true); |
| refPart.setSelection(visiblePart); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ui.internal.PartSashContainer#getVisiblePart(org.eclipse.ui.internal.ILayoutContainer) |
| */ |
| protected LayoutPart getVisiblePart(ILayoutContainer container) { |
| EditorStack refPart = (EditorStack) container; |
| |
| return refPart.getSelection(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ui.internal.PartSashContainer#pickPartToZoom() |
| */ |
| public LayoutPart pickPartToZoom() { |
| return getActiveWorkbook(); |
| } |
| |
| /** |
| * Restore the presentation state. Loop over the workbooks, create the appropriate serializer and pass to the presentation. |
| * |
| * @param areaMem the memento containing presentation |
| * @return the restoration status |
| */ |
| public IStatus restorePresentationState(IMemento areaMem) { |
| for (Iterator i = getEditorWorkbooks().iterator(); i.hasNext();) { |
| final EditorStack workbook = (EditorStack) i.next(); |
| final IMemento memento = workbook.getSavedPresentationState(); |
| if (memento == null) { |
| continue; |
| } |
| final PresentationSerializer serializer = new PresentationSerializer( |
| workbook.getPresentableParts()); |
| StartupThreading.runWithoutExceptions(new StartupRunnable(){ |
| |
| public void runWithException() throws Throwable { |
| workbook.getPresentation().restoreState(serializer, memento); |
| }}); |
| |
| } |
| return new Status(IStatus.OK, PlatformUI.PLUGIN_ID, 0, "", null); //$NON-NLS-1$ |
| } |
| } |