From 2dff9ecb4d8fc2ed06bb8531fe3e2e63f1d4d823 Mon Sep 17 00:00:00 2001 From: Muhammad Zeshan Date: Fri, 17 Jan 2020 12:56:14 -0500 Subject: [PATCH 1/5] add the redo functionality and fix a bug in MPcommand.Set undo function --- .../src/org/openmbee/mpspi/MPAdapter.java | 14 ++++++++ .../org/openmbee/mpspi/svc/MPBaseAdapter.java | 33 +++++++++++++++++++ .../src/org/openmbee/mpspi/svc/MPCommand.java | 2 +- 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/org.openmbee.mpspi/src/org/openmbee/mpspi/MPAdapter.java b/org.openmbee.mpspi/src/org/openmbee/mpspi/MPAdapter.java index 56eddf1..1c1a1de 100644 --- a/org.openmbee.mpspi/src/org/openmbee/mpspi/MPAdapter.java +++ b/org.openmbee.mpspi/src/org/openmbee/mpspi/MPAdapter.java @@ -87,6 +87,20 @@ public enum UndoResult { * */ void storeTransaction() throws MPException; + + public enum RedoResult { + UNSUPPORTED, + DONE, + ERROR, + NEED_REACTIVATE, + EMPTY_STACK + } + + /** + * Revert the last undo transaction + * */ + RedoResult redo() throws MPException; + /** * Return the resource that has been loaded. * diff --git a/org.openmbee.mpspi/src/org/openmbee/mpspi/svc/MPBaseAdapter.java b/org.openmbee.mpspi/src/org/openmbee/mpspi/svc/MPBaseAdapter.java index 0ced61c..85dca20 100644 --- a/org.openmbee.mpspi/src/org/openmbee/mpspi/svc/MPBaseAdapter.java +++ b/org.openmbee.mpspi/src/org/openmbee/mpspi/svc/MPBaseAdapter.java @@ -14,6 +14,7 @@ import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.resource.Resource; import org.openmbee.mpspi.exceptions.MPException; +import org.openmbee.mpspi.exceptions.MPRedoException; import org.openmbee.mpspi.exceptions.MPUndoException; import org.openmbee.mpspi.exceptions.MPUnsupportedOperationException; import org.openmbee.mpspi.modifier.MPModifier; @@ -99,18 +100,21 @@ protected void commit() throws MPException { } } + @SuppressWarnings({ "unchecked", "rawtypes" }) public UndoResult undo() throws MPException { if (undoLogs.isEmpty()) return UndoResult.EMPTY_STACK; try { Stack> undoLog = undoLogs.pop(); + Object redoObject = undoLog.clone(); while (!undoLog.isEmpty()) { List undo = undoLog.pop(); for (MPCommand mpCommand : undo) { mpCommand.undo(); } } + redoStack.add((Stack)redoObject); return UndoResult.DONE; } catch (Exception e) { // clear the undo stack and throw exception @@ -119,6 +123,35 @@ public UndoResult undo() throws MPException { } } + + private Stack>> redoStack = new Stack>>();; + + @Override + public RedoResult redo() throws MPException { + if (redoStack.isEmpty()) + return RedoResult.EMPTY_STACK; + try { + Stack> redoLog = redoStack.pop(); + while (!redoLog.isEmpty()) { + List redo = redoLog.pop(); + for (MPCommand mpCommand : redo) { + mpCommand.execute(); + } + } + return RedoResult.DONE; + } catch (Exception e) { + // clear the redo stack and throw exception + clearRedoStack(); + throw new MPRedoException("Unable to bring back, Please reload the model without saving." , e); + } + } + + private void clearRedoStack() { + redoStack.clear(); + } + + + public void doSet(EObject target, EStructuralFeature feature, Object value, Object oldValue) { if (isTransactionEnabled()) { mpCommandLog.add(new MPCommand.Set(target, feature, value, oldValue, false)); diff --git a/org.openmbee.mpspi/src/org/openmbee/mpspi/svc/MPCommand.java b/org.openmbee.mpspi/src/org/openmbee/mpspi/svc/MPCommand.java index 9784c05..38c3cac 100644 --- a/org.openmbee.mpspi/src/org/openmbee/mpspi/svc/MPCommand.java +++ b/org.openmbee.mpspi/src/org/openmbee/mpspi/svc/MPCommand.java @@ -72,7 +72,7 @@ public Set(EObject target, EStructuralFeature feature, Object newValue, Object o @Override public void undo() { - if (!isFirstValue) { + if (isFirstValue) { target.eUnset(feature); } else { go(target, feature, oldValue); From cc74cdd231fe21cc920c63647ed12ac5b6e37a58 Mon Sep 17 00:00:00 2001 From: Muhammad Zeshan Date: Fri, 17 Jan 2020 13:01:36 -0500 Subject: [PATCH 2/5] forget to add the exception class --- .../mpspi/exceptions/MPRedoException.java | 24 +++++++++++++++++++ .../org/openmbee/mpspi/svc/MPBaseAdapter.java | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 org.openmbee.mpspi/src/org/openmbee/mpspi/exceptions/MPRedoException.java diff --git a/org.openmbee.mpspi/src/org/openmbee/mpspi/exceptions/MPRedoException.java b/org.openmbee.mpspi/src/org/openmbee/mpspi/exceptions/MPRedoException.java new file mode 100644 index 0000000..b02615b --- /dev/null +++ b/org.openmbee.mpspi/src/org/openmbee/mpspi/exceptions/MPRedoException.java @@ -0,0 +1,24 @@ +/** + * + */ +package org.openmbee.mpspi.exceptions; + +/** + * @author mzeshan + * + */ +public class MPRedoException extends MPFatalException { + /** + * + */ + private static final long serialVersionUID = 6684692097946706048L; + + public MPRedoException(String message) { + super(message); + } + + public MPRedoException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/org.openmbee.mpspi/src/org/openmbee/mpspi/svc/MPBaseAdapter.java b/org.openmbee.mpspi/src/org/openmbee/mpspi/svc/MPBaseAdapter.java index 85dca20..a1a820d 100644 --- a/org.openmbee.mpspi/src/org/openmbee/mpspi/svc/MPBaseAdapter.java +++ b/org.openmbee.mpspi/src/org/openmbee/mpspi/svc/MPBaseAdapter.java @@ -142,7 +142,7 @@ public RedoResult redo() throws MPException { } catch (Exception e) { // clear the redo stack and throw exception clearRedoStack(); - throw new MPRedoException("Unable to bring back, Please reload the model without saving." , e); + throw new MPRedoException("Unable to perform redo operation, Please reload the model without saving." , e); } } From d74e2c10ab713d1f7ab312cd996cde99a419edbb Mon Sep 17 00:00:00 2001 From: Muhammad Zeshan <52756438+mzeshan39@users.noreply.github.com> Date: Mon, 3 Feb 2020 18:18:33 -0500 Subject: [PATCH 3/5] Update MPCommand.java --- org.openmbee.mpspi/src/org/openmbee/mpspi/svc/MPCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.openmbee.mpspi/src/org/openmbee/mpspi/svc/MPCommand.java b/org.openmbee.mpspi/src/org/openmbee/mpspi/svc/MPCommand.java index 38c3cac..9784c05 100644 --- a/org.openmbee.mpspi/src/org/openmbee/mpspi/svc/MPCommand.java +++ b/org.openmbee.mpspi/src/org/openmbee/mpspi/svc/MPCommand.java @@ -72,7 +72,7 @@ public Set(EObject target, EStructuralFeature feature, Object newValue, Object o @Override public void undo() { - if (isFirstValue) { + if (!isFirstValue) { target.eUnset(feature); } else { go(target, feature, oldValue); From 1774c8721f70a3864f078ce50f6ac7af3992a88f Mon Sep 17 00:00:00 2001 From: Muhammad Zeshan Date: Tue, 7 Apr 2020 09:42:26 -0400 Subject: [PATCH 4/5] update the redo and undo enum --- .../src/org/openmbee/mpspi/MPAdapter.java | 24 +++++++------------ .../org/openmbee/mpspi/svc/MPBaseAdapter.java | 8 +++---- 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/org.openmbee.mpspi/src/org/openmbee/mpspi/MPAdapter.java b/org.openmbee.mpspi/src/org/openmbee/mpspi/MPAdapter.java index 1c1a1de..7f16f2e 100644 --- a/org.openmbee.mpspi/src/org/openmbee/mpspi/MPAdapter.java +++ b/org.openmbee.mpspi/src/org/openmbee/mpspi/MPAdapter.java @@ -62,19 +62,17 @@ public enum ReloadResult { NEED_REACTIVATE } + public enum DoResult implements UndoResult, RedoResult { + UNSUPPORTED, DONE, ERROR, NEED_REACTIVATE, EMPTY_STACK + } + /** * reload the model * @throws MPException */ ReloadResult reload() throws MPException; - - public enum UndoResult { - UNSUPPORTED, - DONE, - ERROR, - NEED_REACTIVATE, - EMPTY_STACK - } + + public interface UndoResult {} /** * reload the last modification @@ -87,14 +85,8 @@ public enum UndoResult { * */ void storeTransaction() throws MPException; - - public enum RedoResult { - UNSUPPORTED, - DONE, - ERROR, - NEED_REACTIVATE, - EMPTY_STACK - } + public interface RedoResult {} + /** * Revert the last undo transaction diff --git a/org.openmbee.mpspi/src/org/openmbee/mpspi/svc/MPBaseAdapter.java b/org.openmbee.mpspi/src/org/openmbee/mpspi/svc/MPBaseAdapter.java index a1a820d..691564e 100644 --- a/org.openmbee.mpspi/src/org/openmbee/mpspi/svc/MPBaseAdapter.java +++ b/org.openmbee.mpspi/src/org/openmbee/mpspi/svc/MPBaseAdapter.java @@ -103,7 +103,7 @@ protected void commit() throws MPException { @SuppressWarnings({ "unchecked", "rawtypes" }) public UndoResult undo() throws MPException { if (undoLogs.isEmpty()) - return UndoResult.EMPTY_STACK; + return DoResult.EMPTY_STACK; try { Stack> undoLog = undoLogs.pop(); @@ -115,7 +115,7 @@ public UndoResult undo() throws MPException { } } redoStack.add((Stack)redoObject); - return UndoResult.DONE; + return DoResult.DONE; } catch (Exception e) { // clear the undo stack and throw exception clearUndoStack(); @@ -129,7 +129,7 @@ public UndoResult undo() throws MPException { @Override public RedoResult redo() throws MPException { if (redoStack.isEmpty()) - return RedoResult.EMPTY_STACK; + return DoResult.EMPTY_STACK; try { Stack> redoLog = redoStack.pop(); while (!redoLog.isEmpty()) { @@ -138,7 +138,7 @@ public RedoResult redo() throws MPException { mpCommand.execute(); } } - return RedoResult.DONE; + return DoResult.DONE; } catch (Exception e) { // clear the redo stack and throw exception clearRedoStack(); From b8edd81eb57d8c7681e5b5594583cc3d9ac8cf30 Mon Sep 17 00:00:00 2001 From: Muhammad Zeshan Date: Tue, 21 Sep 2021 09:56:01 -0400 Subject: [PATCH 5/5] fix the undo and redo interaction --- .../org/openmbee/mpspi/svc/MPBaseAdapter.java | 37 ++++++++++++------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/org.openmbee.mpspi/src/org/openmbee/mpspi/svc/MPBaseAdapter.java b/org.openmbee.mpspi/src/org/openmbee/mpspi/svc/MPBaseAdapter.java index 691564e..96a1090 100644 --- a/org.openmbee.mpspi/src/org/openmbee/mpspi/svc/MPBaseAdapter.java +++ b/org.openmbee.mpspi/src/org/openmbee/mpspi/svc/MPBaseAdapter.java @@ -46,7 +46,7 @@ private boolean isTransactionEnabled() { protected void setTransaction(boolean flag) { if (flag) { - mpCommandLog = new ArrayList(); + mpCommandLog = new ArrayList(); undoCommandLog = new Stack>(); } else { mpCommandLog = null; @@ -98,6 +98,7 @@ protected void commit() throws MPException { for (MPCommand mpc : mpCommandLog) { mpc.execute(); } + redoStack.clear(); } @SuppressWarnings({ "unchecked", "rawtypes" }) @@ -114,44 +115,54 @@ public UndoResult undo() throws MPException { mpCommand.undo(); } } - redoStack.add((Stack)redoObject); + redoStack.add((Stack) redoObject); return DoResult.DONE; } catch (Exception e) { // clear the undo stack and throw exception clearUndoStack(); - throw new MPUndoException("Unable to revert, Please reload the model without saving." , e); + throw new MPUndoException("Unable to revert, Please reload the model without saving.", e); } } - private Stack>> redoStack = new Stack>>();; - + @Override public RedoResult redo() throws MPException { - if (redoStack.isEmpty()) + if (redoStack.isEmpty()) return DoResult.EMPTY_STACK; try { Stack> redoLog = redoStack.pop(); + Object tmp = redoLog.clone(); + Stack> undoObject = null; + if (tmp instanceof Stack) { + @SuppressWarnings("unchecked") + // This cast is safe as it keeps the same type used internally + Stack> tmp2 = (Stack>) tmp; + undoObject = tmp2; + } + + if (undoObject == null) + throw new IllegalStateException(); + while (!redoLog.isEmpty()) { List redo = redoLog.pop(); for (MPCommand mpCommand : redo) { mpCommand.execute(); } } + undoLogs.push(undoObject); return DoResult.DONE; } catch (Exception e) { // clear the redo stack and throw exception clearRedoStack(); - throw new MPRedoException("Unable to perform redo operation, Please reload the model without saving." , e); + throw new MPRedoException("Unable to perform redo operation, Please reload the model without saving.", e); } } - + private void clearRedoStack() { redoStack.clear(); } - - - + public void doSet(EObject target, EStructuralFeature feature, Object value, Object oldValue) { if (isTransactionEnabled()) { mpCommandLog.add(new MPCommand.Set(target, feature, value, oldValue, false)); @@ -296,12 +307,12 @@ public void removeByIdx(EObject eObj, EStructuralFeature feature, int index) thr public void set(EObject eObj, EStructuralFeature feature, Object value) throws MPException { MPModifier m = mpModifierMap.get(feature); if (m != null) { - Object oldValue = get(eObj, feature); + Object oldValue = get(eObj, feature); m.set(eObj, feature, value, oldValue); } else { if (MPUtil.isVirtual(feature)) return; - Object oldValue = get(eObj, feature); + Object oldValue = get(eObj, feature); doSet(eObj, feature, value, oldValue); } }