blob: 855b64bdb87f6e81cda0301cccdadd37c2701fc5 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2009 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.internal;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.ui.IPropertyListener;
import org.eclipse.ui.ISaveablePart;
import org.eclipse.ui.ISaveablesLifecycleListener;
import org.eclipse.ui.ISaveablesSource;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.IWorkbenchCommandConstants;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.Saveable;
/**
* Global action that saves all targets in the
* workbench that implement ISaveTarget interface.
* The action keeps track of opened save targets
* and their 'save' state. If none of the currently
* opened targets needs saving, it will disable.
* This action is somewhat different from all
* other global actions in that it works on
* multiple targets at the same time i.e. it
* does not disconnect from the target when it
* becomes deactivated.
*/
public class SaveAllAction extends PageEventAction implements IPropertyListener {
/**
* List of parts (element type: <code>IWorkbenchPart</code>)
* against which this class has outstanding property listeners registered.
*/
private List partsWithListeners = new ArrayList(1);
private IWorkbenchPart openPart;
/**
* The default constructor.
*
* @param window the window
*/
public SaveAllAction(IWorkbenchWindow window) {
super(WorkbenchMessages.get().SaveAll_text, window);
setToolTipText(WorkbenchMessages.get().SaveAll_toolTip);
setId("saveAll"); //$NON-NLS-1$
setEnabled(false);
window.getWorkbench().getHelpSystem().setHelp(this,
IWorkbenchHelpContextIds.SAVE_ALL_ACTION);
setImageDescriptor(WorkbenchImages
.getImageDescriptor(ISharedImages.IMG_ETOOL_SAVEALL_EDIT));
setDisabledImageDescriptor(WorkbenchImages
.getImageDescriptor(ISharedImages.IMG_ETOOL_SAVEALL_EDIT_DISABLED));
setActionDefinitionId(IWorkbenchCommandConstants.FILE_SAVE_ALL);
}
/* (non-Javadoc)
* Method declared on PageEventAction.
*/
public void pageActivated(IWorkbenchPage page) {
super.pageActivated(page);
updateState();
}
/* (non-Javadoc)
* Method declared on PageEventAction.
*/
public void pageClosed(IWorkbenchPage page) {
super.pageClosed(page);
updateState();
}
/* (non-Javadoc)
* Method declared on PartEventAction.
*/
public void partClosed(IWorkbenchPart part) {
super.partClosed(part);
if (part instanceof ISaveablePart) {
part.removePropertyListener(this);
partsWithListeners.remove(part);
updateState();
}
}
/* (non-Javadoc)
* Method declared on PartEventAction.
*/
public void partOpened(IWorkbenchPart part) {
super.partOpened(part);
if (part instanceof ISaveablePart) {
part.addPropertyListener(this);
partsWithListeners.add(part);
// We need to temporarily cache the opened part
// because saveable views are not registered
// with a perspective until after this method
// is called. We can't pass it through to
// update because it's protected. An async
// call to update may be a better approach.
// See bug 93784 [WorkbenchParts] View not yet added to perspective when partOpened sent
openPart = part;
updateState();
openPart = null;
}
}
/* (non-Javadoc)
* Method declared on IPropertyListener.
*/
public void propertyChanged(Object source, int propID) {
if (source instanceof ISaveablePart) {
if (propID == ISaveablePart.PROP_DIRTY) {
updateState();
}
}
}
/* (non-Javadoc)
* Method declared on Action.
*/
public void run() {
if (getWorkbenchWindow() == null) {
// action has been disposed
return;
}
WorkbenchPage page = (WorkbenchPage) getActivePage();
if (page != null) {
// The second parameter is true to also save saveables from non-part
// sources, see bug 139004.
page.saveAllEditors(false, true);
updateState();
}
}
/**
* Updates availability depending on number of
* targets that need saving.
*/
protected void updateState() {
// Workaround for bug 93784 [WorkbenchParts] View not yet added to perspective when partOpened sent
if (openPart != null && openPart.getSite().getPage().equals(getActivePage()) && ((ISaveablePart) openPart).isDirty()) {
setEnabled(true);
}
else {
WorkbenchPage page = (WorkbenchPage) getActivePage();
if (page == null) {
setEnabled(false);
} else {
if (page.getDirtyParts().length > 0) {
setEnabled(true);
} else {
// Since Save All also saves saveables from non-part sources,
// look if any such saveables exist and are dirty.
SaveablesList saveablesList = (SaveablesList) page
.getWorkbenchWindow().getWorkbench().getService(
ISaveablesLifecycleListener.class);
ISaveablesSource[] nonPartSources = saveablesList.getNonPartSources();
for (int i = 0; i < nonPartSources.length; i++) {
Saveable[] saveables = nonPartSources[i].getSaveables();
for (int j = 0; j < saveables.length; j++) {
if (saveables[j].isDirty()) {
setEnabled(true);
return;
}
}
}
setEnabled(false);
}
}
}
}
/* (non-Javadoc)
* Method declared on PageEventAction.
*/
public void dispose() {
super.dispose();
for (Iterator it = partsWithListeners.iterator(); it.hasNext();) {
IWorkbenchPart part = (IWorkbenchPart) it.next();
part.removePropertyListener(this);
}
partsWithListeners.clear();
}
}