/*******************************************************************************
* Copyright (c) 2000, 2009 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.part;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.commands.common.EventManager;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IPropertyListener;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPart3;
import org.eclipse.ui.IWorkbenchPartConstants;
import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.internal.WorkbenchPlugin;
/**
* Abstract base implementation of all workbench parts.
* <p>
* This class is not intended to be subclassed by clients outside this package;
* clients should instead subclass <code>ViewPart</code> or
* <code>EditorPart</code>.
* </p>
*
* @see org.eclipse.ui.part.ViewPart
* @see org.eclipse.ui.part.EditorPart
* @noextend This class is not intended to be subclassed by clients.
*/
public abstract class WorkbenchPart extends EventManager implements
IWorkbenchPart3, IExecutableExtension, IWorkbenchPartOrientation {
private String title = ""; //$NON-NLS-1$
private ImageDescriptor imageDescriptor;
private Image titleImage;
private String toolTip = ""; //$NON-NLS-1$
private IConfigurationElement configElement;
private IWorkbenchPartSite partSite;
private String partName = ""; //$NON-NLS-1$
private String contentDescription = ""; //$NON-NLS-1$
private ListenerList partChangeListeners = new ListenerList();
/**
* Creates a new workbench part.
*/
protected WorkbenchPart() {
super();
}
/*
* (non-Javadoc) Method declared on IWorkbenchPart.
*/
public void addPropertyListener(IPropertyListener l) {
addListenerObject(l);
}
/*
* (non-Javadoc) Creates the SWT controls for this workbench part. <p>
* Subclasses must implement this method. For a detailed description of the
* requirements see <code>IWorkbenchPart</code> </p>
*
* @param parent the parent control
*
* @see IWorkbenchPart
*/
public abstract void createPartControl(Composite parent);
/**
* The <code>WorkbenchPart</code> implementation of this
* <code>IWorkbenchPart</code> method disposes the title image loaded by
* <code>setInitializationData</code>. Subclasses may extend.
*/
public void dispose() {
if (imageDescriptor != null) {
JFaceResources.getResources().destroyImage(imageDescriptor);
}
// Clear out the property change listeners as we
// should not be notifying anyone after the part
// has been disposed.
clearListeners();
partChangeListeners.clear();
}
/**
* Fires a property changed event.
*
* @param propertyId
* the id of the property that changed
*/
protected void firePropertyChange(final int propertyId) {
Object[] array = getListeners();
for (int nX = 0; nX < array.length; nX++) {
final IPropertyListener l = (IPropertyListener) array[nX];
try {
l.propertyChanged(WorkbenchPart.this, propertyId);
} catch (RuntimeException e) {
WorkbenchPlugin.log(e);
}
}
}
/**
* {@inheritDoc}
*
* Subclasses may override this method (however, if they do so, they should
* invoke the method on their superclass to ensure that the Platform's
* adapter manager is consulted).
*/
public Object getAdapter(Class adapter) {
/**
* This implementation of the method declared by <code>IAdaptable</code>
* passes the request along to the platform's adapter manager; roughly
* <code>Platform.getAdapterManager().getAdapter(this, adapter)</code>.
*/
return Platform.getAdapterManager().getAdapter(this, adapter);
}
/**
* Returns the configuration element for this part. The configuration
* element comes from the plug-in registry entry for the extension defining
* this part.
*
* @return the configuration element for this part
*/
protected IConfigurationElement getConfigurationElement() {
return configElement;
}
/**
* Returns the default title image.
*
* @return the default image
*/
protected Image getDefaultImage() {
return PlatformUI.getWorkbench().getSharedImages()
.getImage(ISharedImages.IMG_DEF_VIEW);
}
/*
* (non-Javadoc) Method declared on IWorkbenchPart.
*/
public IWorkbenchPartSite getSite() {
return partSite;
}
/**
* {@inheritDoc}
* <p>
* It is considered bad practise to overload or extend this method. Parts
* should set their title by calling setPartName and/or
* setContentDescription.
* </p>
*/
public String getTitle() {
return title;
}
/*
* (non-Javadoc) Method declared on IWorkbenchPart.
*/
public Image getTitleImage() {
if (titleImage != null) {
return titleImage;
}
return getDefaultImage();
}
/*
* (non-Javadoc) Gets the title tool tip text of this part.
*
* @return the tool tip text
*/
public String getTitleToolTip() {
return toolTip;
}
/*
* (non-Javadoc) Method declared on IWorkbenchPart.
*/
public void removePropertyListener(IPropertyListener l) {
removeListenerObject(l);
}
/*
* (non-Javadoc) Asks this part to take focus within the workbench. Parts
* must assign focus to one of the controls contained in the part's parent
* composite. <p> Subclasses must implement this method. For a detailed
* description of the requirements see <code>IWorkbenchPart</code> </p>
*
* @see IWorkbenchPart
*/
public abstract void setFocus();
/**
* {@inheritDoc} The <code>WorkbenchPart</code> implementation of this
* <code>IExecutableExtension</code> records the configuration element in
* and internal state variable (accessible via <code>getConfigElement</code>
* ). It also loads the title image, if one is specified in the
* configuration element. Subclasses may extend.
*
* Should not be called by clients. It is called by the core plugin when
* creating this executable extension.
*/
public void setInitializationData(IConfigurationElement cfig,
String propertyName, Object data) {
// // Save config element.
// configElement = cfig;
//
// // Part name and title.
// partName = Util.safeString(cfig.getAttribute("name"));//$NON-NLS-1$;
// title = partName;
//
// // Icon.
// String strIcon = cfig.getAttribute("icon");//$NON-NLS-1$
// if (strIcon == null) {
// return;
// }
//
// imageDescriptor = AbstractUIPlugin.imageDescriptorFromPlugin(
// configElement.getNamespace(), strIcon);
if (imageDescriptor == null) {
return;
}
titleImage = JFaceResources.getResources().createImageWithDefault(
imageDescriptor);
}
/**
* Sets the part site.
* <p>
* Subclasses must invoke this method from <code>IEditorPart.init</code> and
* <code>IViewPart.init</code>.
*
* @param site
* the workbench part site
*/
protected void setSite(IWorkbenchPartSite site) {
checkSite(site);
this.partSite = site;
}
/**
* Checks that the given site is valid for this type of part. The default
* implementation does nothing.
*
* @param site
* the site to check
* @since 3.1
*/
protected void checkSite(IWorkbenchPartSite site) {
// do nothing
}
/**
* Sets or clears the title of this part. Clients should call this method
* instead of overriding getTitle.
* <p>
* This may change a title that was previously set using setPartName or
* setContentDescription.
* </p>
*
* @deprecated new code should use setPartName and setContentDescription
*
* @param title
* the title, or <code>null</code> to clear
*/
protected void setTitle(String title) {
// title = Util.safeString(title);
//
// // Do not send changes if they are the same
// if (Util.equals(this.title, title)) {
// return;
// }
// this.title = title;
// firePropertyChange(IWorkbenchPart.PROP_TITLE);
}
/**
* Sets or clears the title image of this part.
*
* @param titleImage
* the title image, or <code>null</code> to clear
*/
protected void setTitleImage(Image titleImage) {
Assert.isTrue(titleImage == null || !titleImage.isDisposed());
// Do not send changes if they are the same
if (this.titleImage == titleImage) {
return;
}
this.titleImage = titleImage;
firePropertyChange(IWorkbenchPart.PROP_TITLE);
if (imageDescriptor != null) {
JFaceResources.getResources().destroyImage(imageDescriptor);
imageDescriptor = null;
}
}
/**
* Sets or clears the title tool tip text of this part. Clients should call
* this method instead of overriding <code>getTitleToolTip</code>
*
* @param toolTip
* the new tool tip text, or <code>null</code> to clear
*/
protected void setTitleToolTip(String toolTip) {
// toolTip = Util.safeString(toolTip);
// // Do not send changes if they are the same
// if (Util.equals(this.toolTip, toolTip)) {
// return;
// }
// this.toolTip = toolTip;
// firePropertyChange(IWorkbenchPart.PROP_TITLE);
}
/**
* Show that this part is busy due to a Job running that it is listening to.
*
* @param busy
* boolean to indicate that the busy state has started or ended.
* @see org.eclipse.ui.progress.IWorkbenchSiteProgressService#showBusyForFamily(Object)
* @since 3.0
*/
public void showBusy(boolean busy) {
// By default do nothing
}
/**
* {@inheritDoc}
* <p>
* It is considered bad practise to overload or extend this method. Parts
* should call setPartName to change their part name.
* </p>
*/
public String getPartName() {
return partName;
}
/**
* Sets the name of this part. The name will be shown in the tab area for
* the part. Clients should call this method instead of overriding
* getPartName. Setting this to the empty string will cause a default part
* name to be used.
*
* <p>
* setPartName and setContentDescription are intended to replace setTitle.
* This may change a value that was previously set using setTitle.
* </p>
*
* @param partName
* the part name, as it should be displayed in tabs.
*
* @since 3.0
*/
protected void setPartName(String partName) {
internalSetPartName(partName);
setDefaultTitle();
}
void setDefaultTitle() {
String description = getContentDescription();
String name = getPartName();
String newTitle = name;
// if (!Util.equals(description, "")) { //$NON-NLS-1$
// newTitle = MessageFormat.format(
// WorkbenchMessages.WorkbenchPart_AutoTitleFormat,
// new String[] { name, description });
// }
setTitle(newTitle);
}
/**
* {@inheritDoc}
* <p>
* It is considered bad practise to overload or extend this method. Parts
* should call setContentDescription to change their content description.
* </p>
*/
public String getContentDescription() {
return contentDescription;
}
/**
* Sets the content description for this part. The content description is
* typically a short string describing the current contents of the part.
* Setting this to the empty string will cause a default content description
* to be used. Clients should call this method instead of overriding
* getContentDescription(). For views, the content description is shown (by
* default) in a line near the top of the view. For editors, the content
* description is shown beside the part name when showing a list of editors.
* If the editor is open on a file, this typically contains the path to the
* input file, without the filename or trailing slash.
*
* <p>
* This may overwrite a value that was previously set in setTitle
* </p>
*
* @param description
* the content description
*
* @since 3.0
*/
protected void setContentDescription(String description) {
internalSetContentDescription(description);
setDefaultTitle();
}
void internalSetContentDescription(String description) {
Assert.isNotNull(description);
// Do not send changes if they are the same
// if (Util.equals(contentDescription, description)) {
// return;
// }
this.contentDescription = description;
firePropertyChange(IWorkbenchPartConstants.PROP_CONTENT_DESCRIPTION);
}
void internalSetPartName(String partName) {
// partName = Util.safeString(partName);
Assert.isNotNull(partName);
// Do not send changes if they are the same
// if (Util.equals(this.partName, partName)) {
// return;
// }
this.partName = partName;
firePropertyChange(IWorkbenchPartConstants.PROP_PART_NAME);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.part.IWorkbenchPartOrientation#getOrientation()
*/
public int getOrientation() {
// By default use the orientation in Window
return Window.getDefaultOrientation();
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ui.IWorkbenchPart3#addPartPropertyListener(org.eclipse.jface
* .util.IPropertyChangeListener)
*/
public void addPartPropertyListener(IPropertyChangeListener listener) {
partChangeListeners.add(listener);
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ui.IWorkbenchPart3#removePartPropertyListener(org.eclipse
* .jface.util.IPropertyChangeListener)
*/
public void removePartPropertyListener(IPropertyChangeListener listener) {
partChangeListeners.remove(listener);
}
/**
* @since 3.3
*/
protected void firePartPropertyChanged(String key, String oldValue,
String newValue) {
final PropertyChangeEvent event = new PropertyChangeEvent(this, key,
oldValue, newValue);
Object[] l = partChangeListeners.getListeners();
for (int i = 0; i < l.length; i++) {
try {
((IPropertyChangeListener) l[i]).propertyChange(event);
} catch (RuntimeException e) {
WorkbenchPlugin.log(e);
}
}
}
private Map partProperties = new HashMap();
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.IWorkbenchPart3#setPartProperty(java.lang.String,
* java.lang.String)
*/
public void setPartProperty(String key, String value) {
String oldValue = (String) partProperties.get(key);
if (value == null) {
partProperties.remove(key);
} else {
partProperties.put(key, value);
}
firePartPropertyChanged(key, oldValue, value);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.IWorkbenchPart3#getPartProperty(java.lang.String)
*/
public String getPartProperty(String key) {
return (String) partProperties.get(key);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.IWorkbenchPart3#getPartProperties()
*/
public Map getPartProperties() {
return Collections.unmodifiableMap(partProperties);
}
}