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

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

There is a newer version: 3.133.0
Show newest version
/*******************************************************************************
 * Copyright (c) 2006, 2015 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;

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 * @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