blob: 446a858149a1f28b59d3c7d7b331f4136ebb0d58 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.ui.internal;
import java.util.HashMap;
import java.util.List;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.dynamichelpers.IExtensionChangeHandler;
import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker;
import org.eclipse.jface.util.SafeRunnable;
import org.eclipse.osgi.util.NLS;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IViewReference;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.views.IViewDescriptor;
import org.eclipse.ui.views.IViewRegistry;
/**
* The ViewFactory is used to control the creation and disposal of views.
* It implements a reference counting strategy so that one view can be shared
* by more than one client.
*/
/*package*/class ViewFactory implements IExtensionChangeHandler {
private ReferenceCounter counter;
private HashMap mementoTable = new HashMap();
WorkbenchPage page;
IViewRegistry viewReg;
/**
* Separates a view's primary id from its secondary id in view key strings.
*/
static final String ID_SEP = ":"; //$NON-NLS-1$
/**
* Returns a string representing a view with the given id and (optional) secondary id,
* suitable for use as a key in a map.
*
* @param id primary id of the view
* @param secondaryId secondary id of the view or <code>null</code>
* @return the key
*/
static String getKey(String id, String secondaryId) {
return secondaryId == null ? id : id + ID_SEP + secondaryId;
}
/**
* Returns a string representing the given view reference, suitable for use as a key in a map.
*
* @param viewRef the view reference
* @return the key
*/
static String getKey(IViewReference viewRef) {
return getKey(viewRef.getId(), viewRef.getSecondaryId());
}
/**
* Extracts ths primary id portion of a compound id.
* @param compoundId a compound id of the form: primaryId [':' secondaryId]
* @return the primary id
*/
static String extractPrimaryId(String compoundId) {
int i = compoundId.lastIndexOf(ID_SEP);
if (i == -1) {
return compoundId;
}
return compoundId.substring(0, i);
}
/**
* Extracts ths secondary id portion of a compound id.
* @param compoundId a compound id of the form: primaryId [':' secondaryId]
* @return the secondary id, or <code>null</code> if none
*/
static String extractSecondaryId(String compoundId) {
int i = compoundId.lastIndexOf(ID_SEP);
if (i == -1) {
return null;
}
return compoundId.substring(i + 1);
}
/**
* Returns whether the given view id contains a wildcard. Wildcards cannot
* be used in regular view ids, only placeholders.
*
* @param viewId the view id
* @return <code>true</code> if the given view id contains a wildcard,
* <code>false</code> otherwise
*
* @since 3.1
*/
static boolean hasWildcard(String viewId) {
return viewId.indexOf(PartPlaceholder.WILD_CARD) >= 0;
}
/**
* Constructs a new view factory.
*/
public ViewFactory(WorkbenchPage page, IViewRegistry reg) {
super();
this.page = page;
this.viewReg = reg;
counter = new ReferenceCounter();
page.getExtensionTracker().registerHandler(this, null);
}
/**
* Creates an instance of a view defined by id.
*
* This factory implements reference counting. The first call to this
* method will return a new view. Subsequent calls will return the
* first view with an additional reference count. The view is
* disposed when releaseView is called an equal number of times
* to getView.
*/
public IViewReference createView(final String id) throws PartInitException {
return createView(id, null);
}
/**
* Creates an instance of a view defined by id and secondary id.
*
* This factory implements reference counting. The first call to this
* method will return a new view. Subsequent calls will return the
* first view with an additional reference count. The view is
* disposed when releaseView is called an equal number of times
* to createView.
*/
public IViewReference createView(String id, String secondaryId)
throws PartInitException {
IViewDescriptor desc = viewReg.find(id);
// ensure that the view id is valid
if (desc == null) {
throw new PartInitException(NLS.bind(WorkbenchMessages.ViewFactory_couldNotCreate, id ));
}
// ensure that multiple instances are allowed if a secondary id is given
if (secondaryId != null) {
if (!desc.getAllowMultiple()) {
throw new PartInitException(NLS.bind(WorkbenchMessages.ViewFactory_noMultiple, id));
}
}
String key = getKey(id, secondaryId);
IViewReference ref = (IViewReference) counter.get(key);
if (ref == null) {
IMemento memento = (IMemento) mementoTable.get(key);
ref = new ViewReference(this, id, secondaryId, memento);
mementoTable.remove(key);
counter.put(key, ref);
getWorkbenchPage().partAdded((ViewReference)ref);
} else {
counter.addRef(key);
}
return ref;
}
/**
* Returns the set of views being managed by this factory
*
* @return the set of views being managed by this factory
*/
public IViewReference[] getViewReferences() {
List values = counter.values();
return (IViewReference[]) values.toArray(new IViewReference[values.size()]);
}
/**
* Returns the view with the given id, or <code>null</code> if not found.
*/
public IViewReference getView(String id) {
return getView(id, null);
}
/**
* Returns the view with the given id and secondary id, or <code>null</code> if not found.
*/
public IViewReference getView(String id, String secondaryId) {
String key = getKey(id, secondaryId);
return (IViewReference) counter.get(key);
}
/**
* @return the <code>IViewRegistry</code> used by this factory.
* @since 3.0
*/
public IViewRegistry getViewRegistry() {
return viewReg;
}
/**
* Returns a list of views which are open.
*/
public IViewReference[] getViews() {
List list = counter.values();
IViewReference[] array = new IViewReference[list.size()];
list.toArray(array);
return array;
}
/**
* @return the <code>WorkbenchPage</code> used by this factory.
* @since 3.0
*/
public WorkbenchPage getWorkbenchPage() {
return page;
}
/**
*
* @param viewRef
* @return the current reference count for the given view
*/
public int getReferenceCount(IViewReference viewRef) {
String key = getKey(viewRef);
IViewReference ref = (IViewReference) counter.get(key);
return ref==null ? 0 : counter.getRef(key);
}
/**
* Releases an instance of a view.
*
* This factory does reference counting. For more info see
* getView.
*/
public void releaseView(IViewReference viewRef) {
String key = getKey(viewRef);
IViewReference ref = (IViewReference) counter.get(key);
if (ref == null) {
return;
}
int count = counter.removeRef(key);
if (count <= 0) {
getWorkbenchPage().partRemoved((ViewReference)ref);
}
}
/**
* Restore view states.
*
* @param memento the <code>IMemento</code> to restore from.
* @return <code>IStatus</code>
*/
public IStatus restoreState(IMemento memento) {
IMemento mem[] = memento.getChildren(IWorkbenchConstants.TAG_VIEW);
for (int i = 0; i < mem.length; i++) {
//for dynamic UI - add the next line to replace subsequent code that is commented out
restoreViewState(mem[i]);
}
return new Status(IStatus.OK, PlatformUI.PLUGIN_ID, 0, "", null); //$NON-NLS-1$
}
/**
* Save view states.
*
* @param memento the <code>IMemento</code> to save to.
* @return <code>IStatus</code>
*/
public IStatus saveState(IMemento memento) {
final MultiStatus result = new MultiStatus(PlatformUI.PLUGIN_ID,
IStatus.OK, WorkbenchMessages.ViewFactory_problemsSavingViews, null);
final IViewReference refs[] = getViews();
for (int i = 0; i < refs.length; i++) {
//for dynamic UI - add the following line to replace subsequent code which is commented out
saveViewState(memento, refs[i], result);
}
return result;
}
// for dynamic UI
public IMemento saveViewState(IMemento memento, IViewReference ref,
MultiStatus res) {
final MultiStatus result = res;
final IMemento viewMemento = memento
.createChild(IWorkbenchConstants.TAG_VIEW);
viewMemento.putString(IWorkbenchConstants.TAG_ID, ViewFactory
.getKey(ref));
if (ref instanceof ViewReference) {
viewMemento.putString(IWorkbenchConstants.TAG_PART_NAME,
((ViewReference) ref).getPartName());
}
final IViewReference viewRef = ref;
final IViewPart view = (IViewPart) ref.getPart(false);
if (view != null) {
Platform.run(new SafeRunnable() {
public void run() {
view.saveState(viewMemento
.createChild(IWorkbenchConstants.TAG_VIEW_STATE));
}
public void handleException(Throwable e) {
result
.add(new Status(
IStatus.ERROR,
PlatformUI.PLUGIN_ID,
0,
NLS.bind(WorkbenchMessages.ViewFactory_couldNotSave, viewRef.getTitle() ),
e));
}
});
} else {
IMemento mem = null;
// if we've created the reference once, any previous workbench
// state memento is there. After once, there is no previous
// session state, so it should be null.
if (ref instanceof ViewReference) {
mem = ((ViewReference) ref).getMemento();
if (mem!=null) {
mem = mem.getChild(IWorkbenchConstants.TAG_VIEW_STATE);
}
}
if (mem != null) {
IMemento child = viewMemento
.createChild(IWorkbenchConstants.TAG_VIEW_STATE);
child.putMemento(mem);
}
}
return viewMemento;
}
// for dynamic UI
public void restoreViewState(IMemento memento) {
String compoundId = memento.getString(IWorkbenchConstants.TAG_ID);
mementoTable.put(compoundId, memento);
}
IMemento getViewState(String key) {
IMemento memento = (IMemento) mementoTable.get(key);
if (memento == null) {
return null;
}
return memento.getChild(IWorkbenchConstants.TAG_VIEW_STATE);
}
/* (non-Javadoc)
* @see org.eclipse.core.runtime.dynamicHelpers.IExtensionChangeHandler#removeExtension(org.eclipse.core.runtime.IExtension, java.lang.Object[])
*/
public void removeExtension(IExtension source, Object[] objects) {
for (int i = 0; i < objects.length; i++) {
if (objects[i] instanceof IViewPart) {
IViewPart part = (IViewPart) objects[i];
// String primaryViewId = part.getViewSite().getId();
// String secondaryViewId = part.getViewSite().getSecondaryId();
// IViewReference viewRef = page.findViewReference(
// primaryViewId, secondaryViewId);
// IPerspectiveDescriptor[] descs =
// page.getOpenedPerspectives();
// Perspective active = page.getActivePerspective();
// for (int i = 0; i < descs.length; i++) {
// Perspective nextPerspective = page.findPerspective(descs[i]);
//
// if (nextPerspective == null || active == nextPerspective)
// continue;
//
// page.hideView(nextPerspective, viewRef);
// }
page.hideView(part);
}
}
}
/* (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) {
//Do nothing
}
}