001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.ui.part;
011:
012: import java.util.Collections;
013: import java.util.HashMap;
014: import java.util.Map;
015:
016: import org.eclipse.core.commands.common.EventManager;
017: import org.eclipse.core.runtime.Assert;
018: import org.eclipse.core.runtime.IConfigurationElement;
019: import org.eclipse.core.runtime.IExecutableExtension;
020: import org.eclipse.core.runtime.ListenerList;
021: import org.eclipse.core.runtime.Platform;
022: import org.eclipse.jface.resource.ImageDescriptor;
023: import org.eclipse.jface.resource.JFaceResources;
024: import org.eclipse.jface.util.IPropertyChangeListener;
025: import org.eclipse.jface.util.PropertyChangeEvent;
026: import org.eclipse.jface.window.Window;
027: import org.eclipse.swt.graphics.Image;
028: import org.eclipse.swt.widgets.Composite;
029: import org.eclipse.ui.IPropertyListener;
030: import org.eclipse.ui.ISharedImages;
031: import org.eclipse.ui.IWorkbenchPart;
032: import org.eclipse.ui.IWorkbenchPart3;
033: import org.eclipse.ui.IWorkbenchPartConstants;
034: import org.eclipse.ui.IWorkbenchPartSite;
035: import org.eclipse.ui.PlatformUI;
036: import org.eclipse.ui.internal.WorkbenchMessages;
037: import org.eclipse.ui.internal.WorkbenchPlugin;
038: import org.eclipse.ui.internal.util.Util;
039: import org.eclipse.ui.plugin.AbstractUIPlugin;
040:
041: import com.ibm.icu.text.MessageFormat;
042:
043: /**
044: * Abstract base implementation of all workbench parts.
045: * <p>
046: * This class is not intended to be subclassed by clients outside this
047: * package; clients should instead subclass <code>ViewPart</code> or
048: * <code>EditorPart</code>.
049: * </p>
050: *
051: * @see org.eclipse.ui.part.ViewPart
052: * @see org.eclipse.ui.part.EditorPart
053: */
054: public abstract class WorkbenchPart extends EventManager implements
055: IWorkbenchPart3, IExecutableExtension,
056: IWorkbenchPartOrientation {
057: private String title = ""; //$NON-NLS-1$
058:
059: private ImageDescriptor imageDescriptor;
060:
061: private Image titleImage;
062:
063: private String toolTip = ""; //$NON-NLS-1$
064:
065: private IConfigurationElement configElement;
066:
067: private IWorkbenchPartSite partSite;
068:
069: private String partName = ""; //$NON-NLS-1$
070:
071: private String contentDescription = ""; //$NON-NLS-1$
072:
073: private ListenerList partChangeListeners = new ListenerList();
074:
075: /**
076: * Creates a new workbench part.
077: */
078: protected WorkbenchPart() {
079: super ();
080: }
081:
082: /* (non-Javadoc)
083: * Method declared on IWorkbenchPart.
084: */
085: public void addPropertyListener(IPropertyListener l) {
086: addListenerObject(l);
087: }
088:
089: /* (non-Javadoc)
090: * Creates the SWT controls for this workbench part.
091: * <p>
092: * Subclasses must implement this method. For a detailed description of the
093: * requirements see <code>IWorkbenchPart</code>
094: * </p>
095: *
096: * @param parent the parent control
097: * @see IWorkbenchPart
098: */
099: public abstract void createPartControl(Composite parent);
100:
101: /**
102: * The <code>WorkbenchPart</code> implementation of this
103: * <code>IWorkbenchPart</code> method disposes the title image
104: * loaded by <code>setInitializationData</code>. Subclasses may extend.
105: */
106: public void dispose() {
107: if (imageDescriptor != null) {
108: JFaceResources.getResources().destroyImage(imageDescriptor);
109: }
110:
111: // Clear out the property change listeners as we
112: // should not be notifying anyone after the part
113: // has been disposed.
114: clearListeners();
115: partChangeListeners.clear();
116: }
117:
118: /**
119: * Fires a property changed event.
120: *
121: * @param propertyId the id of the property that changed
122: */
123: protected void firePropertyChange(final int propertyId) {
124: Object[] array = getListeners();
125: for (int nX = 0; nX < array.length; nX++) {
126: final IPropertyListener l = (IPropertyListener) array[nX];
127: try {
128: l.propertyChanged(WorkbenchPart.this , propertyId);
129: } catch (RuntimeException e) {
130: WorkbenchPlugin.log(e);
131: }
132: }
133: }
134:
135: /**
136: * {@inheritDoc}
137: *
138: * Subclasses may override this method (however, if they do so, they
139: * should invoke the method on their superclass to ensure that the
140: * Platform's adapter manager is consulted).
141: */
142: public Object getAdapter(Class adapter) {
143:
144: /**
145: * This implementation of the method declared by <code>IAdaptable</code>
146: * passes the request along to the platform's adapter manager; roughly
147: * <code>Platform.getAdapterManager().getAdapter(this, adapter)</code>.
148: */
149:
150: return Platform.getAdapterManager().getAdapter(this , adapter);
151: }
152:
153: /**
154: * Returns the configuration element for this part. The configuration element
155: * comes from the plug-in registry entry for the extension defining this part.
156: *
157: * @return the configuration element for this part
158: */
159: protected IConfigurationElement getConfigurationElement() {
160: return configElement;
161: }
162:
163: /**
164: * Returns the default title image.
165: *
166: * @return the default image
167: */
168: protected Image getDefaultImage() {
169: return PlatformUI.getWorkbench().getSharedImages().getImage(
170: ISharedImages.IMG_DEF_VIEW);
171: }
172:
173: /* (non-Javadoc)
174: * Method declared on IWorkbenchPart.
175: */
176: public IWorkbenchPartSite getSite() {
177: return partSite;
178: }
179:
180: /**
181: * {@inheritDoc}
182: * <p>
183: * It is considered bad practise to overload or extend this method.
184: * Parts should set their title by calling setPartName and/or setContentDescription.
185: * </p>
186: */
187: public String getTitle() {
188: return title;
189: }
190:
191: /* (non-Javadoc)
192: * Method declared on IWorkbenchPart.
193: */
194: public Image getTitleImage() {
195: if (titleImage != null) {
196: return titleImage;
197: }
198: return getDefaultImage();
199: }
200:
201: /* (non-Javadoc)
202: * Gets the title tool tip text of this part.
203: *
204: * @return the tool tip text
205: */
206: public String getTitleToolTip() {
207: return toolTip;
208: }
209:
210: /* (non-Javadoc)
211: * Method declared on IWorkbenchPart.
212: */
213: public void removePropertyListener(IPropertyListener l) {
214: removeListenerObject(l);
215: }
216:
217: /* (non-Javadoc)
218: * Asks this part to take focus within the workbench.
219: * <p>
220: * Subclasses must implement this method. For a detailed description of the
221: * requirements see <code>IWorkbenchPart</code>
222: * </p>
223: *
224: * @see IWorkbenchPart
225: */
226: public abstract void setFocus();
227:
228: /**
229: * {@inheritDoc}
230: * The <code>WorkbenchPart</code> implementation of this
231: * <code>IExecutableExtension</code> records the configuration element in
232: * and internal state variable (accessible via <code>getConfigElement</code>).
233: * It also loads the title image, if one is specified in the configuration element.
234: * Subclasses may extend.
235: *
236: * Should not be called by clients. It is called by the core plugin when creating
237: * this executable extension.
238: */
239: public void setInitializationData(IConfigurationElement cfig,
240: String propertyName, Object data) {
241:
242: // Save config element.
243: configElement = cfig;
244:
245: // Part name and title.
246: partName = Util.safeString(cfig.getAttribute("name"));//$NON-NLS-1$;
247: title = partName;
248:
249: // Icon.
250: String strIcon = cfig.getAttribute("icon");//$NON-NLS-1$
251: if (strIcon == null) {
252: return;
253: }
254:
255: imageDescriptor = AbstractUIPlugin.imageDescriptorFromPlugin(
256: configElement.getNamespace(), strIcon);
257:
258: if (imageDescriptor == null) {
259: return;
260: }
261:
262: titleImage = JFaceResources.getResources()
263: .createImageWithDefault(imageDescriptor);
264: }
265:
266: /**
267: * Sets the part site.
268: * <p>
269: * Subclasses must invoke this method from <code>IEditorPart.init</code>
270: * and <code>IViewPart.init</code>.
271: *
272: * @param site the workbench part site
273: */
274: protected void setSite(IWorkbenchPartSite site) {
275: checkSite(site);
276: this .partSite = site;
277: }
278:
279: /**
280: * Checks that the given site is valid for this type of part.
281: * The default implementation does nothing.
282: *
283: * @param site the site to check
284: * @since 3.1
285: */
286: protected void checkSite(IWorkbenchPartSite site) {
287: // do nothing
288: }
289:
290: /**
291: * Sets or clears the title of this part. Clients should call this method instead
292: * of overriding getTitle.
293: * <p>
294: * This may change a title that was previously set using setPartName or setContentDescription.
295: * </p>
296: *
297: * @deprecated new code should use setPartName and setContentDescription
298: *
299: * @param title the title, or <code>null</code> to clear
300: */
301: protected void setTitle(String title) {
302: title = Util.safeString(title);
303:
304: //Do not send changes if they are the same
305: if (Util.equals(this .title, title)) {
306: return;
307: }
308: this .title = title;
309: firePropertyChange(IWorkbenchPart.PROP_TITLE);
310: }
311:
312: /**
313: * Sets or clears the title image of this part.
314: *
315: * @param titleImage the title image, or <code>null</code> to clear
316: */
317: protected void setTitleImage(Image titleImage) {
318: Assert.isTrue(titleImage == null || !titleImage.isDisposed());
319: //Do not send changes if they are the same
320: if (this .titleImage == titleImage) {
321: return;
322: }
323: this .titleImage = titleImage;
324: firePropertyChange(IWorkbenchPart.PROP_TITLE);
325: if (imageDescriptor != null) {
326: JFaceResources.getResources().destroyImage(imageDescriptor);
327: imageDescriptor = null;
328: }
329: }
330:
331: /**
332: * Sets or clears the title tool tip text of this part. Clients should
333: * call this method instead of overriding <code>getTitleToolTip</code>
334: *
335: * @param toolTip the new tool tip text, or <code>null</code> to clear
336: */
337: protected void setTitleToolTip(String toolTip) {
338: toolTip = Util.safeString(toolTip);
339: //Do not send changes if they are the same
340: if (Util.equals(this .toolTip, toolTip)) {
341: return;
342: }
343: this .toolTip = toolTip;
344: firePropertyChange(IWorkbenchPart.PROP_TITLE);
345: }
346:
347: /**
348: * Show that this part is busy due to a Job running that it
349: * is listening to.
350: * @param busy boolean to indicate that the busy state has started
351: * or ended.
352: * @see org.eclipse.ui.progress.IWorkbenchSiteProgressService#showBusyForFamily(Object)
353: * @since 3.0
354: */
355: public void showBusy(boolean busy) {
356: //By default do nothing
357: }
358:
359: /**
360: * {@inheritDoc}
361: * <p>
362: * It is considered bad practise to overload or extend this method.
363: * Parts should call setPartName to change their part name.
364: * </p>
365: */
366: public String getPartName() {
367: return partName;
368: }
369:
370: /**
371: * Sets the name of this part. The name will be shown in the tab area for
372: * the part. Clients should call this method instead of overriding getPartName.
373: * Setting this to the empty string will cause a default part name to be used.
374: *
375: * <p>
376: * setPartName and setContentDescription are intended to replace setTitle.
377: * This may change a value that was previously set using setTitle.
378: * </p>
379: *
380: * @param partName the part name, as it should be displayed in tabs.
381: *
382: * @since 3.0
383: */
384: protected void setPartName(String partName) {
385:
386: internalSetPartName(partName);
387:
388: setDefaultTitle();
389: }
390:
391: void setDefaultTitle() {
392: String description = getContentDescription();
393: String name = getPartName();
394: String newTitle = name;
395:
396: if (!Util.equals(description, "")) { //$NON-NLS-1$
397: newTitle = MessageFormat.format(
398: WorkbenchMessages.WorkbenchPart_AutoTitleFormat,
399: new String[] { name, description });
400: }
401:
402: setTitle(newTitle);
403: }
404:
405: /**
406: * {@inheritDoc}
407: * <p>
408: * It is considered bad practise to overload or extend this method.
409: * Parts should call setContentDescription to change their content description.
410: * </p>
411: */
412: public String getContentDescription() {
413: return contentDescription;
414: }
415:
416: /**
417: * Sets the content description for this part. The content description is typically
418: * a short string describing the current contents of the part. Setting this to the
419: * empty string will cause a default content description to be used. Clients should
420: * call this method instead of overriding getContentDescription(). For views, the
421: * content description is shown (by default) in a line near the top of the view. For
422: * editors, the content description is shown beside the part name when showing a
423: * list of editors. If the editor is open on a file, this typically contains the path
424: * to the input file, without the filename or trailing slash.
425: *
426: * <p>
427: * This may overwrite a value that was previously set in setTitle
428: * </p>
429: *
430: * @param description the content description
431: *
432: * @since 3.0
433: */
434: protected void setContentDescription(String description) {
435: internalSetContentDescription(description);
436:
437: setDefaultTitle();
438: }
439:
440: void internalSetContentDescription(String description) {
441: Assert.isNotNull(description);
442:
443: //Do not send changes if they are the same
444: if (Util.equals(contentDescription, description)) {
445: return;
446: }
447: this .contentDescription = description;
448:
449: firePropertyChange(IWorkbenchPartConstants.PROP_CONTENT_DESCRIPTION);
450: }
451:
452: void internalSetPartName(String partName) {
453: partName = Util.safeString(partName);
454:
455: Assert.isNotNull(partName);
456:
457: //Do not send changes if they are the same
458: if (Util.equals(this .partName, partName)) {
459: return;
460: }
461: this .partName = partName;
462:
463: firePropertyChange(IWorkbenchPartConstants.PROP_PART_NAME);
464:
465: }
466:
467: /* (non-Javadoc)
468: * @see org.eclipse.ui.part.IWorkbenchPartOrientation#getOrientation()
469: */
470: public int getOrientation() {
471: //By default use the orientation in Window
472: return Window.getDefaultOrientation();
473: }
474:
475: /* (non-Javadoc)
476: * @see org.eclipse.ui.IWorkbenchPart3#addPartPropertyListener(org.eclipse.jface.util.IPropertyChangeListener)
477: */
478: public void addPartPropertyListener(IPropertyChangeListener listener) {
479: partChangeListeners.add(listener);
480: }
481:
482: /* (non-Javadoc)
483: * @see org.eclipse.ui.IWorkbenchPart3#removePartPropertyListener(org.eclipse.jface.util.IPropertyChangeListener)
484: */
485: public void removePartPropertyListener(
486: IPropertyChangeListener listener) {
487: partChangeListeners.remove(listener);
488: }
489:
490: /**
491: * @since 3.3
492: */
493: protected void firePartPropertyChanged(String key, String oldValue,
494: String newValue) {
495: final PropertyChangeEvent event = new PropertyChangeEvent(this ,
496: key, oldValue, newValue);
497: Object[] l = partChangeListeners.getListeners();
498: for (int i = 0; i < l.length; i++) {
499: try {
500: ((IPropertyChangeListener) l[i]).propertyChange(event);
501: } catch (RuntimeException e) {
502: WorkbenchPlugin.log(e);
503: }
504: }
505: }
506:
507: private Map partProperties = new HashMap();
508:
509: /* (non-Javadoc)
510: * @see org.eclipse.ui.IWorkbenchPart3#setPartProperty(java.lang.String, java.lang.String)
511: */
512: public void setPartProperty(String key, String value) {
513: String oldValue = (String) partProperties.get(key);
514: if (value == null) {
515: partProperties.remove(key);
516: } else {
517: partProperties.put(key, value);
518: }
519: firePartPropertyChanged(key, oldValue, value);
520: }
521:
522: /* (non-Javadoc)
523: * @see org.eclipse.ui.IWorkbenchPart3#getPartProperty(java.lang.String)
524: */
525: public String getPartProperty(String key) {
526: return (String) partProperties.get(key);
527: }
528:
529: /* (non-Javadoc)
530: * @see org.eclipse.ui.IWorkbenchPart3#getPartProperties()
531: */
532: public Map getPartProperties() {
533: return Collections.unmodifiableMap(partProperties);
534: }
535: }
|