blob: ccb4abf554b7d0c9add0868ce1f40367d7e17120 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.ui.internal;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.dynamichelpers.ExtensionTracker;
import org.eclipse.core.runtime.dynamichelpers.IExtensionChangeHandler;
import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.internal.provisional.action.ICoolBarManager2;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.util.SafeRunnable;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.window.Window;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IEditorDescriptor;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IEditorRegistry;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.INavigationHistory;
import org.eclipse.ui.IPartListener;
import org.eclipse.ui.IPartListener2;
import org.eclipse.ui.IPerspectiveDescriptor;
import org.eclipse.ui.IPerspectiveRegistry;
import org.eclipse.ui.IReusableEditor;
import org.eclipse.ui.ISaveablePart;
import org.eclipse.ui.ISaveablesLifecycleListener;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.IShowEditorInput;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IViewReference;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.ui.IWorkbenchPreferenceConstants;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.IWorkingSet;
import org.eclipse.ui.IWorkingSetManager;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.SubActionBars;
import org.eclipse.ui.WorkbenchException;
import org.eclipse.ui.contexts.IContextService;
import org.eclipse.ui.internal.StartupThreading.StartupRunnable;
import org.eclipse.ui.internal.contexts.ContextAuthority;
import org.eclipse.ui.internal.dialogs.CustomizePerspectiveDialog;
import org.eclipse.ui.internal.dnd.SwtUtil;
import org.eclipse.ui.internal.intro.IIntroConstants;
import org.eclipse.ui.internal.misc.UIListenerLogging;
import org.eclipse.ui.internal.misc.UIStats;
import org.eclipse.ui.internal.registry.ActionSetRegistry;
import org.eclipse.ui.internal.registry.EditorDescriptor;
import org.eclipse.ui.internal.registry.EditorRegistry;
import org.eclipse.ui.internal.registry.IActionSetDescriptor;
import org.eclipse.ui.internal.registry.IWorkbenchRegistryConstants;
import org.eclipse.ui.internal.registry.PerspectiveDescriptor;
import org.eclipse.ui.internal.registry.UIExtensionTracker;
import org.eclipse.ui.internal.tweaklets.GrabFocus;
import org.eclipse.ui.internal.tweaklets.TabBehaviour;
import org.eclipse.ui.internal.tweaklets.Tweaklets;
import org.eclipse.ui.internal.util.PrefUtil;
import org.eclipse.ui.internal.util.Util;
import org.eclipse.ui.model.IWorkbenchAdapter;
import org.eclipse.ui.part.MultiEditor;
import org.eclipse.ui.presentations.IStackPresentationSite;
/**
* A collection of views and editors in a workbench.
*/
public class WorkbenchPage extends CompatibleWorkbenchPage implements
IWorkbenchPage {
private static final String ATT_AGGREGATE_WORKING_SET_ID = "aggregateWorkingSetId"; //$NON-NLS-1$
private WorkbenchWindow window;
private IAdaptable input;
private IWorkingSet workingSet;
private AggregateWorkingSet aggregateWorkingSet;
private Composite composite;
//Could be delete. This information is in the active part list;
private ActivationList activationList = new ActivationList();
private EditorManager editorMgr;
private EditorAreaHelper editorPresentation;
private ListenerList propertyChangeListeners = new ListenerList();
private PageSelectionService selectionService = new PageSelectionService(
this);
private WorkbenchPagePartList partList = new WorkbenchPagePartList(selectionService);
private IActionBars actionBars;
private ActionSetManager actionSets;
private ViewFactory viewFactory;
private PerspectiveList perspList = new PerspectiveList();
private PerspectiveDescriptor deferredActivePersp;
private NavigationHistory navigationHistory = new NavigationHistory(this);
private IStickyViewManager stickyViewMan = StickyViewManager.getInstance(this);
/**
* If we're in the process of activating a part, this points to the new part.
* Otherwise, this is null.
*/
private IWorkbenchPartReference partBeingActivated = null;
/**
* Contains a list of perspectives that may be dirty due to plugin
* installation and removal.
*/
private Set dirtyPerspectives = new HashSet();
private IPropertyChangeListener workingSetPropertyChangeListener = new IPropertyChangeListener() {
/*
* Remove the working set from the page if the working set is deleted.
*/
public void propertyChange(PropertyChangeEvent event) {
String property = event.getProperty();
if (IWorkingSetManager.CHANGE_WORKING_SET_REMOVE.equals(property)) {
if(event.getOldValue().equals(workingSet)) {
setWorkingSet(null);
}
// room for optimization here
List newList = new ArrayList(Arrays.asList(workingSets));
if (newList.remove(event.getOldValue())) {
setWorkingSets((IWorkingSet []) newList
.toArray(new IWorkingSet [newList.size()]));
}
}
}
};
private ActionSwitcher actionSwitcher = new ActionSwitcher();
private IExtensionTracker tracker;
// Deferral count... delays disposing parts and sending certain events if nonzero
private int deferCount = 0;
// Parts waiting to be disposed
private List pendingDisposals = new ArrayList();
private IExtensionChangeHandler perspectiveChangeHandler = new IExtensionChangeHandler() {
/* (non-Javadoc)
* @see org.eclipse.core.runtime.dynamicHelpers.IExtensionChangeHandler#removeExtension(org.eclipse.core.runtime.IExtension, java.lang.Object[])
*/
public void removeExtension(IExtension extension, Object[] objects) {
boolean suggestReset = false;
for (int i = 0; i < objects.length; i++) {
if (objects[i] instanceof DirtyPerspectiveMarker) {
String id = ((DirtyPerspectiveMarker)objects[i]).perspectiveId;
if (!dirtyPerspectives.remove(id)) {
dirtyPerspectives.add(id); // otherwise we will be dirty
}
PerspectiveDescriptor persp = (PerspectiveDescriptor) getPerspective();
if (persp == null || persp.hasCustomDefinition()) {
continue;
}
if (persp.getId().equals(id)) {
suggestReset = true;
}
}
}
if (suggestReset) {
suggestReset();
}
}
/* (non-Javadoc)
* @see org.eclipse.core.runtime.dynamicHelpers.IExtensionChangeHandler#addExtension(org.eclipse.core.runtime.dynamicHelpers.IExtensionTracker, org.eclipse.core.runtime.IExtension)
*/
public void addExtension(IExtensionTracker tracker, IExtension extension) {
if (WorkbenchPage.this != getWorkbenchWindow().getActivePage()) {
return;
}
// Get the current perspective.
PerspectiveDescriptor persp = (PerspectiveDescriptor) getPerspective();
if (persp == null) {
return;
}
String currentId = persp.getId();
IConfigurationElement[] elements = extension.getConfigurationElements();
boolean suggestReset = false;
for (int i = 0; i < elements.length; i++) {
// If any of these refer to the current perspective, output
// a message saying this perspective will need to be reset
// in order to see the changes. For any other case, the
// perspective extension registry will be rebuilt anyway so
// just ignore it.
String id = elements[i].getAttribute(IWorkbenchRegistryConstants.ATT_TARGET_ID);
if (id == null) {
continue;
}
if (id.equals(currentId) && !persp.hasCustomDefinition()) {
suggestReset = true;
}
else {
dirtyPerspectives.add(id);
}
DirtyPerspectiveMarker marker = new DirtyPerspectiveMarker(id);
tracker.registerObject(extension, marker, IExtensionTracker.REF_STRONG);
}
if (suggestReset) {
suggestReset();
}
}
};
private IWorkingSet[] workingSets = new IWorkingSet[0];
private String aggregateWorkingSetId;
private IExtensionPoint getPerspectiveExtensionPoint() {
return Platform.getExtensionRegistry().getExtensionPoint(PlatformUI.PLUGIN_ID, IWorkbenchRegistryConstants.PL_PERSPECTIVE_EXTENSIONS);
}
/**
* Manages editor contributions and action set part associations.
*/
private class ActionSwitcher {
private IWorkbenchPart activePart;
private IEditorPart topEditor;
private ArrayList oldActionSets = new ArrayList();
/**
* Updates the contributions given the new part as the active part.
*
* @param newPart
* the new active part, may be <code>null</code>
*/
public void updateActivePart(IWorkbenchPart newPart) {
if (activePart == newPart) {
return;
}
boolean isNewPartAnEditor = newPart instanceof IEditorPart;
if (isNewPartAnEditor) {
String oldId = null;
if (topEditor != null) {
oldId = topEditor.getSite().getId();
}
String newId = newPart.getSite().getId();
// if the active part is an editor and the new editor
// is the same kind of editor, then we don't have to do
// anything
if (activePart == topEditor && newId.equals(oldId)) {
activePart = newPart;
topEditor = (IEditorPart) newPart;
return;
}
// remove the contributions of the old editor
// if it is a different kind of editor
if (oldId != null && !oldId.equals(newId)) {
deactivateContributions(topEditor, true);
}
// if a view was the active part, disable its contributions
if (activePart != null && activePart != topEditor) {
deactivateContributions(activePart, true);
}
// show (and enable) the contributions of the new editor
// if it is a different kind of editor or if the
// old active part was a view
if (!newId.equals(oldId) || activePart != topEditor) {
activateContributions(newPart, true);
}
} else if (newPart == null) {
if (activePart != null) {
// remove all contributions
deactivateContributions(activePart, true);
}
} else {
// new part is a view
// if old active part is a view, remove all contributions,
// but if old part is an editor only disable
if (activePart != null) {
deactivateContributions(activePart,
activePart instanceof IViewPart);
}
activateContributions(newPart, true);
}
ArrayList newActionSets = null;
if (isNewPartAnEditor
|| (activePart == topEditor && newPart == null)) {
newActionSets = calculateActionSets(newPart, null);
} else {
newActionSets = calculateActionSets(newPart, topEditor);
}
if (!updateActionSets(newActionSets)) {
updateActionBars();
}
if (isNewPartAnEditor) {
topEditor = (IEditorPart) newPart;
} else if (activePart == topEditor && newPart == null) {
// since we removed all the contributions, we clear the top
// editor
topEditor = null;
}
activePart = newPart;
}
/**
* Updates the contributions given the new part as the topEditor.
*
* @param newEditor
* the new top editor, may be <code>null</code>
*/
public void updateTopEditor(IEditorPart newEditor) {
if (topEditor == newEditor) {
return;
}
if (activePart == topEditor) {
updateActivePart(newEditor);
return;
}
String oldId = null;
if (topEditor != null) {
oldId = topEditor.getSite().getId();
}
String newId = null;
if (newEditor != null) {
newId = newEditor.getSite().getId();
}
if (oldId == null ? newId == null : oldId.equals(newId)) {
// we don't have to change anything
topEditor = newEditor;
return;
}
// Remove the contributions of the old editor
if (topEditor != null) {
deactivateContributions(topEditor, true);
}
// Show (disabled) the contributions of the new editor
if (newEditor != null) {
activateContributions(newEditor, false);
}
ArrayList newActionSets = calculateActionSets(activePart, newEditor);
if (!updateActionSets(newActionSets)) {
updateActionBars();
}
topEditor = newEditor;
}
/**
* Activates the contributions of the given part. If <code>enable</code>
* is <code>true</code> the contributions are visible and enabled,
* otherwise they are disabled.
*
* @param part
* the part whose contributions are to be activated
* @param enable
* <code>true</code> the contributions are to be enabled,
* not just visible.
*/
private void activateContributions(IWorkbenchPart part, boolean enable) {
PartSite site = (PartSite) part.getSite();
site.activateActionBars(enable);
}
/**
* Deactivates the contributions of the given part. If <code>remove</code>
* is <code>true</code> the contributions are removed, otherwise they
* are disabled.
*
* @param part
* the part whose contributions are to be deactivated
* @param remove
* <code>true</code> the contributions are to be removed,
* not just disabled.
*/
private void deactivateContributions(IWorkbenchPart part, boolean remove) {
PartSite site = (PartSite) part.getSite();
site.deactivateActionBars(remove);
}
/**
* Calculates the action sets to show for the given part and editor
*
* @param part
* the active part, may be <code>null</code>
* @param editor
* the current editor, may be <code>null</code>, may be
* the active part
* @return the new action sets
*/
private ArrayList calculateActionSets(IWorkbenchPart part,
IEditorPart editor) {
ArrayList newActionSets = new ArrayList();
if (part != null) {
IActionSetDescriptor[] partActionSets = WorkbenchPlugin
.getDefault().getActionSetRegistry().getActionSetsFor(
part.getSite().getId());
for (int i = 0; i < partActionSets.length; i++) {
newActionSets.add(partActionSets[i]);
}
}
if (editor != null && editor != part) {
IActionSetDescriptor[] editorActionSets = WorkbenchPlugin
.getDefault().getActionSetRegistry().getActionSetsFor(
editor.getSite().getId());
for (int i = 0; i < editorActionSets.length; i++) {
newActionSets.add(editorActionSets[i]);
}
}
return newActionSets;
}
/**
* Updates the actions we are showing for the active part and current
* editor.
*
* @param newActionSets
* the action sets to show
* @return <code>true</code> if the action sets changed
*/
private boolean updateActionSets(ArrayList newActionSets) {
if (oldActionSets.equals(newActionSets)) {
return false;
}
IContextService service = (IContextService) window
.getService(IContextService.class);
try {
service.activateContext(ContextAuthority.DEFER_EVENTS);
// show the new
for (int i = 0; i < newActionSets.size(); i++) {
actionSets.showAction((IActionSetDescriptor) newActionSets
.get(i));
}
// hide the old
for (int i = 0; i < oldActionSets.size(); i++) {
actionSets.hideAction((IActionSetDescriptor) oldActionSets
.get(i));
}
oldActionSets = newActionSets;
} finally {
service.activateContext(ContextAuthority.SEND_EVENTS);
}
Perspective persp = getActivePerspective();
if (persp == null) {
return false;
}
window.updateActionSets(); // this calls updateActionBars
window.firePerspectiveChanged(WorkbenchPage.this, getPerspective(),
CHANGE_ACTION_SET_SHOW);
return true;
}
}
/**
* Constructs a new page with a given perspective and input.
*
* @param w
* the parent window
* @param layoutID
* must not be <code>null</code>
* @param input
* the page input
* @throws WorkbenchException
* on null layout id
*/
public WorkbenchPage(WorkbenchWindow w, String layoutID, IAdaptable input)
throws WorkbenchException {
super();
if (layoutID == null) {
throw new WorkbenchException(WorkbenchMessages.WorkbenchPage_UndefinedPerspective);
}
init(w, layoutID, input, true);
}
/**
* Constructs a page. <code>restoreState(IMemento)</code> should be
* called to restore this page from data stored in a persistance file.
*
* @param w
* the parent window
* @param input
* the page input
* @throws WorkbenchException
*/
public WorkbenchPage(WorkbenchWindow w, IAdaptable input)
throws WorkbenchException {
super();
init(w, null, input, false);
}
/**
* Activates a part. The part will be brought to the front and given focus.
*
* @param part
* the part to activate
*/
public void activate(IWorkbenchPart part) {
// Sanity check.
if (!certifyPart(part)) {
return;
}
if (window.isClosing()) {
return;
}
if (composite!=null && composite.isVisible()
&& !((GrabFocus)Tweaklets.get(GrabFocus.KEY)).grabFocusAllowed(part)) {
return;
}
// If zoomed, unzoom.
zoomOutIfNecessary(part);
if (part instanceof MultiEditor) {
part = ((MultiEditor) part).getActiveEditor();
}
// Activate part.
//if (window.getActivePage() == this) {
IWorkbenchPartReference ref = getReference(part);
internalBringToTop(ref);
setActivePart(part);
}
/**
* Activates a part. The part is given focus, the pane is hilighted.
*/
private void activatePart(final IWorkbenchPart part) {
Platform.run(new SafeRunnable(WorkbenchMessages.WorkbenchPage_ErrorActivatingView) {
public void run() {
if (part != null) {
//part.setFocus();
PartPane pane = getPane(part);
pane.setFocus();
PartSite site = (PartSite) part.getSite();
pane.showFocus(true);
updateTabList(part);
SubActionBars bars = (SubActionBars) site
.getActionBars();
bars.partChanged(part);
}
}
});
}
/**
* Add a fast view.
*/
public void addFastView(IViewReference ref) {
Perspective persp = getActivePerspective();
if (persp == null) {
return;
}
persp.getFastViewManager().addViewReference(FastViewBar.FASTVIEWBAR_ID, -1, ref, true);
}
/**
* Add a fast view.
*/
public void makeFastView(IViewReference ref) {
Perspective persp = getActivePerspective();
if (persp == null) {
return;
}
FastViewManager fvm = persp.getFastViewManager();
if (fvm.isFastView(ref)) {
return;
}
// Do real work.
persp.makeFastView(ref);
updateActivePart();
// The view is now invisible.
// If it is active then deactivate it.
// Notify listeners.
window.firePerspectiveChanged(this, getPerspective(), ref,
CHANGE_FAST_VIEW_ADD);
window.firePerspectiveChanged(this, getPerspective(),
CHANGE_FAST_VIEW_ADD);
}
/**
* Adds an IPartListener to the part service.
*/
public void addPartListener(IPartListener l) {
partList.getPartService().addPartListener(l);
}
/**
* Adds an IPartListener to the part service.
*/
public void addPartListener(IPartListener2 l) {
partList.getPartService().addPartListener(l);
}
/**
* Implements IWorkbenchPage
*
* @see org.eclipse.ui.IWorkbenchPage#addPropertyChangeListener(IPropertyChangeListener)
* @since 2.0
* @deprecated individual views should store a working set if needed and
* register a property change listener directly with the
* working set manager to receive notification when the view
* working set is removed.
*/
public void addPropertyChangeListener(IPropertyChangeListener listener) {
propertyChangeListeners.add(listener);
}
/*
* (non-Javadoc) Method declared on ISelectionListener.
*/
public void addSelectionListener(ISelectionListener listener) {
selectionService.addSelectionListener(listener);
}
/*
* (non-Javadoc) Method declared on ISelectionListener.
*/
public void addSelectionListener(String partId, ISelectionListener listener) {
selectionService.addSelectionListener(partId, listener);
}
/*
* (non-Javadoc) Method declared on ISelectionListener.
*/
public void addPostSelectionListener(ISelectionListener listener) {
selectionService.addPostSelectionListener(listener);
}
/*
* (non-Javadoc) Method declared on ISelectionListener.
*/
public void addPostSelectionListener(String partId,
ISelectionListener listener) {
selectionService.addPostSelectionListener(partId, listener);
}
private ILayoutContainer getContainer(IWorkbenchPart part) {
PartPane pane = getPane(part);
if (pane == null) {
return null;
}
return pane.getContainer();
}
private ILayoutContainer getContainer(IWorkbenchPartReference part) {
PartPane pane = getPane(part);
if (pane == null) {
return null;
}
return pane.getContainer();
}
private PartPane getPane(IWorkbenchPart part) {
if (part == null) {
return null;
}
return getPane(getReference(part));
}
private PartPane getPane(IWorkbenchPartReference part) {
if (part == null) {
return null;
}
return ((WorkbenchPartReference)part).getPane();
}
/**
* Brings a part to the front of its stack. Does not update the active part or
* active editor. This should only be called if the caller knows that the part
* is not in the same stack as the active part or active editor, or if the caller
* is prepared to update activation after the call.
*
* @param part
*/
private boolean internalBringToTop(IWorkbenchPartReference part) {
boolean broughtToTop = false;
// Move part.
if (part instanceof IEditorReference) {
ILayoutContainer container = getContainer(part);
if (container instanceof PartStack) {
PartStack stack = (PartStack)container;
PartPane newPart = getPane(part);
if (stack.getSelection() != newPart) {
stack.setSelection(newPart);
}
broughtToTop = true;
}
} else if (part instanceof IViewReference) {
Perspective persp = getActivePerspective();
if (persp != null) {
broughtToTop = persp.bringToTop((IViewReference)part);
}
}
// Ensure that this part is considered the most recently activated part
// in this stack
activationList.bringToTop(part);
return broughtToTop;
}
/**
* Moves a part forward in the Z order of a perspective so it is visible.
* If the part is in the same stack as the active part, the new part is
* activated.
*
* @param part
* the part to bring to move forward
*/
public void bringToTop(IWorkbenchPart part) {
// Sanity check.
Perspective persp = getActivePerspective();
if (persp == null || !certifyPart(part)) {
return;
}
if (!((GrabFocus)Tweaklets.get(GrabFocus.KEY)).grabFocusAllowed(part)) {
return;
}
String label = null; // debugging only
if (UIStats.isDebugging(UIStats.BRING_PART_TO_TOP)) {
label = part != null ? part.getTitle() : "none"; //$NON-NLS-1$
}
try {
UIStats.start(UIStats.BRING_PART_TO_TOP, label);
IWorkbenchPartReference ref = getReference(part);
ILayoutContainer activeEditorContainer = getContainer(getActiveEditor());
ILayoutContainer activePartContainer = getContainer(getActivePart());
ILayoutContainer newPartContainer = getContainer(part);
if (newPartContainer == activePartContainer) {
makeActive(ref);
} else if (newPartContainer == activeEditorContainer) {
if (ref instanceof IEditorReference) {
if (part!=null) {
IWorkbenchPartSite site = part.getSite();
if (site instanceof PartSite) {
ref = ((PartSite) site).getPane()
.getPartReference();
}
}
makeActiveEditor((IEditorReference)ref);
} else {
makeActiveEditor(null);
}
} else {
internalBringToTop(ref);
if (ref != null) {
partList.firePartBroughtToTop(ref);
}
}
} finally {
UIStats.end(UIStats.BRING_PART_TO_TOP, part, label);
}
}
/**
* Resets the layout for the perspective. The active part in the old layout
* is activated in the new layout for consistent user context.
*
* Assumes the busy cursor is active.
*/
private void busyResetPerspective() {
ViewIntroAdapterPart introViewAdapter = ((WorkbenchIntroManager) getWorkbenchWindow()
.getWorkbench().getIntroManager()).getViewIntroAdapterPart();
PartPane introPane = null;
boolean introFullScreen = false;
if (introViewAdapter != null) {
introPane = ((PartSite) introViewAdapter.getSite()).getPane();
introViewAdapter.setHandleZoomEvents(false);
introFullScreen = introPane.isZoomed();
}
//try to prevent intro flicker.
if (introFullScreen) {
window.getShell().setRedraw(false);
}
try {
// Always unzoom
if (isZoomed()) {
zoomOut();
}
// Get the current perspective.
// This describes the working layout of the page and differs from
// the original template.
Perspective oldPersp = getActivePerspective();
// Map the current perspective to the original template.
// If the original template cannot be found then it has been deleted.
// In that case just return. (PR#1GDSABU).
IPerspectiveRegistry reg = WorkbenchPlugin.getDefault()
.getPerspectiveRegistry();
PerspectiveDescriptor desc = (PerspectiveDescriptor) reg
.findPerspectiveWithId(oldPersp.getDesc().getId());
if (desc == null) {
desc = (PerspectiveDescriptor) reg
.findPerspectiveWithId(((PerspectiveDescriptor) oldPersp
.getDesc()).getOriginalId());
}
if (desc == null) {
return;
}
// Notify listeners that we are doing a reset.
window.firePerspectiveChanged(this, desc, CHANGE_RESET);
// Create new persp from original template.
// Suppress the perspectiveOpened and perspectiveClosed events otherwise it looks like two
// instances of the same perspective are open temporarily (see bug 127470).
Perspective newPersp = createPerspective(desc, false);
if (newPersp == null) {
// We're not going through with the reset, so it is complete.
window
.firePerspectiveChanged(this, desc,
CHANGE_RESET_COMPLETE);
return;
}
// Update the perspective list and shortcut
perspList.swap(oldPersp, newPersp);
// Install new persp.
setPerspective(newPersp);
// Destroy old persp.
disposePerspective(oldPersp, false);
// Update the Coolbar layout.
resetToolBarLayout();
// restore the maximized intro
if (introViewAdapter != null) {
try {
// ensure that the intro is visible in the new perspective
showView(IIntroConstants.INTRO_VIEW_ID);
if (introFullScreen) {
toggleZoom(introPane.getPartReference());
}
} catch (PartInitException e) {
WorkbenchPlugin.log("Could not restore intro", //$NON-NLS-1$
WorkbenchPlugin.getStatus(e));
} finally {
// we want the intro back to a normal state before we fire the event
introViewAdapter.setHandleZoomEvents(true);
}
}
// Notify listeners that we have completed our reset.
window.firePerspectiveChanged(this, desc, CHANGE_RESET_COMPLETE);
} finally {
// reset the handling of zoom events (possibly for the second time) in case there was
// an exception thrown
if (introViewAdapter != null) {
introViewAdapter.setHandleZoomEvents(true);
}
if (introFullScreen) {
window.getShell().setRedraw(true);
}
}
}
/**
* Implements <code>setPerspective</code>.
*
* Assumes that busy cursor is active.
*
* @param desc
* identifies the new perspective.
*/
private void busySetPerspective(IPerspectiveDescriptor desc) {
// Create new layout.
String label = desc.getId(); // debugging only
Perspective newPersp = null;
try {
UIStats.start(UIStats.SWITCH_PERSPECTIVE, label);
PerspectiveDescriptor realDesc = (PerspectiveDescriptor) desc;
newPersp = findPerspective(realDesc);
if (newPersp == null) {
newPersp = createPerspective(realDesc, true);
if (newPersp == null) {
return;
}
}
// Change layout.
setPerspective(newPersp);
} finally {
UIStats.end(UIStats.SWITCH_PERSPECTIVE, desc.getId(), label);
}
}
/**
* Shows a view.
*
* Assumes that a busy cursor is active.
*/
private IViewPart busyShowView(String viewID, String secondaryID, int mode)
throws PartInitException {
Perspective persp = getActivePerspective();
if (persp == null) {
return null;
}
// If this view is already visible just return.
IViewReference ref = persp.findView(viewID, secondaryID);
IViewPart view = null;
if (ref != null) {
view = ref.getView(true);
}
if (view != null) {
busyShowView(view, mode);
return view;
}
// Show the view.
view = persp.showView(viewID, secondaryID);
if (view != null) {
busyShowView(view, mode);
IWorkbenchPartReference partReference = getReference(view);
PartPane partPane = getPane(partReference);
partPane.setInLayout(true);
window.firePerspectiveChanged(this, getPerspective(),
partReference, CHANGE_VIEW_SHOW);
window.firePerspectiveChanged(this, getPerspective(),
CHANGE_VIEW_SHOW);
}
return view;
}
/*
* Performs showing of the view in the given mode.
*/
private void busyShowView(IViewPart part, int mode) {
if (!((GrabFocus)Tweaklets.get(GrabFocus.KEY)).grabFocusAllowed(part)) {
return;
}
if (mode == VIEW_ACTIVATE) {
activate(part);
} else if (mode == VIEW_VISIBLE) {
IWorkbenchPartReference ref = getActivePartReference();
// if there is no active part or it's not a view, bring to top
if (ref == null || !(ref instanceof IViewReference)) {
bringToTop(part);
} else {
// otherwise check to see if the we're in the same stack as the active view
IViewReference activeView = (IViewReference) ref;
IViewReference[] viewStack = getViewReferenceStack(part);
for (int i = 0; i < viewStack.length; i++) {
if (viewStack[i].equals(activeView)) {
return;
}
}
bringToTop(part);
}
}
}
/**
* Returns whether a part exists in the current page.
*/
private boolean certifyPart(IWorkbenchPart part) {
//Workaround for bug 22325
if (part != null && !(part.getSite() instanceof PartSite)) {
return false;
}
if (part instanceof IEditorPart) {
IEditorReference ref = (IEditorReference) getReference(part);
return ref != null && getEditorManager().containsEditor(ref);
}
if (part instanceof IViewPart) {
Perspective persp = getActivePerspective();
return persp != null && persp.containsView((IViewPart) part);
}
return false;
}
/**
* Closes the perspective.
*/
public boolean close() {
final boolean[] ret = new boolean[1];
BusyIndicator.showWhile(null, new Runnable() {
public void run() {
ret[0] = window.closePage(WorkbenchPage.this, true);
}
});
return ret[0];
}
/**
* See IWorkbenchPage
*/
public boolean closeAllSavedEditors() {
// get the Saved editors
IEditorReference editors[] = getEditorReferences();
IEditorReference savedEditors[] = new IEditorReference[editors.length];
int j = 0;
for (int i = 0; i < editors.length; i++) {
IEditorReference editor = editors[i];
if (!editor.isDirty()) {
savedEditors[j++] = editor;
}
}
//there are no unsaved editors
if (j == 0) {
return true;
}
IEditorReference[] newSaved = new IEditorReference[j];
System.arraycopy(savedEditors, 0, newSaved, 0, j);
return closeEditors(newSaved, false);
}
/**
* See IWorkbenchPage
*/
public boolean closeAllEditors(boolean save) {
return closeEditors(getEditorReferences(), save);
}
private void updateActivePart() {
if (isDeferred()) {
return;
}
IWorkbenchPartReference oldActivePart = partList.getActivePartReference();
IWorkbenchPartReference oldActiveEditor = partList.getActiveEditorReference();
IWorkbenchPartReference newActivePart = null;
IEditorReference newActiveEditor = null;
if (!window.isClosing()) {
// If an editor is active, try to keep an editor active
if (oldActivePart == oldActiveEditor) {
newActiveEditor = (IEditorReference)activationList.getActiveReference(true);
newActivePart = newActiveEditor;
if (newActivePart == null) {
// Only activate a non-editor if there's no editors left
newActivePart = activationList.getActiveReference(false);
}
} else {
// If a non-editor is active, activate whatever was activated most recently
newActivePart = activationList.getActiveReference(false);
if (newActivePart instanceof IEditorReference) {
// If that happens to be an editor, make it the active editor as well
newActiveEditor = (IEditorReference)newActivePart;
} else {
// Otherwise, select whatever editor was most recently active
newActiveEditor = (IEditorReference)activationList.getActiveReference(true);
}
}
}
if (newActiveEditor != oldActiveEditor) {
makeActiveEditor(newActiveEditor);
}
if (newActivePart != oldActivePart) {
makeActive(newActivePart);
}
}
/**
* Makes the given part active. Brings it in front if necessary. Permits null
* (indicating that no part should be active).
*
* @since 3.1
*
* @param ref new active part (or null)
*/
private void makeActive(IWorkbenchPartReference ref) {
if (ref == null) {
setActivePart(null);
} else {
IWorkbenchPart newActive = ref.getPart(true);
if (newActive == null) {
setActivePart(null);
} else {
activate(newActive);
}
}
}
/**
* Makes the given editor active. Brings it to front if necessary. Permits <code>null</code>
* (indicating that no editor is active).
*
* @since 3.1
*
* @param ref the editor to make active, or <code>null</code> for no active editor
*/
private void makeActiveEditor(IEditorReference ref) {
if (ref == getActiveEditorReference()) {
return;
}
IEditorPart part = (ref == null) ? null : ref.getEditor(true);
if (part != null) {
editorMgr.setVisibleEditor(ref, false);
navigationHistory.markEditor(part);
}
actionSwitcher.updateTopEditor(part);
if (ref != null) {
activationList.bringToTop(getReference(part));
}
partList.setActiveEditor(ref);
}
/**
* See IWorkbenchPage
*/
public boolean closeEditors(IEditorReference[] refArray, boolean save) {
if (refArray.length == 0) {
return true;
}
// Check if we're being asked to close any parts that are already closed or cannot
// be closed at this time
ArrayList toClose = new ArrayList();
for (int i = 0; i < refArray.length; i++) {
IEditorReference reference = refArray[i];
// If we're in the middle of creating this part, this is a programming error. Abort the entire
// close operation. This usually occurs if someone tries to open a dialog in a method that
// isn't allowed to do so, and a *syncExec tries to close the part. If this shows up in a log
// file with a dialog's event loop on the stack, then the code that opened the dialog is usually
// at fault.
if (reference == partBeingActivated) {
WorkbenchPlugin.log(new RuntimeException("WARNING: Blocked recursive attempt to close part " //$NON-NLS-1$
+ partBeingActivated.getId() + " while still in the middle of activating it")); //$NON-NLS-1$
return false;
}
if(reference instanceof WorkbenchPartReference) {
WorkbenchPartReference ref = (WorkbenchPartReference) reference;
// If we're being asked to close a part that is disposed (ie: already closed),
// skip it and proceed with closing the remaining parts.
if (ref.isDisposed()) {
continue;
}
}
toClose.add(reference);
}
IEditorReference[] editorRefs = (IEditorReference[]) toClose.toArray(new IEditorReference[toClose.size()]);
// notify the model manager before the close
List partsToClose = new ArrayList();
for (int i = 0; i < editorRefs.length; i++) {
IEditorPart refPart = editorRefs[i].getEditor(false);
if (refPart != null) {
partsToClose.add(refPart);
}
}
SaveablesList modelManager = null;
Object postCloseInfo = null;
if(partsToClose.size()>0) {
modelManager = (SaveablesList) getWorkbenchWindow().getService(ISaveablesLifecycleListener.class);
// this may prompt for saving and return null if the user canceled:
postCloseInfo = modelManager.preCloseParts(partsToClose, save, getWorkbenchWindow());
if (postCloseInfo==null) {
return false;
}
}
// Fire pre-removal changes
for (int i = 0; i < editorRefs.length; i++) {
IEditorReference ref = editorRefs[i];
// Notify interested listeners before the close
window.firePerspectiveChanged(this, getPerspective(), ref,
CHANGE_EDITOR_CLOSE);
}
deferUpdates(true);
try {
if(modelManager!=null) {
modelManager.postClose(postCloseInfo);
}
// Close all editors.
for (int i = 0; i < editorRefs.length; i++) {
IEditorReference ref = editorRefs[i];
// Remove editor from the presentation
editorPresentation.closeEditor(ref);
partRemoved((WorkbenchPartReference)ref);
}
} finally {
deferUpdates(false);
}
// Notify interested listeners after the close
window.firePerspectiveChanged(this, getPerspective(),
CHANGE_EDITOR_CLOSE);
// Return true on success.
return true;
}
/**
* Enables or disables listener notifications. This is used to delay listener notifications until the
* end of a public method.
*
* @param shouldDefer
*/
private void deferUpdates(boolean shouldDefer) {
if (shouldDefer) {
if (deferCount == 0) {
startDeferring();
}
deferCount++;
} else {
deferCount--;
if (deferCount == 0) {
handleDeferredEvents();
}
}
}
private void startDeferring() {
editorPresentation.getLayoutPart().deferUpdates(true);
}
private void handleDeferredEvents() {
editorPresentation.getLayoutPart().deferUpdates(false);
updateActivePart();
WorkbenchPartReference[] disposals = (WorkbenchPartReference[]) pendingDisposals.toArray(new WorkbenchPartReference[pendingDisposals.size()]);
pendingDisposals.clear();
for (int i = 0; i < disposals.length; i++) {
WorkbenchPartReference reference = disposals[i];
disposePart(reference);
}
}
private boolean isDeferred() {
return deferCount > 0;
}
/**
* See IWorkbenchPage#closeEditor
*/
public boolean closeEditor(IEditorReference editorRef, boolean save) {
return closeEditors(new IEditorReference[] {editorRef}, save);
}
/**
* See IWorkbenchPage#closeEditor
*/
public boolean closeEditor(IEditorPart editor, boolean save) {
IWorkbenchPartReference ref = getReference(editor);
if (ref instanceof IEditorReference) {
return closeEditors(new IEditorReference[] {(IEditorReference) ref}, save);
}
return false;
}
/**
* @see IWorkbenchPage#closePerspective(IPerspectiveDescriptor, boolean, boolean)
*/
public void closePerspective(IPerspectiveDescriptor desc, boolean saveParts, boolean closePage) {
Perspective persp = findPerspective(desc);
if (persp != null) {
closePerspective(persp, saveParts, closePage);
}
}
/**
* Closes the specified perspective. If last perspective, then entire page
* is closed.
*
* @param persp
* the perspective to be closed
* @param saveParts
* whether the parts that are being closed should be saved
* (editors if last perspective, views if not shown in other
* parspectives)
*/
/* package */
void closePerspective(Perspective persp, boolean saveParts, boolean closePage) {
// Always unzoom
if (isZoomed()) {
zoomOut();
}
List partsToSave = new ArrayList();
List viewsToClose = new ArrayList();
// collect views that will go away and views that are dirty
IViewReference[] viewReferences = persp.getViewReferences();
for (int i = 0; i < viewReferences.length; i++) {
IViewReference reference = viewReferences[i];
if (getViewFactory().getReferenceCount(reference) == 1) {
IViewPart viewPart = reference.getView(false);
if (viewPart != null) {
viewsToClose.add(viewPart);
if (saveParts && reference.isDirty()) {
partsToSave.add(viewPart);
}
}
}
}
if (saveParts && perspList.size() == 1) {
// collect editors that are dirty
IEditorReference[] editorReferences = getEditorReferences();
for (int i = 0; i < editorReferences.length; i++) {
IEditorReference reference = editorReferences[i];
if (reference.isDirty()) {
IEditorPart editorPart = reference.getEditor(false);
if (editorPart != null) {
partsToSave.add(editorPart);
}
}
}
}
if (saveParts && !partsToSave.isEmpty()) {
if (!EditorManager.saveAll(partsToSave, true, true, false, window)) {
// user canceled
return;
}
}
// Close all editors on last perspective close
if (perspList.size() == 1 && getEditorManager().getEditorCount() > 0) {
// Close all editors
if (!closeAllEditors(false)) {
return;
}
}
// closeAllEditors already notified the saveables list about the editors.
SaveablesList saveablesList = (SaveablesList) getWorkbenchWindow().getWorkbench().getService(ISaveablesLifecycleListener.class);
// we took care of the saving already, so pass in false (postCloseInfo will be non-null)
Object postCloseInfo = saveablesList.preCloseParts(viewsToClose, false, getWorkbenchWindow());
saveablesList.postClose(postCloseInfo);
// Dispose of the perspective
boolean isActive = (perspList.getActive() == persp);
if (isActive) {
setPerspective(perspList.getNextActive());
}
disposePerspective(persp, true);
if (closePage && perspList.size() == 0) {
close();
}
}
/**
* Forces all perspectives on the page to zoom out.
*/
public void unzoomAllPerspectives() {
for (Iterator perspIter = perspList.iterator(); perspIter.hasNext();) {
Perspective persp = (Perspective) perspIter.next();
persp.getPresentation().forceNoZoom();
}
}
/**
* @see IWorkbenchPage#closeAllPerspectives(boolean, boolean)
*/
public void closeAllPerspectives(boolean saveEditors, boolean closePage) {
if (perspList.isEmpty()) {
return;
}
// Always unzoom
if (isZoomed()) {
zoomOut();
}
if(saveEditors) {
if (!saveAllEditors(true)) {
return;
}
}
// Close all editors
if (!closeAllEditors(false)) {
return;
}
// Deactivate the active perspective and part
setPerspective((Perspective) null);
// Close each perspective in turn
PerspectiveList oldList = perspList;
perspList = new PerspectiveList();
Iterator itr = oldList.iterator();
while (itr.hasNext()) {
closePerspective((Perspective) itr.next(), false, false);
}
if (closePage) {
close();
}
}
/**
* Creates the client composite.
*/
private void createClientComposite() {
final Composite parent = window.getPageComposite();
StartupThreading.runWithoutExceptions(new StartupRunnable() {
public void runWithException() {
composite = new Composite(parent, SWT.NONE);
composite.setVisible(false); // Make visible on activate.
// force the client composite to be layed out
parent.layout();
}
});
}
/**
* Creates a new view set. Return null on failure.
*
* @param desc the perspective descriptor
* @param notify whether to fire a perspective opened event
*/
private Perspective createPerspective(PerspectiveDescriptor desc, boolean notify) {
String label = desc.getId(); // debugging only
try {
UIStats.start(UIStats.CREATE_PERSPECTIVE, label);
Perspective persp = new Perspective(desc, this);
perspList.add(persp);
if (notify) {
window.firePerspectiveOpened(this, desc);
}
//if the perspective is fresh and uncustomzied then it is not dirty
//no reset will be prompted for
if (!desc.hasCustomDefinition()) {
dirtyPerspectives.remove(desc.getId());
}
return persp;
} catch (WorkbenchException e) {
if (!((Workbench) window.getWorkbench()).isStarting()) {
MessageDialog
.openError(
window.getShell(),
WorkbenchMessages.Error,
NLS.bind(WorkbenchMessages.Workbench_showPerspectiveError,desc.getId() ));
}
return null;
} finally {
UIStats.end(UIStats.CREATE_PERSPECTIVE, desc.getId(), label);
}
}
/**
* This is called by child objects after a part has been added to the page.
* The page will in turn notify its listeners.
*/
/* package */ void partAdded(WorkbenchPartReference ref) {
activationList.add(ref);
partList.addPart(ref);
updateActivePart();
}
/**
* This is called by child objects after a part has been added to the page.
* The part will be queued for disposal after all listeners have been notified
*/
/* package */ void partRemoved(WorkbenchPartReference ref) {
activationList.remove(ref);
disposePart(ref);
}
private void disposePart(WorkbenchPartReference ref) {
if (isDeferred()) {
pendingDisposals.add(ref);
} else {
partList.removePart(ref);
ref.dispose();
}
}
/**
* Deactivates a part. The pane is unhilighted.
*/
private void deactivatePart(IWorkbenchPart part) {
if (part != null) {
PartSite site = (PartSite) part.getSite();
site.getPane().showFocus(false);
}
}
/**
* Detaches a view from the WorkbenchWindow.
*/
public void detachView(IViewReference ref){
Perspective persp = getActivePerspective();
if(persp == null) {
return;
}
PerspectiveHelper presentation = persp.getPresentation();
presentation.detachPart(ref);
}
/**
* Removes a detachedwindow.
*/
public void attachView(IViewReference ref){
PerspectiveHelper presentation = getPerspectivePresentation();
presentation.attachPart(ref);
}
/**
* Cleanup.
*/
public void dispose() {
// Always unzoom
if (isZoomed()) {
zoomOut();
}
makeActiveEditor(null);
makeActive(null);
// Close and dispose the editors.
closeAllEditors(false);
// Need to make sure model data is cleaned up when the page is
// disposed. Collect all the views on the page and notify the
// saveable list of a pre/post close. This will free model data.
IWorkbenchPartReference[] partsToClose = getOpenParts();
List dirtyParts = new ArrayList(partsToClose.length);
for (int i = 0; i < partsToClose.length; i++) {
IWorkbenchPart part = partsToClose[i].getPart(false);
if (part != null && part instanceof IViewPart) {
dirtyParts.add(part);
}
}
SaveablesList saveablesList = (SaveablesList) getWorkbenchWindow().getWorkbench().getService(ISaveablesLifecycleListener.class);
Object postCloseInfo = saveablesList.preCloseParts(dirtyParts, false,getWorkbenchWindow());
saveablesList.postClose(postCloseInfo);
// Get rid of perspectives. This will close the views.
Iterator itr = perspList.iterator();
while (itr.hasNext()) {
Perspective perspective = (Perspective) itr.next();
window.firePerspectiveClosed(this, perspective.getDesc());
perspective.dispose();
}
perspList = new PerspectiveList();
// Capture views.
IViewReference refs[] = viewFactory.getViews();
if (refs.length > 0) {
// Dispose views.
for (int i = 0; i < refs.length; i++) {
final WorkbenchPartReference ref = (WorkbenchPartReference) refs[i];
//partList.removePart(ref);
//firePartClosed(refs[i]);
Platform.run(new SafeRunnable() {
public void run() {
// WorkbenchPlugin.log(new Status(IStatus.WARNING, WorkbenchPlugin.PI_WORKBENCH,
// Status.OK, "WorkbenchPage leaked a refcount for view " + ref.getId(), null)); //$NON-NLS-1$//$NON-NLS-2$
ref.dispose();
}
public void handleException(Throwable e) {
}
});
}
}
activationList = new ActivationList();
// Get rid of editor presentation.
editorPresentation.dispose();
// Get rid of composite.
composite.dispose();
navigationHistory.dispose();
stickyViewMan.clear();
if (tracker != null) {
tracker.close();
}
// if we're destroying a window in a non-shutdown situation then we should
// clean up the working set we made.
if (!window.getWorkbench().isClosing()) {
if (aggregateWorkingSet != null) {
PlatformUI.getWorkbench().getWorkingSetManager().removeWorkingSet(aggregateWorkingSet);
}
}
}
/**
* Dispose a perspective.
*
* @param persp the perspective descriptor
* @param notify whether to fire a perspective closed event
*/
private void disposePerspective(Perspective persp, boolean notify) {
// Get rid of perspective.
perspList.remove(persp);
if (notify) {
window.firePerspectiveClosed(this, persp.getDesc());
}
persp.dispose();
stickyViewMan.remove(persp.getDesc().getId());
}
/**
* @return NavigationHistory
*/
public INavigationHistory getNavigationHistory() {
return navigationHistory;
}
/**
* Edits the action sets.
*/
public boolean editActionSets() {
Perspective persp = getActivePerspective();
if (persp == null) {
return false;
}
// Create list dialog.
CustomizePerspectiveDialog dlg = window.createCustomizePerspectiveDialog(persp);
// Open.
boolean ret = (dlg.open() == Window.OK);
if (ret) {
window.updateActionSets();
window.firePerspectiveChanged(this, getPerspective(), CHANGE_RESET);
window.firePerspectiveChanged(this, getPerspective(),
CHANGE_RESET_COMPLETE);
}
return ret;
}
/**
* Returns the first view manager with given ID.
*/
public Perspective findPerspective(IPerspectiveDescriptor desc) {
Iterator itr = perspList.iterator();
while (itr.hasNext()) {
Perspective mgr = (Perspective) itr.next();
if (desc.getId().equals(mgr.getDesc().getId())) {
return mgr;
}
}
return null;
}
/**
* See IWorkbenchPage@findView.
*/
public IViewPart findView(String id) {
IViewReference ref = findViewReference(id);
if (ref == null) {
return null;
}
return ref.getView(true);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.IWorkbenchPage
*/
public IViewReference findViewReference(String viewId) {
return findViewReference(viewId, null);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.IWorkbenchPage
*/
public IViewReference findViewReference(String viewId, String secondaryId) {
Perspective persp = getActivePerspective();
if (persp == null) {
return null;
}
return persp.findView(viewId, secondaryId);
}
/**
* Notify property change listeners about a property change.
*
* @param changeId
* the change id
* @param oldValue
* old property value
* @param newValue
* new property value
*/
private void firePropertyChange(String changeId, Object oldValue,
Object newValue) {
UIListenerLogging.logPagePropertyChanged(this, changeId, oldValue, newValue);
Object[] listeners = propertyChangeListeners.getListeners();
PropertyChangeEvent event = new PropertyChangeEvent(this, changeId,
oldValue, newValue);
for (int i = 0; i < listeners.length; i++) {
((IPropertyChangeListener) listeners[i]).propertyChange(event);
}
}
/*
* Returns the action bars.
*/
public IActionBars getActionBars() {
if (actionBars == null) {
actionBars = new WWinActionBars(window);
}
return actionBars;
}
/**
* Returns an array of the visible action sets.
*/
public IActionSetDescriptor[] getActionSets() {
Collection collection = actionSets.getVisibleItems();
return (IActionSetDescriptor[]) collection.toArray(new IActionSetDescriptor[collection.size()]);
}
/**
* @see IWorkbenchPage
*/
public IEditorPart getActiveEditor() {
return partList.getActiveEditor();
}
/**
* Returns the reference for the active editor, or <code>null</code>
* if there is no active editor.
*
* @return the active editor reference or <code>null</code>
*/
public IEditorReference getActiveEditorReference() {
return partList.getActiveEditorReference();
}
/*
* (non-Javadoc) Method declared on IPartService
*/
public IWorkbenchPart getActivePart() {
return partList.getActivePart();
}
/*
* (non-Javadoc) Method declared on IPartService
*/
public IWorkbenchPartReference getActivePartReference() {
return partList.getActivePartReference();
}
/**
* Returns the active perspective for the page, <code>null</code> if
* none.
*/
public Perspective getActivePerspective() {
return perspList.getActive();
}
/**
* Returns the client composite.
*/
public Composite getClientComposite() {
return composite;
}
// for dynamic UI - change access from private to protected
// for testing purposes only, changed from protected to public
/**
* Answer the editor manager for this window.
*/
public EditorManager getEditorManager() {
return editorMgr;
}
/**
* Answer the perspective presentation.
*/
public PerspectiveHelper getPerspectivePresentation() {
if (getActivePerspective() != null) {
return getActivePerspective().getPresentation();
}
return null;
}
/**
* Answer the editor presentation.
*/
public EditorAreaHelper getEditorPresentation() {
return editorPresentation;
}
/**
* See IWorkbenchPage.
*/
public IEditorPart[] getEditors() {
final IEditorReference refs[] = getEditorReferences();
final ArrayList result = new ArrayList(refs.length);
Display d = getWorkbenchWindow().getShell().getDisplay();
//Must be backward compatible.
d.syncExec(new Runnable() {
public void run() {
for (int i = 0; i < refs.length; i++) {
IWorkbenchPart part = refs[i].getPart(true);
if (part != null) {
result.add(part);
}
}
}
});
final IEditorPart editors[] = new IEditorPart[result.size()];
return (IEditorPart[]) result.toArray(editors);
}
public IEditorPart[] getDirtyEditors() {
return getEditorManager().getDirtyEditors();
}
public ISaveablePart[] getDirtyParts() {
List result = new ArrayList(3);
IWorkbenchPartReference[] allParts = getAllParts();
for (int i = 0; i < allParts.length; i++) {
IWorkbenchPartReference reference = allParts[i];
IWorkbenchPart part = reference.getPart(false);
if (part != null && part instanceof ISaveablePart) {
ISaveablePart saveable = (ISaveablePart)part;
if (saveable.isDirty()) {
result.add(saveable);
}
}
}
return (ISaveablePart[]) result.toArray(new ISaveablePart[result.size()]);
}
/**
* See IWorkbenchPage.
*/
public IEditorPart findEditor(IEditorInput input) {
return getEditorManager().findEditor(input);
}
/**
* See IWorkbenchPage.
*/
public IEditorReference[] findEditors(IEditorInput input, String editorId, int matchFlags) {
return getEditorManager().findEditors(input, editorId, matchFlags);
}
/**
* See IWorkbenchPage.
*/
public IEditorReference[] getEditorReferences() {
return editorPresentation.getEditors();
}
/**
* Returns the docked views.
*/
public IViewReference[] getFastViews() {
Perspective persp = getActivePerspective();
if (persp != null) {
return persp.getFastViews();
} else {
return new IViewReference[0];
}
}
/**
* @see IWorkbenchPage
*/
public IAdaptable getInput() {
return input;
}
/**
* Returns the page label. This is a combination of the page input and
* active perspective.
*/
public String getLabel() {
String label = WorkbenchMessages.WorkbenchPage_UnknownLabel;
IWorkbenchAdapter adapter = (IWorkbenchAdapter) Util.getAdapter(input,
IWorkbenchAdapter.class);
if (adapter != null) {
label = adapter.getLabel(input);
}
Perspective persp = getActivePerspective();
if (persp != null) {
label = NLS.bind(WorkbenchMessages.WorkbenchPage_PerspectiveFormat, label, persp.getDesc().getLabel());
} else if (deferredActivePersp != null) {
label = NLS.bind(WorkbenchMessages.WorkbenchPage_PerspectiveFormat,label, deferredActivePersp.getLabel());
}
return label;
}
/**
* Returns the perspective.
*/
public IPerspectiveDescriptor getPerspective() {
if (deferredActivePersp != null) {
return deferredActivePersp;
}
Perspective persp = getActivePerspective();
if (persp != null) {
return persp.getDesc();
} else {
return null;
}
}
/*
* (non-Javadoc) Method declared on ISelectionService
*/
public ISelection getSelection() {
return selectionService.getSelection();
}
/*
* (non-Javadoc) Method declared on ISelectionService
*/
public ISelection getSelection(String partId) {
return selectionService.getSelection(partId);
}
/**
* Returns the ids of the parts to list in the Show In... prompter. This is
* a List of Strings.
*/
public ArrayList getShowInPartIds() {
Perspective persp = getActivePerspective();
if (persp != null) {
return persp.getShowInPartIds();
} else {
return new ArrayList();
}
}
/**
* The user successfully performed a Show In... action on the specified
* part. Update the list of Show In items accordingly.
*/
public void performedShowIn(String partId) {
Perspective persp = getActivePerspective();
if (persp != null) {
persp.performedShowIn(partId);
}
}
/**
* Sorts the given collection of show in target part ids in MRU order.
*/
public void sortShowInPartIds(ArrayList partIds) {
final Perspective persp = getActivePerspective();
if (persp != null) {
Collections.sort(partIds, new Comparator() {
public int compare(Object a, Object b) {
long ta = persp.getShowInTime((String) a);
long tb = persp.getShowInTime((String) b);
return (ta == tb) ? 0 : ((ta > tb) ? -1 : 1);
}
});
}
}
/*
* Returns the view factory.
*/
public ViewFactory getViewFactory() {
if (viewFactory == null) {
viewFactory = new ViewFactory(this, WorkbenchPlugin.getDefault()
.getViewRegistry());
}
return viewFactory;
}
/**
* See IWorkbenchPage.
*/
public IViewReference[] getViewReferences() {
Perspective persp = getActivePerspective();
if (persp != null) {
return persp.getViewReferences();
} else {
return new IViewReference[0];
}
}
/**
* See IWorkbenchPage.
*/
public IViewPart[] getViews() {
return getViews(null, true);
}
/**
* Returns all view parts in the specified perspective
*
* @param persp the perspective
* @return an array of view parts
* @since 3.1
*/
/*package*/IViewPart[] getViews(Perspective persp, boolean restore) {
if (persp == null) {
persp = getActivePerspective();
}
if (persp != null) {
IViewReference refs[] = persp.getViewReferences();
ArrayList parts = new ArrayList(refs.length);
for (int i = 0; i < refs.length; i++) {
IWorkbenchPart part = refs[i].getPart(restore);
if (part != null) {
parts.add(part);
}
}
IViewPart[] result = new IViewPart[parts.size()];
return (IViewPart[]) parts.toArray(result);
}
return new IViewPart[0];
}
/**
* See IWorkbenchPage.
*/
public IWorkbenchWindow getWorkbenchWindow() {
return window;
}
/**
* Implements IWorkbenchPage
*
* @see org.eclipse.ui.IWorkbenchPage#getWorkingSet()
* @since 2.0
* @deprecated individual views should store a working set if needed
*/
public IWorkingSet getWorkingSet() {
return workingSet;
}
/**
* @see IWorkbenchPage
*/
public void hideActionSet(String actionSetID) {
Perspective persp = getActivePerspective();
if (persp != null) {
persp.removeActionSet(actionSetID);
window.updateActionSets();
window.firePerspectiveChanged(this, getPerspective(),
CHANGE_ACTION_SET_HIDE);
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.IWorkbenchPage#hideView(org.eclipse.ui.IViewReference)
*/
public void hideView(IViewReference ref) {
// Sanity check.
if (ref == null) {
return;
}
Perspective persp = getActivePerspective();
if (persp == null) {
return;
}
boolean promptedForSave = false;
IViewPart view = ref.getView(false);
if (view != null) {
if (!certifyPart(view)) {
return;
}
// Confirm.
if (view instanceof ISaveablePart) {
ISaveablePart saveable = (ISaveablePart)view;
if (saveable.isSaveOnCloseNeeded()) {
IWorkbenchWindow window = view.getSite().getWorkbenchWindow();
boolean success = EditorManager.saveAll(Collections.singletonList(view), true, true, false, window);
if (!success) {
// the user cancelled.
return;
}
promptedForSave = true;
}
}
}
int refCount = getViewFactory().getReferenceCount(ref);
SaveablesList saveablesList = null;
Object postCloseInfo = null;
if (refCount == 1) {
IWorkbenchPart actualPart = ref.getPart(false);
if (actualPart != null) {
saveablesList = (SaveablesList) actualPart
.getSite().getService(ISaveablesLifecycleListener.class);
postCloseInfo = saveablesList.preCloseParts(Collections
.singletonList(actualPart), !promptedForSave, this
.getWorkbenchWindow());
if (postCloseInfo==null) {
// cancel
return;
}
}
}
// Notify interested listeners before the hide
window.firePerspectiveChanged(this, persp.getDesc(), ref,
CHANGE_VIEW_HIDE);
PartPane pane = getPane(ref);
pane.setInLayout(false);
updateActivePart();
if (saveablesList != null) {
saveablesList.postClose(postCloseInfo);
}
// Hide the part.
persp.hideView(ref);
// Notify interested listeners after the hide
window.firePerspectiveChanged(this, getPerspective(), CHANGE_VIEW_HIDE);
}
/* package */void refreshActiveView() {
updateActivePart();
}
/**
* See IPerspective
*/
public void hideView(IViewPart view) {
hideView((IViewReference)getReference(view));
}
/**
* Initialize the page.
*
* @param w
* the parent window
* @param layoutID
* may be <code>null</code> if restoring from file
* @param input
* the page input
* @param openExtras
* whether to process the perspective extras preference
*/
private void init(WorkbenchWindow w, String layoutID, IAdaptable input, boolean openExtras)
throws WorkbenchException {
// Save args.
this.window = w;
this.input = input;
actionSets = new ActionSetManager(w);
// Create presentation.
createClientComposite();
editorPresentation = new EditorAreaHelper(this);
editorMgr = new EditorManager(window, this, editorPresentation);
// add this page as a client to be notified when the UI has re-orded perspectives
// so that the order can be properly maintained in the receiver.
// E.g. a UI might support drag-and-drop and will need to make this known to ensure
// #saveState and #restoreState do not lose this re-ordering
w.addPerspectiveReorderListener(new IReorderListener() {
public void reorder(Object perspective, int newLoc) {
perspList.reorder((IPerspectiveDescriptor)perspective, newLoc);
}
});
if (openExtras) {
openPerspectiveExtras();
}
// Get perspective descriptor.
if (layoutID != null) {
PerspectiveDescriptor desc = (PerspectiveDescriptor) WorkbenchPlugin
.getDefault().getPerspectiveRegistry()
.findPerspectiveWithId(layoutID);
if (desc == null) {
throw new WorkbenchException(
NLS.bind(WorkbenchMessages.WorkbenchPage_ErrorCreatingPerspective,layoutID ));
}
Perspective persp = findPerspective(desc);
if (persp == null) {
persp = createPerspective(desc, true);
}
perspList.setActive(persp);
window.firePerspectiveActivated(this, desc);
}
getExtensionTracker()
.registerHandler(
perspectiveChangeHandler,
ExtensionTracker
.createExtensionPointFilter(getPerspectiveExtensionPoint()));
}
/**
* Opens the perspectives specified in the PERSPECTIVE_BAR_EXTRAS preference (see bug 84226).
*/
public void openPerspectiveExtras() {
String extras = PrefUtil.getAPIPreferenceStore().getString(
IWorkbenchPreferenceConstants.PERSPECTIVE_BAR_EXTRAS);
StringTokenizer tok = new StringTokenizer(extras, ", "); //$NON-NLS-1$
ArrayList descs = new ArrayList();
while (tok.hasMoreTokens()) {
String id = tok.nextToken();
IPerspectiveDescriptor desc = WorkbenchPlugin.getDefault().getPerspectiveRegistry().findPerspectiveWithId(id);
if (desc != null) {
descs.add(desc);
}
}
// HACK: The perspective switcher currently adds the button for a new perspective to the beginning of the list.
// So, we process the extra perspectives in reverse order here to have their buttons appear in the order declared.
for (int i = descs.size(); --i >= 0;) {
PerspectiveDescriptor desc = (PerspectiveDescriptor) descs.get(i);
if (findPerspective(desc) == null) {
createPerspective(desc, true);
}
}
}
/**
* See IWorkbenchPage.
*/
public boolean isPartVisible(IWorkbenchPart part) {
PartPane pane = getPane(part);
return pane != null && pane.getVisible();
}
/**
* See IWorkbenchPage.
*/
public boolean isEditorAreaVisible() {
Perspective persp = getActivePerspective();
if (persp == null) {
return false;
}
return persp.isEditorAreaVisible();
}
/**
* Returns whether the view is fast.
*/
public boolean isFastView(IViewReference ref) {
Perspective persp = getActivePerspective();
if (persp != null) {
return persp.isFastView(ref);
} else {
return false;
}
}
/**
* Return whether the view is closeable or not.
*
* @param ref the view reference to check. Must not be <code>null</code>.
* @return true if the part is closeable.
* @since 3.1.1
*/
public boolean isCloseable(IViewReference ref) {
Perspective persp = getActivePerspective();
if (persp != null) {
return persp.isCloseable(ref);
}
return false;
}
/**
* Return whether the view is moveable or not.
*
* @param ref the view reference to check. Must not be <code>null</code>.
* @return true if the part is moveable.
* @since 3.1.1
*/
public boolean isMoveable(IViewReference ref) {
Perspective persp = getActivePerspective();
if (persp != null) {
return persp.isMoveable(ref);
}
return false;
}
/**
* Returns whether the layout of the active
* perspective is fixed.
*/
public boolean isFixedLayout() {
Perspective persp = getActivePerspective();
if (persp != null) {
return persp.isFixedLayout();
} else {
return false;
}
}
/**
* Return the active fast view or null if there are no fast views or if
* there are all minimized.
*/
public IViewReference getActiveFastView() {
Perspective persp = getActivePerspective();
if (persp != null) {
return persp.getActiveFastView();
} else {
return null;
}
}
/**
* Return true if the perspective has a dirty editor.
*/
protected boolean isSaveNeeded() {
return getEditorManager().isSaveAllNeeded();
}
/* (non-Javadoc)
* @see org.eclipse.ui.IWorkbenchPage#isPageZoomed()
*/
public boolean isPageZoomed() {
Perspective persp = getActivePerspective();
if (persp == null) {
return false;
}
if (persp.getPresentation() == null) {
return false;
}
if (Perspective.useNewMinMax(persp))
return persp.getPresentation().getMaximizedStack() != null;
// Default to the legacy code
return isZoomed();
}
/**
* Returns whether the page is zoomed.
* @return <code>true</code> if the page is zoomed.
*
* <strong>NOTE:</strong> As of 3.3 this method should always return 'false'
* when using the new min/max behavior. It is only used for
* legacy 'zoom' handling.
*
*/
public boolean isZoomed() {
Perspective persp = getActivePerspective();
if (persp == null) {
return false;
}
if (persp.getPresentation() == null) {
return false;
}
return persp.getPresentation().isZoomed();
}
/**
* This method is called when the page is activated.
*/
protected void onActivate() {
composite.setVisible(true);
Perspective persp = getActivePerspective();
if (persp != null) {
persp.onActivate();
updateVisibility(null, persp);
}
}
/**
* This method is called when the page is deactivated.
*/
protected void onDeactivate() {
makeActiveEditor(null);
makeActive(null);
if (getActivePerspective() != null) {
getActivePerspective().onDeactivate();
}
composite.setVisible(false);
}
/**
* See IWorkbenchPage.
*/
public void reuseEditor(IReusableEditor editor, IEditorInput input) {
// Rather than calling editor.setInput on the editor directly, we do it through the part reference.
// This case lets us detect badly behaved editors that are not firing a PROP_INPUT event in response
// to the input change... but if all editors obeyed their API contract, the "else" branch would be
// sufficient.
IWorkbenchPartReference ref = getReference(editor);
if (ref instanceof EditorReference) {
EditorReference editorRef = (EditorReference) ref;
editorRef.setInput(input);
} else {
editor.setInput(input);
}
navigationHistory.markEditor(editor);
}
/**
* See IWorkbenchPage.
*/
public IEditorPart openEditor(IEditorInput input, String editorID)
throws PartInitException {
return openEditor(input, editorID, true, MATCH_INPUT);
}
/**
* See IWorkbenchPage.
*/
public IEditorPart openEditor(IEditorInput input, String editorID,
boolean activate) throws PartInitException {
return openEditor(input, editorID, activate, MATCH_INPUT);
}
/**
* See IWorkbenchPage.
*/
public IEditorPart openEditor(final IEditorInput input,
final String editorID, final boolean activate, final int matchFlags)
throws PartInitException {
return openEditor(input, editorID, activate, matchFlags, null);
}
/**
* This is not public API but for use internally. editorState can be <code>null</code>.
*/
public IEditorPart openEditor(final IEditorInput input,
final String editorID, final boolean activate, final int matchFlags,
final IMemento editorState)
throws PartInitException {
if (input == null || editorID == null) {
throw new IllegalArgumentException();
}
final IEditorPart result[] = new IEditorPart[1];
final PartInitException ex[] = new PartInitException[1];
BusyIndicator.showWhile(window.getWorkbench().getDisplay(),
new Runnable() {
public void run() {
try {
result[0] = busyOpenEditor(input, editorID,
activate, matchFlags, editorState);
} catch (PartInitException e) {
ex[0] = e;
}
}
});
if (ex[0] != null) {
throw ex[0];
}
return result[0];
}
/*
* Added to fix Bug 178235 [EditorMgmt] DBCS 3.3 - Cannot open file with external program.
* Opens a new editor using the given input and descriptor. (Normally, editors are opened using
* an editor ID and an input.)
*/
public IEditorPart openEditorFromDescriptor(final IEditorInput input,
final IEditorDescriptor editorDescriptor, final boolean activate,
final IMemento editorState)
throws PartInitException {
if (input == null || !(editorDescriptor instanceof EditorDescriptor)) {
throw new IllegalArgumentException();
}
final IEditorPart result[] = new IEditorPart[1];
final PartInitException ex[] = new PartInitException[1];
BusyIndicator.showWhile(window.getWorkbench().getDisplay(),
new Runnable() {
public void run() {
try {
result[0] = busyOpenEditorFromDescriptor(input, (EditorDescriptor)editorDescriptor,
activate, editorState);
} catch (PartInitException e) {
ex[0] = e;
}
}
});
if (ex[0] != null) {
throw ex[0];
}
return result[0];
}
/**
* @see #openEditor(IEditorInput, String, boolean, int)
*/
private IEditorPart busyOpenEditor(IEditorInput input, String editorID,
boolean activate, int matchFlags, IMemento editorState) throws PartInitException {
final Workbench workbench = (Workbench) getWorkbenchWindow()
.getWorkbench();
workbench.largeUpdateStart();
try {
return busyOpenEditorBatched(input, editorID, activate, matchFlags, editorState);
} finally {
workbench.largeUpdateEnd();
}
}
/*
* Added to fix Bug 178235 [EditorMgmt] DBCS 3.3 - Cannot open file with external program.
* See openEditorFromDescriptor().
*/
private IEditorPart busyOpenEditorFromDescriptor(IEditorInput input, EditorDescriptor editorDescriptor,
boolean activate, IMemento editorState) throws PartInitException {
final Workbench workbench = (Workbench) getWorkbenchWindow()
.getWorkbench();
workbench.largeUpdateStart();
try {
return busyOpenEditorFromDescriptorBatched(input, editorDescriptor, activate, editorState);
} finally {
workbench.largeUpdateEnd();
}
}
/**
* Do not call this method. Use <code>busyOpenEditor</code>.
*
* @see IWorkbenchPage#openEditor(IEditorInput, String, boolean)
*/
private IEditorPart busyOpenEditorBatched(IEditorInput input,
String editorID, boolean activate, int matchFlags, IMemento editorState) throws PartInitException {
// If an editor already exists for the input, use it.
IEditorPart editor = null;
// Reuse an existing open editor, unless we are in "new editor tab management" mode
editor = getEditorManager().findEditor(editorID, input, ((TabBehaviour)Tweaklets.get(TabBehaviour.KEY)).getReuseEditorMatchFlags(matchFlags));
if (editor != null) {
if (IEditorRegistry.SYSTEM_EXTERNAL_EDITOR_ID.equals(editorID)) {
if (editor.isDirty()) {
MessageDialog dialog = new MessageDialog(
getWorkbenchWindow().getShell(),
WorkbenchMessages.Save,
null, // accept the default window icon
NLS.bind(WorkbenchMessages.WorkbenchPage_editorAlreadyOpenedMsg, input.getName()),
MessageDialog.QUESTION, new String[] {
IDialogConstants.YES_LABEL,
IDialogConstants.NO_LABEL,
IDialogConstants.CANCEL_LABEL }, 0);
int saveFile = dialog.open();
if (saveFile == 0) {
try {
final IEditorPart editorToSave = editor;
getWorkbenchWindow().run(false, false,
new IRunnableWithProgress() {
public void run(IProgressMonitor monitor)
throws InvocationTargetException,
InterruptedException {
editorToSave.doSave(monitor);
}
});
} catch (InvocationTargetException e) {
throw (RuntimeException) e.getTargetException();
} catch (InterruptedException e) {
return null;
}
} else if (saveFile == 2) {
return null;
}
}
} else {
// do the IShowEditorInput notification before showing the editor
// to reduce flicker
if (editor instanceof IShowEditorInput) {
((IShowEditorInput) editor).showEditorInput(input);
}
showEditor(activate, editor);
return editor;
}
}
// Otherwise, create a new one. This may cause the new editor to
// become the visible (i.e top) editor.
IEditorReference ref = null;
ref = getEditorManager().openEditor(editorID, input, true, editorState);
if (ref != null) {
editor = ref.getEditor(true);
}
if (editor != null) {
setEditorAreaVisible(true);
if (activate) {
if (editor instanceof MultiEditor) {
activate(((MultiEditor) editor).getActiveEditor());
} else {
activate(editor);
}
} else {
bringToTop(editor);
}
window.firePerspectiveChanged(this, getPerspective(), ref,
CHANGE_EDITOR_OPEN);
window.firePerspectiveChanged(this, getPerspective(),
CHANGE_EDITOR_OPEN);
}
return editor;
}
/*
* Added to fix Bug 178235 [EditorMgmt] DBCS 3.3 - Cannot open file with external program.
* See openEditorFromDescriptor().
*/
private IEditorPart busyOpenEditorFromDescriptorBatched(IEditorInput input,
EditorDescriptor editorDescriptor, boolean activate, IMemento editorState) throws PartInitException {
IEditorPart editor = null;
// Create a new one. This may cause the new editor to
// become the visible (i.e top) editor.
IEditorReference ref = null;
ref = getEditorManager().openEditorFromDescriptor(editorDescriptor, input, editorState);
if (ref != null) {
editor = ref.getEditor(true);
}
if (editor != null) {
setEditorAreaVisible(true);
if (activate) {
if (editor instanceof MultiEditor) {
activate(((MultiEditor) editor).getActiveEditor());
} else {
activate(editor);
}
} else {
bringToTop(editor);
}
window.firePerspectiveChanged(this, getPerspective(), ref,
CHANGE_EDITOR_OPEN);
window.firePerspectiveChanged(this, getPerspective(),
CHANGE_EDITOR_OPEN);
}
return editor;
}
public void openEmptyTab() {
IEditorPart editor = null;
EditorReference ref = null;
ref = (EditorReference) getEditorManager().openEmptyTab();
if (ref != null) {
editor = ref.getEmptyEditor((EditorDescriptor) ((EditorRegistry) WorkbenchPlugin
.getDefault().getEditorRegistry())
.findEditor(EditorRegistry.EMPTY_EDITOR_ID));
}
if (editor != null) {
setEditorAreaVisible(true);
activate(editor);
window.firePerspectiveChanged(this, getPerspective(), ref,
CHANGE_EDITOR_OPEN);
window.firePerspectiveChanged(this, getPerspective(),
CHANGE_EDITOR_OPEN);
}
}
private void showEditor(boolean activate, IEditorPart editor) {
setEditorAreaVisible(true);
if (activate) {
zoomOutIfNecessary(editor);
activate(editor);
} else {
bringToTop(editor);
}
}
/**
* See IWorkbenchPage.
*/
public boolean isEditorPinned(IEditorPart editor) {
WorkbenchPartReference ref = (WorkbenchPartReference)getReference(editor);
return ref != null && ref.isPinned();
}
/**
* Returns whether changes to a part will affect zoom. There are a few
* conditions for this .. - we are zoomed. - the part is contained in the
* main window. - the part is not the zoom part - the part is not a fast
* view - the part and the zoom part are not in the same editor workbook
*/
private boolean partChangeAffectsZoom(IWorkbenchPartReference ref) {
PartPane pane = ((WorkbenchPartReference) ref).getPane();
if (pane instanceof MultiEditorInnerPane) {
pane = ((MultiEditorInnerPane) pane).getParentPane();
}
return getActivePerspective().getPresentation().partChangeAffectsZoom(
pane);
}
/**
* Removes a fast view.
*/
public void removeFastView(IViewReference ref) {
Perspective persp = getActivePerspective();
if (persp == null) {
return;
}
// Do real work.
persp.removeFastView(ref);
// Notify listeners.
window.firePerspectiveChanged(this, getPerspective(), ref,
CHANGE_FAST_VIEW_REMOVE);
window.firePerspectiveChanged(this, getPerspective(),
CHANGE_FAST_VIEW_REMOVE);
}
/**
* Removes an IPartListener from the part service.
*/
public void removePartListener(IPartListener l) {
partList.getPartService().removePartListener(l);
}
/**
* Removes an IPartListener from the part service.
*/
public void removePartListener(IPartListener2 l) {
partList.getPartService().removePartListener(l);
}
/**
* Implements IWorkbenchPage
*
* @see org.eclipse.ui.IWorkbenchPage#removePropertyChangeListener(IPropertyChangeListener)
* @since 2.0
* @deprecated individual views should store a working set if needed and
* register a property change listener directly with the
* working set manager to receive notification when the view
* working set is removed.
*/
public void removePropertyChangeListener(IPropertyChangeListener listener) {
propertyChangeListeners.remove(listener);
}
/*
* (non-Javadoc) Method declared on ISelectionListener.
*/
public void removeSelectionListener(ISelectionListener listener) {
selectionService.removeSelectionListener(listener);
}
/*
* (non-Javadoc) Method declared on ISelectionListener.
*/
public void removeSelectionListener(String partId,
ISelectionListener listener) {
selectionService.removeSelectionListener(partId, listener);
}
/*
* (non-Javadoc) Method declared on ISelectionListener.
*/
public void removePostSelectionListener(ISelectionListener listener) {
selectionService.removePostSelectionListener(listener);
}
/*
* (non-Javadoc) Method declared on ISelectionListener.
*/
public void removePostSelectionListener(String partId,
ISelectionListener listener) {
selectionService.removePostSelectionListener(partId, listener);
}
/**
* This method is called when a part is activated by clicking within it. In
* response, the part, the pane, and all of its actions will be activated.
*
* In the current design this method is invoked by the part pane when the
* pane, the part, or any children gain focus.
*/
public void requestActivation(IWorkbenchPart part) {
// Sanity check.
if (!certifyPart(part)) {
return;
}
if (part instanceof MultiEditor) {
part = ((MultiEditor) part).getActiveEditor();
}
// Real work.
setActivePart(part);
}
/**
* Resets the layout for the perspective. The active part in the old layout
* is activated in the new layout for consistent user context.
*/
public void resetPerspective() {
// Run op in busy cursor.
// Use set redraw to eliminate the "flash" that can occur in the
// coolbar as the perspective is reset.
ICoolBarManager2 mgr = (ICoolBarManager2) window.getCoolBarManager2();
try {
mgr.getControl2().setRedraw(false);
BusyIndicator.showWhile(null, new Runnable() {
public void run() {
busyResetPerspective();
}
});
} finally {
mgr.getControl2().setRedraw(true);
}
}
/**
* Restore this page from the memento and ensure that the active
* perspective is equals the active descriptor otherwise create a new
* perspective for that descriptor. If activeDescriptor is null active the
* old perspective.
*/
public IStatus restoreState(IMemento memento,
final IPerspectiveDescriptor activeDescriptor) {
StartupThreading.runWithoutExceptions(new StartupRunnable() {
public void runWithException() throws Throwable {
deferUpdates(true);
}});
try {
// Restore working set
String pageName = memento.getString(IWorkbenchConstants.TAG_LABEL);
String label = null; // debugging only
if (UIStats.isDebugging(UIStats.RESTORE_WORKBENCH)) {
label = pageName == null ? "" : "::" + pageName; //$NON-NLS-1$ //$NON-NLS-2$
}
try {
UIStats.start(UIStats.RESTORE_WORKBENCH, "WorkbenchPage" + label); //$NON-NLS-1$
if (pageName == null) {
pageName = ""; //$NON-NLS-1$
}
final MultiStatus result = new MultiStatus(
PlatformUI.PLUGIN_ID,
IStatus.OK,
NLS.bind(WorkbenchMessages.WorkbenchPage_unableToRestorePerspective, pageName ),
null);
String workingSetName = memento
.getString(IWorkbenchConstants.TAG_WORKING_SET);
if (workingSetName != null) {
AbstractWorkingSetManager workingSetManager = (AbstractWorkingSetManager) getWorkbenchWindow()
.getWorkbench().getWorkingSetManager();
setWorkingSet(workingSetManager.getWorkingSet(workingSetName));
}
IMemento workingSetMem = memento
.getChild(IWorkbenchConstants.TAG_WORKING_SETS);
if (workingSetMem != null) {
IMemento[] workingSetChildren = workingSetMem
.getChildren(IWorkbenchConstants.TAG_WORKING_SET);
List workingSetList = new ArrayList(
workingSetChildren.length);
for (int i = 0; i < workingSetChildren.length; i++) {
IWorkingSet set = getWorkbenchWindow().getWorkbench()
.getWorkingSetManager().getWorkingSet(
workingSetChildren[i].getID());
if (set != null) {
workingSetList.add(set);
}
}
workingSets = (IWorkingSet[]) workingSetList
.toArray(new IWorkingSet[workingSetList.size()]);
}
aggregateWorkingSetId = memento.getString(ATT_AGGREGATE_WORKING_SET_ID);
IWorkingSet setWithId = window.getWorkbench().getWorkingSetManager().getWorkingSet(aggregateWorkingSetId);
// check to see if the set has already been made and assign it if it has
if (setWithId instanceof AggregateWorkingSet) {
aggregateWorkingSet = (AggregateWorkingSet) setWithId;
}
// Restore editor manager.
IMemento childMem = memento
.getChild(IWorkbenchConstants.TAG_EDITORS);
result.merge(getEditorManager().restoreState(childMem));
childMem = memento.getChild(IWorkbenchConstants.TAG_VIEWS);
if (childMem != null) {
result.merge(getViewFactory().restoreState(childMem));
}
// Get persp block.
childMem = memento.getChild(IWorkbenchConstants.TAG_PERSPECTIVES);
String activePartID = childMem
.getString(IWorkbenchConstants.TAG_ACTIVE_PART);
String activePartSecondaryID = null;
if (activePartID != null) {
activePartSecondaryID = ViewFactory
.extractSecondaryId(activePartID);
if (activePartSecondaryID != null) {
activePartID = ViewFactory.extractPrimaryId(activePartID);
}
}
final String activePerspectiveID = childMem
.getString(IWorkbenchConstants.TAG_ACTIVE_PERSPECTIVE);
// Restore perspectives.
final IMemento perspMems[] = childMem
.getChildren(IWorkbenchConstants.TAG_PERSPECTIVE);
final Perspective activePerspectiveArray [] = new Perspective[1];
for (int i = 0; i < perspMems.length; i++) {
final IMemento current = perspMems[i];
StartupThreading
.runWithoutExceptions(new StartupRunnable() {
public void runWithException() throws Throwable {
Perspective persp = new Perspective(null,
WorkbenchPage.this);
result.merge(persp.restoreState(current));
final IPerspectiveDescriptor desc = persp
.getDesc();
if (desc.equals(activeDescriptor)) {
activePerspectiveArray[0] = persp;
} else if ((activePerspectiveArray[0] == null)
&& desc.getId().equals(
activePerspectiveID)) {
activePerspectiveArray[0] = persp;
}
perspList.add(persp);
window.firePerspectiveOpened(
WorkbenchPage.this, desc);
}
});
}
Perspective activePerspective = activePerspectiveArray[0];
boolean restoreActivePerspective = false;
if (activeDescriptor == null) {
restoreActivePerspective = true;
} else if (activePerspective != null
&& activePerspective.getDesc().equals(activeDescriptor)) {
restoreActivePerspective = true;
} else {
restoreActivePerspective = false;
activePerspective = createPerspective((PerspectiveDescriptor) activeDescriptor, true);
if (activePerspective == null) {
result
.merge(new Status(
IStatus.ERROR,
PlatformUI.PLUGIN_ID,
0,
NLS.bind(WorkbenchMessages.Workbench_showPerspectiveError, activeDescriptor.getId() ),
null));
}
}
perspList.setActive(activePerspective);
// Make sure we have a valid perspective to work with,
// otherwise return.
activePerspective = perspList.getActive();
if (activePerspective == null) {
activePerspective = perspList.getNextActive();
perspList.setActive(activePerspective);
}
if (activePerspective != null && restoreActivePerspective) {
result.merge(activePerspective.restoreState());
}
if (activePerspective != null) {
final Perspective myPerspective = activePerspective;
final String myActivePartId = activePartID, mySecondaryId = activePartSecondaryID;
StartupThreading.runWithoutExceptions(new StartupRunnable() {
public void runWithException() throws Throwable {
window.firePerspectiveActivated(WorkbenchPage.this, myPerspective
.getDesc());
// Restore active part.
if (myActivePartId != null) {
IViewReference ref = myPerspective.findView(
myActivePartId, mySecondaryId);
if (ref != null) {
activationList.setActive(ref);
}
}
}});
}
childMem = memento
.getChild(IWorkbenchConstants.TAG_NAVIGATION_HISTORY);
if (childMem != null) {
navigationHistory.restoreState(childMem);
} else if (getActiveEditor() != null) {
navigationHistory.markEditor(getActiveEditor());
}
// restore sticky view state
stickyViewMan.restore(memento);
return result;
} finally {
String blame = activeDescriptor == null ? pageName : activeDescriptor.getId();
UIStats.end(UIStats.RESTORE_WORKBENCH, blame, "WorkbenchPage" + label); //$NON-NLS-1$
}
} finally {
StartupThreading.runWithoutExceptions(new StartupRunnable() {
public void runWithException() throws Throwable {
deferUpdates(false);
}
});
}
}
/**
* See IWorkbenchPage
*/
public boolean saveAllEditors(boolean confirm) {
return saveAllEditors(confirm, false);
}
/**
* @param confirm
* @param addNonPartSources true if saveables from non-part sources should be saved too
* @return false if the user cancelled
*
*/
public boolean saveAllEditors(boolean confirm, boolean addNonPartSources) {
return getEditorManager().saveAll(confirm, false, addNonPartSources);
}
/*
* Saves the workbench part.
*/
protected boolean savePart(ISaveablePart saveable, IWorkbenchPart part,
boolean confirm) {
// Do not certify part do allow editors inside a multipageeditor to
// call this.
return getEditorManager().savePart(saveable, part, confirm);
}
/**
* Saves an editors in the workbench. If <code>confirm</code> is <code>true</code>
* the user is prompted to confirm the command.
*
* @param confirm
* if user confirmation should be sought
* @return <code>true</code> if the command succeeded, or <code>false</code>
* if the user cancels the command
*/
public boolean saveEditor(IEditorPart editor, boolean confirm) {
return savePart(editor, editor, confirm);
}
/**
* Saves the current perspective.
*/
public void savePerspective() {
Perspective persp = getActivePerspective();
if (persp == null) {
return;
}
// Always unzoom.
if (isZoomed()) {
zoomOut();
}
persp.saveDesc();
}
/**
* Saves the perspective.
*/
public void savePerspectiveAs(IPerspectiveDescriptor newDesc) {
Perspective persp = getActivePerspective();
if (persp == null) {
return;
}
IPerspectiveDescriptor oldDesc = persp.getDesc();
// Always unzoom.
if (isZoomed()) {
zoomOut();
}
persp.saveDescAs(newDesc);
window.firePerspectiveSavedAs(this, oldDesc, newDesc);
}
/**
* Save the state of the page.
*/
public IStatus saveState(IMemento memento) {
// We must unzoom to get correct layout.
if (isZoomed()) {
zoomOut();
}
MultiStatus result = new MultiStatus(
PlatformUI.PLUGIN_ID,
IStatus.OK,
NLS.bind(WorkbenchMessages.WorkbenchPage_unableToSavePerspective, getLabel()),
null);
// Save editor manager.
IMemento childMem = memento
.createChild(IWorkbenchConstants.TAG_EDITORS);
result.merge(editorMgr.saveState(childMem));
childMem = memento.createChild(IWorkbenchConstants.TAG_VIEWS);
result.merge(getViewFactory().saveState(childMem));
// Create persp block.
childMem = memento.createChild(IWorkbenchConstants.TAG_PERSPECTIVES);
if (getPerspective() != null) {
childMem.putString(IWorkbenchConstants.TAG_ACTIVE_PERSPECTIVE,
getPerspective().getId());
}
if (getActivePart() != null) {
if (getActivePart() instanceof IViewPart) {
IViewReference ref = (IViewReference) getReference(getActivePart());
if (ref != null) {
childMem.putString(IWorkbenchConstants.TAG_ACTIVE_PART,
ViewFactory.getKey(ref));
}
} else {
childMem.putString(IWorkbenchConstants.TAG_ACTIVE_PART,
getActivePart().getSite().getId());
}
}
// Save each perspective in opened order
Iterator itr = perspList.iterator();
while (itr.hasNext()) {
Perspective persp = (Perspective) itr.next();
IMemento gChildMem = childMem
.createChild(IWorkbenchConstants.TAG_PERSPECTIVE);
result.merge(persp.saveState(gChildMem));
}
// Save working set if set
if (workingSet != null) {
memento.putString(IWorkbenchConstants.TAG_WORKING_SET, workingSet
.getName());
}
IMemento workingSetMem = memento
.createChild(IWorkbenchConstants.TAG_WORKING_SETS);
for (int i = 0; i < workingSets.length; i++) {
workingSetMem.createChild(IWorkbenchConstants.TAG_WORKING_SET,
workingSets[i].getName());
}
if (aggregateWorkingSetId != null) {
memento.putString(ATT_AGGREGATE_WORKING_SET_ID, aggregateWorkingSetId);
}
navigationHistory.saveState(memento
.createChild(IWorkbenchConstants.TAG_NAVIGATION_HISTORY));
// save the sticky activation state
stickyViewMan.save(memento);
return result;
}
private String getId(IWorkbenchPart part) {
return getId(getReference(part));
}
private String getId(IWorkbenchPartReference ref) {
if (ref == null) {
return "null"; //$NON-NLS-1$
} return ref.getId();
}
/**
* Sets the active part.
*/
private void setActivePart(IWorkbenchPart newPart) {
// Optimize it.
if (getActivePart() == newPart) {
return;
}
if (partBeingActivated != null) {
if (partBeingActivated.getPart(false) != newPart) {
WorkbenchPlugin.log(new RuntimeException(NLS.bind(
"WARNING: Prevented recursive attempt to activate part {0} while still in the middle of activating part {1}", //$NON-NLS-1$
getId(newPart), getId(partBeingActivated))));
}
return;
}
//No need to change the history if the active editor is becoming the
// active part
String label = null; // debugging only
if (UIStats.isDebugging(UIStats.ACTIVATE_PART)) {
label = newPart != null ? newPart.getTitle() : "none"; //$NON-NLS-1$
}
try {
IWorkbenchPartReference partref = getReference(newPart);
IWorkbenchPartReference realPartRef = null;
if (newPart != null) {
IWorkbenchPartSite site = newPart.getSite();
if (site instanceof PartSite) {
realPartRef = ((PartSite) site).getPane()
.getPartReference();
}
}
partBeingActivated = realPartRef;
UIStats.start(UIStats.ACTIVATE_PART, label);
// Notify perspective. It may deactivate fast view.
Perspective persp = getActivePerspective();
if (persp != null) {
persp.partActivated(newPart);
}
// Deactivate old part
IWorkbenchPart oldPart = getActivePart();
if (oldPart != null) {
deactivatePart(oldPart);
}
// Set active part.
if (newPart != null) {
activationList.setActive(newPart);
if (newPart instanceof IEditorPart) {
makeActiveEditor((IEditorReference)realPartRef);
}
}
activatePart(newPart);
actionSwitcher.updateActivePart(newPart);
partList.setActivePart(partref);
} finally {
partBeingActivated = null;
Object blame = newPart == null ? (Object)this : newPart;
UIStats.end(UIStats.ACTIVATE_PART, blame, label);
}
}
/**
* See IWorkbenchPage.
*/
public void setEditorAreaVisible(boolean showEditorArea) {
Perspective persp = getActivePerspective();
if (persp == null) {
return;
}
if (showEditorArea == persp.isEditorAreaVisible()) {
return;
}
// If parts change always update zoom.
if (isZoomed()) {
zoomOut();
}
// Update editor area visibility.
if (showEditorArea) {
persp.showEditorArea();
window.firePerspectiveChanged(this, getPerspective(),
CHANGE_EDITOR_AREA_SHOW);
} else {
persp.hideEditorArea();
updateActivePart();
window.firePerspectiveChanged(this, getPerspective(),
CHANGE_EDITOR_AREA_HIDE);
}
}
/**
* Sets the layout of the page. Assumes the new perspective is not null.
* Keeps the active part if possible. Updates the window menubar and
* toolbar if necessary.
*/
private void setPerspective(Perspective newPersp) {
// Don't do anything if already active layout
Perspective oldPersp = getActivePerspective();
if (oldPersp == newPersp) {
return;
}
window.largeUpdateStart();
try {
if (oldPersp != null) {
// fire the pre-deactivate
window.firePerspectivePreDeactivate(this, oldPersp.getDesc());
}
if (newPersp != null) {
IStatus status = newPersp.restoreState();
if (status.getSeverity() != IStatus.OK) {
String title = WorkbenchMessages.WorkbenchPage_problemRestoringTitle;
String msg = WorkbenchMessages.WorkbenchPage_errorReadingState;
ErrorDialog.openError(getWorkbenchWindow().getShell(), title,
msg, status);
}
}
// Deactivate the old layout
if (oldPersp != null) {
oldPersp.onDeactivate();
// Notify listeners of deactivation
window.firePerspectiveDeactivated(this, oldPersp.getDesc());
}
// Activate the new layout
perspList.setActive(newPersp);
if (newPersp != null) {
newPersp.onActivate();
// Notify listeners of activation
window.firePerspectiveActivated(this, newPersp.getDesc());
}
updateVisibility(oldPersp, newPersp);
// Update the window
window.updateActionSets();
// Update sticky views
stickyViewMan.update(oldPersp, newPersp);
} finally {
window.largeUpdateEnd();
if (newPersp == null) {
return;
}
IPerspectiveDescriptor desc = newPersp.getDesc();
if (desc == null) {
return;
}
if (dirtyPerspectives.remove(desc.getId())) {
suggestReset();
}
}
}
void perspectiveActionSetChanged(Perspective perspective, IActionSetDescriptor descriptor, int changeType) {
if (perspective == getActivePerspective()) {
actionSets.change(descriptor, changeType);
}
}
/*
* Update visibility state of all views.
*/
private void updateVisibility(Perspective oldPersp, Perspective newPersp) {
// Flag all parts in the old perspective
IWorkbenchPartReference[] oldRefs = new IWorkbenchPartReference[0];
if (oldPersp != null) {
oldRefs = oldPersp.getViewReferences();
for (int i = 0; i < oldRefs.length; i++) {
PartPane pane = ((WorkbenchPartReference) oldRefs[i]).getPane();
pane.setInLayout(false);
}
}
PerspectiveHelper pres = null;
// Make parts in the new perspective visible
if (newPersp != null) {
pres = newPersp.getPresentation();
IWorkbenchPartReference[] newRefs = newPersp.getViewReferences();
for (int i = 0; i < newRefs.length; i++) {
WorkbenchPartReference ref = (WorkbenchPartReference)newRefs[i];
PartPane pane = ref.getPane();
if (pres.isPartVisible(ref)) {
activationList.bringToTop(ref);
}
pane.setInLayout(true);
}
}
updateActivePart();
// Hide any parts in the old perspective that are no longer visible
for (int i = 0; i < oldRefs.length; i++) {
WorkbenchPartReference ref = (WorkbenchPartReference)oldRefs[i];
PartPane pane = ref.getPane();
if (pres == null || !pres.isPartVisible(ref)) {
pane.setVisible(false);
}
}
}
/**
* Sets the perspective.
*
* @param desc
* identifies the new perspective.
*/
public void setPerspective(final IPerspectiveDescriptor desc) {
if (Util.equals(getPerspective(), desc)) {
return;
}
// Going from multiple to single rows can make the coolbar
// and its adjacent views appear jumpy as perspectives are
// switched. Turn off redraw to help with this.
ICoolBarManager2 mgr = (ICoolBarManager2) window.getCoolBarManager2();
try {
mgr.getControl2().setRedraw(false);
getClientComposite().setRedraw(false);
// Run op in busy cursor.
BusyIndicator.showWhile(null, new Runnable() {
public void run() {
busySetPerspective(desc);
}
});
} finally {
getClientComposite().setRedraw(true);
mgr.getControl2().setRedraw(true);
IWorkbenchPart part = getActivePart();
if (part != null) {
part.setFocus();
}
}
}
/**
* Allow access to the part service for this page ... used internally to
* propogate certain types of events to the page part listeners.
* @return the part service for this page.
*/
public PartService getPartService() {
return (PartService)partList.getPartService();
}
/**
* Restore the toolbar layout for the active perspective.
*/
protected void resetToolBarLayout() {
ICoolBarManager2 mgr = (ICoolBarManager2) window.getCoolBarManager2();
mgr.resetItemOrder();
}
/**
* Sets the active working set for the workbench page. Notifies property
* change listener about the change.
*
* @param newWorkingSet
* the active working set for the page. May be null.
* @since 2.0
* @deprecated individual views should store a working set if needed
*/
public void setWorkingSet(IWorkingSet newWorkingSet) {
IWorkingSet oldWorkingSet = workingSet;
workingSet = newWorkingSet;
if (oldWorkingSet != newWorkingSet) {
firePropertyChange(CHANGE_WORKING_SET_REPLACE, oldWorkingSet,
newWorkingSet);
}
if (newWorkingSet != null) {
WorkbenchPlugin.getDefault().getWorkingSetManager()
.addPropertyChangeListener(workingSetPropertyChangeListener);
} else {
WorkbenchPlugin.getDefault().getWorkingSetManager()
.removePropertyChangeListener(workingSetPropertyChangeListener);
}
}
/**
* @see IWorkbenchPage
*/
public void showActionSet(String actionSetID) {
Perspective persp = getActivePerspective();
if (persp != null) {
ActionSetRegistry reg = WorkbenchPlugin.getDefault()
.getActionSetRegistry();
IActionSetDescriptor desc = reg.findActionSet(actionSetID);
if (desc != null) {
persp.addActionSet(desc);
window.updateActionSets();
window.firePerspectiveChanged(this, getPerspective(),
CHANGE_ACTION_SET_SHOW);
}
}
}
/**
* See IWorkbenchPage.
*/
public IViewPart showView(String viewID) throws PartInitException {
return showView(viewID, null, VIEW_ACTIVATE);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.IWorkbenchPage#showView(java.lang.String,
* java.lang.String, int)
*/
public IViewPart showView(final String viewID, final String secondaryID,
final int mode) throws PartInitException {
if (secondaryID != null) {
if (secondaryID.length() == 0
|| secondaryID.indexOf(ViewFactory.ID_SEP) != -1) {
throw new IllegalArgumentException(WorkbenchMessages.WorkbenchPage_IllegalSecondaryId);
}
}
if (!certifyMode(mode)) {
throw new IllegalArgumentException(WorkbenchMessages.WorkbenchPage_IllegalViewMode);
}
// Run op in busy cursor.
final Object[] result = new Object[1];
BusyIndicator.showWhile(null, new Runnable() {
public void run() {
try {
result[0] = busyShowView(viewID, secondaryID, mode);
} catch (PartInitException e) {
result[0] = e;
}
}
});
if (result[0] instanceof IViewPart) {
return (IViewPart) result[0];
} else if (result[0] instanceof PartInitException) {
throw (PartInitException) result[0];
} else {
throw new PartInitException(WorkbenchMessages.WorkbenchPage_AbnormalWorkbenchCondition);
}
}
/**
* @param mode the mode to test
* @return whether the mode is recognized
* @since 3.0
*/
private boolean certifyMode(int mode) {
switch (mode) {
case VIEW_ACTIVATE:
case VIEW_VISIBLE:
case VIEW_CREATE:
return true;
default:
return false;
}
}
/**
* Hides the active fast view. Has no effect if there is no fast view active.
*/
public void hideFastView() {
Perspective persp = getActivePerspective();
if (persp != null) {
IViewReference ref = persp.getActiveFastView();
if (ref != null) {
toggleFastView(ref);
}
}
}
/**
* Toggles the visibility of a fast view. If the view is active it is
* deactivated. Otherwise, it is activated.
*/
public void toggleFastView(IViewReference ref) {
Perspective persp = getActivePerspective();
if (persp != null) {
persp.toggleFastView(ref);
// if the fast view has been deactivated
if (ref != persp.getActiveFastView()) {
IWorkbenchPart previouslyActive = activationList
.getPreviouslyActive();
IEditorPart activeEditor = getActiveEditor();
if (activeEditor != null
&& previouslyActive instanceof IEditorPart) {
setActivePart(activeEditor);
} else {
setActivePart(previouslyActive);
}
}
}
}
/**
* Sets the state of the given part.
*
* @param ref part whose state should be modified (not null)
* @param newState one of the IStackPresentationSite.STATE_* constants
*/
public void setState(IWorkbenchPartReference ref, int newState) {
Perspective persp = getActivePerspective();
if (persp == null) {
return;
}
PartPane pane = ((WorkbenchPartReference) ref).getPane();
// If target part is detached fire the zoom event. Note this doesn't
// actually cause any changes in size and is required to support
// intro state changes. We may want to introduce the notion of a zoomed
// (fullscreen) detached view at a later time.
if (!pane.isDocked()) {
pane.setZoomed(newState == IStackPresentationSite.STATE_MAXIMIZED);
return;
}
if (ref instanceof IViewReference
&& persp.isFastView((IViewReference) ref)) {
persp.setFastViewState(newState);
return;
}
if (Perspective.useNewMinMax(persp)) {
// set the container's state to the new one
PartStack parent = ((PartStack)pane.getContainer());
parent.setState(newState);
return;
}
boolean wasZoomed = isZoomed();
boolean isZoomed = newState == IStackPresentationSite.STATE_MAXIMIZED;
// Update zoom status.
if (wasZoomed && !isZoomed) {
zoomOut();
} else if (!wasZoomed && isZoomed) {
persp.getPresentation().zoomIn(ref);
activate(ref.getPart(true));
}
PartStack parent = ((PartStack)pane.getContainer());
if (parent != null) {
parent.setMinimized(newState == IStackPresentationSite.STATE_MINIMIZED);
}
}
/* (non-Javadoc)
* @see org.eclipse.ui.IWorkbenchPage#setPartState(org.eclipse.ui.IWorkbenchPartReference, int)
*/
public void setPartState(IWorkbenchPartReference ref, int state) {
setState(ref, state);
}
/**
* Returns the maximized/minimized/restored state of the given part reference
*
* @param ref part to query (not null)
* @return one of the IStackPresentationSite.STATE_* constants
*/
int getState(IWorkbenchPartReference ref) {
Perspective persp = getActivePerspective();
if (persp == null) {
return IStackPresentationSite.STATE_RESTORED;
}
PartPane pane = ((WorkbenchPartReference) ref).getPane();
if (ref instanceof IViewReference
&& persp.isFastView((IViewReference) ref)) {
return persp.getFastViewState();
}
PartStack parent = ((PartStack)pane.getContainer());
if (parent != null) {
return parent.getState();
}
return IStackPresentationSite.STATE_RESTORED;
}
/* (non-Javadoc)
* @see org.eclipse.ui.IWorkbenchPage#getPartState(org.eclipse.ui.IWorkbenchPartReference)
*/
public int getPartState(IWorkbenchPartReference ref) {
return getState(ref);
}
/* (non-Javadoc)
* @see org.eclipse.ui.IWorkbenchPage#toggleZoom(org.eclipse.ui.IWorkbenchPartReference)
*/
public void toggleZoom(IWorkbenchPartReference ref) {
int oldState = getState(ref);
boolean shouldZoom = oldState != IStackPresentationSite.STATE_MAXIMIZED;
int newState = shouldZoom ? IStackPresentationSite.STATE_MAXIMIZED : IStackPresentationSite.STATE_RESTORED;
setState(ref, newState);
}
/**
* updateActionBars method comment.
*/
public void updateActionBars() {
window.updateActionBars();
}
/**
* Sets the tab list of this page's composite appropriately when a part is
* activated.
*/
private void updateTabList(IWorkbenchPart part) {
PartSite site = (PartSite) part.getSite();
PartPane pane = site.getPane();
if (pane instanceof ViewPane) {
ViewPane viewPane = (ViewPane) pane;
Control[] tabList = viewPane.getTabList();
if (!pane.isDocked()) {
viewPane.getControl().getShell().setTabList(tabList);
} else {
getClientComposite().setTabList(tabList);
}
} else if (pane instanceof EditorPane) {
EditorSashContainer ea = ((EditorPane) pane).getWorkbook()
.getEditorArea();
ea.updateTabList();
getClientComposite().setTabList(new Control[] { ea.getParent() });
}
}
/* (non-Javadoc)
* @see org.eclipse.ui.IWorkbenchPage#zoomOut()
*/
public void zoomOut() {
Perspective persp = getActivePerspective();
if (persp != null) {
persp.getPresentation().zoomOut();
}
}
/**
* Zooms out a zoomed in part if it is necessary to do so for the user to
* view the IWorkbenchPart that is the argument. Otherwise, does nothing.
*
* @param part
* the part to be made viewable
*/
private void zoomOutIfNecessary(IWorkbenchPart part) {
if (isZoomed() && partChangeAffectsZoom(((PartSite)part.getSite()).getPartReference())) {
zoomOut();
}
}
/**
*
*/
public int getEditorReuseThreshold() {
return ((TabBehaviour)Tweaklets.get(TabBehaviour.KEY)).getEditorReuseThreshold();
}
/**
*
*/
public void setEditorReuseThreshold(int openEditors) {
}
/*
* Returns the editors in activation order (oldest first).
*/
public IEditorReference[] getSortedEditors() {
return activationList.getEditors();
}
/**
* @see IWorkbenchPage#getOpenPerspectives()
*/
public IPerspectiveDescriptor[] getOpenPerspectives() {
Perspective opened[] = perspList.getOpenedPerspectives();
IPerspectiveDescriptor[] result = new IPerspectiveDescriptor[opened.length];
for (int i = 0; i < result.length; i++) {
result[i] = opened[i].getDesc();
}
return result;
}
/**
* Return all open Perspective objects.
*
* @return all open Perspective objects
* @since 3.1
*/
/*package*/Perspective [] getOpenInternalPerspectives() {
return perspList.getOpenedPerspectives();
}
/**
* Checks perspectives in the order they were activiated
* for the specfied part. The first sorted perspective
* that contains the specified part is returned.
*
* @param part specified part to search for
* @return the first sorted perspespective containing the part
* @since 3.1
*/
/*package*/Perspective getFirstPerspectiveWithView(IViewPart part) {
Perspective [] perspectives = perspList.getSortedPerspectives();
for (int i=perspectives.length - 1; i >= 0; i--) {
if (perspectives[i].containsView(part)) {
return perspectives[i];
}
}
// we should never get here
return null;
}
/**
* Returns the perspectives in activation order (oldest first).
*/
public IPerspectiveDescriptor[] getSortedPerspectives() {
Perspective sortedArray[] = perspList.getSortedPerspectives();
IPerspectiveDescriptor[] result = new IPerspectiveDescriptor[sortedArray.length];
for (int i = 0; i < result.length; i++) {
result[i] = sortedArray[i].getDesc();
}
return result;
}
/*
* Returns the parts in activation order (oldest first).
*/
public IWorkbenchPartReference[] getSortedParts() {
return activationList.getParts();
}
/**
* Returns the reference to the given part, or <code>null</code> if it has no reference
* (i.e. it is not a top-level part in this workbench page).
*
* @param part the part
* @return the part's reference or <code>null</code> if the given part does not belong
* to this workbench page
*/
public IWorkbenchPartReference getReference(IWorkbenchPart part) {
if (part == null) {
return null;
}
IWorkbenchPartSite site = part.getSite();
if (!(site instanceof PartSite)) {
return null;
}
PartSite partSite = ((PartSite) site);
PartPane pane = partSite.getPane();
if (pane instanceof MultiEditorInnerPane) {
MultiEditorInnerPane innerPane = (MultiEditorInnerPane) pane;
return innerPane.getParentPane().getPartReference();
}
return partSite.getPartReference();
}
private class ActivationList {
//List of parts in the activation order (oldest first)
List parts = new ArrayList();
/*
* Add/Move the active part to end of the list;
*/
void setActive(IWorkbenchPart part) {
if (parts.size() <= 0) {
return;
}
IWorkbenchPartReference ref = getReference(part);
if (ref != null) {
if (ref == parts.get(parts.size() - 1)) {
return;
}
parts.remove(ref);
parts.add(ref);
}
}
/*
* Ensures that the given part appears AFTER any other part in the same
* container.
*/
void bringToTop(IWorkbenchPartReference ref) {
ILayoutContainer targetContainer = getContainer(ref);
int newIndex = lastIndexOfContainer(targetContainer);
//New index can be -1 if there is no last index
if (newIndex >= 0 && ref == parts.get(newIndex))
return;
parts.remove(ref);
if(newIndex >= 0)
parts.add(newIndex, ref);
else
parts.add(ref);
}
/*
* Returns the last (most recent) index of the given container in the activation list, or returns
* -1 if the given container does not appear in the activation list.
*/
int lastIndexOfContainer(ILayoutContainer container) {
for (int i = parts.size() - 1; i >= 0; i--) {
IWorkbenchPartReference ref = (IWorkbenchPartReference)parts.get(i);
ILayoutContainer cnt = getContainer(ref);
if (cnt == container) {
return i;
}
}
return -1;
}
/*
* Add/Move the active part to end of the list;
*/
void setActive(IWorkbenchPartReference ref) {
setActive(ref.getPart(true));
}
/*
* Add the active part to the beginning of the list.
*/
void add(IWorkbenchPartReference ref) {
if (parts.indexOf(ref) >= 0) {
return;
}
IWorkbenchPart part = ref.getPart(false);
if (part != null) {
PartPane pane = ((PartSite) part.getSite()).getPane();
if (pane instanceof MultiEditorInnerPane) {
MultiEditorInnerPane innerPane = (MultiEditorInnerPane) pane;
add(innerPane.getParentPane().getPartReference());
return;
}
}
parts.add(0, ref);
}
/*
* Return the active part. Filter fast views.
*/
IWorkbenchPart getActive() {
if (parts.isEmpty()) {
return null;
}
return getActive(parts.size() - 1);
}
/*
* Return the previously active part. Filter fast views.
*/
IWorkbenchPart getPreviouslyActive() {
if (parts.size() < 2) {
return null;
}
return getActive(parts.size() - 2);
}
private IWorkbenchPart getActive(int start) {
IWorkbenchPartReference ref = getActiveReference(start, false);
if (ref == null) {
return null;
}
return ref.getPart(true);
}
public IWorkbenchPartReference getActiveReference(boolean editorsOnly) {
return getActiveReference(parts.size() - 1, editorsOnly);
}
private IWorkbenchPartReference getActiveReference(int start, boolean editorsOnly) {
// First look for parts that aren't obscured by the current zoom state
IWorkbenchPartReference nonObscured = getActiveReference(start, editorsOnly, true);
if (nonObscured != null) {
return nonObscured;
}
// Now try all the rest of the parts
return getActiveReference(start, editorsOnly, false);
}
/*
* Find a part in the list starting from the end and filter
* and views from other perspectives. Will filter fast views
* unless 'includeActiveFastViews' is true;
*/
private IWorkbenchPartReference getActiveReference(int start, boolean editorsOnly, boolean skipPartsObscuredByZoom) {
IWorkbenchPartReference[] views = getViewReferences();
for (int i = start; i >= 0; i--) {
WorkbenchPartReference ref = (WorkbenchPartReference) parts
.get(i);
if (editorsOnly && !(ref instanceof IEditorReference)) {
continue;
}
// Skip parts whose containers have disabled auto-focus
PartPane pane = ref.getPane();
if (pane != null) {
if (!pane.allowsAutoFocus()) {
continue;
}
if (skipPartsObscuredByZoom) {
if (pane.isObscuredByZoom()) {
continue;
}
}
}
// Skip fastviews (unless overridden)
if (ref instanceof IViewReference) {
if (ref == getActiveFastView() || !((IViewReference) ref).isFastView()) {
for (int j = 0; j < views.length; j++) {
if (views[j] == ref) {
return ref;
}
}
}
} else {
return ref;
}
}
return null;
}
/*
* Retuns the index of the part within the activation list. The higher
* the index, the more recently it was used.
*/
int indexOf(IWorkbenchPart part) {
IWorkbenchPartReference ref = getReference(part);
if (ref == null) {
return -1;
}
return parts.indexOf(ref);
}
/*
* Returns the index of the part reference within the activation list.
* The higher the index, the more recent it was used.
*/
int indexOf(IWorkbenchPartReference ref) {
return parts.indexOf(ref);
}
/*
* Remove a part from the list
*/
boolean remove(IWorkbenchPartReference ref) {
return parts.remove(ref);
}
/*
* Returns the editors in activation order (oldest first).
*/
private IEditorReference[] getEditors() {
ArrayList editors = new ArrayList(parts.size());
for (Iterator i = parts.iterator(); i.hasNext();) {
IWorkbenchPartReference part = (IWorkbenchPartReference) i
.next();
if (part instanceof IEditorReference) {
editors.add(part);
}
}
return (IEditorReference[]) editors
.toArray(new IEditorReference[editors.size()]);
}
/*
* Return a list with all parts (editors and views).
*/
private IWorkbenchPartReference[] getParts() {
IWorkbenchPartReference[] views = getViewReferences();
ArrayList resultList = new ArrayList(parts.size());
for (Iterator iterator = parts.iterator(); iterator.hasNext();) {
IWorkbenchPartReference ref = (IWorkbenchPartReference) iterator
.next();
if (ref instanceof IViewReference) {
//Filter views from other perspectives
for (int i = 0; i < views.length; i++) {
if (views[i] == ref) {
resultList.add(ref);
break;
}
}
} else {
resultList.add(ref);
}
}
IWorkbenchPartReference[] result = new IWorkbenchPartReference[resultList
.size()];
return (IWorkbenchPartReference[]) resultList.toArray(result);
}
/*
* Returns the topmost editor on the stack, or null if none.
*/
IEditorPart getTopEditor() {
IEditorReference editor = (IEditorReference)getActiveReference(parts.size() - 1, true);
if (editor == null) {
return null;
}
return editor.getEditor(true);
}
}
/**
* Helper class to keep track of all opened perspective. Both the opened
* and used order is kept.
*/
private class PerspectiveList {
/**
* List of perspectives in the order they were opened;
*/
private List openedList;
/**
* List of perspectives in the order they were used. Last element is
* the most recently used, and first element is the least recently
* used.
*/
private List usedList;
/**
* The perspective explicitly set as being the active one
*/
private Perspective active;
/**
* Creates an empty instance of the perspective list
*/
public PerspectiveList() {
openedList = new ArrayList();
usedList = new ArrayList();
}
/**
* Update the order of the perspectives in the opened list
*
* @param perspective
* @param newLoc
*/
public void reorder(IPerspectiveDescriptor perspective, int newLoc) {
int oldLocation = 0;
Perspective movedPerspective = null;
for (Iterator iterator = openedList.iterator(); iterator.hasNext();) {
Perspective openPerspective = (Perspective) iterator.next();
if (openPerspective.getDesc().equals(perspective)) {
oldLocation = openedList.indexOf(openPerspective);
movedPerspective = openPerspective;
}
}
if (oldLocation == newLoc) {
return;
}
openedList.remove(oldLocation);
openedList.add(newLoc, movedPerspective);
}
/**
* Return all perspectives in the order they were activated.
*
* @return an array of perspectives sorted by activation order, least
* recently activated perspective last.
*/
public Perspective[] getSortedPerspectives() {
Perspective[] result = new Perspective[usedList.size()];
return (Perspective[]) usedList.toArray(result);
}
/**
* Adds a perspective to the list. No check is done for a duplicate when
* adding.
* @param perspective the perspective to add
* @return boolean <code>true</code> if the perspective was added
*/
public boolean add(Perspective perspective) {
openedList.add(perspective);
usedList.add(0, perspective);
//It will be moved to top only when activated.
return true;
}
/**
* Returns an iterator on the perspective list in the order they were
* opened.
*/
public Iterator iterator() {
return openedList.iterator();
}
/**
* Returns an array with all opened perspectives
*/
public Perspective[] getOpenedPerspectives() {
Perspective[] result = new Perspective[openedList.size()];
return (Perspective[]) openedList.toArray(result);
}
/**
* Removes a perspective from the list.
*/
public boolean remove(Perspective perspective) {
if (active == perspective) {
updateActionSets(active, null);
active = null;
}
usedList.remove(perspective);
return openedList.remove(perspective);
}
/**
* Swap the opened order of old perspective with the new perspective.
*/
public void swap(Perspective oldPerspective, Perspective newPerspective) {
int oldIndex = openedList.indexOf(oldPerspective);
int newIndex = openedList.indexOf(newPerspective);
if (oldIndex < 0 || newIndex < 0) {
return;
}
openedList.set(oldIndex, newPerspective);
openedList.set(newIndex, oldPerspective);
}
/**
* Returns whether the list contains any perspectives
*/
public boolean isEmpty() {
return openedList.isEmpty();
}
/**
* Returns the most recently used perspective in the list.
*/
public Perspective getActive() {
return active;
}
/**
* Returns the next most recently used perspective in the list.
*/
public Perspective getNextActive() {
if (active == null) {
if (usedList.isEmpty()) {
return null;
} else {
return (Perspective) usedList.get(usedList.size() - 1);
}
} else {
if (usedList.size() < 2) {
return null;
} else {
return (Perspective) usedList.get(usedList.size() - 2);
}
}
}
/**
* Returns the number of perspectives opened
*/
public int size() {
return openedList.size();
}
/**
* Marks the specified perspective as the most recently used one in the
* list.
*/
public void setActive(Perspective perspective) {
if (perspective == active) {
return;
}
updateActionSets(active, perspective);
active = perspective;
if (perspective != null) {
usedList.remove(perspective);
usedList.add(perspective);
}
}
private void updateActionSets(Perspective oldPersp, Perspective newPersp) {
// Update action sets
IContextService service = (IContextService) window
.getService(IContextService.class);
try {
service.activateContext(ContextAuthority.DEFER_EVENTS);
if (newPersp != null) {
IActionSetDescriptor[] newAlwaysOn = newPersp
.getAlwaysOnActionSets();
for (int i = 0; i < newAlwaysOn.length; i++) {
IActionSetDescriptor descriptor = newAlwaysOn[i];
actionSets.showAction(descriptor);
}
IActionSetDescriptor[] newAlwaysOff = newPersp
.getAlwaysOffActionSets();
for (int i = 0; i < newAlwaysOff.length; i++) {
IActionSetDescriptor descriptor = newAlwaysOff[i];
actionSets.maskAction(descriptor);
}
}
if (oldPersp != null) {
IActionSetDescriptor[] newAlwaysOn = oldPersp
.getAlwaysOnActionSets();
for (int i = 0; i < newAlwaysOn.length; i++) {
IActionSetDescriptor descriptor = newAlwaysOn[i];
actionSets.hideAction(descriptor);
}
IActionSetDescriptor[] newAlwaysOff = oldPersp
.getAlwaysOffActionSets();
for (int i = 0; i < newAlwaysOff.length; i++) {
IActionSetDescriptor descriptor = newAlwaysOff[i];
actionSets.unmaskAction(descriptor);
}
}
} finally {
service.activateContext(ContextAuthority.SEND_EVENTS);
}
}
}
// for dynamic UI
protected void addPerspective(Perspective persp) {
perspList.add(persp);
window.firePerspectiveOpened(this, persp.getDesc());
}
/**
* Find the stack of view references stacked with this view part.
*
* @param part
* the part
* @return the stack of references
* @since 3.0
*/
private IViewReference[] getViewReferenceStack(IViewPart part) {
// Sanity check.
Perspective persp = getActivePerspective();
if (persp == null || !certifyPart(part)) {
return null;
}
ILayoutContainer container = ((PartSite) part.getSite()).getPane()
.getContainer();
if (container instanceof ViewStack) {
ViewStack folder = (ViewStack) container;
final ArrayList list = new ArrayList(folder.getChildren().length);
for (int i = 0; i < folder.getChildren().length; i++) {
LayoutPart layoutPart = folder.getChildren()[i];
if (layoutPart instanceof ViewPane) {
IViewReference view = ((ViewPane) layoutPart)
.getViewReference();
if (view != null) {
list.add(view);
}
}
}
// sort the list by activation order (most recently activated first)
Collections.sort(list, new Comparator() {
public int compare(Object o1, Object o2) {
int pos1 = (-1)
* activationList
.indexOf((IWorkbenchPartReference) o1);
int pos2 = (-1)
* activationList
.indexOf((IWorkbenchPartReference) o2);
return pos1 - pos2;
}
});
return (IViewReference[]) list.toArray(new IViewReference[list
.size()]);
}
return new IViewReference[] { (IViewReference) getReference(part) };
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.IWorkbenchPage#getViewStack(org.eclipse.ui.IViewPart)
*/
public IViewPart[] getViewStack(IViewPart part) {
IViewReference[] refStack = getViewReferenceStack(part);
if (refStack == null) {
return null;
}
List result = new ArrayList();
for (int i = 0; i < refStack.length; i++) {
IViewPart next = refStack[i].getView(false);
if (next != null) {
result.add(next);
}
}
return (IViewPart[]) result.toArray(new IViewPart[result.size()]);
}
/**
* Allow for programmatically resizing a part.
* <p>
* <em>EXPERIMENTAL</em>
* </p>
* <p>
* Known limitations:
* <ul>
* <li>currently applies only to views</li>
* <li>has no effect when view is zoomed</li>
* </ul>
*/
public void resizeView(IViewPart part, int width, int height) {
SashInfo sashInfo = new SashInfo();
PartPane pane = ((PartSite) part.getSite()).getPane();
ILayoutContainer container = pane.getContainer();
LayoutTree tree = getPerspectivePresentation().getLayout().root
.find(((ViewStack) container));
// retrieve our layout sashes from the layout tree
findSashParts(tree, pane.findSashes(), sashInfo);
// first set the width
float deltaWidth = width - pane.getBounds().width;
if (sashInfo.right != null) {
Rectangle rightBounds = sashInfo.rightNode.getBounds();
// set the new ratio
sashInfo.right.setRatio(((deltaWidth + sashInfo.right
.getBounds().x) - rightBounds.x)
/ rightBounds.width);
// complete the resize
sashInfo.rightNode.setBounds(rightBounds);
} else if (sashInfo.left != null) {
Rectangle leftBounds = sashInfo.leftNode.getBounds();
// set the ratio
sashInfo.left
.setRatio(((sashInfo.left.getBounds().x - deltaWidth) - leftBounds.x)
/ leftBounds.width);
// complete the resize
sashInfo.leftNode.setBounds(sashInfo.leftNode.getBounds());
}
// next set the height
float deltaHeight = height - pane.getBounds().height;
if (sashInfo.bottom != null) {
Rectangle bottomBounds = sashInfo.bottomNode.getBounds();
// set the new ratio
sashInfo.bottom.setRatio(((deltaHeight + sashInfo.bottom
.getBounds().y) - bottomBounds.y)
/ bottomBounds.height);
// complete the resize
sashInfo.bottomNode.setBounds(bottomBounds);
} else if (sashInfo.top != null) {
Rectangle topBounds = sashInfo.topNode.getBounds();
// set the ratio
sashInfo.top
.setRatio(((sashInfo.top.getBounds().y - deltaHeight) - topBounds.y)
/ topBounds.height);
// complete the resize
sashInfo.topNode.setBounds(topBounds);
}
}
// provides sash information for the given pane
private class SashInfo {
private LayoutPartSash right;
private LayoutPartSash left;
private LayoutPartSash top;
private LayoutPartSash bottom;
private LayoutTreeNode rightNode;
private LayoutTreeNode leftNode;
private LayoutTreeNode topNode;
private LayoutTreeNode bottomNode;
}
private void findSashParts(LayoutTree tree, PartPane.Sashes sashes,
SashInfo info) {
LayoutTree parent = tree.getParent();
if (parent == null) {
return;
}
if (parent.part instanceof LayoutPartSash) {
// get the layout part sash from this tree node
LayoutPartSash sash = (LayoutPartSash) parent.part;
// make sure it has a sash control
Control control = sash.getControl();
if (control != null) {
// check for a vertical sash
if (sash.isVertical()) {
if (sashes.left == control) {
info.left = sash;
info.leftNode = parent.findSash(sash);
} else if (sashes.right == control) {
info.right = sash;
info.rightNode = parent.findSash(sash);
}
}
// check for a horizontal sash
else {
if (sashes.top == control) {
info.top = sash;
info.topNode = parent.findSash(sash);
} else if (sashes.bottom == control) {
info.bottom = sash;
info.bottomNode = parent.findSash(sash);
}
}
}
}
// recursive call to continue up the tree
findSashParts(parent, sashes, info);
}
/**
* Returns all parts that are owned by this page
*
* @return
*/
IWorkbenchPartReference[] getAllParts() {
IViewReference[] views = viewFactory.getViews();
IEditorReference[] editors = getEditorReferences();
IWorkbenchPartReference[] result = new IWorkbenchPartReference[views.length + editors.length];
int resultIdx = 0;
for (int i = 0; i < views.length; i++) {
result[resultIdx++] = views[i];
}
for (int i = 0; i < editors.length; i++) {
result[resultIdx++] = editors[i];
}
return result;
}
/**
* Returns all open parts that are owned by this page (that is, all parts
* for which a part opened event would have been sent -- these would be
* activated parts whose controls have already been created.
*/
IWorkbenchPartReference[] getOpenParts() {
IWorkbenchPartReference[] refs = getAllParts();
List result = new ArrayList();
for (int i = 0; i < refs.length; i++) {
IWorkbenchPartReference reference = refs[i];
IWorkbenchPart part = reference.getPart(false);
if (part != null) {
result.add(reference);
}
}
return (IWorkbenchPartReference[]) result.toArray(new IWorkbenchPartReference[result.size()]);
}
/**
* Sanity-checks the objects in this page. Throws an Assertation exception
* if an object's internal state is invalid. ONLY INTENDED FOR USE IN THE
* UI TEST SUITES.
*/
public void testInvariants() {
Perspective persp = getActivePerspective();
if (persp != null) {
persp.testInvariants();
// When we have widgets, ensure that there is no situation where the editor area is visible
// and the perspective doesn't want an editor area.
if (!SwtUtil.isDisposed(getClientComposite()) && editorPresentation.getLayoutPart().isVisible()) {
Assert.isTrue(persp.isEditorAreaVisible());
}
}
}
/* (non-Javadoc)
* @see org.eclipse.ui.IWorkbenchPage#getExtensionTracker()
*/
public IExtensionTracker getExtensionTracker() {
if (tracker == null) {
tracker = new UIExtensionTracker(getWorkbenchWindow().getWorkbench().getDisplay());
}
return tracker;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.IWorkbenchPage#getNewWizardShortcuts()
*/
public String[] getNewWizardShortcuts() {
Perspective persp = getActivePerspective();
if (persp == null) {
return new String[0];
}
return persp.getNewWizardShortcuts();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.IWorkbenchPage#getPerspectiveShortcuts()
*/
public String[] getPerspectiveShortcuts() {
Perspective persp = getActivePerspective();
if (persp == null) {
return new String[0];
}
return persp.getPerspectiveShortcuts();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.IWorkbenchPage#getShowViewShortcuts()
*/
public String[] getShowViewShortcuts() {
Perspective persp = getActivePerspective();
if (persp == null) {
return new String[0];
}
return persp.getShowViewShortcuts();
}
/**
* @since 3.1
*/
private void suggestReset() {
final IWorkbench workbench = getWorkbenchWindow().getWorkbench();
workbench.getDisplay().asyncExec(new Runnable() {
public void run() {
Shell parentShell = null;
IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
if (window == null) {
if (workbench.getWorkbenchWindowCount() == 0) {
return;
}
window = workbench.getWorkbenchWindows()[0];
}
parentShell = window.getShell();
if (MessageDialog
.openQuestion(
parentShell,
WorkbenchMessages.Dynamic_resetPerspectiveTitle,
WorkbenchMessages.Dynamic_resetPerspectiveMessage)) {
IWorkbenchPage page = window.getActivePage();
if (page == null) {
return;
}
page.resetPerspective();
}
}
});
}
public boolean isPartVisible(IWorkbenchPartReference reference) {
IWorkbenchPart part = reference.getPart(false);
// Can't be visible if it isn't created yet
if (part == null) {
return false;
}
return isPartVisible(part);
}
public IWorkingSet[] getWorkingSets() {
return workingSets;
}
public void setWorkingSets(IWorkingSet[] newWorkingSets) {
if (newWorkingSets == null) {
newWorkingSets = new IWorkingSet[0];
}
IWorkingSet[] oldWorkingSets = workingSets;
// filter out any duplicates if necessary
if (newWorkingSets.length > 1) {
Set setOfSets = new HashSet();
for (int i = 0; i < newWorkingSets.length; i++) {
if (newWorkingSets[i] == null) {
throw new IllegalArgumentException();
}
setOfSets.add(newWorkingSets[i]);
}
newWorkingSets = (IWorkingSet[]) setOfSets
.toArray(new IWorkingSet[setOfSets.size()]);
}
workingSets = newWorkingSets;
if (!Arrays.equals(oldWorkingSets, newWorkingSets)) {
firePropertyChange(CHANGE_WORKING_SETS_REPLACE, oldWorkingSets,
newWorkingSets);
if (aggregateWorkingSet != null) {
aggregateWorkingSet.setComponents(workingSets);
}
}
if (newWorkingSets != null) {
WorkbenchPlugin
.getDefault()
.getWorkingSetManager()
.addPropertyChangeListener(workingSetPropertyChangeListener);
} else {
WorkbenchPlugin.getDefault().getWorkingSetManager()
.removePropertyChangeListener(
workingSetPropertyChangeListener);
}
}
public IWorkingSet getAggregateWorkingSet() {
if (aggregateWorkingSet == null) {
IWorkingSetManager workingSetManager = PlatformUI.getWorkbench()
.getWorkingSetManager();
aggregateWorkingSet = (AggregateWorkingSet) workingSetManager.getWorkingSet(
getAggregateWorkingSetId());
if (aggregateWorkingSet == null) {
aggregateWorkingSet = (AggregateWorkingSet) workingSetManager
.createAggregateWorkingSet(
getAggregateWorkingSetId(),
WorkbenchMessages.WorkbenchPage_workingSet_default_label,
getWorkingSets());
workingSetManager.addWorkingSet(aggregateWorkingSet);
}
}
return aggregateWorkingSet;
}
private String getAggregateWorkingSetId() {
if (aggregateWorkingSetId == null) {
aggregateWorkingSetId = "Aggregate for window " + System.currentTimeMillis(); //$NON-NLS-1$
}
return aggregateWorkingSetId;
}
}