All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.ui.Saveable Maven / Gradle / Ivy

/*******************************************************************************
 * Copyright (c) 2006, 2015 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/

package org.eclipse.ui;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.window.IShellProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.internal.InternalSaveable;
import org.eclipse.ui.internal.PartSite;
import org.eclipse.ui.progress.IJobRunnable;

/**
 * A Saveable represents a unit of saveability, e.g. an editable
 * subset of the underlying domain model that may contain unsaved changes.
 * Different workbench parts (editors and views) may present the same saveables
 * in different ways. This interface allows the workbench to provide more
 * appropriate handling of operations such as saving and closing workbench
 * parts. For example, if two editors sharing the same saveable with unsaved
 * changes are closed simultaneously, the user is only prompted to save the
 * changes once for the shared saveable, rather than once for each editor.
 * 

* Workbench parts that work in terms of saveables should implement * {@link ISaveablesSource}. *

* * @see ISaveablesSource * @since 3.2 */ public abstract class Saveable extends InternalSaveable implements IAdaptable { /** * Either {@code null} or the System's {@link SWT#CURSOR_WAIT} cursor instance. * Should never be disposed. */ private Cursor waitCursor; private Cursor originalCursor; /** * Attempts to show this saveable in the given page and returns * true on success. The default implementation does nothing and * returns false. * * @param page the workbench page in which to show this saveable * @return true if this saveable is now visible to the user * @since 3.3 */ public boolean show(IWorkbenchPage page) { if (page == null) { // I wish it was easier to avoid warnings about unused parameters } return false; } /** * Returns the name of this saveable for display purposes. * * @return the model's name; never null. */ public abstract String getName(); /** * Returns the tool tip text for this saveable. This text is used to * differentiate between two inputs with the same name. For instance, * MyClass.java in folder X and MyClass.java in folder Y. The format of the text * varies between input types. * * @return the tool tip text; never null */ public abstract String getToolTipText(); /** * Returns the image descriptor for this saveable. * * @return the image descriptor for this model; may be null if * there is no image */ public abstract ImageDescriptor getImageDescriptor(); /** * Saves the contents of this saveable. *

* If the save is cancelled through user action, or for any other reason, the * part should invoke setCancelled on the * IProgressMonitor to inform the caller. *

*

* This method is long-running; progress and cancellation are provided by the * given progress monitor. *

* * @param monitor the progress monitor * @throws CoreException if the save fails; it is the caller's responsibility to * report the failure to the user */ public abstract void doSave(IProgressMonitor monitor) throws CoreException; /** * Returns whether the contents of this saveable have changed since the last * save operation. *

* Note: this method is called frequently, for example by actions to * determine their enabled status. *

* * @return true if the contents have been modified and need saving, * and false if they have not changed since the last save */ public abstract boolean isDirty(); /** * Clients must implement equals and hashCode as defined in * {@link Object#equals(Object)} and {@link Object#hashCode()}. Two saveables * should be equal if their dirty state is shared, and saving one will save the * other. If two saveables are equal, their names, tooltips, and images should * be the same because only one of them will be shown when prompting the user to * save. * * @param object the object to compare * @return true if this Saveable is equal to the given object */ @Override public abstract boolean equals(Object object); /** * Clients must implement equals and hashCode as defined in * {@link Object#equals(Object)} and {@link Object#hashCode()}. Two saveables * should be equal if their dirty state is shared, and saving one will save the * other. If two saveables are equal, their hash codes MUST be the same, and * their names, tooltips, and images should be the same because only one of them * will be shown when prompting the user to save. *

* IMPORTANT: Implementers should ensure that the hashCode returned is * sufficiently unique so as not to collide with hashCodes returned by other * implementations. It is suggested that the defining plug-in's ID be used as * part of the returned hashCode, as in the following example: *

* *
	 *     int PRIME = 31;
	 *     int hash = ...; // compute the "normal" hash code, e.g. based on some identifier unique within the defining plug-in
	 *     return hash * PRIME + MY_PLUGIN_ID.hashCode();
	 * 
* * @return a hash code */ @Override public abstract int hashCode(); /** * Saves this saveable, or prepares this saveable for a background save * operation. Returns null if this saveable has been successfully saved, or a * job runnable that needs to be run to complete the save in the background. * This method is called in the UI thread. If this saveable supports saving in * the background, it should do only minimal work. However, since the job * runnable returned by this method (if any) will not run on the UI thread, this * method should copy any state that can only be accessed from the UI thread so * that the job runnable will be able to access it. *

* The supplied shell provider can be used from within this method and from * within the job runnable for the purpose of parenting dialogs. Care should be * taken not to open dialogs gratuitously and only if user input is required for * cases where the save cannot otherwise proceed - note that in any given save * operation, many saveable objects may be saved at the same time. In * particular, errors should be signaled by throwing an exception, or if an * error occurs while running the job runnable, an error status should be * returned. *

*

* If the foreground part of the save is cancelled through user action, or for * any other reason, the part should invoke setCancelled on the * IProgressMonitor to inform the caller. If the background part of * the save is cancelled, the job should return a {@link IStatus#CANCEL} status. *

*

* This method is long-running; progress and cancellation are provided by the * given progress monitor. *

*

* The default implementation of this method calls * {@link #doSave(IProgressMonitor)} and returns null. *

* * @param monitor a progress monitor used for reporting progress and * cancellation * @param shellProvider an object that can provide a shell for parenting dialogs * @return null if this saveable has been saved successfully, or a * job runnable that needs to be run to complete the save in the * background. * @throws CoreException if the save fails; it is the caller's responsibility to * report the failure to the user * @since 3.3 */ public IJobRunnable doSave(IProgressMonitor monitor, IShellProvider shellProvider) throws CoreException { doSave(monitor); return null; } /** * Disables the UI of the given parts containing this saveable if necessary. * This method is not intended to be called by clients. A corresponding call to *

* Saveables that can be saved in the background should ensure that the user * cannot make changes to their data from the UI, for example by disabling * controls, unless they are prepared to handle this case. This method is called * on the UI thread after a job runnable has been returned from * {@link #doSave(IProgressMonitor, IShellProvider)} and before spinning the * event loop. The closing flag indicates that this saveable is * currently being saved in response to closing a workbench part, in which case * further changes to this saveable through the UI must be prevented. *

*

* The default implementation calls setEnabled(false) on the given parts' * composites. *

* * @param parts the workbench parts containing this saveable * @param closing a boolean flag indicating whether the save was triggered by a * request to close a workbench part, and all of the given parts * will be closed after the save operation finishes successfully. * * @since 3.3 */ public void disableUI(IWorkbenchPart[] parts, boolean closing) { for (IWorkbenchPart workbenchPart : parts) { Composite paneComposite = (Composite) ((PartSite) workbenchPart.getSite()).getModel().getWidget(); Control[] paneChildren = paneComposite.getChildren(); Composite toDisable = ((Composite) paneChildren[0]); toDisable.setEnabled(false); if (waitCursor == null) { waitCursor = workbenchPart.getSite().getWorkbenchWindow().getShell().getDisplay() .getSystemCursor(SWT.CURSOR_WAIT); } if (waitCursor.equals(paneComposite.getCursor())) { originalCursor = paneComposite.getCursor(); paneComposite.setCursor(waitCursor); } } } /** * Enables the UI of the given parts containing this saveable after a background * save operation has finished. This method is not intended to be called by * clients. *

* The default implementation calls setEnabled(true) on the given parts' * composites. *

* * @param parts the workbench parts containing this saveable * * @since 3.3 */ public void enableUI(IWorkbenchPart[] parts) { for (IWorkbenchPart workbenchPart : parts) { Composite paneComposite = (Composite) ((PartSite) workbenchPart.getSite()).getModel().getWidget(); Control[] paneChildren = paneComposite.getChildren(); Composite toEnable = ((Composite) paneChildren[0]); paneComposite.setCursor(originalCursor); if (waitCursor != null) { /* * waitCursor is always the System SWT.CURSOR_WAIT instance and should never be * disposed */ waitCursor = null; } toEnable.setEnabled(true); } } /** * This implementation of {@link IAdaptable#getAdapter(Class)} returns * null. Subclasses may override. This allows two unrelated * subclasses of Saveable to implement {@link #equals(Object)} and * {@link #hashCode()} based on an underlying implementation class that is * shared by both Saveable subclasses. * * @since 3.3 */ @Override public T getAdapter(Class adapter) { return null; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy