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.internal;
011:
012: import java.util.ArrayList;
013: import java.util.Iterator;
014: import java.util.List;
015:
016: import org.eclipse.ui.IPropertyListener;
017: import org.eclipse.ui.ISaveablePart;
018: import org.eclipse.ui.ISaveablesLifecycleListener;
019: import org.eclipse.ui.ISaveablesSource;
020: import org.eclipse.ui.IWorkbenchPage;
021: import org.eclipse.ui.IWorkbenchPart;
022: import org.eclipse.ui.IWorkbenchWindow;
023: import org.eclipse.ui.Saveable;
024:
025: /**
026: * Global action that saves all targets in the
027: * workbench that implement ISaveTarget interface.
028: * The action keeps track of opened save targets
029: * and their 'save' state. If none of the currently
030: * opened targets needs saving, it will disable.
031: * This action is somewhat different from all
032: * other global actions in that it works on
033: * multiple targets at the same time i.e. it
034: * does not disconnect from the target when it
035: * becomes deactivated.
036: */
037: public class SaveAllAction extends PageEventAction implements
038: IPropertyListener {
039: /**
040: * List of parts (element type: <code>IWorkbenchPart</code>)
041: * against which this class has outstanding property listeners registered.
042: */
043: private List partsWithListeners = new ArrayList(1);
044: private IWorkbenchPart openPart;
045:
046: /**
047: * The default constructor.
048: *
049: * @param window the window
050: */
051: public SaveAllAction(IWorkbenchWindow window) {
052: super (WorkbenchMessages.SaveAll_text, window);
053: setToolTipText(WorkbenchMessages.SaveAll_toolTip);
054: setId("saveAll"); //$NON-NLS-1$
055: setEnabled(false);
056: window.getWorkbench().getHelpSystem().setHelp(this ,
057: IWorkbenchHelpContextIds.SAVE_ALL_ACTION);
058: setImageDescriptor(WorkbenchImages
059: .getImageDescriptor(IWorkbenchGraphicConstants.IMG_ETOOL_SAVEALL_EDIT));
060: setDisabledImageDescriptor(WorkbenchImages
061: .getImageDescriptor(IWorkbenchGraphicConstants.IMG_ETOOL_SAVEALL_EDIT_DISABLED));
062: setActionDefinitionId("org.eclipse.ui.file.saveAll"); //$NON-NLS-1$
063: }
064:
065: /* (non-Javadoc)
066: * Method declared on PageEventAction.
067: */
068: public void pageActivated(IWorkbenchPage page) {
069: super .pageActivated(page);
070: updateState();
071: }
072:
073: /* (non-Javadoc)
074: * Method declared on PageEventAction.
075: */
076: public void pageClosed(IWorkbenchPage page) {
077: super .pageClosed(page);
078: updateState();
079: }
080:
081: /* (non-Javadoc)
082: * Method declared on PartEventAction.
083: */
084: public void partClosed(IWorkbenchPart part) {
085: super .partClosed(part);
086: if (part instanceof ISaveablePart) {
087: part.removePropertyListener(this );
088: partsWithListeners.remove(part);
089: updateState();
090: }
091: }
092:
093: /* (non-Javadoc)
094: * Method declared on PartEventAction.
095: */
096: public void partOpened(IWorkbenchPart part) {
097: super .partOpened(part);
098: if (part instanceof ISaveablePart) {
099: part.addPropertyListener(this );
100: partsWithListeners.add(part);
101: // We need to temporarily cache the opened part
102: // because saveable views are not registered
103: // with a perspective until after this method
104: // is called. We can't pass it through to
105: // update because it's protected. An async
106: // call to update may be a better approach.
107: // See bug 93784 [WorkbenchParts] View not yet added to perspective when partOpened sent
108: openPart = part;
109: updateState();
110: openPart = null;
111: }
112: }
113:
114: /* (non-Javadoc)
115: * Method declared on IPropertyListener.
116: */
117: public void propertyChanged(Object source, int propID) {
118: if (source instanceof ISaveablePart) {
119: if (propID == ISaveablePart.PROP_DIRTY) {
120: updateState();
121: }
122: }
123: }
124:
125: /* (non-Javadoc)
126: * Method declared on Action.
127: */
128: public void run() {
129: if (getWorkbenchWindow() == null) {
130: // action has been disposed
131: return;
132: }
133: WorkbenchPage page = (WorkbenchPage) getActivePage();
134: if (page != null) {
135: // The second parameter is true to also save saveables from non-part
136: // sources, see bug 139004.
137: page.saveAllEditors(false, true);
138: updateState();
139: }
140: }
141:
142: /**
143: * Updates availability depending on number of
144: * targets that need saving.
145: */
146: protected void updateState() {
147: // Workaround for bug 93784 [WorkbenchParts] View not yet added to perspective when partOpened sent
148: if (openPart != null
149: && openPart.getSite().getPage().equals(getActivePage())
150: && ((ISaveablePart) openPart).isDirty()) {
151: setEnabled(true);
152: } else {
153: WorkbenchPage page = (WorkbenchPage) getActivePage();
154: if (page == null) {
155: setEnabled(false);
156: } else {
157: if (page.getDirtyParts().length > 0) {
158: setEnabled(true);
159: } else {
160: // Since Save All also saves saveables from non-part sources,
161: // look if any such saveables exist and are dirty.
162: SaveablesList saveablesList = (SaveablesList) page
163: .getWorkbenchWindow().getWorkbench()
164: .getService(
165: ISaveablesLifecycleListener.class);
166: ISaveablesSource[] nonPartSources = saveablesList
167: .getNonPartSources();
168: for (int i = 0; i < nonPartSources.length; i++) {
169: Saveable[] saveables = nonPartSources[i]
170: .getSaveables();
171: for (int j = 0; j < saveables.length; j++) {
172: if (saveables[j].isDirty()) {
173: setEnabled(true);
174: return;
175: }
176: }
177: }
178: setEnabled(false);
179: }
180: }
181: }
182: }
183:
184: /* (non-Javadoc)
185: * Method declared on PageEventAction.
186: */
187: public void dispose() {
188: super .dispose();
189: for (Iterator it = partsWithListeners.iterator(); it.hasNext();) {
190: IWorkbenchPart part = (IWorkbenchPart) it.next();
191: part.removePropertyListener(this);
192: }
193: partsWithListeners.clear();
194: }
195: }
|