0001: /*******************************************************************************
0002: * Copyright (c) 2000, 2007 IBM Corporation and others.
0003: * All rights reserved. This program and the accompanying materials
0004: * are made available under the terms of the Eclipse Public License v1.0
0005: * which accompanies this distribution, and is available at
0006: * http://www.eclipse.org/legal/epl-v10.html
0007: *
0008: * Contributors:
0009: * IBM Corporation - initial API and implementation
0010: *******************************************************************************/package org.eclipse.ui.internal;
0011:
0012: import java.lang.reflect.InvocationTargetException;
0013: import java.util.ArrayList;
0014: import java.util.Arrays;
0015: import java.util.Collection;
0016: import java.util.Collections;
0017: import java.util.Comparator;
0018: import java.util.HashSet;
0019: import java.util.Iterator;
0020: import java.util.List;
0021: import java.util.Set;
0022: import java.util.StringTokenizer;
0023:
0024: import org.eclipse.core.runtime.Assert;
0025: import org.eclipse.core.runtime.IAdaptable;
0026: import org.eclipse.core.runtime.IConfigurationElement;
0027: import org.eclipse.core.runtime.IExtension;
0028: import org.eclipse.core.runtime.IExtensionPoint;
0029: import org.eclipse.core.runtime.IProgressMonitor;
0030: import org.eclipse.core.runtime.IStatus;
0031: import org.eclipse.core.runtime.ListenerList;
0032: import org.eclipse.core.runtime.MultiStatus;
0033: import org.eclipse.core.runtime.Platform;
0034: import org.eclipse.core.runtime.Status;
0035: import org.eclipse.core.runtime.dynamichelpers.ExtensionTracker;
0036: import org.eclipse.core.runtime.dynamichelpers.IExtensionChangeHandler;
0037: import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker;
0038: import org.eclipse.jface.dialogs.ErrorDialog;
0039: import org.eclipse.jface.dialogs.IDialogConstants;
0040: import org.eclipse.jface.dialogs.MessageDialog;
0041: import org.eclipse.jface.internal.provisional.action.ICoolBarManager2;
0042: import org.eclipse.jface.operation.IRunnableWithProgress;
0043: import org.eclipse.jface.util.IPropertyChangeListener;
0044: import org.eclipse.jface.util.PropertyChangeEvent;
0045: import org.eclipse.jface.util.SafeRunnable;
0046: import org.eclipse.jface.viewers.ISelection;
0047: import org.eclipse.jface.window.Window;
0048: import org.eclipse.osgi.util.NLS;
0049: import org.eclipse.swt.SWT;
0050: import org.eclipse.swt.custom.BusyIndicator;
0051: import org.eclipse.swt.graphics.Rectangle;
0052: import org.eclipse.swt.widgets.Composite;
0053: import org.eclipse.swt.widgets.Control;
0054: import org.eclipse.swt.widgets.Display;
0055: import org.eclipse.swt.widgets.Shell;
0056: import org.eclipse.ui.IActionBars;
0057: import org.eclipse.ui.IEditorDescriptor;
0058: import org.eclipse.ui.IEditorInput;
0059: import org.eclipse.ui.IEditorPart;
0060: import org.eclipse.ui.IEditorReference;
0061: import org.eclipse.ui.IEditorRegistry;
0062: import org.eclipse.ui.IMemento;
0063: import org.eclipse.ui.INavigationHistory;
0064: import org.eclipse.ui.IPartListener;
0065: import org.eclipse.ui.IPartListener2;
0066: import org.eclipse.ui.IPerspectiveDescriptor;
0067: import org.eclipse.ui.IPerspectiveRegistry;
0068: import org.eclipse.ui.IReusableEditor;
0069: import org.eclipse.ui.ISaveablePart;
0070: import org.eclipse.ui.ISaveablesLifecycleListener;
0071: import org.eclipse.ui.ISelectionListener;
0072: import org.eclipse.ui.IShowEditorInput;
0073: import org.eclipse.ui.IViewPart;
0074: import org.eclipse.ui.IViewReference;
0075: import org.eclipse.ui.IWorkbench;
0076: import org.eclipse.ui.IWorkbenchPage;
0077: import org.eclipse.ui.IWorkbenchPart;
0078: import org.eclipse.ui.IWorkbenchPartReference;
0079: import org.eclipse.ui.IWorkbenchPartSite;
0080: import org.eclipse.ui.IWorkbenchPreferenceConstants;
0081: import org.eclipse.ui.IWorkbenchWindow;
0082: import org.eclipse.ui.IWorkingSet;
0083: import org.eclipse.ui.IWorkingSetManager;
0084: import org.eclipse.ui.PartInitException;
0085: import org.eclipse.ui.PlatformUI;
0086: import org.eclipse.ui.SubActionBars;
0087: import org.eclipse.ui.WorkbenchException;
0088: import org.eclipse.ui.contexts.IContextService;
0089: import org.eclipse.ui.internal.StartupThreading.StartupRunnable;
0090: import org.eclipse.ui.internal.contexts.ContextAuthority;
0091: import org.eclipse.ui.internal.dialogs.CustomizePerspectiveDialog;
0092: import org.eclipse.ui.internal.dnd.SwtUtil;
0093: import org.eclipse.ui.internal.intro.IIntroConstants;
0094: import org.eclipse.ui.internal.misc.UIListenerLogging;
0095: import org.eclipse.ui.internal.misc.UIStats;
0096: import org.eclipse.ui.internal.registry.ActionSetRegistry;
0097: import org.eclipse.ui.internal.registry.EditorDescriptor;
0098: import org.eclipse.ui.internal.registry.EditorRegistry;
0099: import org.eclipse.ui.internal.registry.IActionSetDescriptor;
0100: import org.eclipse.ui.internal.registry.IWorkbenchRegistryConstants;
0101: import org.eclipse.ui.internal.registry.PerspectiveDescriptor;
0102: import org.eclipse.ui.internal.registry.UIExtensionTracker;
0103: import org.eclipse.ui.internal.tweaklets.GrabFocus;
0104: import org.eclipse.ui.internal.tweaklets.TabBehaviour;
0105: import org.eclipse.ui.internal.tweaklets.Tweaklets;
0106: import org.eclipse.ui.internal.util.PrefUtil;
0107: import org.eclipse.ui.internal.util.Util;
0108: import org.eclipse.ui.model.IWorkbenchAdapter;
0109: import org.eclipse.ui.part.MultiEditor;
0110: import org.eclipse.ui.presentations.IStackPresentationSite;
0111:
0112: /**
0113: * A collection of views and editors in a workbench.
0114: */
0115: public class WorkbenchPage extends CompatibleWorkbenchPage implements
0116: IWorkbenchPage {
0117:
0118: private static final String ATT_AGGREGATE_WORKING_SET_ID = "aggregateWorkingSetId"; //$NON-NLS-1$
0119:
0120: private WorkbenchWindow window;
0121:
0122: private IAdaptable input;
0123:
0124: private IWorkingSet workingSet;
0125:
0126: private AggregateWorkingSet aggregateWorkingSet;
0127:
0128: private Composite composite;
0129:
0130: //Could be delete. This information is in the active part list;
0131: private ActivationList activationList = new ActivationList();
0132:
0133: /**
0134: * This field controls whether or not the ActivationList will
0135: * remove Fast Views from its list of active views. It's currently
0136: * only <core>true</code> when new editors are added, allowing
0137: * a minimized View that opens (but doesn't activate) a new editor
0138: * to remain active.
0139: */
0140: private boolean includeActiveFastViews = false;
0141:
0142: private EditorManager editorMgr;
0143:
0144: private EditorAreaHelper editorPresentation;
0145:
0146: private ListenerList propertyChangeListeners = new ListenerList();
0147:
0148: private PageSelectionService selectionService = new PageSelectionService(
0149: this );
0150:
0151: private WorkbenchPagePartList partList = new WorkbenchPagePartList(
0152: selectionService);
0153:
0154: private IActionBars actionBars;
0155:
0156: private ActionSetManager actionSets;
0157:
0158: private ViewFactory viewFactory;
0159:
0160: private PerspectiveList perspList = new PerspectiveList();
0161:
0162: private PerspectiveDescriptor deferredActivePersp;
0163:
0164: private NavigationHistory navigationHistory = new NavigationHistory(
0165: this );
0166:
0167: private IStickyViewManager stickyViewMan = StickyViewManager
0168: .getInstance(this );
0169:
0170: /**
0171: * If we're in the process of activating a part, this points to the new part.
0172: * Otherwise, this is null.
0173: */
0174: private IWorkbenchPartReference partBeingActivated = null;
0175:
0176: /**
0177: * Contains a list of perspectives that may be dirty due to plugin
0178: * installation and removal.
0179: */
0180: private Set dirtyPerspectives = new HashSet();
0181:
0182: private IPropertyChangeListener workingSetPropertyChangeListener = new IPropertyChangeListener() {
0183: /*
0184: * Remove the working set from the page if the working set is deleted.
0185: */
0186: public void propertyChange(PropertyChangeEvent event) {
0187: String property = event.getProperty();
0188: if (IWorkingSetManager.CHANGE_WORKING_SET_REMOVE
0189: .equals(property)) {
0190: if (event.getOldValue().equals(workingSet)) {
0191: setWorkingSet(null);
0192: }
0193:
0194: // room for optimization here
0195: List newList = new ArrayList(Arrays.asList(workingSets));
0196: if (newList.remove(event.getOldValue())) {
0197: setWorkingSets((IWorkingSet[]) newList
0198: .toArray(new IWorkingSet[newList.size()]));
0199: }
0200: }
0201: }
0202: };
0203:
0204: private ActionSwitcher actionSwitcher = new ActionSwitcher();
0205:
0206: private IExtensionTracker tracker;
0207:
0208: // Deferral count... delays disposing parts and sending certain events if nonzero
0209: private int deferCount = 0;
0210: // Parts waiting to be disposed
0211: private List pendingDisposals = new ArrayList();
0212:
0213: private IExtensionChangeHandler perspectiveChangeHandler = new IExtensionChangeHandler() {
0214:
0215: /* (non-Javadoc)
0216: * @see org.eclipse.core.runtime.dynamicHelpers.IExtensionChangeHandler#removeExtension(org.eclipse.core.runtime.IExtension, java.lang.Object[])
0217: */
0218: public void removeExtension(IExtension extension,
0219: Object[] objects) {
0220: boolean suggestReset = false;
0221: for (int i = 0; i < objects.length; i++) {
0222: if (objects[i] instanceof DirtyPerspectiveMarker) {
0223: String id = ((DirtyPerspectiveMarker) objects[i]).perspectiveId;
0224: if (!dirtyPerspectives.remove(id)) {
0225: dirtyPerspectives.add(id); // otherwise we will be dirty
0226: }
0227: PerspectiveDescriptor persp = (PerspectiveDescriptor) getPerspective();
0228: if (persp == null || persp.hasCustomDefinition()) {
0229: continue;
0230: }
0231: if (persp.getId().equals(id)) {
0232: suggestReset = true;
0233: }
0234: }
0235: }
0236: if (suggestReset) {
0237: suggestReset();
0238: }
0239: }
0240:
0241: /* (non-Javadoc)
0242: * @see org.eclipse.core.runtime.dynamicHelpers.IExtensionChangeHandler#addExtension(org.eclipse.core.runtime.dynamicHelpers.IExtensionTracker, org.eclipse.core.runtime.IExtension)
0243: */
0244: public void addExtension(IExtensionTracker tracker,
0245: IExtension extension) {
0246: if (WorkbenchPage.this != getWorkbenchWindow()
0247: .getActivePage()) {
0248: return;
0249: }
0250:
0251: // Get the current perspective.
0252: PerspectiveDescriptor persp = (PerspectiveDescriptor) getPerspective();
0253: if (persp == null) {
0254: return;
0255: }
0256: String currentId = persp.getId();
0257: IConfigurationElement[] elements = extension
0258: .getConfigurationElements();
0259: boolean suggestReset = false;
0260: for (int i = 0; i < elements.length; i++) {
0261: // If any of these refer to the current perspective, output
0262: // a message saying this perspective will need to be reset
0263: // in order to see the changes. For any other case, the
0264: // perspective extension registry will be rebuilt anyway so
0265: // just ignore it.
0266: String id = elements[i]
0267: .getAttribute(IWorkbenchRegistryConstants.ATT_TARGET_ID);
0268: if (id == null) {
0269: continue;
0270: }
0271: if (id.equals(currentId)
0272: && !persp.hasCustomDefinition()) {
0273: suggestReset = true;
0274: } else {
0275: dirtyPerspectives.add(id);
0276: }
0277: DirtyPerspectiveMarker marker = new DirtyPerspectiveMarker(
0278: id);
0279: tracker.registerObject(extension, marker,
0280: IExtensionTracker.REF_STRONG);
0281: }
0282: if (suggestReset) {
0283: suggestReset();
0284: }
0285:
0286: }
0287: };
0288: private IWorkingSet[] workingSets = new IWorkingSet[0];
0289: private String aggregateWorkingSetId;
0290:
0291: private IExtensionPoint getPerspectiveExtensionPoint() {
0292: return Platform.getExtensionRegistry().getExtensionPoint(
0293: PlatformUI.PLUGIN_ID,
0294: IWorkbenchRegistryConstants.PL_PERSPECTIVE_EXTENSIONS);
0295: }
0296:
0297: /**
0298: * Manages editor contributions and action set part associations.
0299: */
0300: private class ActionSwitcher {
0301: private IWorkbenchPart activePart;
0302:
0303: private IEditorPart topEditor;
0304:
0305: private ArrayList oldActionSets = new ArrayList();
0306:
0307: /**
0308: * Updates the contributions given the new part as the active part.
0309: *
0310: * @param newPart
0311: * the new active part, may be <code>null</code>
0312: */
0313: public void updateActivePart(IWorkbenchPart newPart) {
0314: if (activePart == newPart) {
0315: return;
0316: }
0317:
0318: boolean isNewPartAnEditor = newPart instanceof IEditorPart;
0319: if (isNewPartAnEditor) {
0320: String oldId = null;
0321: if (topEditor != null) {
0322: oldId = topEditor.getSite().getId();
0323: }
0324: String newId = newPart.getSite().getId();
0325:
0326: // if the active part is an editor and the new editor
0327: // is the same kind of editor, then we don't have to do
0328: // anything
0329: if (activePart == topEditor && newId.equals(oldId)) {
0330: activePart = newPart;
0331: topEditor = (IEditorPart) newPart;
0332: return;
0333: }
0334:
0335: // remove the contributions of the old editor
0336: // if it is a different kind of editor
0337: if (oldId != null && !oldId.equals(newId)) {
0338: deactivateContributions(topEditor, true);
0339: }
0340:
0341: // if a view was the active part, disable its contributions
0342: if (activePart != null && activePart != topEditor) {
0343: deactivateContributions(activePart, true);
0344: }
0345:
0346: // show (and enable) the contributions of the new editor
0347: // if it is a different kind of editor or if the
0348: // old active part was a view
0349: if (!newId.equals(oldId) || activePart != topEditor) {
0350: activateContributions(newPart, true);
0351: }
0352:
0353: } else if (newPart == null) {
0354: if (activePart != null) {
0355: // remove all contributions
0356: deactivateContributions(activePart, true);
0357: }
0358: } else {
0359: // new part is a view
0360:
0361: // if old active part is a view, remove all contributions,
0362: // but if old part is an editor only disable
0363: if (activePart != null) {
0364: deactivateContributions(activePart,
0365: activePart instanceof IViewPart);
0366: }
0367:
0368: activateContributions(newPart, true);
0369: }
0370:
0371: ArrayList newActionSets = null;
0372: if (isNewPartAnEditor
0373: || (activePart == topEditor && newPart == null)) {
0374: newActionSets = calculateActionSets(newPart, null);
0375: } else {
0376: newActionSets = calculateActionSets(newPart, topEditor);
0377: }
0378:
0379: if (!updateActionSets(newActionSets)) {
0380: updateActionBars();
0381: }
0382:
0383: if (isNewPartAnEditor) {
0384: topEditor = (IEditorPart) newPart;
0385: } else if (activePart == topEditor && newPart == null) {
0386: // since we removed all the contributions, we clear the top
0387: // editor
0388: topEditor = null;
0389: }
0390:
0391: activePart = newPart;
0392: }
0393:
0394: /**
0395: * Updates the contributions given the new part as the topEditor.
0396: *
0397: * @param newEditor
0398: * the new top editor, may be <code>null</code>
0399: */
0400: public void updateTopEditor(IEditorPart newEditor) {
0401: if (topEditor == newEditor) {
0402: return;
0403: }
0404:
0405: if (activePart == topEditor) {
0406: updateActivePart(newEditor);
0407: return;
0408: }
0409:
0410: String oldId = null;
0411: if (topEditor != null) {
0412: oldId = topEditor.getSite().getId();
0413: }
0414: String newId = null;
0415: if (newEditor != null) {
0416: newId = newEditor.getSite().getId();
0417: }
0418: if (oldId == null ? newId == null : oldId.equals(newId)) {
0419: // we don't have to change anything
0420: topEditor = newEditor;
0421: return;
0422: }
0423:
0424: // Remove the contributions of the old editor
0425: if (topEditor != null) {
0426: deactivateContributions(topEditor, true);
0427: }
0428:
0429: // Show (disabled) the contributions of the new editor
0430: if (newEditor != null) {
0431: activateContributions(newEditor, false);
0432: }
0433:
0434: ArrayList newActionSets = calculateActionSets(activePart,
0435: newEditor);
0436: if (!updateActionSets(newActionSets)) {
0437: updateActionBars();
0438: }
0439:
0440: topEditor = newEditor;
0441: }
0442:
0443: /**
0444: * Activates the contributions of the given part. If <code>enable</code>
0445: * is <code>true</code> the contributions are visible and enabled,
0446: * otherwise they are disabled.
0447: *
0448: * @param part
0449: * the part whose contributions are to be activated
0450: * @param enable
0451: * <code>true</code> the contributions are to be enabled,
0452: * not just visible.
0453: */
0454: private void activateContributions(IWorkbenchPart part,
0455: boolean enable) {
0456: PartSite site = (PartSite) part.getSite();
0457: site.activateActionBars(enable);
0458: }
0459:
0460: /**
0461: * Deactivates the contributions of the given part. If <code>remove</code>
0462: * is <code>true</code> the contributions are removed, otherwise they
0463: * are disabled.
0464: *
0465: * @param part
0466: * the part whose contributions are to be deactivated
0467: * @param remove
0468: * <code>true</code> the contributions are to be removed,
0469: * not just disabled.
0470: */
0471: private void deactivateContributions(IWorkbenchPart part,
0472: boolean remove) {
0473: PartSite site = (PartSite) part.getSite();
0474: site.deactivateActionBars(remove);
0475: }
0476:
0477: /**
0478: * Calculates the action sets to show for the given part and editor
0479: *
0480: * @param part
0481: * the active part, may be <code>null</code>
0482: * @param editor
0483: * the current editor, may be <code>null</code>, may be
0484: * the active part
0485: * @return the new action sets
0486: */
0487: private ArrayList calculateActionSets(IWorkbenchPart part,
0488: IEditorPart editor) {
0489: ArrayList newActionSets = new ArrayList();
0490: if (part != null) {
0491: IActionSetDescriptor[] partActionSets = WorkbenchPlugin
0492: .getDefault().getActionSetRegistry()
0493: .getActionSetsFor(part.getSite().getId());
0494: for (int i = 0; i < partActionSets.length; i++) {
0495: newActionSets.add(partActionSets[i]);
0496: }
0497: }
0498: if (editor != null && editor != part) {
0499: IActionSetDescriptor[] editorActionSets = WorkbenchPlugin
0500: .getDefault().getActionSetRegistry()
0501: .getActionSetsFor(editor.getSite().getId());
0502: for (int i = 0; i < editorActionSets.length; i++) {
0503: newActionSets.add(editorActionSets[i]);
0504: }
0505: }
0506: return newActionSets;
0507: }
0508:
0509: /**
0510: * Updates the actions we are showing for the active part and current
0511: * editor.
0512: *
0513: * @param newActionSets
0514: * the action sets to show
0515: * @return <code>true</code> if the action sets changed
0516: */
0517: private boolean updateActionSets(ArrayList newActionSets) {
0518: if (oldActionSets.equals(newActionSets)) {
0519: return false;
0520: }
0521:
0522: IContextService service = (IContextService) window
0523: .getService(IContextService.class);
0524: try {
0525: service.activateContext(ContextAuthority.DEFER_EVENTS);
0526:
0527: // show the new
0528: for (int i = 0; i < newActionSets.size(); i++) {
0529: actionSets
0530: .showAction((IActionSetDescriptor) newActionSets
0531: .get(i));
0532: }
0533:
0534: // hide the old
0535: for (int i = 0; i < oldActionSets.size(); i++) {
0536: actionSets
0537: .hideAction((IActionSetDescriptor) oldActionSets
0538: .get(i));
0539: }
0540:
0541: oldActionSets = newActionSets;
0542:
0543: } finally {
0544: service.activateContext(ContextAuthority.SEND_EVENTS);
0545: }
0546: Perspective persp = getActivePerspective();
0547: if (persp == null) {
0548: return false;
0549: }
0550:
0551: window.updateActionSets(); // this calls updateActionBars
0552: window.firePerspectiveChanged(WorkbenchPage.this ,
0553: getPerspective(), CHANGE_ACTION_SET_SHOW);
0554: return true;
0555: }
0556:
0557: }
0558:
0559: /**
0560: * Constructs a new page with a given perspective and input.
0561: *
0562: * @param w
0563: * the parent window
0564: * @param layoutID
0565: * must not be <code>null</code>
0566: * @param input
0567: * the page input
0568: * @throws WorkbenchException
0569: * on null layout id
0570: */
0571: public WorkbenchPage(WorkbenchWindow w, String layoutID,
0572: IAdaptable input) throws WorkbenchException {
0573: super ();
0574: if (layoutID == null) {
0575: throw new WorkbenchException(
0576: WorkbenchMessages.WorkbenchPage_UndefinedPerspective);
0577: }
0578: init(w, layoutID, input, true);
0579: }
0580:
0581: /**
0582: * Constructs a page. <code>restoreState(IMemento)</code> should be
0583: * called to restore this page from data stored in a persistance file.
0584: *
0585: * @param w
0586: * the parent window
0587: * @param input
0588: * the page input
0589: * @throws WorkbenchException
0590: */
0591: public WorkbenchPage(WorkbenchWindow w, IAdaptable input)
0592: throws WorkbenchException {
0593: super ();
0594: init(w, null, input, false);
0595: }
0596:
0597: /**
0598: * Activates a part. The part will be brought to the front and given focus.
0599: *
0600: * @param part
0601: * the part to activate
0602: */
0603: public void activate(IWorkbenchPart part) {
0604: // Sanity check.
0605: if (!certifyPart(part)) {
0606: return;
0607: }
0608:
0609: if (window.isClosing()) {
0610: return;
0611: }
0612:
0613: if (composite != null
0614: && composite.isVisible()
0615: && !((GrabFocus) Tweaklets.get(GrabFocus.KEY))
0616: .grabFocusAllowed(part)) {
0617: return;
0618: }
0619:
0620: // If zoomed, unzoom.
0621: zoomOutIfNecessary(part);
0622:
0623: if (part instanceof MultiEditor) {
0624: part = ((MultiEditor) part).getActiveEditor();
0625: }
0626: // Activate part.
0627: //if (window.getActivePage() == this) {
0628: IWorkbenchPartReference ref = getReference(part);
0629: internalBringToTop(ref);
0630: setActivePart(part);
0631: }
0632:
0633: /**
0634: * Activates a part. The part is given focus, the pane is hilighted.
0635: */
0636: private void activatePart(final IWorkbenchPart part) {
0637: Platform.run(new SafeRunnable(
0638: WorkbenchMessages.WorkbenchPage_ErrorActivatingView) {
0639: public void run() {
0640: if (part != null) {
0641: //part.setFocus();
0642: PartPane pane = getPane(part);
0643: pane.setFocus();
0644: PartSite site = (PartSite) part.getSite();
0645: pane.showFocus(true);
0646: updateTabList(part);
0647: SubActionBars bars = (SubActionBars) site
0648: .getActionBars();
0649: bars.partChanged(part);
0650: }
0651: }
0652: });
0653: }
0654:
0655: /**
0656: * Add a fast view.
0657: */
0658: public void addFastView(IViewReference ref) {
0659: Perspective persp = getActivePerspective();
0660: if (persp == null) {
0661: return;
0662: }
0663:
0664: persp.getFastViewManager().addViewReference(
0665: FastViewBar.FASTVIEWBAR_ID, -1, ref, true);
0666: }
0667:
0668: /**
0669: * Add a fast view.
0670: */
0671: public void makeFastView(IViewReference ref) {
0672: Perspective persp = getActivePerspective();
0673: if (persp == null) {
0674: return;
0675: }
0676:
0677: FastViewManager fvm = persp.getFastViewManager();
0678: if (fvm.isFastView(ref)) {
0679: return;
0680: }
0681:
0682: // Do real work.
0683: persp.makeFastView(ref);
0684:
0685: updateActivePart();
0686:
0687: // The view is now invisible.
0688: // If it is active then deactivate it.
0689:
0690: // Notify listeners.
0691: window.firePerspectiveChanged(this , getPerspective(), ref,
0692: CHANGE_FAST_VIEW_ADD);
0693: window.firePerspectiveChanged(this , getPerspective(),
0694: CHANGE_FAST_VIEW_ADD);
0695: }
0696:
0697: /**
0698: * Adds an IPartListener to the part service.
0699: */
0700: public void addPartListener(IPartListener l) {
0701: partList.getPartService().addPartListener(l);
0702: }
0703:
0704: /**
0705: * Adds an IPartListener to the part service.
0706: */
0707: public void addPartListener(IPartListener2 l) {
0708: partList.getPartService().addPartListener(l);
0709: }
0710:
0711: /**
0712: * Implements IWorkbenchPage
0713: *
0714: * @see org.eclipse.ui.IWorkbenchPage#addPropertyChangeListener(IPropertyChangeListener)
0715: * @since 2.0
0716: * @deprecated individual views should store a working set if needed and
0717: * register a property change listener directly with the
0718: * working set manager to receive notification when the view
0719: * working set is removed.
0720: */
0721: public void addPropertyChangeListener(
0722: IPropertyChangeListener listener) {
0723: propertyChangeListeners.add(listener);
0724: }
0725:
0726: /*
0727: * (non-Javadoc) Method declared on ISelectionListener.
0728: */
0729: public void addSelectionListener(ISelectionListener listener) {
0730: selectionService.addSelectionListener(listener);
0731: }
0732:
0733: /*
0734: * (non-Javadoc) Method declared on ISelectionListener.
0735: */
0736: public void addSelectionListener(String partId,
0737: ISelectionListener listener) {
0738: selectionService.addSelectionListener(partId, listener);
0739: }
0740:
0741: /*
0742: * (non-Javadoc) Method declared on ISelectionListener.
0743: */
0744: public void addPostSelectionListener(ISelectionListener listener) {
0745: selectionService.addPostSelectionListener(listener);
0746: }
0747:
0748: /*
0749: * (non-Javadoc) Method declared on ISelectionListener.
0750: */
0751: public void addPostSelectionListener(String partId,
0752: ISelectionListener listener) {
0753: selectionService.addPostSelectionListener(partId, listener);
0754: }
0755:
0756: private ILayoutContainer getContainer(IWorkbenchPart part) {
0757: PartPane pane = getPane(part);
0758: if (pane == null) {
0759: return null;
0760: }
0761:
0762: return pane.getContainer();
0763: }
0764:
0765: private ILayoutContainer getContainer(IWorkbenchPartReference part) {
0766: PartPane pane = getPane(part);
0767: if (pane == null) {
0768: return null;
0769: }
0770:
0771: return pane.getContainer();
0772: }
0773:
0774: private PartPane getPane(IWorkbenchPart part) {
0775: if (part == null) {
0776: return null;
0777: }
0778: return getPane(getReference(part));
0779: }
0780:
0781: private PartPane getPane(IWorkbenchPartReference part) {
0782: if (part == null) {
0783: return null;
0784: }
0785:
0786: return ((WorkbenchPartReference) part).getPane();
0787: }
0788:
0789: /**
0790: * Brings a part to the front of its stack. Does not update the active part or
0791: * active editor. This should only be called if the caller knows that the part
0792: * is not in the same stack as the active part or active editor, or if the caller
0793: * is prepared to update activation after the call.
0794: *
0795: * @param part
0796: */
0797: private boolean internalBringToTop(IWorkbenchPartReference part) {
0798:
0799: boolean broughtToTop = false;
0800:
0801: // Move part.
0802: if (part instanceof IEditorReference) {
0803: ILayoutContainer container = getContainer(part);
0804: if (container instanceof PartStack) {
0805: PartStack stack = (PartStack) container;
0806: PartPane newPart = getPane(part);
0807: if (stack.getSelection() != newPart) {
0808: stack.setSelection(newPart);
0809: }
0810: broughtToTop = true;
0811: }
0812: } else if (part instanceof IViewReference) {
0813: Perspective persp = getActivePerspective();
0814: if (persp != null) {
0815: broughtToTop = persp.bringToTop((IViewReference) part);
0816: }
0817: }
0818:
0819: // Ensure that this part is considered the most recently activated part
0820: // in this stack
0821: activationList.bringToTop(part);
0822:
0823: return broughtToTop;
0824: }
0825:
0826: /**
0827: * Moves a part forward in the Z order of a perspective so it is visible.
0828: * If the part is in the same stack as the active part, the new part is
0829: * activated.
0830: *
0831: * @param part
0832: * the part to bring to move forward
0833: */
0834: public void bringToTop(IWorkbenchPart part) {
0835: // Sanity check.
0836: Perspective persp = getActivePerspective();
0837: if (persp == null || !certifyPart(part)) {
0838: return;
0839: }
0840:
0841: if (!((GrabFocus) Tweaklets.get(GrabFocus.KEY))
0842: .grabFocusAllowed(part)) {
0843: return;
0844: }
0845:
0846: String label = null; // debugging only
0847: if (UIStats.isDebugging(UIStats.BRING_PART_TO_TOP)) {
0848: label = part != null ? part.getTitle() : "none"; //$NON-NLS-1$
0849: }
0850:
0851: try {
0852: UIStats.start(UIStats.BRING_PART_TO_TOP, label);
0853:
0854: IWorkbenchPartReference ref = getReference(part);
0855: ILayoutContainer activeEditorContainer = getContainer(getActiveEditor());
0856: ILayoutContainer activePartContainer = getContainer(getActivePart());
0857: ILayoutContainer newPartContainer = getContainer(part);
0858:
0859: if (newPartContainer == activePartContainer) {
0860: makeActive(ref);
0861: } else if (newPartContainer == activeEditorContainer) {
0862: if (ref instanceof IEditorReference) {
0863: if (part != null) {
0864: IWorkbenchPartSite site = part.getSite();
0865: if (site instanceof PartSite) {
0866: ref = ((PartSite) site).getPane()
0867: .getPartReference();
0868: }
0869: }
0870: makeActiveEditor((IEditorReference) ref);
0871: } else {
0872: makeActiveEditor(null);
0873: }
0874: } else {
0875: internalBringToTop(ref);
0876: if (ref != null) {
0877: partList.firePartBroughtToTop(ref);
0878: }
0879: }
0880: } finally {
0881: UIStats.end(UIStats.BRING_PART_TO_TOP, part, label);
0882: }
0883: }
0884:
0885: /**
0886: * Resets the layout for the perspective. The active part in the old layout
0887: * is activated in the new layout for consistent user context.
0888: *
0889: * Assumes the busy cursor is active.
0890: */
0891: private void busyResetPerspective() {
0892:
0893: ViewIntroAdapterPart introViewAdapter = ((WorkbenchIntroManager) getWorkbenchWindow()
0894: .getWorkbench().getIntroManager())
0895: .getViewIntroAdapterPart();
0896: PartPane introPane = null;
0897: boolean introFullScreen = false;
0898: if (introViewAdapter != null) {
0899: introPane = ((PartSite) introViewAdapter.getSite())
0900: .getPane();
0901: introViewAdapter.setHandleZoomEvents(false);
0902: introFullScreen = introPane.isZoomed();
0903: }
0904:
0905: //try to prevent intro flicker.
0906: if (introFullScreen) {
0907: window.getShell().setRedraw(false);
0908: }
0909:
0910: try {
0911:
0912: // Always unzoom
0913: if (isZoomed()) {
0914: zoomOut();
0915: }
0916:
0917: // Get the current perspective.
0918: // This describes the working layout of the page and differs from
0919: // the original template.
0920: Perspective oldPersp = getActivePerspective();
0921:
0922: // Map the current perspective to the original template.
0923: // If the original template cannot be found then it has been deleted.
0924: // In that case just return. (PR#1GDSABU).
0925: IPerspectiveRegistry reg = WorkbenchPlugin.getDefault()
0926: .getPerspectiveRegistry();
0927: PerspectiveDescriptor desc = (PerspectiveDescriptor) reg
0928: .findPerspectiveWithId(oldPersp.getDesc().getId());
0929: if (desc == null) {
0930: desc = (PerspectiveDescriptor) reg
0931: .findPerspectiveWithId(((PerspectiveDescriptor) oldPersp
0932: .getDesc()).getOriginalId());
0933: }
0934: if (desc == null) {
0935: return;
0936: }
0937:
0938: // Notify listeners that we are doing a reset.
0939: window.firePerspectiveChanged(this , desc, CHANGE_RESET);
0940:
0941: // Create new persp from original template.
0942: // Suppress the perspectiveOpened and perspectiveClosed events otherwise it looks like two
0943: // instances of the same perspective are open temporarily (see bug 127470).
0944: Perspective newPersp = createPerspective(desc, false);
0945: if (newPersp == null) {
0946: // We're not going through with the reset, so it is complete.
0947: window.firePerspectiveChanged(this , desc,
0948: CHANGE_RESET_COMPLETE);
0949: return;
0950: }
0951:
0952: // Update the perspective list and shortcut
0953: perspList.swap(oldPersp, newPersp);
0954:
0955: // Install new persp.
0956: setPerspective(newPersp);
0957:
0958: // Destroy old persp.
0959: disposePerspective(oldPersp, false);
0960:
0961: // Update the Coolbar layout.
0962: resetToolBarLayout();
0963:
0964: // restore the maximized intro
0965: if (introViewAdapter != null) {
0966: try {
0967: // ensure that the intro is visible in the new perspective
0968: showView(IIntroConstants.INTRO_VIEW_ID);
0969: if (introFullScreen) {
0970: toggleZoom(introPane.getPartReference());
0971: }
0972: } catch (PartInitException e) {
0973: WorkbenchPlugin.log("Could not restore intro", //$NON-NLS-1$
0974: WorkbenchPlugin.getStatus(e));
0975: } finally {
0976: // we want the intro back to a normal state before we fire the event
0977: introViewAdapter.setHandleZoomEvents(true);
0978: }
0979: }
0980: // Notify listeners that we have completed our reset.
0981: window.firePerspectiveChanged(this , desc,
0982: CHANGE_RESET_COMPLETE);
0983: } finally {
0984: // reset the handling of zoom events (possibly for the second time) in case there was
0985: // an exception thrown
0986: if (introViewAdapter != null) {
0987: introViewAdapter.setHandleZoomEvents(true);
0988: }
0989:
0990: if (introFullScreen) {
0991: window.getShell().setRedraw(true);
0992: }
0993: }
0994:
0995: }
0996:
0997: /**
0998: * Implements <code>setPerspective</code>.
0999: *
1000: * Assumes that busy cursor is active.
1001: *
1002: * @param desc
1003: * identifies the new perspective.
1004: */
1005: private void busySetPerspective(IPerspectiveDescriptor desc) {
1006: // Create new layout.
1007: String label = desc.getId(); // debugging only
1008: Perspective newPersp = null;
1009: try {
1010: UIStats.start(UIStats.SWITCH_PERSPECTIVE, label);
1011: PerspectiveDescriptor realDesc = (PerspectiveDescriptor) desc;
1012: newPersp = findPerspective(realDesc);
1013: if (newPersp == null) {
1014: newPersp = createPerspective(realDesc, true);
1015: if (newPersp == null) {
1016: return;
1017: }
1018: }
1019:
1020: // Change layout.
1021: setPerspective(newPersp);
1022: } finally {
1023: UIStats
1024: .end(UIStats.SWITCH_PERSPECTIVE, desc.getId(),
1025: label);
1026: }
1027: }
1028:
1029: /**
1030: * Shows a view.
1031: *
1032: * Assumes that a busy cursor is active.
1033: */
1034: private IViewPart busyShowView(String viewID, String secondaryID,
1035: int mode) throws PartInitException {
1036: Perspective persp = getActivePerspective();
1037: if (persp == null) {
1038: return null;
1039: }
1040:
1041: // If this view is already visible just return.
1042: IViewReference ref = persp.findView(viewID, secondaryID);
1043: IViewPart view = null;
1044: if (ref != null) {
1045: view = ref.getView(true);
1046: }
1047: if (view != null) {
1048: busyShowView(view, mode);
1049: return view;
1050: }
1051:
1052: // Show the view.
1053: view = persp.showView(viewID, secondaryID);
1054: if (view != null) {
1055: busyShowView(view, mode);
1056:
1057: IWorkbenchPartReference partReference = getReference(view);
1058: PartPane partPane = getPane(partReference);
1059: partPane.setInLayout(true);
1060:
1061: window.firePerspectiveChanged(this , getPerspective(),
1062: partReference, CHANGE_VIEW_SHOW);
1063: window.firePerspectiveChanged(this , getPerspective(),
1064: CHANGE_VIEW_SHOW);
1065: }
1066: return view;
1067: }
1068:
1069: /*
1070: * Performs showing of the view in the given mode.
1071: */
1072: private void busyShowView(IViewPart part, int mode) {
1073: if (!((GrabFocus) Tweaklets.get(GrabFocus.KEY))
1074: .grabFocusAllowed(part)) {
1075: return;
1076: }
1077: if (mode == VIEW_ACTIVATE) {
1078: activate(part);
1079: } else if (mode == VIEW_VISIBLE) {
1080: IWorkbenchPartReference ref = getActivePartReference();
1081: // if there is no active part or it's not a view, bring to top
1082: if (ref == null || !(ref instanceof IViewReference)) {
1083: bringToTop(part);
1084: } else {
1085: // otherwise check to see if the we're in the same stack as the active view
1086: IViewReference activeView = (IViewReference) ref;
1087: IViewReference[] viewStack = getViewReferenceStack(part);
1088: for (int i = 0; i < viewStack.length; i++) {
1089: if (viewStack[i].equals(activeView)) {
1090: return;
1091: }
1092: }
1093: bringToTop(part);
1094: }
1095: }
1096: }
1097:
1098: /**
1099: * Returns whether a part exists in the current page.
1100: */
1101: private boolean certifyPart(IWorkbenchPart part) {
1102: //Workaround for bug 22325
1103: if (part != null && !(part.getSite() instanceof PartSite)) {
1104: return false;
1105: }
1106:
1107: if (part instanceof IEditorPart) {
1108: IEditorReference ref = (IEditorReference) getReference(part);
1109: return ref != null
1110: && getEditorManager().containsEditor(ref);
1111: }
1112: if (part instanceof IViewPart) {
1113: Perspective persp = getActivePerspective();
1114: return persp != null
1115: && persp.containsView((IViewPart) part);
1116: }
1117: return false;
1118: }
1119:
1120: /**
1121: * Closes the perspective.
1122: */
1123: public boolean close() {
1124: final boolean[] ret = new boolean[1];
1125: BusyIndicator.showWhile(null, new Runnable() {
1126: public void run() {
1127: ret[0] = window.closePage(WorkbenchPage.this , true);
1128: }
1129: });
1130: return ret[0];
1131: }
1132:
1133: /**
1134: * See IWorkbenchPage
1135: */
1136: public boolean closeAllSavedEditors() {
1137: // get the Saved editors
1138: IEditorReference editors[] = getEditorReferences();
1139: IEditorReference savedEditors[] = new IEditorReference[editors.length];
1140: int j = 0;
1141: for (int i = 0; i < editors.length; i++) {
1142: IEditorReference editor = editors[i];
1143: if (!editor.isDirty()) {
1144: savedEditors[j++] = editor;
1145: }
1146: }
1147: //there are no unsaved editors
1148: if (j == 0) {
1149: return true;
1150: }
1151: IEditorReference[] newSaved = new IEditorReference[j];
1152: System.arraycopy(savedEditors, 0, newSaved, 0, j);
1153: return closeEditors(newSaved, false);
1154: }
1155:
1156: /**
1157: * See IWorkbenchPage
1158: */
1159: public boolean closeAllEditors(boolean save) {
1160: return closeEditors(getEditorReferences(), save);
1161: }
1162:
1163: private void updateActivePart() {
1164:
1165: if (isDeferred()) {
1166: return;
1167: }
1168:
1169: IWorkbenchPartReference oldActivePart = partList
1170: .getActivePartReference();
1171: IWorkbenchPartReference oldActiveEditor = partList
1172: .getActiveEditorReference();
1173: IWorkbenchPartReference newActivePart = null;
1174: IEditorReference newActiveEditor = null;
1175:
1176: if (!window.isClosing()) {
1177: // If an editor is active, try to keep an editor active
1178: if (oldActivePart == oldActiveEditor) {
1179: newActiveEditor = (IEditorReference) activationList
1180: .getActiveReference(true);
1181: newActivePart = newActiveEditor;
1182: if (newActivePart == null) {
1183: // Only activate a non-editor if there's no editors left
1184: newActivePart = activationList
1185: .getActiveReference(false);
1186: }
1187: } else {
1188: // If a non-editor is active, activate whatever was activated most recently
1189: newActivePart = activationList
1190: .getActiveReference(false);
1191:
1192: if (newActivePart instanceof IEditorReference) {
1193: // If that happens to be an editor, make it the active editor as well
1194: newActiveEditor = (IEditorReference) newActivePart;
1195: } else {
1196: // Otherwise, select whatever editor was most recently active
1197: newActiveEditor = (IEditorReference) activationList
1198: .getActiveReference(true);
1199: }
1200: }
1201: }
1202:
1203: if (newActiveEditor != oldActiveEditor) {
1204: makeActiveEditor(newActiveEditor);
1205: }
1206:
1207: if (newActivePart != oldActivePart) {
1208: makeActive(newActivePart);
1209: }
1210: }
1211:
1212: /**
1213: * Makes the given part active. Brings it in front if necessary. Permits null
1214: * (indicating that no part should be active).
1215: *
1216: * @since 3.1
1217: *
1218: * @param ref new active part (or null)
1219: */
1220: private void makeActive(IWorkbenchPartReference ref) {
1221: if (ref == null) {
1222: setActivePart(null);
1223: } else {
1224: IWorkbenchPart newActive = ref.getPart(true);
1225: if (newActive == null) {
1226: setActivePart(null);
1227: } else {
1228: activate(newActive);
1229: }
1230: }
1231: }
1232:
1233: /**
1234: * Makes the given editor active. Brings it to front if necessary. Permits <code>null</code>
1235: * (indicating that no editor is active).
1236: *
1237: * @since 3.1
1238: *
1239: * @param ref the editor to make active, or <code>null</code> for no active editor
1240: */
1241: private void makeActiveEditor(IEditorReference ref) {
1242: if (ref == getActiveEditorReference()) {
1243: return;
1244: }
1245:
1246: IEditorPart part = (ref == null) ? null : ref.getEditor(true);
1247:
1248: if (part != null) {
1249: editorMgr.setVisibleEditor(ref, false);
1250: navigationHistory.markEditor(part);
1251: }
1252:
1253: actionSwitcher.updateTopEditor(part);
1254:
1255: if (ref != null) {
1256: activationList.bringToTop(getReference(part));
1257: }
1258:
1259: partList.setActiveEditor(ref);
1260: }
1261:
1262: /**
1263: * See IWorkbenchPage
1264: */
1265: public boolean closeEditors(IEditorReference[] refArray,
1266: boolean save) {
1267: if (refArray.length == 0) {
1268: return true;
1269: }
1270:
1271: // Check if we're being asked to close any parts that are already closed or cannot
1272: // be closed at this time
1273: ArrayList toClose = new ArrayList();
1274: for (int i = 0; i < refArray.length; i++) {
1275: IEditorReference reference = refArray[i];
1276:
1277: // If we're in the middle of creating this part, this is a programming error. Abort the entire
1278: // close operation. This usually occurs if someone tries to open a dialog in a method that
1279: // isn't allowed to do so, and a *syncExec tries to close the part. If this shows up in a log
1280: // file with a dialog's event loop on the stack, then the code that opened the dialog is usually
1281: // at fault.
1282: if (reference == partBeingActivated) {
1283: WorkbenchPlugin
1284: .log(new RuntimeException(
1285: "WARNING: Blocked recursive attempt to close part " //$NON-NLS-1$
1286: + partBeingActivated.getId()
1287: + " while still in the middle of activating it")); //$NON-NLS-1$
1288: return false;
1289: }
1290:
1291: if (reference instanceof WorkbenchPartReference) {
1292: WorkbenchPartReference ref = (WorkbenchPartReference) reference;
1293:
1294: // If we're being asked to close a part that is disposed (ie: already closed),
1295: // skip it and proceed with closing the remaining parts.
1296: if (ref.isDisposed()) {
1297: continue;
1298: }
1299: }
1300:
1301: toClose.add(reference);
1302: }
1303:
1304: IEditorReference[] editorRefs = (IEditorReference[]) toClose
1305: .toArray(new IEditorReference[toClose.size()]);
1306:
1307: // notify the model manager before the close
1308: List partsToClose = new ArrayList();
1309: for (int i = 0; i < editorRefs.length; i++) {
1310: IEditorPart refPart = editorRefs[i].getEditor(false);
1311: if (refPart != null) {
1312: partsToClose.add(refPart);
1313: }
1314: }
1315: SaveablesList modelManager = null;
1316: Object postCloseInfo = null;
1317: if (partsToClose.size() > 0) {
1318: modelManager = (SaveablesList) getWorkbenchWindow()
1319: .getService(ISaveablesLifecycleListener.class);
1320: // this may prompt for saving and return null if the user canceled:
1321: postCloseInfo = modelManager.preCloseParts(partsToClose,
1322: save, getWorkbenchWindow());
1323: if (postCloseInfo == null) {
1324: return false;
1325: }
1326: }
1327:
1328: // Fire pre-removal changes
1329: for (int i = 0; i < editorRefs.length; i++) {
1330: IEditorReference ref = editorRefs[i];
1331:
1332: // Notify interested listeners before the close
1333: window.firePerspectiveChanged(this , getPerspective(), ref,
1334: CHANGE_EDITOR_CLOSE);
1335:
1336: }
1337:
1338: deferUpdates(true);
1339: try {
1340: if (modelManager != null) {
1341: modelManager.postClose(postCloseInfo);
1342: }
1343:
1344: // Close all editors.
1345: for (int i = 0; i < editorRefs.length; i++) {
1346: IEditorReference ref = editorRefs[i];
1347:
1348: // Remove editor from the presentation
1349: editorPresentation.closeEditor(ref);
1350:
1351: partRemoved((WorkbenchPartReference) ref);
1352: }
1353: } finally {
1354: deferUpdates(false);
1355: }
1356:
1357: // Notify interested listeners after the close
1358: window.firePerspectiveChanged(this , getPerspective(),
1359: CHANGE_EDITOR_CLOSE);
1360:
1361: // Return true on success.
1362: return true;
1363: }
1364:
1365: /**
1366: * Enables or disables listener notifications. This is used to delay listener notifications until the
1367: * end of a public method.
1368: *
1369: * @param shouldDefer
1370: */
1371: private void deferUpdates(boolean shouldDefer) {
1372: if (shouldDefer) {
1373: if (deferCount == 0) {
1374: startDeferring();
1375: }
1376: deferCount++;
1377: } else {
1378: deferCount--;
1379: if (deferCount == 0) {
1380: handleDeferredEvents();
1381: }
1382: }
1383: }
1384:
1385: private void startDeferring() {
1386: editorPresentation.getLayoutPart().deferUpdates(true);
1387: }
1388:
1389: private void handleDeferredEvents() {
1390: editorPresentation.getLayoutPart().deferUpdates(false);
1391: updateActivePart();
1392: WorkbenchPartReference[] disposals = (WorkbenchPartReference[]) pendingDisposals
1393: .toArray(new WorkbenchPartReference[pendingDisposals
1394: .size()]);
1395: pendingDisposals.clear();
1396: for (int i = 0; i < disposals.length; i++) {
1397: WorkbenchPartReference reference = disposals[i];
1398: disposePart(reference);
1399: }
1400:
1401: }
1402:
1403: private boolean isDeferred() {
1404: return deferCount > 0;
1405: }
1406:
1407: /**
1408: * See IWorkbenchPage#closeEditor
1409: */
1410: public boolean closeEditor(IEditorReference editorRef, boolean save) {
1411: return closeEditors(new IEditorReference[] { editorRef }, save);
1412: }
1413:
1414: /**
1415: * See IWorkbenchPage#closeEditor
1416: */
1417: public boolean closeEditor(IEditorPart editor, boolean save) {
1418: IWorkbenchPartReference ref = getReference(editor);
1419: if (ref instanceof IEditorReference) {
1420: return closeEditors(
1421: new IEditorReference[] { (IEditorReference) ref },
1422: save);
1423: }
1424: return false;
1425: }
1426:
1427: /**
1428: * @see IWorkbenchPage#closePerspective(IPerspectiveDescriptor, boolean, boolean)
1429: */
1430: public void closePerspective(IPerspectiveDescriptor desc,
1431: boolean saveParts, boolean closePage) {
1432: Perspective persp = findPerspective(desc);
1433: if (persp != null) {
1434: closePerspective(persp, saveParts, closePage);
1435: }
1436: }
1437:
1438: /**
1439: * Closes the specified perspective. If last perspective, then entire page
1440: * is closed.
1441: *
1442: * @param persp
1443: * the perspective to be closed
1444: * @param saveParts
1445: * whether the parts that are being closed should be saved
1446: * (editors if last perspective, views if not shown in other
1447: * parspectives)
1448: */
1449: /* package */
1450: void closePerspective(Perspective persp, boolean saveParts,
1451: boolean closePage) {
1452:
1453: // Always unzoom
1454: if (isZoomed()) {
1455: zoomOut();
1456: }
1457:
1458: List partsToSave = new ArrayList();
1459: List viewsToClose = new ArrayList();
1460: // collect views that will go away and views that are dirty
1461: IViewReference[] viewReferences = persp.getViewReferences();
1462: for (int i = 0; i < viewReferences.length; i++) {
1463: IViewReference reference = viewReferences[i];
1464: if (getViewFactory().getReferenceCount(reference) == 1) {
1465: IViewPart viewPart = reference.getView(false);
1466: if (viewPart != null) {
1467: viewsToClose.add(viewPart);
1468: if (saveParts && reference.isDirty()) {
1469: partsToSave.add(viewPart);
1470: }
1471: }
1472: }
1473: }
1474: if (saveParts && perspList.size() == 1) {
1475: // collect editors that are dirty
1476: IEditorReference[] editorReferences = getEditorReferences();
1477: for (int i = 0; i < editorReferences.length; i++) {
1478: IEditorReference reference = editorReferences[i];
1479: if (reference.isDirty()) {
1480: IEditorPart editorPart = reference.getEditor(false);
1481: if (editorPart != null) {
1482: partsToSave.add(editorPart);
1483: }
1484: }
1485: }
1486: }
1487: if (saveParts && !partsToSave.isEmpty()) {
1488: if (!EditorManager.saveAll(partsToSave, true, true, false,
1489: window)) {
1490: // user canceled
1491: return;
1492: }
1493: }
1494: // Close all editors on last perspective close
1495: if (perspList.size() == 1
1496: && getEditorManager().getEditorCount() > 0) {
1497: // Close all editors
1498: if (!closeAllEditors(false)) {
1499: return;
1500: }
1501: }
1502:
1503: // closeAllEditors already notified the saveables list about the editors.
1504: SaveablesList saveablesList = (SaveablesList) getWorkbenchWindow()
1505: .getWorkbench().getService(
1506: ISaveablesLifecycleListener.class);
1507: // we took care of the saving already, so pass in false (postCloseInfo will be non-null)
1508: Object postCloseInfo = saveablesList.preCloseParts(
1509: viewsToClose, false, getWorkbenchWindow());
1510: saveablesList.postClose(postCloseInfo);
1511:
1512: // Dispose of the perspective
1513: boolean isActive = (perspList.getActive() == persp);
1514: if (isActive) {
1515: setPerspective(perspList.getNextActive());
1516: }
1517: disposePerspective(persp, true);
1518: if (closePage && perspList.size() == 0) {
1519: close();
1520: }
1521: }
1522:
1523: /**
1524: * Forces all perspectives on the page to zoom out.
1525: */
1526: public void unzoomAllPerspectives() {
1527: for (Iterator perspIter = perspList.iterator(); perspIter
1528: .hasNext();) {
1529: Perspective persp = (Perspective) perspIter.next();
1530: persp.getPresentation().forceNoZoom();
1531: }
1532: }
1533:
1534: /**
1535: * @see IWorkbenchPage#closeAllPerspectives(boolean, boolean)
1536: */
1537: public void closeAllPerspectives(boolean saveEditors,
1538: boolean closePage) {
1539:
1540: if (perspList.isEmpty()) {
1541: return;
1542: }
1543:
1544: // Always unzoom
1545: if (isZoomed()) {
1546: zoomOut();
1547: }
1548:
1549: if (saveEditors) {
1550: if (!saveAllEditors(true)) {
1551: return;
1552: }
1553: }
1554: // Close all editors
1555: if (!closeAllEditors(false)) {
1556: return;
1557: }
1558:
1559: // Deactivate the active perspective and part
1560: setPerspective((Perspective) null);
1561:
1562: // Close each perspective in turn
1563: PerspectiveList oldList = perspList;
1564: perspList = new PerspectiveList();
1565: Iterator itr = oldList.iterator();
1566: while (itr.hasNext()) {
1567: closePerspective((Perspective) itr.next(), false, false);
1568: }
1569: if (closePage) {
1570: close();
1571: }
1572: }
1573:
1574: /**
1575: * Creates the client composite.
1576: */
1577: private void createClientComposite() {
1578: final Composite parent = window.getPageComposite();
1579: StartupThreading.runWithoutExceptions(new StartupRunnable() {
1580:
1581: public void runWithException() {
1582: composite = new Composite(parent, SWT.NONE);
1583: composite.setVisible(false); // Make visible on activate.
1584: // force the client composite to be layed out
1585: parent.layout();
1586: }
1587: });
1588:
1589: }
1590:
1591: /**
1592: * Creates a new view set. Return null on failure.
1593: *
1594: * @param desc the perspective descriptor
1595: * @param notify whether to fire a perspective opened event
1596: */
1597: private Perspective createPerspective(PerspectiveDescriptor desc,
1598: boolean notify) {
1599: String label = desc.getId(); // debugging only
1600: try {
1601: UIStats.start(UIStats.CREATE_PERSPECTIVE, label);
1602: Perspective persp = new Perspective(desc, this );
1603: perspList.add(persp);
1604: if (notify) {
1605: window.firePerspectiveOpened(this , desc);
1606: }
1607: //if the perspective is fresh and uncustomzied then it is not dirty
1608: //no reset will be prompted for
1609: if (!desc.hasCustomDefinition()) {
1610: dirtyPerspectives.remove(desc.getId());
1611: }
1612: return persp;
1613: } catch (WorkbenchException e) {
1614: if (!((Workbench) window.getWorkbench()).isStarting()) {
1615: MessageDialog
1616: .openError(
1617: window.getShell(),
1618: WorkbenchMessages.Error,
1619: NLS
1620: .bind(
1621: WorkbenchMessages.Workbench_showPerspectiveError,
1622: desc.getId()));
1623: }
1624: return null;
1625: } finally {
1626: UIStats
1627: .end(UIStats.CREATE_PERSPECTIVE, desc.getId(),
1628: label);
1629: }
1630: }
1631:
1632: /**
1633: * This is called by child objects after a part has been added to the page.
1634: * The page will in turn notify its listeners.
1635: */
1636: /* package */void partAdded(WorkbenchPartReference ref) {
1637: activationList.add(ref);
1638: partList.addPart(ref);
1639:
1640: // If we're adding a new editor then allow fast views
1641: // to remain open
1642: if (ref instanceof IEditorReference) {
1643: includeActiveFastViews = true;
1644: updateActivePart();
1645: includeActiveFastViews = false;
1646: } else
1647: updateActivePart();
1648: }
1649:
1650: /**
1651: * This is called by child objects after a part has been added to the page.
1652: * The part will be queued for disposal after all listeners have been notified
1653: */
1654: /* package */void partRemoved(WorkbenchPartReference ref) {
1655: activationList.remove(ref);
1656: disposePart(ref);
1657: }
1658:
1659: private void disposePart(WorkbenchPartReference ref) {
1660: if (isDeferred()) {
1661: pendingDisposals.add(ref);
1662: } else {
1663: partList.removePart(ref);
1664: ref.dispose();
1665: }
1666: }
1667:
1668: /**
1669: * Deactivates a part. The pane is unhilighted.
1670: */
1671: private void deactivatePart(IWorkbenchPart part) {
1672: if (part != null) {
1673: PartSite site = (PartSite) part.getSite();
1674: site.getPane().showFocus(false);
1675: }
1676: }
1677:
1678: /**
1679: * Detaches a view from the WorkbenchWindow.
1680: */
1681: public void detachView(IViewReference ref) {
1682: Perspective persp = getActivePerspective();
1683: if (persp == null) {
1684: return;
1685: }
1686:
1687: PerspectiveHelper presentation = persp.getPresentation();
1688: presentation.detachPart(ref);
1689: }
1690:
1691: /**
1692: * Removes a detachedwindow.
1693: */
1694: public void attachView(IViewReference ref) {
1695: PerspectiveHelper presentation = getPerspectivePresentation();
1696: presentation.attachPart(ref);
1697: }
1698:
1699: /**
1700: * Cleanup.
1701: */
1702: public void dispose() {
1703:
1704: // Always unzoom
1705: if (isZoomed()) {
1706: zoomOut();
1707: }
1708:
1709: makeActiveEditor(null);
1710: makeActive(null);
1711:
1712: // Close and dispose the editors.
1713: closeAllEditors(false);
1714:
1715: // Need to make sure model data is cleaned up when the page is
1716: // disposed. Collect all the views on the page and notify the
1717: // saveable list of a pre/post close. This will free model data.
1718: IWorkbenchPartReference[] partsToClose = getOpenParts();
1719: List dirtyParts = new ArrayList(partsToClose.length);
1720: for (int i = 0; i < partsToClose.length; i++) {
1721: IWorkbenchPart part = partsToClose[i].getPart(false);
1722: if (part != null && part instanceof IViewPart) {
1723: dirtyParts.add(part);
1724: }
1725: }
1726: SaveablesList saveablesList = (SaveablesList) getWorkbenchWindow()
1727: .getWorkbench().getService(
1728: ISaveablesLifecycleListener.class);
1729: Object postCloseInfo = saveablesList.preCloseParts(dirtyParts,
1730: false, getWorkbenchWindow());
1731: saveablesList.postClose(postCloseInfo);
1732:
1733: // Get rid of perspectives. This will close the views.
1734: Iterator itr = perspList.iterator();
1735: while (itr.hasNext()) {
1736: Perspective perspective = (Perspective) itr.next();
1737: window.firePerspectiveClosed(this , perspective.getDesc());
1738: perspective.dispose();
1739: }
1740: perspList = new PerspectiveList();
1741:
1742: // Capture views.
1743: IViewReference refs[] = viewFactory.getViews();
1744:
1745: if (refs.length > 0) {
1746: // Dispose views.
1747: for (int i = 0; i < refs.length; i++) {
1748: final WorkbenchPartReference ref = (WorkbenchPartReference) refs[i];
1749: //partList.removePart(ref);
1750: //firePartClosed(refs[i]);
1751: Platform.run(new SafeRunnable() {
1752: public void run() {
1753: // WorkbenchPlugin.log(new Status(IStatus.WARNING, WorkbenchPlugin.PI_WORKBENCH,
1754: // Status.OK, "WorkbenchPage leaked a refcount for view " + ref.getId(), null)); //$NON-NLS-1$//$NON-NLS-2$
1755:
1756: ref.dispose();
1757: }
1758:
1759: public void handleException(Throwable e) {
1760: }
1761: });
1762: }
1763: }
1764:
1765: activationList = new ActivationList();
1766:
1767: // Get rid of editor presentation.
1768: editorPresentation.dispose();
1769:
1770: // Get rid of composite.
1771: composite.dispose();
1772:
1773: navigationHistory.dispose();
1774:
1775: stickyViewMan.clear();
1776:
1777: if (tracker != null) {
1778: tracker.close();
1779: }
1780:
1781: // if we're destroying a window in a non-shutdown situation then we should
1782: // clean up the working set we made.
1783: if (!window.getWorkbench().isClosing()) {
1784: if (aggregateWorkingSet != null) {
1785: PlatformUI.getWorkbench().getWorkingSetManager()
1786: .removeWorkingSet(aggregateWorkingSet);
1787: }
1788: }
1789: }
1790:
1791: /**
1792: * Dispose a perspective.
1793: *
1794: * @param persp the perspective descriptor
1795: * @param notify whether to fire a perspective closed event
1796: */
1797: private void disposePerspective(Perspective persp, boolean notify) {
1798: // Get rid of perspective.
1799: perspList.remove(persp);
1800: if (notify) {
1801: window.firePerspectiveClosed(this , persp.getDesc());
1802: }
1803: persp.dispose();
1804:
1805: stickyViewMan.remove(persp.getDesc().getId());
1806: }
1807:
1808: /**
1809: * @return NavigationHistory
1810: */
1811: public INavigationHistory getNavigationHistory() {
1812: return navigationHistory;
1813: }
1814:
1815: /**
1816: * Edits the action sets.
1817: */
1818: public boolean editActionSets() {
1819: Perspective persp = getActivePerspective();
1820: if (persp == null) {
1821: return false;
1822: }
1823:
1824: // Create list dialog.
1825: CustomizePerspectiveDialog dlg = window
1826: .createCustomizePerspectiveDialog(persp);
1827:
1828: // Open.
1829: boolean ret = (dlg.open() == Window.OK);
1830: if (ret) {
1831: window.updateActionSets();
1832: window.firePerspectiveChanged(this , getPerspective(),
1833: CHANGE_RESET);
1834: window.firePerspectiveChanged(this , getPerspective(),
1835: CHANGE_RESET_COMPLETE);
1836: }
1837: return ret;
1838: }
1839:
1840: /**
1841: * Returns the first view manager with given ID.
1842: */
1843: public Perspective findPerspective(IPerspectiveDescriptor desc) {
1844: Iterator itr = perspList.iterator();
1845: while (itr.hasNext()) {
1846: Perspective mgr = (Perspective) itr.next();
1847: if (desc.getId().equals(mgr.getDesc().getId())) {
1848: return mgr;
1849: }
1850: }
1851: return null;
1852: }
1853:
1854: /**
1855: * See IWorkbenchPage@findView.
1856: */
1857: public IViewPart findView(String id) {
1858: IViewReference ref = findViewReference(id);
1859: if (ref == null) {
1860: return null;
1861: }
1862: return ref.getView(true);
1863: }
1864:
1865: /*
1866: * (non-Javadoc)
1867: *
1868: * @see org.eclipse.ui.IWorkbenchPage
1869: */
1870: public IViewReference findViewReference(String viewId) {
1871: return findViewReference(viewId, null);
1872: }
1873:
1874: /*
1875: * (non-Javadoc)
1876: *
1877: * @see org.eclipse.ui.IWorkbenchPage
1878: */
1879: public IViewReference findViewReference(String viewId,
1880: String secondaryId) {
1881: Perspective persp = getActivePerspective();
1882: if (persp == null) {
1883: return null;
1884: }
1885: return persp.findView(viewId, secondaryId);
1886: }
1887:
1888: /**
1889: * Notify property change listeners about a property change.
1890: *
1891: * @param changeId
1892: * the change id
1893: * @param oldValue
1894: * old property value
1895: * @param newValue
1896: * new property value
1897: */
1898: private void firePropertyChange(String changeId, Object oldValue,
1899: Object newValue) {
1900:
1901: UIListenerLogging.logPagePropertyChanged(this , changeId,
1902: oldValue, newValue);
1903:
1904: Object[] listeners = propertyChangeListeners.getListeners();
1905: PropertyChangeEvent event = new PropertyChangeEvent(this ,
1906: changeId, oldValue, newValue);
1907:
1908: for (int i = 0; i < listeners.length; i++) {
1909: ((IPropertyChangeListener) listeners[i])
1910: .propertyChange(event);
1911: }
1912: }
1913:
1914: /*
1915: * Returns the action bars.
1916: */
1917: public IActionBars getActionBars() {
1918: if (actionBars == null) {
1919: actionBars = new WWinActionBars(window);
1920: }
1921: return actionBars;
1922: }
1923:
1924: /**
1925: * Returns an array of the visible action sets.
1926: */
1927: public IActionSetDescriptor[] getActionSets() {
1928: Collection collection = actionSets.getVisibleItems();
1929:
1930: return (IActionSetDescriptor[]) collection
1931: .toArray(new IActionSetDescriptor[collection.size()]);
1932: }
1933:
1934: /**
1935: * @see IWorkbenchPage
1936: */
1937: public IEditorPart getActiveEditor() {
1938: return partList.getActiveEditor();
1939: }
1940:
1941: /**
1942: * Returns the reference for the active editor, or <code>null</code>
1943: * if there is no active editor.
1944: *
1945: * @return the active editor reference or <code>null</code>
1946: */
1947: public IEditorReference getActiveEditorReference() {
1948: return partList.getActiveEditorReference();
1949: }
1950:
1951: /*
1952: * (non-Javadoc) Method declared on IPartService
1953: */
1954: public IWorkbenchPart getActivePart() {
1955: return partList.getActivePart();
1956: }
1957:
1958: /*
1959: * (non-Javadoc) Method declared on IPartService
1960: */
1961: public IWorkbenchPartReference getActivePartReference() {
1962: return partList.getActivePartReference();
1963: }
1964:
1965: /**
1966: * Returns the active perspective for the page, <code>null</code> if
1967: * none.
1968: */
1969: public Perspective getActivePerspective() {
1970: return perspList.getActive();
1971: }
1972:
1973: /**
1974: * Returns the client composite.
1975: */
1976: public Composite getClientComposite() {
1977: return composite;
1978: }
1979:
1980: // for dynamic UI - change access from private to protected
1981: // for testing purposes only, changed from protected to public
1982: /**
1983: * Answer the editor manager for this window.
1984: */
1985: public EditorManager getEditorManager() {
1986: return editorMgr;
1987: }
1988:
1989: /**
1990: * Answer the perspective presentation.
1991: */
1992: public PerspectiveHelper getPerspectivePresentation() {
1993: if (getActivePerspective() != null) {
1994: return getActivePerspective().getPresentation();
1995: }
1996: return null;
1997: }
1998:
1999: /**
2000: * Answer the editor presentation.
2001: */
2002: public EditorAreaHelper getEditorPresentation() {
2003: return editorPresentation;
2004: }
2005:
2006: /**
2007: * See IWorkbenchPage.
2008: */
2009: public IEditorPart[] getEditors() {
2010: final IEditorReference refs[] = getEditorReferences();
2011: final ArrayList result = new ArrayList(refs.length);
2012: Display d = getWorkbenchWindow().getShell().getDisplay();
2013: //Must be backward compatible.
2014: d.syncExec(new Runnable() {
2015: public void run() {
2016: for (int i = 0; i < refs.length; i++) {
2017: IWorkbenchPart part = refs[i].getPart(true);
2018: if (part != null) {
2019: result.add(part);
2020: }
2021: }
2022: }
2023: });
2024: final IEditorPart editors[] = new IEditorPart[result.size()];
2025: return (IEditorPart[]) result.toArray(editors);
2026: }
2027:
2028: public IEditorPart[] getDirtyEditors() {
2029: return getEditorManager().getDirtyEditors();
2030: }
2031:
2032: public ISaveablePart[] getDirtyParts() {
2033: List result = new ArrayList(3);
2034: IWorkbenchPartReference[] allParts = getAllParts();
2035: for (int i = 0; i < allParts.length; i++) {
2036: IWorkbenchPartReference reference = allParts[i];
2037:
2038: IWorkbenchPart part = reference.getPart(false);
2039: if (part != null && part instanceof ISaveablePart) {
2040: ISaveablePart saveable = (ISaveablePart) part;
2041: if (saveable.isDirty()) {
2042: result.add(saveable);
2043: }
2044: }
2045: }
2046:
2047: return (ISaveablePart[]) result
2048: .toArray(new ISaveablePart[result.size()]);
2049: }
2050:
2051: /**
2052: * See IWorkbenchPage.
2053: */
2054: public IEditorPart findEditor(IEditorInput input) {
2055: return getEditorManager().findEditor(input);
2056: }
2057:
2058: /**
2059: * See IWorkbenchPage.
2060: */
2061: public IEditorReference[] findEditors(IEditorInput input,
2062: String editorId, int matchFlags) {
2063: return getEditorManager().findEditors(input, editorId,
2064: matchFlags);
2065: }
2066:
2067: /**
2068: * See IWorkbenchPage.
2069: */
2070: public IEditorReference[] getEditorReferences() {
2071: return editorPresentation.getEditors();
2072: }
2073:
2074: /**
2075: * Returns the docked views.
2076: */
2077: public IViewReference[] getFastViews() {
2078: Perspective persp = getActivePerspective();
2079: if (persp != null) {
2080: return persp.getFastViews();
2081: } else {
2082: return new IViewReference[0];
2083: }
2084: }
2085:
2086: /**
2087: * @see IWorkbenchPage
2088: */
2089: public IAdaptable getInput() {
2090: return input;
2091: }
2092:
2093: /**
2094: * Returns the page label. This is a combination of the page input and
2095: * active perspective.
2096: */
2097: public String getLabel() {
2098: String label = WorkbenchMessages.WorkbenchPage_UnknownLabel;
2099: IWorkbenchAdapter adapter = (IWorkbenchAdapter) Util
2100: .getAdapter(input, IWorkbenchAdapter.class);
2101: if (adapter != null) {
2102: label = adapter.getLabel(input);
2103: }
2104: Perspective persp = getActivePerspective();
2105: if (persp != null) {
2106: label = NLS.bind(
2107: WorkbenchMessages.WorkbenchPage_PerspectiveFormat,
2108: label, persp.getDesc().getLabel());
2109: } else if (deferredActivePersp != null) {
2110: label = NLS.bind(
2111: WorkbenchMessages.WorkbenchPage_PerspectiveFormat,
2112: label, deferredActivePersp.getLabel());
2113: }
2114: return label;
2115: }
2116:
2117: /**
2118: * Returns the perspective.
2119: */
2120: public IPerspectiveDescriptor getPerspective() {
2121: if (deferredActivePersp != null) {
2122: return deferredActivePersp;
2123: }
2124: Perspective persp = getActivePerspective();
2125: if (persp != null) {
2126: return persp.getDesc();
2127: } else {
2128: return null;
2129: }
2130: }
2131:
2132: /*
2133: * (non-Javadoc) Method declared on ISelectionService
2134: */
2135: public ISelection getSelection() {
2136: return selectionService.getSelection();
2137: }
2138:
2139: /*
2140: * (non-Javadoc) Method declared on ISelectionService
2141: */
2142: public ISelection getSelection(String partId) {
2143: return selectionService.getSelection(partId);
2144: }
2145:
2146: /**
2147: * Returns the ids of the parts to list in the Show In... prompter. This is
2148: * a List of Strings.
2149: */
2150: public ArrayList getShowInPartIds() {
2151: Perspective persp = getActivePerspective();
2152: if (persp != null) {
2153: return persp.getShowInPartIds();
2154: } else {
2155: return new ArrayList();
2156: }
2157: }
2158:
2159: /**
2160: * The user successfully performed a Show In... action on the specified
2161: * part. Update the list of Show In items accordingly.
2162: */
2163: public void performedShowIn(String partId) {
2164: Perspective persp = getActivePerspective();
2165: if (persp != null) {
2166: persp.performedShowIn(partId);
2167: }
2168: }
2169:
2170: /**
2171: * Sorts the given collection of show in target part ids in MRU order.
2172: */
2173: public void sortShowInPartIds(ArrayList partIds) {
2174: final Perspective persp = getActivePerspective();
2175: if (persp != null) {
2176: Collections.sort(partIds, new Comparator() {
2177: public int compare(Object a, Object b) {
2178: long ta = persp.getShowInTime((String) a);
2179: long tb = persp.getShowInTime((String) b);
2180: return (ta == tb) ? 0 : ((ta > tb) ? -1 : 1);
2181: }
2182: });
2183: }
2184: }
2185:
2186: /*
2187: * Returns the view factory.
2188: */
2189: public ViewFactory getViewFactory() {
2190: if (viewFactory == null) {
2191: viewFactory = new ViewFactory(this , WorkbenchPlugin
2192: .getDefault().getViewRegistry());
2193: }
2194: return viewFactory;
2195: }
2196:
2197: /**
2198: * See IWorkbenchPage.
2199: */
2200: public IViewReference[] getViewReferences() {
2201: Perspective persp = getActivePerspective();
2202: if (persp != null) {
2203: return persp.getViewReferences();
2204: } else {
2205: return new IViewReference[0];
2206: }
2207: }
2208:
2209: /**
2210: * See IWorkbenchPage.
2211: */
2212: public IViewPart[] getViews() {
2213: return getViews(null, true);
2214: }
2215:
2216: /**
2217: * Returns all view parts in the specified perspective
2218: *
2219: * @param persp the perspective
2220: * @return an array of view parts
2221: * @since 3.1
2222: */
2223: /*package*/IViewPart[] getViews(Perspective persp, boolean restore) {
2224: if (persp == null) {
2225: persp = getActivePerspective();
2226: }
2227:
2228: if (persp != null) {
2229: IViewReference refs[] = persp.getViewReferences();
2230: ArrayList parts = new ArrayList(refs.length);
2231: for (int i = 0; i < refs.length; i++) {
2232: IWorkbenchPart part = refs[i].getPart(restore);
2233: if (part != null) {
2234: parts.add(part);
2235: }
2236: }
2237: IViewPart[] result = new IViewPart[parts.size()];
2238: return (IViewPart[]) parts.toArray(result);
2239: }
2240: return new IViewPart[0];
2241: }
2242:
2243: /**
2244: * See IWorkbenchPage.
2245: */
2246: public IWorkbenchWindow getWorkbenchWindow() {
2247: return window;
2248: }
2249:
2250: /**
2251: * Implements IWorkbenchPage
2252: *
2253: * @see org.eclipse.ui.IWorkbenchPage#getWorkingSet()
2254: * @since 2.0
2255: * @deprecated individual views should store a working set if needed
2256: */
2257: public IWorkingSet getWorkingSet() {
2258: return workingSet;
2259: }
2260:
2261: /**
2262: * @see IWorkbenchPage
2263: */
2264: public void hideActionSet(String actionSetID) {
2265: Perspective persp = getActivePerspective();
2266: if (persp != null) {
2267: persp.removeActionSet(actionSetID);
2268: window.updateActionSets();
2269: window.firePerspectiveChanged(this , getPerspective(),
2270: CHANGE_ACTION_SET_HIDE);
2271: }
2272: }
2273:
2274: /*
2275: * (non-Javadoc)
2276: *
2277: * @see org.eclipse.ui.IWorkbenchPage#hideView(org.eclipse.ui.IViewReference)
2278: */
2279: public void hideView(IViewReference ref) {
2280:
2281: // Sanity check.
2282: if (ref == null) {
2283: return;
2284: }
2285:
2286: Perspective persp = getActivePerspective();
2287: if (persp == null) {
2288: return;
2289: }
2290:
2291: boolean promptedForSave = false;
2292: IViewPart view = ref.getView(false);
2293: if (view != null) {
2294:
2295: if (!certifyPart(view)) {
2296: return;
2297: }
2298:
2299: // Confirm.
2300: if (view instanceof ISaveablePart) {
2301: ISaveablePart saveable = (ISaveablePart) view;
2302: if (saveable.isSaveOnCloseNeeded()) {
2303: IWorkbenchWindow window = view.getSite()
2304: .getWorkbenchWindow();
2305: boolean success = EditorManager.saveAll(Collections
2306: .singletonList(view), true, true, false,
2307: window);
2308: if (!success) {
2309: // the user cancelled.
2310: return;
2311: }
2312: promptedForSave = true;
2313: }
2314: }
2315: }
2316:
2317: int refCount = getViewFactory().getReferenceCount(ref);
2318: SaveablesList saveablesList = null;
2319: Object postCloseInfo = null;
2320: if (refCount == 1) {
2321: IWorkbenchPart actualPart = ref.getPart(false);
2322: if (actualPart != null) {
2323: saveablesList = (SaveablesList) actualPart.getSite()
2324: .getService(ISaveablesLifecycleListener.class);
2325: postCloseInfo = saveablesList.preCloseParts(Collections
2326: .singletonList(actualPart), !promptedForSave,
2327: this .getWorkbenchWindow());
2328: if (postCloseInfo == null) {
2329: // cancel
2330: return;
2331: }
2332: }
2333: }
2334:
2335: // Notify interested listeners before the hide
2336: window.firePerspectiveChanged(this , persp.getDesc(), ref,
2337: CHANGE_VIEW_HIDE);
2338:
2339: PartPane pane = getPane(ref);
2340: pane.setInLayout(false);
2341:
2342: updateActivePart();
2343:
2344: if (saveablesList != null) {
2345: saveablesList.postClose(postCloseInfo);
2346: }
2347:
2348: // Hide the part.
2349: persp.hideView(ref);
2350:
2351: // Notify interested listeners after the hide
2352: window.firePerspectiveChanged(this , getPerspective(),
2353: CHANGE_VIEW_HIDE);
2354: }
2355:
2356: /* package */void refreshActiveView() {
2357: updateActivePart();
2358: }
2359:
2360: /**
2361: * See IPerspective
2362: */
2363: public void hideView(IViewPart view) {
2364: hideView((IViewReference) getReference(view));
2365: }
2366:
2367: /**
2368: * Initialize the page.
2369: *
2370: * @param w
2371: * the parent window
2372: * @param layoutID
2373: * may be <code>null</code> if restoring from file
2374: * @param input
2375: * the page input
2376: * @param openExtras
2377: * whether to process the perspective extras preference
2378: */
2379: private void init(WorkbenchWindow w, String layoutID,
2380: IAdaptable input, boolean openExtras)
2381: throws WorkbenchException {
2382: // Save args.
2383: this .window = w;
2384: this .input = input;
2385: actionSets = new ActionSetManager(w);
2386:
2387: // Create presentation.
2388: createClientComposite();
2389: editorPresentation = new EditorAreaHelper(this );
2390: editorMgr = new EditorManager(window, this , editorPresentation);
2391:
2392: // add this page as a client to be notified when the UI has re-orded perspectives
2393: // so that the order can be properly maintained in the receiver.
2394: // E.g. a UI might support drag-and-drop and will need to make this known to ensure
2395: // #saveState and #restoreState do not lose this re-ordering
2396: w.addPerspectiveReorderListener(new IReorderListener() {
2397: public void reorder(Object perspective, int newLoc) {
2398: perspList.reorder((IPerspectiveDescriptor) perspective,
2399: newLoc);
2400: }
2401: });
2402:
2403: if (openExtras) {
2404: openPerspectiveExtras();
2405: }
2406:
2407: // Get perspective descriptor.
2408: if (layoutID != null) {
2409: PerspectiveDescriptor desc = (PerspectiveDescriptor) WorkbenchPlugin
2410: .getDefault().getPerspectiveRegistry()
2411: .findPerspectiveWithId(layoutID);
2412: if (desc == null) {
2413: throw new WorkbenchException(
2414: NLS
2415: .bind(
2416: WorkbenchMessages.WorkbenchPage_ErrorCreatingPerspective,
2417: layoutID));
2418: }
2419: Perspective persp = findPerspective(desc);
2420: if (persp == null) {
2421: persp = createPerspective(desc, true);
2422: }
2423: perspList.setActive(persp);
2424: window.firePerspectiveActivated(this , desc);
2425: }
2426:
2427: getExtensionTracker()
2428: .registerHandler(
2429: perspectiveChangeHandler,
2430: ExtensionTracker
2431: .createExtensionPointFilter(getPerspectiveExtensionPoint()));
2432: }
2433:
2434: /**
2435: * Opens the perspectives specified in the PERSPECTIVE_BAR_EXTRAS preference (see bug 84226).
2436: */
2437: public void openPerspectiveExtras() {
2438: String extras = PrefUtil.getAPIPreferenceStore().getString(
2439: IWorkbenchPreferenceConstants.PERSPECTIVE_BAR_EXTRAS);
2440: StringTokenizer tok = new StringTokenizer(extras, ", "); //$NON-NLS-1$
2441: ArrayList descs = new ArrayList();
2442: while (tok.hasMoreTokens()) {
2443: String id = tok.nextToken();
2444: IPerspectiveDescriptor desc = WorkbenchPlugin.getDefault()
2445: .getPerspectiveRegistry().findPerspectiveWithId(id);
2446: if (desc != null) {
2447: descs.add(desc);
2448: }
2449: }
2450: // HACK: The perspective switcher currently adds the button for a new perspective to the beginning of the list.
2451: // So, we process the extra perspectives in reverse order here to have their buttons appear in the order declared.
2452: for (int i = descs.size(); --i >= 0;) {
2453: PerspectiveDescriptor desc = (PerspectiveDescriptor) descs
2454: .get(i);
2455: if (findPerspective(desc) == null) {
2456: createPerspective(desc, true);
2457: }
2458: }
2459: }
2460:
2461: /**
2462: * See IWorkbenchPage.
2463: */
2464: public boolean isPartVisible(IWorkbenchPart part) {
2465: PartPane pane = getPane(part);
2466: return pane != null && pane.getVisible();
2467: }
2468:
2469: /**
2470: * See IWorkbenchPage.
2471: */
2472: public boolean isEditorAreaVisible() {
2473: Perspective persp = getActivePerspective();
2474: if (persp == null) {
2475: return false;
2476: }
2477: return persp.isEditorAreaVisible();
2478: }
2479:
2480: /**
2481: * Returns whether the view is fast.
2482: */
2483: public boolean isFastView(IViewReference ref) {
2484: Perspective persp = getActivePerspective();
2485: if (persp != null) {
2486: return persp.isFastView(ref);
2487: } else {
2488: return false;
2489: }
2490: }
2491:
2492: /**
2493: * Return whether the view is closeable or not.
2494: *
2495: * @param ref the view reference to check. Must not be <code>null</code>.
2496: * @return true if the part is closeable.
2497: * @since 3.1.1
2498: */
2499: public boolean isCloseable(IViewReference ref) {
2500: Perspective persp = getActivePerspective();
2501: if (persp != null) {
2502: return persp.isCloseable(ref);
2503: }
2504: return false;
2505: }
2506:
2507: /**
2508: * Return whether the view is moveable or not.
2509: *
2510: * @param ref the view reference to check. Must not be <code>null</code>.
2511: * @return true if the part is moveable.
2512: * @since 3.1.1
2513: */
2514: public boolean isMoveable(IViewReference ref) {
2515: Perspective persp = getActivePerspective();
2516: if (persp != null) {
2517: return persp.isMoveable(ref);
2518: }
2519: return false;
2520: }
2521:
2522: /**
2523: * Returns whether the layout of the active
2524: * perspective is fixed.
2525: */
2526: public boolean isFixedLayout() {
2527: Perspective persp = getActivePerspective();
2528: if (persp != null) {
2529: return persp.isFixedLayout();
2530: } else {
2531: return false;
2532: }
2533: }
2534:
2535: /**
2536: * Return the active fast view or null if there are no fast views or if
2537: * there are all minimized.
2538: */
2539: public IViewReference getActiveFastView() {
2540: Perspective persp = getActivePerspective();
2541: if (persp != null) {
2542: return persp.getActiveFastView();
2543: } else {
2544: return null;
2545: }
2546: }
2547:
2548: /**
2549: * Return true if the perspective has a dirty editor.
2550: */
2551: protected boolean isSaveNeeded() {
2552: return getEditorManager().isSaveAllNeeded();
2553: }
2554:
2555: /* (non-Javadoc)
2556: * @see org.eclipse.ui.IWorkbenchPage#isPageZoomed()
2557: */
2558: public boolean isPageZoomed() {
2559: Perspective persp = getActivePerspective();
2560: if (persp == null) {
2561: return false;
2562: }
2563: if (persp.getPresentation() == null) {
2564: return false;
2565: }
2566:
2567: if (Perspective.useNewMinMax(persp))
2568: return persp.getPresentation().getMaximizedStack() != null;
2569:
2570: // Default to the legacy code
2571: return isZoomed();
2572: }
2573:
2574: /**
2575: * Returns whether the page is zoomed.
2576: * @return <code>true</code> if the page is zoomed.
2577: *
2578: * <strong>NOTE:</strong> As of 3.3 this method should always return 'false'
2579: * when using the new min/max behavior. It is only used for
2580: * legacy 'zoom' handling.
2581: *
2582: */
2583: public boolean isZoomed() {
2584: Perspective persp = getActivePerspective();
2585: if (persp == null) {
2586: return false;
2587: }
2588: if (persp.getPresentation() == null) {
2589: return false;
2590: }
2591: return persp.getPresentation().isZoomed();
2592: }
2593:
2594: /**
2595: * This method is called when the page is activated.
2596: */
2597: protected void onActivate() {
2598: composite.setVisible(true);
2599: Perspective persp = getActivePerspective();
2600:
2601: if (persp != null) {
2602: persp.onActivate();
2603: updateVisibility(null, persp);
2604: }
2605: }
2606:
2607: /**
2608: * This method is called when the page is deactivated.
2609: */
2610: protected void onDeactivate() {
2611: makeActiveEditor(null);
2612: makeActive(null);
2613: if (getActivePerspective() != null) {
2614: getActivePerspective().onDeactivate();
2615: }
2616: composite.setVisible(false);
2617: }
2618:
2619: /**
2620: * See IWorkbenchPage.
2621: */
2622: public void reuseEditor(IReusableEditor editor, IEditorInput input) {
2623:
2624: // Rather than calling editor.setInput on the editor directly, we do it through the part reference.
2625: // This case lets us detect badly behaved editors that are not firing a PROP_INPUT event in response
2626: // to the input change... but if all editors obeyed their API contract, the "else" branch would be
2627: // sufficient.
2628: IWorkbenchPartReference ref = getReference(editor);
2629: if (ref instanceof EditorReference) {
2630: EditorReference editorRef = (EditorReference) ref;
2631:
2632: editorRef.setInput(input);
2633: } else {
2634: editor.setInput(input);
2635: }
2636: navigationHistory.markEditor(editor);
2637: }
2638:
2639: /**
2640: * See IWorkbenchPage.
2641: */
2642: public IEditorPart openEditor(IEditorInput input, String editorID)
2643: throws PartInitException {
2644: return openEditor(input, editorID, true, MATCH_INPUT);
2645: }
2646:
2647: /**
2648: * See IWorkbenchPage.
2649: */
2650: public IEditorPart openEditor(IEditorInput input, String editorID,
2651: boolean activate) throws PartInitException {
2652: return openEditor(input, editorID, activate, MATCH_INPUT);
2653: }
2654:
2655: /**
2656: * See IWorkbenchPage.
2657: */
2658: public IEditorPart openEditor(final IEditorInput input,
2659: final String editorID, final boolean activate,
2660: final int matchFlags) throws PartInitException {
2661: return openEditor(input, editorID, activate, matchFlags, null);
2662: }
2663:
2664: /**
2665: * This is not public API but for use internally. editorState can be <code>null</code>.
2666: */
2667: public IEditorPart openEditor(final IEditorInput input,
2668: final String editorID, final boolean activate,
2669: final int matchFlags, final IMemento editorState)
2670: throws PartInitException {
2671: if (input == null || editorID == null) {
2672: throw new IllegalArgumentException();
2673: }
2674:
2675: final IEditorPart result[] = new IEditorPart[1];
2676: final PartInitException ex[] = new PartInitException[1];
2677: BusyIndicator.showWhile(window.getWorkbench().getDisplay(),
2678: new Runnable() {
2679: public void run() {
2680: try {
2681: result[0] = busyOpenEditor(input, editorID,
2682: activate, matchFlags, editorState);
2683: } catch (PartInitException e) {
2684: ex[0] = e;
2685: }
2686: }
2687: });
2688: if (ex[0] != null) {
2689: throw ex[0];
2690: }
2691: return result[0];
2692: }
2693:
2694: /*
2695: * Added to fix Bug 178235 [EditorMgmt] DBCS 3.3 - Cannot open file with external program.
2696: * Opens a new editor using the given input and descriptor. (Normally, editors are opened using
2697: * an editor ID and an input.)
2698: */
2699: public IEditorPart openEditorFromDescriptor(
2700: final IEditorInput input,
2701: final IEditorDescriptor editorDescriptor,
2702: final boolean activate, final IMemento editorState)
2703: throws PartInitException {
2704: if (input == null
2705: || !(editorDescriptor instanceof EditorDescriptor)) {
2706: throw new IllegalArgumentException();
2707: }
2708:
2709: final IEditorPart result[] = new IEditorPart[1];
2710: final PartInitException ex[] = new PartInitException[1];
2711: BusyIndicator.showWhile(window.getWorkbench().getDisplay(),
2712: new Runnable() {
2713: public void run() {
2714: try {
2715: result[0] = busyOpenEditorFromDescriptor(
2716: input,
2717: (EditorDescriptor) editorDescriptor,
2718: activate, editorState);
2719: } catch (PartInitException e) {
2720: ex[0] = e;
2721: }
2722: }
2723: });
2724: if (ex[0] != null) {
2725: throw ex[0];
2726: }
2727: return result[0];
2728: }
2729:
2730: /**
2731: * @see #openEditor(IEditorInput, String, boolean, int)
2732: */
2733: private IEditorPart busyOpenEditor(IEditorInput input,
2734: String editorID, boolean activate, int matchFlags,
2735: IMemento editorState) throws PartInitException {
2736:
2737: final Workbench workbench = (Workbench) getWorkbenchWindow()
2738: .getWorkbench();
2739: workbench.largeUpdateStart();
2740:
2741: try {
2742: return busyOpenEditorBatched(input, editorID, activate,
2743: matchFlags, editorState);
2744:
2745: } finally {
2746: workbench.largeUpdateEnd();
2747: }
2748: }
2749:
2750: /*
2751: * Added to fix Bug 178235 [EditorMgmt] DBCS 3.3 - Cannot open file with external program.
2752: * See openEditorFromDescriptor().
2753: */
2754: private IEditorPart busyOpenEditorFromDescriptor(
2755: IEditorInput input, EditorDescriptor editorDescriptor,
2756: boolean activate, IMemento editorState)
2757: throws PartInitException {
2758:
2759: final Workbench workbench = (Workbench) getWorkbenchWindow()
2760: .getWorkbench();
2761: workbench.largeUpdateStart();
2762:
2763: try {
2764: return busyOpenEditorFromDescriptorBatched(input,
2765: editorDescriptor, activate, editorState);
2766:
2767: } finally {
2768: workbench.largeUpdateEnd();
2769: }
2770: }
2771:
2772: /**
2773: * Do not call this method. Use <code>busyOpenEditor</code>.
2774: *
2775: * @see IWorkbenchPage#openEditor(IEditorInput, String, boolean)
2776: */
2777: private IEditorPart busyOpenEditorBatched(IEditorInput input,
2778: String editorID, boolean activate, int matchFlags,
2779: IMemento editorState) throws PartInitException {
2780:
2781: // If an editor already exists for the input, use it.
2782: IEditorPart editor = null;
2783: // Reuse an existing open editor, unless we are in "new editor tab management" mode
2784: editor = getEditorManager().findEditor(
2785: editorID,
2786: input,
2787: ((TabBehaviour) Tweaklets.get(TabBehaviour.KEY))
2788: .getReuseEditorMatchFlags(matchFlags));
2789: if (editor != null) {
2790: if (IEditorRegistry.SYSTEM_EXTERNAL_EDITOR_ID
2791: .equals(editorID)) {
2792: if (editor.isDirty()) {
2793: MessageDialog dialog = new MessageDialog(
2794: getWorkbenchWindow().getShell(),
2795: WorkbenchMessages.Save,
2796: null, // accept the default window icon
2797: NLS
2798: .bind(
2799: WorkbenchMessages.WorkbenchPage_editorAlreadyOpenedMsg,
2800: input.getName()),
2801: MessageDialog.QUESTION, new String[] {
2802: IDialogConstants.YES_LABEL,
2803: IDialogConstants.NO_LABEL,
2804: IDialogConstants.CANCEL_LABEL }, 0);
2805: int saveFile = dialog.open();
2806: if (saveFile == 0) {
2807: try {
2808: final IEditorPart editorToSave = editor;
2809: getWorkbenchWindow().run(false, false,
2810: new IRunnableWithProgress() {
2811: public void run(
2812: IProgressMonitor monitor)
2813: throws InvocationTargetException,
2814: InterruptedException {
2815: editorToSave
2816: .doSave(monitor);
2817: }
2818: });
2819: } catch (InvocationTargetException e) {
2820: throw (RuntimeException) e
2821: .getTargetException();
2822: } catch (InterruptedException e) {
2823: return null;
2824: }
2825: } else if (saveFile == 2) {
2826: return null;
2827: }
2828: }
2829: } else {
2830: // do the IShowEditorInput notification before showing the editor
2831: // to reduce flicker
2832: if (editor instanceof IShowEditorInput) {
2833: ((IShowEditorInput) editor).showEditorInput(input);
2834: }
2835: showEditor(activate, editor);
2836: return editor;
2837: }
2838: }
2839:
2840: // Otherwise, create a new one. This may cause the new editor to
2841: // become the visible (i.e top) editor.
2842: IEditorReference ref = null;
2843: ref = getEditorManager().openEditor(editorID, input, true,
2844: editorState);
2845: if (ref != null) {
2846: editor = ref.getEditor(true);
2847: }
2848:
2849: if (editor != null) {
2850: setEditorAreaVisible(true);
2851: if (activate) {
2852: if (editor instanceof MultiEditor) {
2853: activate(((MultiEditor) editor).getActiveEditor());
2854: } else {
2855: activate(editor);
2856: }
2857: } else {
2858: bringToTop(editor);
2859: }
2860: window.firePerspectiveChanged(this , getPerspective(), ref,
2861: CHANGE_EDITOR_OPEN);
2862: window.firePerspectiveChanged(this , getPerspective(),
2863: CHANGE_EDITOR_OPEN);
2864: }
2865:
2866: return editor;
2867: }
2868:
2869: /*
2870: * Added to fix Bug 178235 [EditorMgmt] DBCS 3.3 - Cannot open file with external program.
2871: * See openEditorFromDescriptor().
2872: */
2873: private IEditorPart busyOpenEditorFromDescriptorBatched(
2874: IEditorInput input, EditorDescriptor editorDescriptor,
2875: boolean activate, IMemento editorState)
2876: throws PartInitException {
2877:
2878: IEditorPart editor = null;
2879: // Create a new one. This may cause the new editor to
2880: // become the visible (i.e top) editor.
2881: IEditorReference ref = null;
2882: ref = getEditorManager().openEditorFromDescriptor(
2883: editorDescriptor, input, editorState);
2884: if (ref != null) {
2885: editor = ref.getEditor(true);
2886: }
2887:
2888: if (editor != null) {
2889: setEditorAreaVisible(true);
2890: if (activate) {
2891: if (editor instanceof MultiEditor) {
2892: activate(((MultiEditor) editor).getActiveEditor());
2893: } else {
2894: activate(editor);
2895: }
2896: } else {
2897: bringToTop(editor);
2898: }
2899: window.firePerspectiveChanged(this , getPerspective(), ref,
2900: CHANGE_EDITOR_OPEN);
2901: window.firePerspectiveChanged(this , getPerspective(),
2902: CHANGE_EDITOR_OPEN);
2903: }
2904:
2905: return editor;
2906: }
2907:
2908: public void openEmptyTab() {
2909: IEditorPart editor = null;
2910: EditorReference ref = null;
2911: ref = (EditorReference) getEditorManager().openEmptyTab();
2912: if (ref != null) {
2913: editor = ref
2914: .getEmptyEditor((EditorDescriptor) ((EditorRegistry) WorkbenchPlugin
2915: .getDefault().getEditorRegistry())
2916: .findEditor(EditorRegistry.EMPTY_EDITOR_ID));
2917: }
2918:
2919: if (editor != null) {
2920: setEditorAreaVisible(true);
2921: activate(editor);
2922: window.firePerspectiveChanged(this , getPerspective(), ref,
2923: CHANGE_EDITOR_OPEN);
2924: window.firePerspectiveChanged(this , getPerspective(),
2925: CHANGE_EDITOR_OPEN);
2926: }
2927: }
2928:
2929: private void showEditor(boolean activate, IEditorPart editor) {
2930: setEditorAreaVisible(true);
2931: if (activate) {
2932: zoomOutIfNecessary(editor);
2933: activate(editor);
2934: } else {
2935: bringToTop(editor);
2936: }
2937: }
2938:
2939: /**
2940: * See IWorkbenchPage.
2941: */
2942: public boolean isEditorPinned(IEditorPart editor) {
2943: WorkbenchPartReference ref = (WorkbenchPartReference) getReference(editor);
2944: return ref != null && ref.isPinned();
2945: }
2946:
2947: /**
2948: * Returns whether changes to a part will affect zoom. There are a few
2949: * conditions for this .. - we are zoomed. - the part is contained in the
2950: * main window. - the part is not the zoom part - the part is not a fast
2951: * view - the part and the zoom part are not in the same editor workbook
2952: */
2953: private boolean partChangeAffectsZoom(IWorkbenchPartReference ref) {
2954: PartPane pane = ((WorkbenchPartReference) ref).getPane();
2955: if (pane instanceof MultiEditorInnerPane) {
2956: pane = ((MultiEditorInnerPane) pane).getParentPane();
2957: }
2958: return getActivePerspective().getPresentation()
2959: .partChangeAffectsZoom(pane);
2960: }
2961:
2962: /**
2963: * Removes a fast view.
2964: */
2965: public void removeFastView(IViewReference ref) {
2966: Perspective persp = getActivePerspective();
2967: if (persp == null) {
2968: return;
2969: }
2970:
2971: // Do real work.
2972: persp.removeFastView(ref);
2973:
2974: // Notify listeners.
2975: window.firePerspectiveChanged(this , getPerspective(), ref,
2976: CHANGE_FAST_VIEW_REMOVE);
2977: window.firePerspectiveChanged(this , getPerspective(),
2978: CHANGE_FAST_VIEW_REMOVE);
2979: }
2980:
2981: /**
2982: * Removes an IPartListener from the part service.
2983: */
2984: public void removePartListener(IPartListener l) {
2985: partList.getPartService().removePartListener(l);
2986: }
2987:
2988: /**
2989: * Removes an IPartListener from the part service.
2990: */
2991: public void removePartListener(IPartListener2 l) {
2992: partList.getPartService().removePartListener(l);
2993: }
2994:
2995: /**
2996: * Implements IWorkbenchPage
2997: *
2998: * @see org.eclipse.ui.IWorkbenchPage#removePropertyChangeListener(IPropertyChangeListener)
2999: * @since 2.0
3000: * @deprecated individual views should store a working set if needed and
3001: * register a property change listener directly with the
3002: * working set manager to receive notification when the view
3003: * working set is removed.
3004: */
3005: public void removePropertyChangeListener(
3006: IPropertyChangeListener listener) {
3007: propertyChangeListeners.remove(listener);
3008: }
3009:
3010: /*
3011: * (non-Javadoc) Method declared on ISelectionListener.
3012: */
3013: public void removeSelectionListener(ISelectionListener listener) {
3014: selectionService.removeSelectionListener(listener);
3015: }
3016:
3017: /*
3018: * (non-Javadoc) Method declared on ISelectionListener.
3019: */
3020: public void removeSelectionListener(String partId,
3021: ISelectionListener listener) {
3022: selectionService.removeSelectionListener(partId, listener);
3023: }
3024:
3025: /*
3026: * (non-Javadoc) Method declared on ISelectionListener.
3027: */
3028: public void removePostSelectionListener(ISelectionListener listener) {
3029: selectionService.removePostSelectionListener(listener);
3030: }
3031:
3032: /*
3033: * (non-Javadoc) Method declared on ISelectionListener.
3034: */
3035: public void removePostSelectionListener(String partId,
3036: ISelectionListener listener) {
3037: selectionService.removePostSelectionListener(partId, listener);
3038: }
3039:
3040: /**
3041: * This method is called when a part is activated by clicking within it. In
3042: * response, the part, the pane, and all of its actions will be activated.
3043: *
3044: * In the current design this method is invoked by the part pane when the
3045: * pane, the part, or any children gain focus.
3046: */
3047: public void requestActivation(IWorkbenchPart part) {
3048: // Sanity check.
3049: if (!certifyPart(part)) {
3050: return;
3051: }
3052:
3053: if (part instanceof MultiEditor) {
3054: part = ((MultiEditor) part).getActiveEditor();
3055: }
3056:
3057: // Real work.
3058: setActivePart(part);
3059: }
3060:
3061: /**
3062: * Resets the layout for the perspective. The active part in the old layout
3063: * is activated in the new layout for consistent user context.
3064: */
3065: public void resetPerspective() {
3066: // Run op in busy cursor.
3067: // Use set redraw to eliminate the "flash" that can occur in the
3068: // coolbar as the perspective is reset.
3069: ICoolBarManager2 mgr = (ICoolBarManager2) window
3070: .getCoolBarManager2();
3071: try {
3072: mgr.getControl2().setRedraw(false);
3073: BusyIndicator.showWhile(null, new Runnable() {
3074: public void run() {
3075: busyResetPerspective();
3076: }
3077: });
3078: } finally {
3079: mgr.getControl2().setRedraw(true);
3080: }
3081: }
3082:
3083: /**
3084: * Restore this page from the memento and ensure that the active
3085: * perspective is equals the active descriptor otherwise create a new
3086: * perspective for that descriptor. If activeDescriptor is null active the
3087: * old perspective.
3088: */
3089: public IStatus restoreState(IMemento memento,
3090: final IPerspectiveDescriptor activeDescriptor) {
3091: StartupThreading.runWithoutExceptions(new StartupRunnable() {
3092:
3093: public void runWithException() throws Throwable {
3094: deferUpdates(true);
3095: }
3096: });
3097:
3098: try {
3099: // Restore working set
3100: String pageName = memento
3101: .getString(IWorkbenchConstants.TAG_LABEL);
3102:
3103: String label = null; // debugging only
3104: if (UIStats.isDebugging(UIStats.RESTORE_WORKBENCH)) {
3105: label = pageName == null ? "" : "::" + pageName; //$NON-NLS-1$ //$NON-NLS-2$
3106: }
3107:
3108: try {
3109: UIStats.start(UIStats.RESTORE_WORKBENCH,
3110: "WorkbenchPage" + label); //$NON-NLS-1$
3111: if (pageName == null) {
3112: pageName = ""; //$NON-NLS-1$
3113: }
3114: final MultiStatus result = new MultiStatus(
3115: PlatformUI.PLUGIN_ID,
3116: IStatus.OK,
3117: NLS
3118: .bind(
3119: WorkbenchMessages.WorkbenchPage_unableToRestorePerspective,
3120: pageName), null);
3121:
3122: String workingSetName = memento
3123: .getString(IWorkbenchConstants.TAG_WORKING_SET);
3124: if (workingSetName != null) {
3125: AbstractWorkingSetManager workingSetManager = (AbstractWorkingSetManager) getWorkbenchWindow()
3126: .getWorkbench().getWorkingSetManager();
3127: setWorkingSet(workingSetManager
3128: .getWorkingSet(workingSetName));
3129: }
3130:
3131: IMemento workingSetMem = memento
3132: .getChild(IWorkbenchConstants.TAG_WORKING_SETS);
3133: if (workingSetMem != null) {
3134: IMemento[] workingSetChildren = workingSetMem
3135: .getChildren(IWorkbenchConstants.TAG_WORKING_SET);
3136: List workingSetList = new ArrayList(
3137: workingSetChildren.length);
3138: for (int i = 0; i < workingSetChildren.length; i++) {
3139: IWorkingSet set = getWorkbenchWindow()
3140: .getWorkbench().getWorkingSetManager()
3141: .getWorkingSet(
3142: workingSetChildren[i].getID());
3143: if (set != null) {
3144: workingSetList.add(set);
3145: }
3146: }
3147:
3148: workingSets = (IWorkingSet[]) workingSetList
3149: .toArray(new IWorkingSet[workingSetList
3150: .size()]);
3151: }
3152:
3153: aggregateWorkingSetId = memento
3154: .getString(ATT_AGGREGATE_WORKING_SET_ID);
3155:
3156: IWorkingSet setWithId = window.getWorkbench()
3157: .getWorkingSetManager().getWorkingSet(
3158: aggregateWorkingSetId);
3159:
3160: // check to see if the set has already been made and assign it if it has
3161: if (setWithId instanceof AggregateWorkingSet) {
3162: aggregateWorkingSet = (AggregateWorkingSet) setWithId;
3163: }
3164: // Restore editor manager.
3165: IMemento childMem = memento
3166: .getChild(IWorkbenchConstants.TAG_EDITORS);
3167: result.merge(getEditorManager().restoreState(childMem));
3168:
3169: childMem = memento
3170: .getChild(IWorkbenchConstants.TAG_VIEWS);
3171: if (childMem != null) {
3172: result.merge(getViewFactory()
3173: .restoreState(childMem));
3174: }
3175:
3176: // Get persp block.
3177: childMem = memento
3178: .getChild(IWorkbenchConstants.TAG_PERSPECTIVES);
3179: String activePartID = childMem
3180: .getString(IWorkbenchConstants.TAG_ACTIVE_PART);
3181: String activePartSecondaryID = null;
3182: if (activePartID != null) {
3183: activePartSecondaryID = ViewFactory
3184: .extractSecondaryId(activePartID);
3185: if (activePartSecondaryID != null) {
3186: activePartID = ViewFactory
3187: .extractPrimaryId(activePartID);
3188: }
3189: }
3190: final String activePerspectiveID = childMem
3191: .getString(IWorkbenchConstants.TAG_ACTIVE_PERSPECTIVE);
3192:
3193: // Restore perspectives.
3194: final IMemento perspMems[] = childMem
3195: .getChildren(IWorkbenchConstants.TAG_PERSPECTIVE);
3196: final Perspective activePerspectiveArray[] = new Perspective[1];
3197:
3198: for (int i = 0; i < perspMems.length; i++) {
3199:
3200: final IMemento current = perspMems[i];
3201: StartupThreading
3202: .runWithoutExceptions(new StartupRunnable() {
3203:
3204: public void runWithException()
3205: throws Throwable {
3206: Perspective persp = new Perspective(
3207: null, WorkbenchPage.this );
3208: result.merge(persp
3209: .restoreState(current));
3210: final IPerspectiveDescriptor desc = persp
3211: .getDesc();
3212: if (desc.equals(activeDescriptor)) {
3213: activePerspectiveArray[0] = persp;
3214: } else if ((activePerspectiveArray[0] == null)
3215: && desc
3216: .getId()
3217: .equals(
3218: activePerspectiveID)) {
3219: activePerspectiveArray[0] = persp;
3220: }
3221: perspList.add(persp);
3222: window.firePerspectiveOpened(
3223: WorkbenchPage.this , desc);
3224: }
3225: });
3226: }
3227: Perspective activePerspective = activePerspectiveArray[0];
3228: boolean restoreActivePerspective = false;
3229: if (activeDescriptor == null) {
3230: restoreActivePerspective = true;
3231:
3232: } else if (activePerspective != null
3233: && activePerspective.getDesc().equals(
3234: activeDescriptor)) {
3235: restoreActivePerspective = true;
3236: } else {
3237: restoreActivePerspective = false;
3238: activePerspective = createPerspective(
3239: (PerspectiveDescriptor) activeDescriptor,
3240: true);
3241: if (activePerspective == null) {
3242: result
3243: .merge(new Status(
3244: IStatus.ERROR,
3245: PlatformUI.PLUGIN_ID,
3246: 0,
3247: NLS
3248: .bind(
3249: WorkbenchMessages.Workbench_showPerspectiveError,
3250: activeDescriptor
3251: .getId()),
3252: null));
3253: }
3254: }
3255:
3256: perspList.setActive(activePerspective);
3257:
3258: // Make sure we have a valid perspective to work with,
3259: // otherwise return.
3260: activePerspective = perspList.getActive();
3261: if (activePerspective == null) {
3262: activePerspective = perspList.getNextActive();
3263: perspList.setActive(activePerspective);
3264: }
3265: if (activePerspective != null
3266: && restoreActivePerspective) {
3267: result.merge(activePerspective.restoreState());
3268: }
3269:
3270: if (activePerspective != null) {
3271: final Perspective myPerspective = activePerspective;
3272: final String myActivePartId = activePartID, mySecondaryId = activePartSecondaryID;
3273: StartupThreading
3274: .runWithoutExceptions(new StartupRunnable() {
3275:
3276: public void runWithException()
3277: throws Throwable {
3278: window.firePerspectiveActivated(
3279: WorkbenchPage.this ,
3280: myPerspective.getDesc());
3281:
3282: // Restore active part.
3283: if (myActivePartId != null) {
3284: IViewReference ref = myPerspective
3285: .findView(
3286: myActivePartId,
3287: mySecondaryId);
3288:
3289: if (ref != null) {
3290: activationList
3291: .setActive(ref);
3292: }
3293: }
3294: }
3295: });
3296:
3297: }
3298:
3299: childMem = memento
3300: .getChild(IWorkbenchConstants.TAG_NAVIGATION_HISTORY);
3301: if (childMem != null) {
3302: navigationHistory.restoreState(childMem);
3303: } else if (getActiveEditor() != null) {
3304: navigationHistory.markEditor(getActiveEditor());
3305: }
3306:
3307: // restore sticky view state
3308: stickyViewMan.restore(memento);
3309:
3310: return result;
3311: } finally {
3312: String blame = activeDescriptor == null ? pageName
3313: : activeDescriptor.getId();
3314: UIStats.end(UIStats.RESTORE_WORKBENCH, blame,
3315: "WorkbenchPage" + label); //$NON-NLS-1$
3316: }
3317: } finally {
3318: StartupThreading
3319: .runWithoutExceptions(new StartupRunnable() {
3320:
3321: public void runWithException() throws Throwable {
3322: deferUpdates(false);
3323: }
3324: });
3325: }
3326: }
3327:
3328: /**
3329: * See IWorkbenchPage
3330: */
3331: public boolean saveAllEditors(boolean confirm) {
3332: return saveAllEditors(confirm, false);
3333: }
3334:
3335: /**
3336: * @param confirm
3337: * @param addNonPartSources true if saveables from non-part sources should be saved too
3338: * @return false if the user cancelled
3339: *
3340: */
3341: public boolean saveAllEditors(boolean confirm,
3342: boolean addNonPartSources) {
3343: return getEditorManager().saveAll(confirm, false,
3344: addNonPartSources);
3345: }
3346:
3347: /*
3348: * Saves the workbench part.
3349: */
3350: protected boolean savePart(ISaveablePart saveable,
3351: IWorkbenchPart part, boolean confirm) {
3352: // Do not certify part do allow editors inside a multipageeditor to
3353: // call this.
3354: return getEditorManager().savePart(saveable, part, confirm);
3355: }
3356:
3357: /**
3358: * Saves an editors in the workbench. If <code>confirm</code> is <code>true</code>
3359: * the user is prompted to confirm the command.
3360: *
3361: * @param confirm
3362: * if user confirmation should be sought
3363: * @return <code>true</code> if the command succeeded, or <code>false</code>
3364: * if the user cancels the command
3365: */
3366: public boolean saveEditor(IEditorPart editor, boolean confirm) {
3367: return savePart(editor, editor, confirm);
3368: }
3369:
3370: /**
3371: * Saves the current perspective.
3372: */
3373: public void savePerspective() {
3374: Perspective persp = getActivePerspective();
3375: if (persp == null) {
3376: return;
3377: }
3378:
3379: // Always unzoom.
3380: if (isZoomed()) {
3381: zoomOut();
3382: }
3383:
3384: persp.saveDesc();
3385: }
3386:
3387: /**
3388: * Saves the perspective.
3389: */
3390: public void savePerspectiveAs(IPerspectiveDescriptor newDesc) {
3391: Perspective persp = getActivePerspective();
3392: if (persp == null) {
3393: return;
3394: }
3395: IPerspectiveDescriptor oldDesc = persp.getDesc();
3396:
3397: // Always unzoom.
3398: if (isZoomed()) {
3399: zoomOut();
3400: }
3401:
3402: persp.saveDescAs(newDesc);
3403: window.firePerspectiveSavedAs(this , oldDesc, newDesc);
3404: }
3405:
3406: /**
3407: * Save the state of the page.
3408: */
3409: public IStatus saveState(IMemento memento) {
3410: // We must unzoom to get correct layout.
3411: if (isZoomed()) {
3412: zoomOut();
3413: }
3414:
3415: MultiStatus result = new MultiStatus(
3416: PlatformUI.PLUGIN_ID,
3417: IStatus.OK,
3418: NLS
3419: .bind(
3420: WorkbenchMessages.WorkbenchPage_unableToSavePerspective,
3421: getLabel()), null);
3422:
3423: // Save editor manager.
3424: IMemento childMem = memento
3425: .createChild(IWorkbenchConstants.TAG_EDITORS);
3426: result.merge(editorMgr.saveState(childMem));
3427:
3428: childMem = memento.createChild(IWorkbenchConstants.TAG_VIEWS);
3429: result.merge(getViewFactory().saveState(childMem));
3430:
3431: // Create persp block.
3432: childMem = memento
3433: .createChild(IWorkbenchConstants.TAG_PERSPECTIVES);
3434: if (getPerspective() != null) {
3435: childMem.putString(
3436: IWorkbenchConstants.TAG_ACTIVE_PERSPECTIVE,
3437: getPerspective().getId());
3438: }
3439: if (getActivePart() != null) {
3440: if (getActivePart() instanceof IViewPart) {
3441: IViewReference ref = (IViewReference) getReference(getActivePart());
3442: if (ref != null) {
3443: childMem.putString(
3444: IWorkbenchConstants.TAG_ACTIVE_PART,
3445: ViewFactory.getKey(ref));
3446: }
3447: } else {
3448: childMem.putString(IWorkbenchConstants.TAG_ACTIVE_PART,
3449: getActivePart().getSite().getId());
3450: }
3451: }
3452:
3453: // Save each perspective in opened order
3454: Iterator itr = perspList.iterator();
3455: while (itr.hasNext()) {
3456: Perspective persp = (Perspective) itr.next();
3457: IMemento gChildMem = childMem
3458: .createChild(IWorkbenchConstants.TAG_PERSPECTIVE);
3459: result.merge(persp.saveState(gChildMem));
3460: }
3461: // Save working set if set
3462: if (workingSet != null) {
3463: memento.putString(IWorkbenchConstants.TAG_WORKING_SET,
3464: workingSet.getName());
3465: }
3466:
3467: IMemento workingSetMem = memento
3468: .createChild(IWorkbenchConstants.TAG_WORKING_SETS);
3469: for (int i = 0; i < workingSets.length; i++) {
3470: workingSetMem.createChild(
3471: IWorkbenchConstants.TAG_WORKING_SET, workingSets[i]
3472: .getName());
3473: }
3474:
3475: if (aggregateWorkingSetId != null) {
3476: memento.putString(ATT_AGGREGATE_WORKING_SET_ID,
3477: aggregateWorkingSetId);
3478: }
3479:
3480: navigationHistory
3481: .saveState(memento
3482: .createChild(IWorkbenchConstants.TAG_NAVIGATION_HISTORY));
3483:
3484: // save the sticky activation state
3485: stickyViewMan.save(memento);
3486:
3487: return result;
3488: }
3489:
3490: private String getId(IWorkbenchPart part) {
3491: return getId(getReference(part));
3492: }
3493:
3494: private String getId(IWorkbenchPartReference ref) {
3495: if (ref == null) {
3496: return "null"; //$NON-NLS-1$
3497: }
3498: return ref.getId();
3499: }
3500:
3501: /**
3502: * Sets the active part.
3503: */
3504: private void setActivePart(IWorkbenchPart newPart) {
3505: // Optimize it.
3506: if (getActivePart() == newPart) {
3507: return;
3508: }
3509:
3510: if (partBeingActivated != null) {
3511: if (partBeingActivated.getPart(false) != newPart) {
3512: WorkbenchPlugin
3513: .log(new RuntimeException(
3514: NLS
3515: .bind(
3516: "WARNING: Prevented recursive attempt to activate part {0} while still in the middle of activating part {1}", //$NON-NLS-1$
3517: getId(newPart),
3518: getId(partBeingActivated))));
3519: }
3520: return;
3521: }
3522:
3523: //No need to change the history if the active editor is becoming the
3524: // active part
3525: String label = null; // debugging only
3526: if (UIStats.isDebugging(UIStats.ACTIVATE_PART)) {
3527: label = newPart != null ? newPart.getTitle() : "none"; //$NON-NLS-1$
3528: }
3529: try {
3530: IWorkbenchPartReference partref = getReference(newPart);
3531: IWorkbenchPartReference realPartRef = null;
3532: if (newPart != null) {
3533: IWorkbenchPartSite site = newPart.getSite();
3534: if (site instanceof PartSite) {
3535: realPartRef = ((PartSite) site).getPane()
3536: .getPartReference();
3537: }
3538: }
3539:
3540: partBeingActivated = realPartRef;
3541:
3542: UIStats.start(UIStats.ACTIVATE_PART, label);
3543: // Notify perspective. It may deactivate fast view.
3544: Perspective persp = getActivePerspective();
3545: if (persp != null) {
3546: persp.partActivated(newPart);
3547: }
3548:
3549: // Deactivate old part
3550: IWorkbenchPart oldPart = getActivePart();
3551: if (oldPart != null) {
3552: deactivatePart(oldPart);
3553: }
3554:
3555: // Set active part.
3556: if (newPart != null) {
3557: activationList.setActive(newPart);
3558: if (newPart instanceof IEditorPart) {
3559: makeActiveEditor((IEditorReference) realPartRef);
3560: }
3561: }
3562: activatePart(newPart);
3563:
3564: actionSwitcher.updateActivePart(newPart);
3565:
3566: partList.setActivePart(partref);
3567: } finally {
3568: partBeingActivated = null;
3569: Object blame = newPart == null ? (Object) this : newPart;
3570: UIStats.end(UIStats.ACTIVATE_PART, blame, label);
3571: }
3572: }
3573:
3574: /**
3575: * See IWorkbenchPage.
3576: */
3577: public void setEditorAreaVisible(boolean showEditorArea) {
3578: Perspective persp = getActivePerspective();
3579: if (persp == null) {
3580: return;
3581: }
3582: if (showEditorArea == persp.isEditorAreaVisible()) {
3583: return;
3584: }
3585: // If parts change always update zoom.
3586: if (isZoomed()) {
3587: zoomOut();
3588: }
3589: // Update editor area visibility.
3590: if (showEditorArea) {
3591: persp.showEditorArea();
3592: window.firePerspectiveChanged(this , getPerspective(),
3593: CHANGE_EDITOR_AREA_SHOW);
3594: } else {
3595: persp.hideEditorArea();
3596: updateActivePart();
3597: window.firePerspectiveChanged(this , getPerspective(),
3598: CHANGE_EDITOR_AREA_HIDE);
3599: }
3600: }
3601:
3602: /**
3603: * Sets the layout of the page. Assumes the new perspective is not null.
3604: * Keeps the active part if possible. Updates the window menubar and
3605: * toolbar if necessary.
3606: */
3607: private void setPerspective(Perspective newPersp) {
3608: // Don't do anything if already active layout
3609: Perspective oldPersp = getActivePerspective();
3610: if (oldPersp == newPersp) {
3611: return;
3612: }
3613:
3614: window.largeUpdateStart();
3615: try {
3616: if (oldPersp != null) {
3617: // fire the pre-deactivate
3618: window.firePerspectivePreDeactivate(this , oldPersp
3619: .getDesc());
3620: }
3621:
3622: if (newPersp != null) {
3623: IStatus status = newPersp.restoreState();
3624: if (status.getSeverity() != IStatus.OK) {
3625: String title = WorkbenchMessages.WorkbenchPage_problemRestoringTitle;
3626: String msg = WorkbenchMessages.WorkbenchPage_errorReadingState;
3627: ErrorDialog.openError(getWorkbenchWindow()
3628: .getShell(), title, msg, status);
3629: }
3630: }
3631:
3632: // Deactivate the old layout
3633: if (oldPersp != null) {
3634: oldPersp.onDeactivate();
3635:
3636: // Notify listeners of deactivation
3637: window.firePerspectiveDeactivated(this , oldPersp
3638: .getDesc());
3639: }
3640:
3641: // Activate the new layout
3642: perspList.setActive(newPersp);
3643: if (newPersp != null) {
3644: newPersp.onActivate();
3645:
3646: // Notify listeners of activation
3647: window.firePerspectiveActivated(this , newPersp
3648: .getDesc());
3649: }
3650:
3651: updateVisibility(oldPersp, newPersp);
3652:
3653: // Update the window
3654: window.updateActionSets();
3655:
3656: // Update sticky views
3657: stickyViewMan.update(oldPersp, newPersp);
3658:
3659: } finally {
3660: window.largeUpdateEnd();
3661: if (newPersp == null) {
3662: return;
3663: }
3664: IPerspectiveDescriptor desc = newPersp.getDesc();
3665: if (desc == null) {
3666: return;
3667: }
3668: if (dirtyPerspectives.remove(desc.getId())) {
3669: suggestReset();
3670: }
3671: }
3672: }
3673:
3674: void perspectiveActionSetChanged(Perspective perspective,
3675: IActionSetDescriptor descriptor, int changeType) {
3676: if (perspective == getActivePerspective()) {
3677: actionSets.change(descriptor, changeType);
3678: }
3679: }
3680:
3681: /*
3682: * Update visibility state of all views.
3683: */
3684: private void updateVisibility(Perspective oldPersp,
3685: Perspective newPersp) {
3686:
3687: // Flag all parts in the old perspective
3688: IWorkbenchPartReference[] oldRefs = new IWorkbenchPartReference[0];
3689: if (oldPersp != null) {
3690: oldRefs = oldPersp.getViewReferences();
3691: for (int i = 0; i < oldRefs.length; i++) {
3692: PartPane pane = ((WorkbenchPartReference) oldRefs[i])
3693: .getPane();
3694: pane.setInLayout(false);
3695: }
3696: }
3697:
3698: PerspectiveHelper pres = null;
3699: // Make parts in the new perspective visible
3700: if (newPersp != null) {
3701: pres = newPersp.getPresentation();
3702: IWorkbenchPartReference[] newRefs = newPersp
3703: .getViewReferences();
3704: for (int i = 0; i < newRefs.length; i++) {
3705: WorkbenchPartReference ref = (WorkbenchPartReference) newRefs[i];
3706: PartPane pane = ref.getPane();
3707: if (pres.isPartVisible(ref)) {
3708: activationList.bringToTop(ref);
3709: }
3710:
3711: pane.setInLayout(true);
3712: }
3713: }
3714:
3715: updateActivePart();
3716:
3717: // Hide any parts in the old perspective that are no longer visible
3718: for (int i = 0; i < oldRefs.length; i++) {
3719: WorkbenchPartReference ref = (WorkbenchPartReference) oldRefs[i];
3720:
3721: PartPane pane = ref.getPane();
3722: if (pres == null || !pres.isPartVisible(ref)) {
3723: pane.setVisible(false);
3724: }
3725: }
3726: }
3727:
3728: /**
3729: * Sets the perspective.
3730: *
3731: * @param desc
3732: * identifies the new perspective.
3733: */
3734: public void setPerspective(final IPerspectiveDescriptor desc) {
3735: if (Util.equals(getPerspective(), desc)) {
3736: return;
3737: }
3738: // Going from multiple to single rows can make the coolbar
3739: // and its adjacent views appear jumpy as perspectives are
3740: // switched. Turn off redraw to help with this.
3741: ICoolBarManager2 mgr = (ICoolBarManager2) window
3742: .getCoolBarManager2();
3743: try {
3744: mgr.getControl2().setRedraw(false);
3745: getClientComposite().setRedraw(false);
3746: // Run op in busy cursor.
3747: BusyIndicator.showWhile(null, new Runnable() {
3748: public void run() {
3749: busySetPerspective(desc);
3750: }
3751: });
3752: } finally {
3753: getClientComposite().setRedraw(true);
3754: mgr.getControl2().setRedraw(true);
3755: IWorkbenchPart part = getActivePart();
3756: if (part != null) {
3757: part.setFocus();
3758: }
3759: }
3760: }
3761:
3762: /**
3763: * Allow access to the part service for this page ... used internally to
3764: * propogate certain types of events to the page part listeners.
3765: * @return the part service for this page.
3766: */
3767: public PartService getPartService() {
3768: return (PartService) partList.getPartService();
3769: }
3770:
3771: /**
3772: * Restore the toolbar layout for the active perspective.
3773: */
3774: protected void resetToolBarLayout() {
3775: ICoolBarManager2 mgr = (ICoolBarManager2) window
3776: .getCoolBarManager2();
3777: mgr.resetItemOrder();
3778: }
3779:
3780: /**
3781: * Sets the active working set for the workbench page. Notifies property
3782: * change listener about the change.
3783: *
3784: * @param newWorkingSet
3785: * the active working set for the page. May be null.
3786: * @since 2.0
3787: * @deprecated individual views should store a working set if needed
3788: */
3789: public void setWorkingSet(IWorkingSet newWorkingSet) {
3790: IWorkingSet oldWorkingSet = workingSet;
3791:
3792: workingSet = newWorkingSet;
3793: if (oldWorkingSet != newWorkingSet) {
3794: firePropertyChange(CHANGE_WORKING_SET_REPLACE,
3795: oldWorkingSet, newWorkingSet);
3796: }
3797: if (newWorkingSet != null) {
3798: WorkbenchPlugin.getDefault().getWorkingSetManager()
3799: .addPropertyChangeListener(
3800: workingSetPropertyChangeListener);
3801: } else {
3802: WorkbenchPlugin.getDefault().getWorkingSetManager()
3803: .removePropertyChangeListener(
3804: workingSetPropertyChangeListener);
3805: }
3806: }
3807:
3808: /**
3809: * @see IWorkbenchPage
3810: */
3811: public void showActionSet(String actionSetID) {
3812: Perspective persp = getActivePerspective();
3813: if (persp != null) {
3814: ActionSetRegistry reg = WorkbenchPlugin.getDefault()
3815: .getActionSetRegistry();
3816:
3817: IActionSetDescriptor desc = reg.findActionSet(actionSetID);
3818: if (desc != null) {
3819: persp.addActionSet(desc);
3820: window.updateActionSets();
3821: window.firePerspectiveChanged(this , getPerspective(),
3822: CHANGE_ACTION_SET_SHOW);
3823: }
3824: }
3825: }
3826:
3827: /**
3828: * See IWorkbenchPage.
3829: */
3830: public IViewPart showView(String viewID) throws PartInitException {
3831: return showView(viewID, null, VIEW_ACTIVATE);
3832: }
3833:
3834: /*
3835: * (non-Javadoc)
3836: *
3837: * @see org.eclipse.ui.IWorkbenchPage#showView(java.lang.String,
3838: * java.lang.String, int)
3839: */
3840: public IViewPart showView(final String viewID,
3841: final String secondaryID, final int mode)
3842: throws PartInitException {
3843:
3844: if (secondaryID != null) {
3845: if (secondaryID.length() == 0
3846: || secondaryID.indexOf(ViewFactory.ID_SEP) != -1) {
3847: throw new IllegalArgumentException(
3848: WorkbenchMessages.WorkbenchPage_IllegalSecondaryId);
3849: }
3850: }
3851: if (!certifyMode(mode)) {
3852: throw new IllegalArgumentException(
3853: WorkbenchMessages.WorkbenchPage_IllegalViewMode);
3854: }
3855:
3856: // Run op in busy cursor.
3857: final Object[] result = new Object[1];
3858: BusyIndicator.showWhile(null, new Runnable() {
3859: public void run() {
3860: try {
3861: result[0] = busyShowView(viewID, secondaryID, mode);
3862: } catch (PartInitException e) {
3863: result[0] = e;
3864: }
3865: }
3866: });
3867: if (result[0] instanceof IViewPart) {
3868: return (IViewPart) result[0];
3869: } else if (result[0] instanceof PartInitException) {
3870: throw (PartInitException) result[0];
3871: } else {
3872: throw new PartInitException(
3873: WorkbenchMessages.WorkbenchPage_AbnormalWorkbenchCondition);
3874: }
3875: }
3876:
3877: /**
3878: * @param mode the mode to test
3879: * @return whether the mode is recognized
3880: * @since 3.0
3881: */
3882: private boolean certifyMode(int mode) {
3883: switch (mode) {
3884: case VIEW_ACTIVATE:
3885: case VIEW_VISIBLE:
3886: case VIEW_CREATE:
3887: return true;
3888: default:
3889: return false;
3890: }
3891: }
3892:
3893: /**
3894: * Hides the active fast view. Has no effect if there is no fast view active.
3895: */
3896: public void hideFastView() {
3897: Perspective persp = getActivePerspective();
3898: if (persp != null) {
3899: IViewReference ref = persp.getActiveFastView();
3900: if (ref != null) {
3901: toggleFastView(ref);
3902: }
3903: }
3904: }
3905:
3906: /**
3907: * Toggles the visibility of a fast view. If the view is active it is
3908: * deactivated. Otherwise, it is activated.
3909: */
3910: public void toggleFastView(IViewReference ref) {
3911: Perspective persp = getActivePerspective();
3912: if (persp != null) {
3913: persp.toggleFastView(ref);
3914: // if the fast view has been deactivated
3915: if (ref != persp.getActiveFastView()) {
3916: IWorkbenchPart previouslyActive = activationList
3917: .getPreviouslyActive();
3918: IEditorPart activeEditor = getActiveEditor();
3919: if (activeEditor != null
3920: && previouslyActive instanceof IEditorPart) {
3921: setActivePart(activeEditor);
3922: } else {
3923: setActivePart(previouslyActive);
3924: }
3925: }
3926: }
3927: }
3928:
3929: /**
3930: * Sets the state of the given part.
3931: *
3932: * @param ref part whose state should be modified (not null)
3933: * @param newState one of the IStackPresentationSite.STATE_* constants
3934: */
3935: public void setState(IWorkbenchPartReference ref, int newState) {
3936: Perspective persp = getActivePerspective();
3937: if (persp == null) {
3938: return;
3939: }
3940:
3941: PartPane pane = ((WorkbenchPartReference) ref).getPane();
3942:
3943: // If target part is detached fire the zoom event. Note this doesn't
3944: // actually cause any changes in size and is required to support
3945: // intro state changes. We may want to introduce the notion of a zoomed
3946: // (fullscreen) detached view at a later time.
3947: if (!pane.isDocked()) {
3948: pane
3949: .setZoomed(newState == IStackPresentationSite.STATE_MAXIMIZED);
3950: return;
3951: }
3952:
3953: if (ref instanceof IViewReference
3954: && persp.isFastView((IViewReference) ref)) {
3955: persp.setFastViewState(newState);
3956: return;
3957: }
3958:
3959: if (Perspective.useNewMinMax(persp)) {
3960: // set the container's state to the new one
3961: PartStack parent = ((PartStack) pane.getContainer());
3962: parent.setState(newState);
3963: return;
3964: }
3965:
3966: boolean wasZoomed = isZoomed();
3967: boolean isZoomed = newState == IStackPresentationSite.STATE_MAXIMIZED;
3968:
3969: // Update zoom status.
3970: if (wasZoomed && !isZoomed) {
3971: zoomOut();
3972: } else if (!wasZoomed && isZoomed) {
3973: persp.getPresentation().zoomIn(ref);
3974: activate(ref.getPart(true));
3975: }
3976:
3977: PartStack parent = ((PartStack) pane.getContainer());
3978:
3979: if (parent != null) {
3980: parent
3981: .setMinimized(newState == IStackPresentationSite.STATE_MINIMIZED);
3982: }
3983: }
3984:
3985: /* (non-Javadoc)
3986: * @see org.eclipse.ui.IWorkbenchPage#setPartState(org.eclipse.ui.IWorkbenchPartReference, int)
3987: */
3988: public void setPartState(IWorkbenchPartReference ref, int state) {
3989: setState(ref, state);
3990: }
3991:
3992: /**
3993: * Returns the maximized/minimized/restored state of the given part reference
3994: *
3995: * @param ref part to query (not null)
3996: * @return one of the IStackPresentationSite.STATE_* constants
3997: */
3998: int getState(IWorkbenchPartReference ref) {
3999: Perspective persp = getActivePerspective();
4000: if (persp == null) {
4001: return IStackPresentationSite.STATE_RESTORED;
4002: }
4003:
4004: PartPane pane = ((WorkbenchPartReference) ref).getPane();
4005:
4006: if (ref instanceof IViewReference
4007: && persp.isFastView((IViewReference) ref)) {
4008: return persp.getFastViewState();
4009: }
4010:
4011: PartStack parent = ((PartStack) pane.getContainer());
4012:
4013: if (parent != null) {
4014: return parent.getState();
4015: }
4016:
4017: return IStackPresentationSite.STATE_RESTORED;
4018: }
4019:
4020: /* (non-Javadoc)
4021: * @see org.eclipse.ui.IWorkbenchPage#getPartState(org.eclipse.ui.IWorkbenchPartReference)
4022: */
4023: public int getPartState(IWorkbenchPartReference ref) {
4024: return getState(ref);
4025: }
4026:
4027: /* (non-Javadoc)
4028: * @see org.eclipse.ui.IWorkbenchPage#toggleZoom(org.eclipse.ui.IWorkbenchPartReference)
4029: */
4030: public void toggleZoom(IWorkbenchPartReference ref) {
4031: int oldState = getState(ref);
4032: boolean shouldZoom = oldState != IStackPresentationSite.STATE_MAXIMIZED;
4033: int newState = shouldZoom ? IStackPresentationSite.STATE_MAXIMIZED
4034: : IStackPresentationSite.STATE_RESTORED;
4035:
4036: setState(ref, newState);
4037: }
4038:
4039: /**
4040: * updateActionBars method comment.
4041: */
4042: public void updateActionBars() {
4043: window.updateActionBars();
4044: }
4045:
4046: /**
4047: * Sets the tab list of this page's composite appropriately when a part is
4048: * activated.
4049: */
4050: private void updateTabList(IWorkbenchPart part) {
4051: PartSite site = (PartSite) part.getSite();
4052: PartPane pane = site.getPane();
4053: if (pane instanceof ViewPane) {
4054: ViewPane viewPane = (ViewPane) pane;
4055: Control[] tabList = viewPane.getTabList();
4056: if (!pane.isDocked()) {
4057: viewPane.getControl().getShell().setTabList(tabList);
4058: } else {
4059: getClientComposite().setTabList(tabList);
4060: }
4061: } else if (pane instanceof EditorPane) {
4062: EditorSashContainer ea = ((EditorPane) pane).getWorkbook()
4063: .getEditorArea();
4064: ea.updateTabList();
4065: getClientComposite().setTabList(
4066: new Control[] { ea.getParent() });
4067: }
4068: }
4069:
4070: /* (non-Javadoc)
4071: * @see org.eclipse.ui.IWorkbenchPage#zoomOut()
4072: */
4073: public void zoomOut() {
4074: Perspective persp = getActivePerspective();
4075: if (persp != null) {
4076: persp.getPresentation().zoomOut();
4077: }
4078: }
4079:
4080: /**
4081: * Zooms out a zoomed in part if it is necessary to do so for the user to
4082: * view the IWorkbenchPart that is the argument. Otherwise, does nothing.
4083: *
4084: * @param part
4085: * the part to be made viewable
4086: */
4087: private void zoomOutIfNecessary(IWorkbenchPart part) {
4088: if (isZoomed()
4089: && partChangeAffectsZoom(((PartSite) part.getSite())
4090: .getPartReference())) {
4091: zoomOut();
4092: }
4093: }
4094:
4095: /**
4096: *
4097: */
4098: public int getEditorReuseThreshold() {
4099: return ((TabBehaviour) Tweaklets.get(TabBehaviour.KEY))
4100: .getEditorReuseThreshold();
4101: }
4102:
4103: /**
4104: *
4105: */
4106: public void setEditorReuseThreshold(int openEditors) {
4107: }
4108:
4109: /*
4110: * Returns the editors in activation order (oldest first).
4111: */
4112: public IEditorReference[] getSortedEditors() {
4113: return activationList.getEditors();
4114: }
4115:
4116: /**
4117: * @see IWorkbenchPage#getOpenPerspectives()
4118: */
4119: public IPerspectiveDescriptor[] getOpenPerspectives() {
4120: Perspective opened[] = perspList.getOpenedPerspectives();
4121: IPerspectiveDescriptor[] result = new IPerspectiveDescriptor[opened.length];
4122: for (int i = 0; i < result.length; i++) {
4123: result[i] = opened[i].getDesc();
4124: }
4125: return result;
4126: }
4127:
4128: /**
4129: * Return all open Perspective objects.
4130: *
4131: * @return all open Perspective objects
4132: * @since 3.1
4133: */
4134: /*package*/Perspective[] getOpenInternalPerspectives() {
4135: return perspList.getOpenedPerspectives();
4136: }
4137:
4138: /**
4139: * Checks perspectives in the order they were activiated
4140: * for the specfied part. The first sorted perspective
4141: * that contains the specified part is returned.
4142: *
4143: * @param part specified part to search for
4144: * @return the first sorted perspespective containing the part
4145: * @since 3.1
4146: */
4147: /*package*/Perspective getFirstPerspectiveWithView(IViewPart part) {
4148: Perspective[] perspectives = perspList.getSortedPerspectives();
4149: for (int i = perspectives.length - 1; i >= 0; i--) {
4150: if (perspectives[i].containsView(part)) {
4151: return perspectives[i];
4152: }
4153: }
4154: // we should never get here
4155: return null;
4156: }
4157:
4158: /**
4159: * Returns the perspectives in activation order (oldest first).
4160: */
4161: public IPerspectiveDescriptor[] getSortedPerspectives() {
4162: Perspective sortedArray[] = perspList.getSortedPerspectives();
4163: IPerspectiveDescriptor[] result = new IPerspectiveDescriptor[sortedArray.length];
4164: for (int i = 0; i < result.length; i++) {
4165: result[i] = sortedArray[i].getDesc();
4166: }
4167: return result;
4168: }
4169:
4170: /*
4171: * Returns the parts in activation order (oldest first).
4172: */
4173: public IWorkbenchPartReference[] getSortedParts() {
4174: return activationList.getParts();
4175: }
4176:
4177: /**
4178: * Returns the reference to the given part, or <code>null</code> if it has no reference
4179: * (i.e. it is not a top-level part in this workbench page).
4180: *
4181: * @param part the part
4182: * @return the part's reference or <code>null</code> if the given part does not belong
4183: * to this workbench page
4184: */
4185: public IWorkbenchPartReference getReference(IWorkbenchPart part) {
4186: if (part == null) {
4187: return null;
4188: }
4189: IWorkbenchPartSite site = part.getSite();
4190: if (!(site instanceof PartSite)) {
4191: return null;
4192: }
4193: PartSite partSite = ((PartSite) site);
4194: PartPane pane = partSite.getPane();
4195: if (pane instanceof MultiEditorInnerPane) {
4196: MultiEditorInnerPane innerPane = (MultiEditorInnerPane) pane;
4197: return innerPane.getParentPane().getPartReference();
4198: }
4199: return partSite.getPartReference();
4200: }
4201:
4202: private class ActivationList {
4203: //List of parts in the activation order (oldest first)
4204: List parts = new ArrayList();
4205:
4206: /*
4207: * Add/Move the active part to end of the list;
4208: */
4209: void setActive(IWorkbenchPart part) {
4210: if (parts.size() <= 0) {
4211: return;
4212: }
4213: IWorkbenchPartReference ref = getReference(part);
4214: if (ref != null) {
4215: if (ref == parts.get(parts.size() - 1)) {
4216: return;
4217: }
4218: parts.remove(ref);
4219: parts.add(ref);
4220: }
4221: }
4222:
4223: /*
4224: * Ensures that the given part appears AFTER any other part in the same
4225: * container.
4226: */
4227: void bringToTop(IWorkbenchPartReference ref) {
4228: ILayoutContainer targetContainer = getContainer(ref);
4229:
4230: int newIndex = lastIndexOfContainer(targetContainer);
4231:
4232: //New index can be -1 if there is no last index
4233: if (newIndex >= 0 && ref == parts.get(newIndex))
4234: return;
4235:
4236: parts.remove(ref);
4237: if (newIndex >= 0)
4238: parts.add(newIndex, ref);
4239: else
4240: parts.add(ref);
4241: }
4242:
4243: /*
4244: * Returns the last (most recent) index of the given container in the activation list, or returns
4245: * -1 if the given container does not appear in the activation list.
4246: */
4247: int lastIndexOfContainer(ILayoutContainer container) {
4248: for (int i = parts.size() - 1; i >= 0; i--) {
4249: IWorkbenchPartReference ref = (IWorkbenchPartReference) parts
4250: .get(i);
4251:
4252: ILayoutContainer cnt = getContainer(ref);
4253: if (cnt == container) {
4254: return i;
4255: }
4256: }
4257:
4258: return -1;
4259: }
4260:
4261: /*
4262: * Add/Move the active part to end of the list;
4263: */
4264: void setActive(IWorkbenchPartReference ref) {
4265: setActive(ref.getPart(true));
4266: }
4267:
4268: /*
4269: * Add the active part to the beginning of the list.
4270: */
4271: void add(IWorkbenchPartReference ref) {
4272: if (parts.indexOf(ref) >= 0) {
4273: return;
4274: }
4275:
4276: IWorkbenchPart part = ref.getPart(false);
4277: if (part != null) {
4278: PartPane pane = ((PartSite) part.getSite()).getPane();
4279: if (pane instanceof MultiEditorInnerPane) {
4280: MultiEditorInnerPane innerPane = (MultiEditorInnerPane) pane;
4281: add(innerPane.getParentPane().getPartReference());
4282: return;
4283: }
4284: }
4285: parts.add(0, ref);
4286: }
4287:
4288: /*
4289: * Return the active part. Filter fast views.
4290: */
4291: IWorkbenchPart getActive() {
4292: if (parts.isEmpty()) {
4293: return null;
4294: }
4295: return getActive(parts.size() - 1);
4296: }
4297:
4298: /*
4299: * Return the previously active part. Filter fast views.
4300: */
4301: IWorkbenchPart getPreviouslyActive() {
4302: if (parts.size() < 2) {
4303: return null;
4304: }
4305: return getActive(parts.size() - 2);
4306: }
4307:
4308: private IWorkbenchPart getActive(int start) {
4309: IWorkbenchPartReference ref = getActiveReference(start,
4310: false);
4311:
4312: if (ref == null) {
4313: return null;
4314: }
4315:
4316: return ref.getPart(true);
4317: }
4318:
4319: public IWorkbenchPartReference getActiveReference(
4320: boolean editorsOnly) {
4321: return getActiveReference(parts.size() - 1, editorsOnly);
4322: }
4323:
4324: private IWorkbenchPartReference getActiveReference(int start,
4325: boolean editorsOnly) {
4326: // First look for parts that aren't obscured by the current zoom state
4327: IWorkbenchPartReference nonObscured = getActiveReference(
4328: start, editorsOnly, true);
4329:
4330: if (nonObscured != null) {
4331: return nonObscured;
4332: }
4333:
4334: // Now try all the rest of the parts
4335: return getActiveReference(start, editorsOnly, false);
4336: }
4337:
4338: /*
4339: * Find a part in the list starting from the end and filter
4340: * and views from other perspectives. Will filter fast views
4341: * unless 'includeActiveFastViews' is true;
4342: */
4343: private IWorkbenchPartReference getActiveReference(int start,
4344: boolean editorsOnly, boolean skipPartsObscuredByZoom) {
4345: IWorkbenchPartReference[] views = getViewReferences();
4346: for (int i = start; i >= 0; i--) {
4347: WorkbenchPartReference ref = (WorkbenchPartReference) parts
4348: .get(i);
4349:
4350: if (editorsOnly && !(ref instanceof IEditorReference)) {
4351: continue;
4352: }
4353:
4354: // Skip parts whose containers have disabled auto-focus
4355: PartPane pane = ref.getPane();
4356:
4357: if (pane != null) {
4358: if (!pane.allowsAutoFocus()) {
4359: continue;
4360: }
4361:
4362: if (skipPartsObscuredByZoom) {
4363: if (pane.isObscuredByZoom()) {
4364: continue;
4365: }
4366: }
4367: }
4368:
4369: // Skip fastviews (unless overridden)
4370: if (ref instanceof IViewReference) {
4371: if (includeActiveFastViews
4372: || !((IViewReference) ref).isFastView()) {
4373: for (int j = 0; j < views.length; j++) {
4374: if (views[j] == ref) {
4375: return ref;
4376: }
4377: }
4378: }
4379: } else {
4380: return ref;
4381: }
4382: }
4383: return null;
4384: }
4385:
4386: /*
4387: * Retuns the index of the part within the activation list. The higher
4388: * the index, the more recently it was used.
4389: */
4390: int indexOf(IWorkbenchPart part) {
4391: IWorkbenchPartReference ref = getReference(part);
4392: if (ref == null) {
4393: return -1;
4394: }
4395: return parts.indexOf(ref);
4396: }
4397:
4398: /*
4399: * Returns the index of the part reference within the activation list.
4400: * The higher the index, the more recent it was used.
4401: */
4402: int indexOf(IWorkbenchPartReference ref) {
4403: return parts.indexOf(ref);
4404: }
4405:
4406: /*
4407: * Remove a part from the list
4408: */
4409: boolean remove(IWorkbenchPartReference ref) {
4410: return parts.remove(ref);
4411: }
4412:
4413: /*
4414: * Returns the editors in activation order (oldest first).
4415: */
4416: private IEditorReference[] getEditors() {
4417: ArrayList editors = new ArrayList(parts.size());
4418: for (Iterator i = parts.iterator(); i.hasNext();) {
4419: IWorkbenchPartReference part = (IWorkbenchPartReference) i
4420: .next();
4421: if (part instanceof IEditorReference) {
4422: editors.add(part);
4423: }
4424: }
4425: return (IEditorReference[]) editors
4426: .toArray(new IEditorReference[editors.size()]);
4427: }
4428:
4429: /*
4430: * Return a list with all parts (editors and views).
4431: */
4432: private IWorkbenchPartReference[] getParts() {
4433: IWorkbenchPartReference[] views = getViewReferences();
4434: ArrayList resultList = new ArrayList(parts.size());
4435: for (Iterator iterator = parts.iterator(); iterator
4436: .hasNext();) {
4437: IWorkbenchPartReference ref = (IWorkbenchPartReference) iterator
4438: .next();
4439: if (ref instanceof IViewReference) {
4440: //Filter views from other perspectives
4441: for (int i = 0; i < views.length; i++) {
4442: if (views[i] == ref) {
4443: resultList.add(ref);
4444: break;
4445: }
4446: }
4447: } else {
4448: resultList.add(ref);
4449: }
4450: }
4451: IWorkbenchPartReference[] result = new IWorkbenchPartReference[resultList
4452: .size()];
4453: return (IWorkbenchPartReference[]) resultList
4454: .toArray(result);
4455: }
4456:
4457: /*
4458: * Returns the topmost editor on the stack, or null if none.
4459: */
4460: IEditorPart getTopEditor() {
4461: IEditorReference editor = (IEditorReference) getActiveReference(
4462: parts.size() - 1, true);
4463:
4464: if (editor == null) {
4465: return null;
4466: }
4467:
4468: return editor.getEditor(true);
4469: }
4470: }
4471:
4472: /**
4473: * Helper class to keep track of all opened perspective. Both the opened
4474: * and used order is kept.
4475: */
4476: private class PerspectiveList {
4477: /**
4478: * List of perspectives in the order they were opened;
4479: */
4480: private List openedList;
4481:
4482: /**
4483: * List of perspectives in the order they were used. Last element is
4484: * the most recently used, and first element is the least recently
4485: * used.
4486: */
4487: private List usedList;
4488:
4489: /**
4490: * The perspective explicitly set as being the active one
4491: */
4492: private Perspective active;
4493:
4494: /**
4495: * Creates an empty instance of the perspective list
4496: */
4497: public PerspectiveList() {
4498: openedList = new ArrayList();
4499: usedList = new ArrayList();
4500: }
4501:
4502: /**
4503: * Update the order of the perspectives in the opened list
4504: *
4505: * @param perspective
4506: * @param newLoc
4507: */
4508: public void reorder(IPerspectiveDescriptor perspective,
4509: int newLoc) {
4510: int oldLocation = 0;
4511: Perspective movedPerspective = null;
4512: for (Iterator iterator = openedList.iterator(); iterator
4513: .hasNext();) {
4514: Perspective openPerspective = (Perspective) iterator
4515: .next();
4516: if (openPerspective.getDesc().equals(perspective)) {
4517: oldLocation = openedList.indexOf(openPerspective);
4518: movedPerspective = openPerspective;
4519: }
4520: }
4521:
4522: if (oldLocation == newLoc) {
4523: return;
4524: }
4525:
4526: openedList.remove(oldLocation);
4527: openedList.add(newLoc, movedPerspective);
4528:
4529: }
4530:
4531: /**
4532: * Return all perspectives in the order they were activated.
4533: *
4534: * @return an array of perspectives sorted by activation order, least
4535: * recently activated perspective last.
4536: */
4537: public Perspective[] getSortedPerspectives() {
4538: Perspective[] result = new Perspective[usedList.size()];
4539: return (Perspective[]) usedList.toArray(result);
4540: }
4541:
4542: /**
4543: * Adds a perspective to the list. No check is done for a duplicate when
4544: * adding.
4545: * @param perspective the perspective to add
4546: * @return boolean <code>true</code> if the perspective was added
4547: */
4548: public boolean add(Perspective perspective) {
4549: openedList.add(perspective);
4550: usedList.add(0, perspective);
4551: //It will be moved to top only when activated.
4552: return true;
4553: }
4554:
4555: /**
4556: * Returns an iterator on the perspective list in the order they were
4557: * opened.
4558: */
4559: public Iterator iterator() {
4560: return openedList.iterator();
4561: }
4562:
4563: /**
4564: * Returns an array with all opened perspectives
4565: */
4566: public Perspective[] getOpenedPerspectives() {
4567: Perspective[] result = new Perspective[openedList.size()];
4568: return (Perspective[]) openedList.toArray(result);
4569: }
4570:
4571: /**
4572: * Removes a perspective from the list.
4573: */
4574: public boolean remove(Perspective perspective) {
4575: if (active == perspective) {
4576: updateActionSets(active, null);
4577: active = null;
4578: }
4579: usedList.remove(perspective);
4580: return openedList.remove(perspective);
4581: }
4582:
4583: /**
4584: * Swap the opened order of old perspective with the new perspective.
4585: */
4586: public void swap(Perspective oldPerspective,
4587: Perspective newPerspective) {
4588: int oldIndex = openedList.indexOf(oldPerspective);
4589: int newIndex = openedList.indexOf(newPerspective);
4590:
4591: if (oldIndex < 0 || newIndex < 0) {
4592: return;
4593: }
4594:
4595: openedList.set(oldIndex, newPerspective);
4596: openedList.set(newIndex, oldPerspective);
4597: }
4598:
4599: /**
4600: * Returns whether the list contains any perspectives
4601: */
4602: public boolean isEmpty() {
4603: return openedList.isEmpty();
4604: }
4605:
4606: /**
4607: * Returns the most recently used perspective in the list.
4608: */
4609: public Perspective getActive() {
4610: return active;
4611: }
4612:
4613: /**
4614: * Returns the next most recently used perspective in the list.
4615: */
4616: public Perspective getNextActive() {
4617: if (active == null) {
4618: if (usedList.isEmpty()) {
4619: return null;
4620: } else {
4621: return (Perspective) usedList
4622: .get(usedList.size() - 1);
4623: }
4624: } else {
4625: if (usedList.size() < 2) {
4626: return null;
4627: } else {
4628: return (Perspective) usedList
4629: .get(usedList.size() - 2);
4630: }
4631: }
4632: }
4633:
4634: /**
4635: * Returns the number of perspectives opened
4636: */
4637: public int size() {
4638: return openedList.size();
4639: }
4640:
4641: /**
4642: * Marks the specified perspective as the most recently used one in the
4643: * list.
4644: */
4645: public void setActive(Perspective perspective) {
4646: if (perspective == active) {
4647: return;
4648: }
4649:
4650: updateActionSets(active, perspective);
4651: active = perspective;
4652:
4653: if (perspective != null) {
4654: usedList.remove(perspective);
4655: usedList.add(perspective);
4656: }
4657: }
4658:
4659: private void updateActionSets(Perspective oldPersp,
4660: Perspective newPersp) {
4661: // Update action sets
4662:
4663: IContextService service = (IContextService) window
4664: .getService(IContextService.class);
4665: try {
4666: service.activateContext(ContextAuthority.DEFER_EVENTS);
4667: if (newPersp != null) {
4668: IActionSetDescriptor[] newAlwaysOn = newPersp
4669: .getAlwaysOnActionSets();
4670: for (int i = 0; i < newAlwaysOn.length; i++) {
4671: IActionSetDescriptor descriptor = newAlwaysOn[i];
4672:
4673: actionSets.showAction(descriptor);
4674: }
4675:
4676: IActionSetDescriptor[] newAlwaysOff = newPersp
4677: .getAlwaysOffActionSets();
4678: for (int i = 0; i < newAlwaysOff.length; i++) {
4679: IActionSetDescriptor descriptor = newAlwaysOff[i];
4680:
4681: actionSets.maskAction(descriptor);
4682: }
4683: }
4684:
4685: if (oldPersp != null) {
4686: IActionSetDescriptor[] newAlwaysOn = oldPersp
4687: .getAlwaysOnActionSets();
4688: for (int i = 0; i < newAlwaysOn.length; i++) {
4689: IActionSetDescriptor descriptor = newAlwaysOn[i];
4690:
4691: actionSets.hideAction(descriptor);
4692: }
4693:
4694: IActionSetDescriptor[] newAlwaysOff = oldPersp
4695: .getAlwaysOffActionSets();
4696: for (int i = 0; i < newAlwaysOff.length; i++) {
4697: IActionSetDescriptor descriptor = newAlwaysOff[i];
4698:
4699: actionSets.unmaskAction(descriptor);
4700: }
4701: }
4702: } finally {
4703: service.activateContext(ContextAuthority.SEND_EVENTS);
4704: }
4705: }
4706: }
4707:
4708: // for dynamic UI
4709: protected void addPerspective(Perspective persp) {
4710: perspList.add(persp);
4711: window.firePerspectiveOpened(this , persp.getDesc());
4712: }
4713:
4714: /**
4715: * Find the stack of view references stacked with this view part.
4716: *
4717: * @param part
4718: * the part
4719: * @return the stack of references
4720: * @since 3.0
4721: */
4722: private IViewReference[] getViewReferenceStack(IViewPart part) {
4723: // Sanity check.
4724: Perspective persp = getActivePerspective();
4725: if (persp == null || !certifyPart(part)) {
4726: return null;
4727: }
4728:
4729: ILayoutContainer container = ((PartSite) part.getSite())
4730: .getPane().getContainer();
4731: if (container instanceof ViewStack) {
4732: ViewStack folder = (ViewStack) container;
4733: final ArrayList list = new ArrayList(
4734: folder.getChildren().length);
4735: for (int i = 0; i < folder.getChildren().length; i++) {
4736: LayoutPart layoutPart = folder.getChildren()[i];
4737: if (layoutPart instanceof ViewPane) {
4738: IViewReference view = ((ViewPane) layoutPart)
4739: .getViewReference();
4740: if (view != null) {
4741: list.add(view);
4742: }
4743: }
4744: }
4745:
4746: // sort the list by activation order (most recently activated first)
4747: Collections.sort(list, new Comparator() {
4748: public int compare(Object o1, Object o2) {
4749: int pos1 = (-1)
4750: * activationList
4751: .indexOf((IWorkbenchPartReference) o1);
4752: int pos2 = (-1)
4753: * activationList
4754: .indexOf((IWorkbenchPartReference) o2);
4755: return pos1 - pos2;
4756: }
4757: });
4758:
4759: return (IViewReference[]) list
4760: .toArray(new IViewReference[list.size()]);
4761: }
4762:
4763: return new IViewReference[] { (IViewReference) getReference(part) };
4764: }
4765:
4766: /*
4767: * (non-Javadoc)
4768: *
4769: * @see org.eclipse.ui.IWorkbenchPage#getViewStack(org.eclipse.ui.IViewPart)
4770: */
4771: public IViewPart[] getViewStack(IViewPart part) {
4772: IViewReference[] refStack = getViewReferenceStack(part);
4773: if (refStack == null) {
4774: return null;
4775: }
4776:
4777: List result = new ArrayList();
4778:
4779: for (int i = 0; i < refStack.length; i++) {
4780: IViewPart next = refStack[i].getView(false);
4781: if (next != null) {
4782: result.add(next);
4783: }
4784: }
4785:
4786: return (IViewPart[]) result
4787: .toArray(new IViewPart[result.size()]);
4788: }
4789:
4790: /**
4791: * Allow for programmatically resizing a part.
4792: * <p>
4793: * <em>EXPERIMENTAL</em>
4794: * </p>
4795: * <p>
4796: * Known limitations:
4797: * <ul>
4798: * <li>currently applies only to views</li>
4799: * <li>has no effect when view is zoomed</li>
4800: * </ul>
4801: */
4802: public void resizeView(IViewPart part, int width, int height) {
4803: SashInfo sashInfo = new SashInfo();
4804: PartPane pane = ((PartSite) part.getSite()).getPane();
4805: ILayoutContainer container = pane.getContainer();
4806: LayoutTree tree = getPerspectivePresentation().getLayout().root
4807: .find(((ViewStack) container));
4808:
4809: // retrieve our layout sashes from the layout tree
4810: findSashParts(tree, pane.findSashes(), sashInfo);
4811:
4812: // first set the width
4813: float deltaWidth = width - pane.getBounds().width;
4814: if (sashInfo.right != null) {
4815: Rectangle rightBounds = sashInfo.rightNode.getBounds();
4816: // set the new ratio
4817: sashInfo.right.setRatio(((deltaWidth + sashInfo.right
4818: .getBounds().x) - rightBounds.x)
4819: / rightBounds.width);
4820: // complete the resize
4821: sashInfo.rightNode.setBounds(rightBounds);
4822: } else if (sashInfo.left != null) {
4823: Rectangle leftBounds = sashInfo.leftNode.getBounds();
4824: // set the ratio
4825: sashInfo.left
4826: .setRatio(((sashInfo.left.getBounds().x - deltaWidth) - leftBounds.x)
4827: / leftBounds.width);
4828: // complete the resize
4829: sashInfo.leftNode.setBounds(sashInfo.leftNode.getBounds());
4830: }
4831:
4832: // next set the height
4833: float deltaHeight = height - pane.getBounds().height;
4834: if (sashInfo.bottom != null) {
4835: Rectangle bottomBounds = sashInfo.bottomNode.getBounds();
4836: // set the new ratio
4837: sashInfo.bottom.setRatio(((deltaHeight + sashInfo.bottom
4838: .getBounds().y) - bottomBounds.y)
4839: / bottomBounds.height);
4840: // complete the resize
4841: sashInfo.bottomNode.setBounds(bottomBounds);
4842: } else if (sashInfo.top != null) {
4843: Rectangle topBounds = sashInfo.topNode.getBounds();
4844: // set the ratio
4845: sashInfo.top
4846: .setRatio(((sashInfo.top.getBounds().y - deltaHeight) - topBounds.y)
4847: / topBounds.height);
4848: // complete the resize
4849: sashInfo.topNode.setBounds(topBounds);
4850: }
4851:
4852: }
4853:
4854: // provides sash information for the given pane
4855: private class SashInfo {
4856: private LayoutPartSash right;
4857:
4858: private LayoutPartSash left;
4859:
4860: private LayoutPartSash top;
4861:
4862: private LayoutPartSash bottom;
4863:
4864: private LayoutTreeNode rightNode;
4865:
4866: private LayoutTreeNode leftNode;
4867:
4868: private LayoutTreeNode topNode;
4869:
4870: private LayoutTreeNode bottomNode;
4871: }
4872:
4873: private void findSashParts(LayoutTree tree, PartPane.Sashes sashes,
4874: SashInfo info) {
4875: LayoutTree parent = tree.getParent();
4876: if (parent == null) {
4877: return;
4878: }
4879:
4880: if (parent.part instanceof LayoutPartSash) {
4881: // get the layout part sash from this tree node
4882: LayoutPartSash sash = (LayoutPartSash) parent.part;
4883: // make sure it has a sash control
4884: Control control = sash.getControl();
4885: if (control != null) {
4886: // check for a vertical sash
4887: if (sash.isVertical()) {
4888: if (sashes.left == control) {
4889: info.left = sash;
4890: info.leftNode = parent.findSash(sash);
4891: } else if (sashes.right == control) {
4892: info.right = sash;
4893: info.rightNode = parent.findSash(sash);
4894: }
4895: }
4896: // check for a horizontal sash
4897: else {
4898: if (sashes.top == control) {
4899: info.top = sash;
4900: info.topNode = parent.findSash(sash);
4901: } else if (sashes.bottom == control) {
4902: info.bottom = sash;
4903: info.bottomNode = parent.findSash(sash);
4904: }
4905: }
4906: }
4907: }
4908: // recursive call to continue up the tree
4909: findSashParts(parent, sashes, info);
4910: }
4911:
4912: /**
4913: * Returns all parts that are owned by this page
4914: *
4915: * @return
4916: */
4917: IWorkbenchPartReference[] getAllParts() {
4918: IViewReference[] views = viewFactory.getViews();
4919: IEditorReference[] editors = getEditorReferences();
4920:
4921: IWorkbenchPartReference[] result = new IWorkbenchPartReference[views.length
4922: + editors.length];
4923: int resultIdx = 0;
4924:
4925: for (int i = 0; i < views.length; i++) {
4926: result[resultIdx++] = views[i];
4927: }
4928:
4929: for (int i = 0; i < editors.length; i++) {
4930: result[resultIdx++] = editors[i];
4931: }
4932:
4933: return result;
4934: }
4935:
4936: /**
4937: * Returns all open parts that are owned by this page (that is, all parts
4938: * for which a part opened event would have been sent -- these would be
4939: * activated parts whose controls have already been created.
4940: */
4941: IWorkbenchPartReference[] getOpenParts() {
4942: IWorkbenchPartReference[] refs = getAllParts();
4943: List result = new ArrayList();
4944:
4945: for (int i = 0; i < refs.length; i++) {
4946: IWorkbenchPartReference reference = refs[i];
4947:
4948: IWorkbenchPart part = reference.getPart(false);
4949: if (part != null) {
4950: result.add(reference);
4951: }
4952: }
4953:
4954: return (IWorkbenchPartReference[]) result
4955: .toArray(new IWorkbenchPartReference[result.size()]);
4956: }
4957:
4958: /**
4959: * Sanity-checks the objects in this page. Throws an Assertation exception
4960: * if an object's internal state is invalid. ONLY INTENDED FOR USE IN THE
4961: * UI TEST SUITES.
4962: */
4963: public void testInvariants() {
4964: Perspective persp = getActivePerspective();
4965:
4966: if (persp != null) {
4967:
4968: persp.testInvariants();
4969:
4970: // When we have widgets, ensure that there is no situation where the editor area is visible
4971: // and the perspective doesn't want an editor area.
4972: if (!SwtUtil.isDisposed(getClientComposite())
4973: && editorPresentation.getLayoutPart().isVisible()) {
4974: Assert.isTrue(persp.isEditorAreaVisible());
4975: }
4976: }
4977:
4978: }
4979:
4980: /* (non-Javadoc)
4981: * @see org.eclipse.ui.IWorkbenchPage#getExtensionTracker()
4982: */
4983: public IExtensionTracker getExtensionTracker() {
4984: if (tracker == null) {
4985: tracker = new UIExtensionTracker(getWorkbenchWindow()
4986: .getWorkbench().getDisplay());
4987: }
4988: return tracker;
4989: }
4990:
4991: /*
4992: * (non-Javadoc)
4993: *
4994: * @see org.eclipse.ui.IWorkbenchPage#getNewWizardShortcuts()
4995: */
4996: public String[] getNewWizardShortcuts() {
4997: Perspective persp = getActivePerspective();
4998: if (persp == null) {
4999: return new String[0];
5000: }
5001: return persp.getNewWizardShortcuts();
5002: }
5003:
5004: /*
5005: * (non-Javadoc)
5006: *
5007: * @see org.eclipse.ui.IWorkbenchPage#getPerspectiveShortcuts()
5008: */
5009: public String[] getPerspectiveShortcuts() {
5010: Perspective persp = getActivePerspective();
5011: if (persp == null) {
5012: return new String[0];
5013: }
5014: return persp.getPerspectiveShortcuts();
5015: }
5016:
5017: /*
5018: * (non-Javadoc)
5019: *
5020: * @see org.eclipse.ui.IWorkbenchPage#getShowViewShortcuts()
5021: */
5022: public String[] getShowViewShortcuts() {
5023: Perspective persp = getActivePerspective();
5024: if (persp == null) {
5025: return new String[0];
5026: }
5027: return persp.getShowViewShortcuts();
5028: }
5029:
5030: /**
5031: * @since 3.1
5032: */
5033: private void suggestReset() {
5034: final IWorkbench workbench = getWorkbenchWindow()
5035: .getWorkbench();
5036: workbench.getDisplay().asyncExec(new Runnable() {
5037: public void run() {
5038: Shell parentShell = null;
5039:
5040: IWorkbenchWindow window = workbench
5041: .getActiveWorkbenchWindow();
5042: if (window == null) {
5043: if (workbench.getWorkbenchWindowCount() == 0) {
5044: return;
5045: }
5046: window = workbench.getWorkbenchWindows()[0];
5047: }
5048:
5049: parentShell = window.getShell();
5050:
5051: if (MessageDialog
5052: .openQuestion(
5053: parentShell,
5054: WorkbenchMessages.Dynamic_resetPerspectiveTitle,
5055: WorkbenchMessages.Dynamic_resetPerspectiveMessage)) {
5056: IWorkbenchPage page = window.getActivePage();
5057: if (page == null) {
5058: return;
5059: }
5060: page.resetPerspective();
5061: }
5062: }
5063: });
5064:
5065: }
5066:
5067: public boolean isPartVisible(IWorkbenchPartReference reference) {
5068: IWorkbenchPart part = reference.getPart(false);
5069: // Can't be visible if it isn't created yet
5070: if (part == null) {
5071: return false;
5072: }
5073:
5074: return isPartVisible(part);
5075: }
5076:
5077: public IWorkingSet[] getWorkingSets() {
5078: return workingSets;
5079: }
5080:
5081: public void setWorkingSets(IWorkingSet[] newWorkingSets) {
5082: if (newWorkingSets == null) {
5083: newWorkingSets = new IWorkingSet[0];
5084: }
5085:
5086: IWorkingSet[] oldWorkingSets = workingSets;
5087:
5088: // filter out any duplicates if necessary
5089: if (newWorkingSets.length > 1) {
5090: Set setOfSets = new HashSet();
5091: for (int i = 0; i < newWorkingSets.length; i++) {
5092: if (newWorkingSets[i] == null) {
5093: throw new IllegalArgumentException();
5094: }
5095: setOfSets.add(newWorkingSets[i]);
5096: }
5097: newWorkingSets = (IWorkingSet[]) setOfSets
5098: .toArray(new IWorkingSet[setOfSets.size()]);
5099: }
5100:
5101: workingSets = newWorkingSets;
5102: if (!Arrays.equals(oldWorkingSets, newWorkingSets)) {
5103: firePropertyChange(CHANGE_WORKING_SETS_REPLACE,
5104: oldWorkingSets, newWorkingSets);
5105: if (aggregateWorkingSet != null) {
5106: aggregateWorkingSet.setComponents(workingSets);
5107: }
5108: }
5109: if (newWorkingSets != null) {
5110: WorkbenchPlugin.getDefault().getWorkingSetManager()
5111: .addPropertyChangeListener(
5112: workingSetPropertyChangeListener);
5113: } else {
5114: WorkbenchPlugin.getDefault().getWorkingSetManager()
5115: .removePropertyChangeListener(
5116: workingSetPropertyChangeListener);
5117: }
5118: }
5119:
5120: public IWorkingSet getAggregateWorkingSet() {
5121: if (aggregateWorkingSet == null) {
5122: IWorkingSetManager workingSetManager = PlatformUI
5123: .getWorkbench().getWorkingSetManager();
5124: aggregateWorkingSet = (AggregateWorkingSet) workingSetManager
5125: .getWorkingSet(getAggregateWorkingSetId());
5126: if (aggregateWorkingSet == null) {
5127: aggregateWorkingSet = (AggregateWorkingSet) workingSetManager
5128: .createAggregateWorkingSet(
5129: getAggregateWorkingSetId(),
5130: WorkbenchMessages.WorkbenchPage_workingSet_default_label,
5131: getWorkingSets());
5132: workingSetManager.addWorkingSet(aggregateWorkingSet);
5133: }
5134: }
5135: return aggregateWorkingSet;
5136: }
5137:
5138: private String getAggregateWorkingSetId() {
5139: if (aggregateWorkingSetId == null) {
5140: aggregateWorkingSetId = "Aggregate for window " + System.currentTimeMillis(); //$NON-NLS-1$
5141: }
5142: return aggregateWorkingSetId;
5143: }
5144: }
|