| //------------------------------------------------------------------------------ |
| // 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(); |
| } |
| |
| } |