001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 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 org.eclipse.core.runtime.Assert;
013: import org.eclipse.core.runtime.IConfigurationElement;
014: import org.eclipse.core.runtime.IProgressMonitor;
015: import org.eclipse.ui.IEditorInput;
016: import org.eclipse.ui.IEditorPart;
017: import org.eclipse.ui.IEditorSite;
018: import org.eclipse.ui.IPropertyListener;
019: import org.eclipse.ui.IWorkbenchPartConstants;
020: import org.eclipse.ui.IWorkbenchPartSite;
021: import org.eclipse.ui.PartInitException;
022:
023: /**
024: * Abstract base implementation of all workbench editors.
025: * <p>
026: * This class should be subclassed by clients wishing to define new editors.
027: * The name of the subclass should be given as the <code>"class"</code>
028: * attribute in a <code>editor</code> extension contributed to the workbench's
029: * view extension point (named <code>"org.eclipse.ui.editors"</code>).
030: * For example, the plug-in's XML markup might contain:
031: * <pre>
032: * <extension point="org.eclipse.ui.editors">
033: * <editor id="com.example.myplugin.ed"
034: * name="My Editor"
035: * icon="./images/cedit.gif"
036: * extensions="foo"
037: * class="com.example.myplugin.MyFooEditor"
038: * contributorClass="com.example.myplugin.MyFooEditorContributor"
039: * />
040: * </extension>
041: * </pre>
042: * where <code>com.example.myplugin.MyEditor</code> is the name of the
043: * <code>EditorPart</code> subclass.
044: * </p>
045: * <p>
046: * Subclasses must implement the following methods:
047: * <ul>
048: * <li><code>IEditorPart.init</code> - to initialize editor when assigned its site</li>
049: * <li><code>IWorkbenchPart.createPartControl</code> - to create the editor's controls </li>
050: * <li><code>IWorkbenchPart.setFocus</code> - to accept focus</li>
051: * <li><code>IEditorPart.isDirty</code> - to decide whether a significant change has
052: * occurred</li>
053: * <li><code>IEditorPart.doSave</code> - to save contents of editor</li>
054: * <li><code>IEditorPart.doSaveAs</code> - to save contents of editor</li>
055: * <li><code>IEditorPart.isSaveAsAllowed</code> - to control Save As</li>
056: * </ul>
057: * </p>
058: * <p>
059: * Subclasses may extend or reimplement the following methods as required:
060: * <ul>
061: * <li><code>IExecutableExtension.setInitializationData</code> - extend to provide additional
062: * initialization when editor extension is instantiated</li>
063: * <li><code>IWorkbenchPart.dispose</code> - extend to provide additional cleanup</li>
064: * <li><code>IAdaptable.getAdapter</code> - reimplement to make the editor
065: * adaptable</li>
066: * </ul>
067: * </p>
068: */
069: public abstract class EditorPart extends WorkbenchPart implements
070: IEditorPart {
071:
072: /**
073: * Editor input, or <code>null</code> if none.
074: */
075: private IEditorInput editorInput = null;
076:
077: /**
078: * Listens to PROP_TITLE property changes in this object until the first call to
079: * setContentDescription. Used for compatibility with old parts that call setTitle
080: * or overload getTitle instead of using setContentDescription.
081: */
082: private IPropertyListener compatibilityTitleListener = new IPropertyListener() {
083: /* (non-Javadoc)
084: * @see org.eclipse.ui.IPropertyListener#propertyChanged(java.lang.Object, int)
085: */
086: public void propertyChanged(Object source, int propId) {
087: if (propId == IWorkbenchPartConstants.PROP_TITLE) {
088: setDefaultPartName();
089: }
090: }
091: };
092:
093: /**
094: * Creates a new workbench editor.
095: */
096: protected EditorPart() {
097: super ();
098:
099: addPropertyListener(compatibilityTitleListener);
100: }
101:
102: /* (non-Javadoc)
103: * Saves the contents of this editor.
104: * <p>
105: * Subclasses must override this method to implement the open-save-close lifecycle
106: * for an editor. For greater details, see <code>IEditorPart</code>
107: * </p>
108: *
109: * @see IEditorPart
110: */
111: public abstract void doSave(IProgressMonitor monitor);
112:
113: /* (non-Javadoc)
114: * Saves the contents of this editor to another object.
115: * <p>
116: * Subclasses must override this method to implement the open-save-close lifecycle
117: * for an editor. For greater details, see <code>IEditorPart</code>
118: * </p>
119: *
120: * @see IEditorPart
121: */
122: public abstract void doSaveAs();
123:
124: /* (non-Javadoc)
125: * Method declared on IEditorPart.
126: */
127: public IEditorInput getEditorInput() {
128: return editorInput;
129: }
130:
131: /* (non-Javadoc)
132: * Method declared on IEditorPart.
133: */
134: public IEditorSite getEditorSite() {
135: return (IEditorSite) getSite();
136: }
137:
138: /* (non-Javadoc)
139: * Gets the title tool tip text of this part.
140: *
141: * @return the tool tip text
142: */
143: public String getTitleToolTip() {
144: if (editorInput == null) {
145: return super .getTitleToolTip();
146: } else {
147: return editorInput.getToolTipText();
148: }
149: }
150:
151: /* (non-Javadoc)
152: * Initializes the editor part with a site and input.
153: * <p>
154: * Subclasses of <code>EditorPart</code> must implement this method. Within
155: * the implementation subclasses should verify that the input type is acceptable
156: * and then save the site and input. Here is sample code:
157: * </p>
158: * <pre>
159: * if (!(input instanceof IFileEditorInput))
160: * throw new PartInitException("Invalid Input: Must be IFileEditorInput");
161: * setSite(site);
162: * setInput(input);
163: * </pre>
164: */
165: public abstract void init(IEditorSite site, IEditorInput input)
166: throws PartInitException;
167:
168: /* (non-Javadoc)
169: * Returns whether the contents of this editor have changed since the last save
170: * operation.
171: * <p>
172: * Subclasses must override this method to implement the open-save-close lifecycle
173: * for an editor. For greater details, see <code>IEditorPart</code>
174: * </p>
175: *
176: * @see IEditorPart
177: */
178: public abstract boolean isDirty();
179:
180: /* (non-Javadoc)
181: * Returns whether the "save as" operation is supported by this editor.
182: * <p>
183: * Subclasses must override this method to implement the open-save-close lifecycle
184: * for an editor. For greater details, see <code>IEditorPart</code>
185: * </p>
186: *
187: * @see IEditorPart
188: */
189: public abstract boolean isSaveAsAllowed();
190:
191: /* (non-Javadoc)
192: * Returns whether the contents of this editor should be saved when the editor
193: * is closed.
194: * <p>
195: * This method returns <code>true</code> if and only if the editor is dirty
196: * (<code>isDirty</code>).
197: * </p>
198: */
199: public boolean isSaveOnCloseNeeded() {
200: return isDirty();
201: }
202:
203: /**
204: * Sets the input to this editor. This method simply updates the internal
205: * member variable.
206: *
207: * <p>Unlike most of the other set methods on this class, this method does
208: * not fire a property change. Clients that call this method from a subclass
209: * must ensure that they fire an IWorkbenchPartConstants.PROP_INPUT property
210: * change after calling this method but before leaving whatever public method
211: * they are in. Clients that expose this method as public API must fire
212: * the property change within their implementation of setInput.</p>
213: *
214: * <p>Note that firing a property change may cause listeners to immediately
215: * reach back and call methods on this editor. Care should be taken not to
216: * fire the property change until the editor has fully updated its internal
217: * state to reflect the new input.</p>
218: *
219: * @param input the editor input
220: *
221: * @see #setInputWithNotify(IEditorInput)
222: */
223: protected void setInput(IEditorInput input) {
224: editorInput = input;
225: }
226:
227: /**
228: * Sets the input to this editor and fires a PROP_INPUT property change if
229: * the input has changed. This is the convenience method implementation.
230: *
231: * <p>Note that firing a property change may cause other objects to reach back
232: * and invoke methods on the editor. Care should be taken not to call this method
233: * until the editor has fully updated its internal state to reflect the
234: * new input.</p>
235: *
236: * @since 3.2
237: *
238: * @param input the editor input
239: */
240: protected void setInputWithNotify(IEditorInput input) {
241: if (input != editorInput) {
242: editorInput = input;
243: firePropertyChange(PROP_INPUT);
244: }
245: }
246:
247: /* (non-Javadoc)
248: * @see org.eclipse.ui.part.WorkbenchPart#setContentDescription(java.lang.String)
249: */
250: protected void setContentDescription(String description) {
251: if (compatibilityTitleListener != null) {
252: removePropertyListener(compatibilityTitleListener);
253: compatibilityTitleListener = null;
254: }
255:
256: super .setContentDescription(description);
257: }
258:
259: /* (non-Javadoc)
260: * @see org.eclipse.ui.part.WorkbenchPart#setPartName(java.lang.String)
261: */
262: protected void setPartName(String partName) {
263: if (compatibilityTitleListener != null) {
264: removePropertyListener(compatibilityTitleListener);
265: compatibilityTitleListener = null;
266: }
267:
268: super .setPartName(partName);
269: }
270:
271: /* (non-Javadoc)
272: * @see org.eclipse.core.runtime.IExecutableExtension#setInitializationData(org.eclipse.core.runtime.IConfigurationElement, java.lang.String, java.lang.Object)
273: */
274: public void setInitializationData(IConfigurationElement cfig,
275: String propertyName, Object data) {
276: super .setInitializationData(cfig, propertyName, data);
277:
278: setDefaultPartName();
279: }
280:
281: private void setDefaultPartName() {
282: if (compatibilityTitleListener == null) {
283: return;
284: }
285:
286: internalSetPartName(getTitle());
287: }
288:
289: /**
290: * Set the default title for the receiver.
291: */
292: void setDefaultTitle() {
293: setTitle(getPartName());
294: }
295:
296: /**
297: * Checks that the given site is valid for this type of part.
298: * The site for an editor must be an <code>IEditorSite</code>.
299: *
300: * @param site the site to check
301: * @since 3.1
302: */
303: protected final void checkSite(IWorkbenchPartSite site) {
304: super .checkSite(site);
305: Assert.isTrue(site instanceof IEditorSite,
306: "The site for an editor must be an IEditorSite"); //$NON-NLS-1$
307: }
308:
309: }
|