KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > Saveable


1 /*******************************************************************************
2  * Copyright (c) 2006, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11
12 package org.eclipse.ui;
13
14 import org.eclipse.core.runtime.CoreException;
15 import org.eclipse.core.runtime.IAdaptable;
16 import org.eclipse.core.runtime.IProgressMonitor;
17 import org.eclipse.core.runtime.IStatus;
18 import org.eclipse.jface.resource.ImageDescriptor;
19 import org.eclipse.jface.window.IShellProvider;
20 import org.eclipse.swt.SWT;
21 import org.eclipse.swt.graphics.Cursor;
22 import org.eclipse.swt.widgets.Composite;
23 import org.eclipse.swt.widgets.Control;
24 import org.eclipse.ui.internal.InternalSaveable;
25 import org.eclipse.ui.internal.PartSite;
26 import org.eclipse.ui.progress.IJobRunnable;
27
28 /**
29  * A <code>Saveable</code> represents a unit of saveability, e.g. an editable
30  * subset of the underlying domain model that may contain unsaved changes.
31  * Different workbench parts (editors and views) may present the same saveables
32  * in different ways. This interface allows the workbench to provide more
33  * appropriate handling of operations such as saving and closing workbench
34  * parts. For example, if two editors sharing the same saveable with unsaved
35  * changes are closed simultaneously, the user is only prompted to save the
36  * changes once for the shared saveable, rather than once for each editor.
37  * <p>
38  * Workbench parts that work in terms of saveables should implement
39  * {@link ISaveablesSource}.
40  * </p>
41  *
42  * @see ISaveablesSource
43  * @since 3.2
44  */

45 public abstract class Saveable extends InternalSaveable implements IAdaptable {
46
47     private Cursor waitCursor;
48     private Cursor originalCursor;
49
50     /**
51      * Attempts to show this saveable in the given page and returns
52      * <code>true</code> on success. The default implementation does nothing
53      * and returns <code>false</code>.
54      *
55      * @param page
56      * the workbench page in which to show this saveable
57      * @return <code>true</code> if this saveable is now visible to the user
58      * @since 3.3
59      */

60     public boolean show(IWorkbenchPage page) {
61         if (page == null) {
62             // I wish it was easier to avoid warnings about unused parameters
63
}
64         return false;
65     }
66
67     /**
68      * Returns the name of this saveable for display purposes.
69      *
70      * @return the model's name; never <code>null</code>.
71      */

72     public abstract String JavaDoc getName();
73
74     /**
75      * Returns the tool tip text for this saveable. This text is used to
76      * differentiate between two inputs with the same name. For instance,
77      * MyClass.java in folder X and MyClass.java in folder Y. The format of the
78      * text varies between input types.
79      *
80      * @return the tool tip text; never <code>null</code>
81      */

82     public abstract String JavaDoc getToolTipText();
83
84     /**
85      * Returns the image descriptor for this saveable.
86      *
87      * @return the image descriptor for this model; may be <code>null</code>
88      * if there is no image
89      */

90     public abstract ImageDescriptor getImageDescriptor();
91
92     /**
93      * Saves the contents of this saveable.
94      * <p>
95      * If the save is cancelled through user action, or for any other reason,
96      * the part should invoke <code>setCancelled</code> on the
97      * <code>IProgressMonitor</code> to inform the caller.
98      * </p>
99      * <p>
100      * This method is long-running; progress and cancellation are provided by
101      * the given progress monitor.
102      * </p>
103      *
104      * @param monitor
105      * the progress monitor
106      * @throws CoreException
107      * if the save fails; it is the caller's responsibility to
108      * report the failure to the user
109      */

110     public abstract void doSave(IProgressMonitor monitor) throws CoreException;
111
112     /**
113      * Returns whether the contents of this saveable have changed since the last
114      * save operation.
115      * <p>
116      * <b>Note:</b> this method is called frequently, for example by actions to
117      * determine their enabled status.
118      * </p>
119      *
120      * @return <code>true</code> if the contents have been modified and need
121      * saving, and <code>false</code> if they have not changed since
122      * the last save
123      */

124     public abstract boolean isDirty();
125
126     /**
127      * Clients must implement equals and hashCode as defined in
128      * {@link Object#equals(Object)} and {@link Object#hashCode()}. Two
129      * saveables should be equal if their dirty state is shared, and saving one
130      * will save the other. If two saveables are equal, their names, tooltips,
131      * and images should be the same because only one of them will be shown when
132      * prompting the user to save.
133      *
134      * @param object
135      * @return true if this Saveable is equal to the given object
136      */

137     public abstract boolean equals(Object JavaDoc object);
138
139     /**
140      * Clients must implement equals and hashCode as defined in
141      * {@link Object#equals(Object)} and {@link Object#hashCode()}. Two
142      * saveables should be equal if their dirty state is shared, and saving one
143      * will save the other. If two saveables are equal, their hash codes MUST be
144      * the same, and their names, tooltips, and images should be the same
145      * because only one of them will be shown when prompting the user to save.
146      * <p>
147      * IMPORTANT: Implementers should ensure that the hashCode returned is
148      * sufficiently unique so as not to collide with hashCodes returned by other
149      * implementations. It is suggested that the defining plug-in's ID be used
150      * as part of the returned hashCode, as in the following example:
151      * </p>
152      *
153      * <pre>
154      * int PRIME = 31;
155      * int hash = ...; // compute the &quot;normal&quot; hash code, e.g. based on some identifier unique within the defining plug-in
156      * return hash * PRIME + MY_PLUGIN_ID.hashCode();
157      * </pre>
158      *
159      * @return a hash code
160      */

161     public abstract int hashCode();
162
163     /**
164      * Saves this saveable, or prepares this saveable for a background save
165      * operation. Returns null if this saveable has been successfully saved, or
166      * a job runnable that needs to be run to complete the save in the
167      * background. This method is called in the UI thread. If this saveable
168      * supports saving in the background, it should do only minimal work.
169      * However, since the job runnable returned by this method (if any) will not
170      * run on the UI thread, this method should copy any state that can only be
171      * accessed from the UI thread so that the job runnable will be able to
172      * access it.
173      * <p>
174      * The supplied shell provider can be used from within this method and from
175      * within the job runnable for the purpose of parenting dialogs. Care should
176      * be taken not to open dialogs gratuitously and only if user input is
177      * required for cases where the save cannot otherwise proceed - note that in
178      * any given save operation, many saveable objects may be saved at the same
179      * time. In particular, errors should be signaled by throwing an exception,
180      * or if an error occurs while running the job runnable, an error status
181      * should be returned.
182      * </p>
183      * <p>
184      * If the foreground part of the save is cancelled through user action, or
185      * for any other reason, the part should invoke <code>setCancelled</code>
186      * on the <code>IProgressMonitor</code> to inform the caller. If the
187      * background part of the save is cancelled, the job should return a
188      * {@link IStatus#CANCEL} status.
189      * </p>
190      * <p>
191      * This method is long-running; progress and cancellation are provided by
192      * the given progress monitor.
193      * </p>
194      * <p>
195      * The default implementation of this method calls
196      * {@link #doSave(IProgressMonitor)} and returns <code>null</code>.
197      * </p>
198      *
199      * @param monitor
200      * a progress monitor used for reporting progress and
201      * cancellation
202      * @param shellProvider
203      * an object that can provide a shell for parenting dialogs
204      * @return <code>null</code> if this saveable has been saved successfully,
205      * or a job runnable that needs to be run to complete the save in
206      * the background.
207      *
208      * @since 3.3
209      */

210     public IJobRunnable doSave(IProgressMonitor monitor,
211             IShellProvider shellProvider) throws CoreException {
212         doSave(monitor);
213         return null;
214     }
215
216     /**
217      * Disables the UI of the given parts containing this saveable if necessary.
218      * This method is not intended to be called by clients. A corresponding call
219      * to
220      * <p>
221      * Saveables that can be saved in the background should ensure that the user
222      * cannot make changes to their data from the UI, for example by disabling
223      * controls, unless they are prepared to handle this case. This method is
224      * called on the UI thread after a job runnable has been returned from
225      * {@link #doSave(IProgressMonitor, IShellProvider)} and before
226      * spinning the event loop. The <code>closing</code> flag indicates that
227      * this saveable is currently being saved in response to closing a workbench
228      * part, in which case further changes to this saveable through the UI must
229      * be prevented.
230      * </p>
231      * <p>
232      * The default implementation calls setEnabled(false) on the given parts'
233      * composites.
234      * </p>
235      *
236      * @param parts
237      * the workbench parts containing this saveable
238      * @param closing
239      * a boolean flag indicating whether the save was triggered by a
240      * request to close a workbench part, and all of the given parts
241      * will be closed after the save operation finishes successfully.
242      *
243      * @since 3.3
244      */

245     public void disableUI(IWorkbenchPart[] parts, boolean closing) {
246         for (int i = 0; i < parts.length; i++) {
247             IWorkbenchPart workbenchPart = parts[i];
248             Composite paneComposite = (Composite) ((PartSite) workbenchPart
249                     .getSite()).getPane().getControl();
250             Control[] paneChildren = paneComposite.getChildren();
251             Composite toDisable = ((Composite) paneChildren[0]);
252             toDisable.setEnabled(false);
253             if (waitCursor == null) {
254                 waitCursor = new Cursor(workbenchPart.getSite().getWorkbenchWindow().getShell().getDisplay(), SWT.CURSOR_WAIT);
255             }
256             originalCursor = paneComposite.getCursor();
257             paneComposite.setCursor(waitCursor);
258         }
259     }
260
261     /**
262      * Enables the UI of the given parts containing this saveable after a
263      * background save operation has finished. This method is not intended to be
264      * called by clients.
265      * <p>
266      * The default implementation calls setEnabled(true) on the given parts'
267      * composites.
268      * </p>
269      *
270      * @param parts
271      * the workbench parts containing this saveable
272      *
273      * @since 3.3
274      */

275     public void enableUI(IWorkbenchPart[] parts) {
276         for (int i = 0; i < parts.length; i++) {
277             IWorkbenchPart workbenchPart = parts[i];
278             Composite paneComposite = (Composite) ((PartSite) workbenchPart
279                     .getSite()).getPane().getControl();
280             Control[] paneChildren = paneComposite.getChildren();
281             Composite toEnable = ((Composite) paneChildren[0]);
282             paneComposite.setCursor(originalCursor);
283             if (waitCursor!=null && !waitCursor.isDisposed()) {
284                 waitCursor.dispose();
285                 waitCursor = null;
286             }
287             toEnable.setEnabled(true);
288         }
289     }
290
291     /**
292      * This implementation of {@link IAdaptable#getAdapter(Class)} returns
293      * <code>null</code>. Subclasses may override. This allows two unrelated
294      * subclasses of Saveable to implement {@link #equals(Object)} and
295      * {@link #hashCode()} based on an underlying implementation class that is
296      * shared by both Saveable subclasses.
297      *
298      * @since 3.3
299      */

300     public Object JavaDoc getAdapter(Class JavaDoc adapter) {
301         return null;
302     }
303 }
304
Popular Tags