blob: 368d35b64ec8536a3011e4ff4844f570e1ab1c88 [file] [log] [blame]
//------------------------------------------------------------------------------
// Copyright (c) 2005, 2006 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 implementation
//------------------------------------------------------------------------------
package org.eclipse.epf.library.edit.command;
import java.util.EventObject;
import java.util.Iterator;
import org.eclipse.emf.common.CommonPlugin;
import org.eclipse.emf.common.command.BasicCommandStack;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.common.command.CommandStackListener;
import org.eclipse.emf.common.util.WrappedException;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.epf.library.edit.LibraryEditResources;
import org.eclipse.epf.library.edit.process.command.BSDragAndDropCommand;
import org.eclipse.epf.library.edit.util.TngUtil;
import org.eclipse.osgi.util.NLS;
/**
* A command stack that tries its best to fully revert to its initial state.
*
* @author Phong Nguyen Le
* @since 1.0
*/
public class FullyRevertibleCommandStack extends BasicCommandStack {
public static interface IErrorReporter {
void showError(String msg);
}
private IErrorReporter errReporter;
private ActionManager actionMgr;
public FullyRevertibleCommandStack(ActionManager actionMgr) {
this.actionMgr = actionMgr;
}
public FullyRevertibleCommandStack(ActionManager actionMgr,
IErrorReporter errReporter) {
this(actionMgr);
this.errReporter = errReporter;
}
public void setErrorReporter(IErrorReporter errReporter) {
this.errReporter = errReporter;
}
public boolean doExecute(Command command) {
if (!command.canUndo())
return false; // throw new IllegalArgumentException("Cannot
// execute command that cannot de undone");
super.execute(command);
// special handling for ActivityDropCommand
//
// TODO: all commands must return a correct value in getAffectedObject()
// if getAffectedObject() return an empty collection, the action manager
// will not register it as a modifier of the resources returned by getModifiedResources()
// and the editor might not be marked dirty as the result.
//
if(command instanceof BSDragAndDropCommand && command.getAffectedObjects().isEmpty()) {
if(top != -1) {
commandList.remove(top--);
if(top != -1) {
mostRecentCommand = (Command) commandList.get(top);
}
else {
mostRecentCommand = null;
}
}
return false;
}
boolean ret = getMostRecentCommand() != null;
if (ret && actionMgr != null) {
if (command instanceof IResourceAwareCommand) {
for (Iterator iter = ((IResourceAwareCommand) command)
.getModifiedResources().iterator(); iter.hasNext();) {
Resource resource = (Resource) iter.next();
actionMgr.registerAsModifierOf(resource);
}
} else {
EObject modified = TngUtil.getOwner(command);
if (modified != null) {
actionMgr.registerAsModifierOf(modified);
}
}
}
notifyListeners(new CommandStackChangedEvent(this,
CommandStackChangedEvent.EXECUTED));
return ret;
}
public void execute(Command command) {
doExecute(command);
}
public void redo() {
super.redo();
notifyListeners(new CommandStackChangedEvent(this,
CommandStackChangedEvent.EXECUTED));
}
public void undo() {
if (canUndo()) {
Command command = (Command) commandList.get(top--);
try {
command.undo();
mostRecentCommand = command;
} catch (RuntimeException exception) {
CommonPlugin.INSTANCE
.log(new WrappedException(
CommonPlugin.INSTANCE
.getString("_UI_IgnoreException_exception"), exception).fillInStackTrace()); //$NON-NLS-1$
mostRecentCommand = null;
top++;
if (errReporter != null) {
Object[] object = new Object[1];
object[0] = command;
object[1] = exception;
errReporter.showError(NLS.bind(LibraryEditResources.undoCommandError_msg, object));
}
}
notifyListeners(new CommandStackChangedEvent(this,
CommandStackChangedEvent.UNDO));
}
}
public boolean undoAll() {
try {
while (canUndo()) {
Command command = (Command) commandList.get(top--);
try {
command.undo();
mostRecentCommand = command;
} catch (RuntimeException exception) {
CommonPlugin.INSTANCE
.log(new WrappedException(
CommonPlugin.INSTANCE
.getString("_UI_IgnoreException_exception"), exception).fillInStackTrace()); //$NON-NLS-1$
mostRecentCommand = null;
top++;
if (errReporter != null) {
// errReporter.showError("Cannot undo command: '" +
// command + "', exception: " + exception);
Object[] object = new Object[1];
object[0] = command;
object[1] = exception;
errReporter
.showError(NLS.bind(LibraryEditResources.undoCommandError_msg, object));
}
return false;
}
}
} finally {
notifyListeners(new CommandStackChangedEvent(this,
CommandStackChangedEvent.UNDO_ALL));
}
return true;
}
protected void notifyListeners(EventObject event) {
for (Iterator i = listeners.iterator(); i.hasNext();) {
((CommandStackListener) i.next()).commandStackChanged(event);
}
}
protected void notifyListeners() {
//
}
public void saveIsDone() {
super.saveIsDone();
notifyListeners(new CommandStackChangedEvent(this,
CommandStackChangedEvent.SAVED));
commandList.clear();
top = -1;
saveIndex = -1;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.common.command.BasicCommandStack#isSaveNeeded()
*/
public boolean isSaveNeeded() {
return super.isSaveNeeded();
}
}