Bug 429684 - Application Model Editor does not display element after
"Undo" (CTRL+Z) operation

I changed also labels for undo/redo.
I add to revert the code fixed for the bug about classpath URI (#
412567) and this will remove the update of the field decorator when the
editor is opened...

Change-Id: I1490cccdae414ac981a9fbd7898190fef5b1e3f5
Signed-off-by: Olivier Prouvost <olivier.prouvost@opcoach.com>
diff --git a/bundles/org.eclipse.e4.tools.emf.editor3x/src/org/eclipse/e4/tools/emf/editor3x/RedoAction.java b/bundles/org.eclipse.e4.tools.emf.editor3x/src/org/eclipse/e4/tools/emf/editor3x/RedoAction.java
index 4a1a5f5..09ccb0b 100644
--- a/bundles/org.eclipse.e4.tools.emf.editor3x/src/org/eclipse/e4/tools/emf/editor3x/RedoAction.java
+++ b/bundles/org.eclipse.e4.tools.emf.editor3x/src/org/eclipse/e4/tools/emf/editor3x/RedoAction.java
@@ -11,6 +11,7 @@
 package org.eclipse.e4.tools.emf.editor3x;
 
 import org.eclipse.e4.tools.emf.ui.common.IModelResource;
+import org.eclipse.emf.common.command.Command;
 import org.eclipse.jface.action.Action;
 
 public class RedoAction extends Action {
@@ -45,9 +46,12 @@
 
 	private void update() {
 		if (resource.getEditingDomain().getCommandStack().canRedo()) {
+
+			Command redoCommand = resource.getEditingDomain().getCommandStack().getRedoCommand();
+			String label = UndoAction.getCommandLabel(redoCommand);
+
 			setText(Messages.RedoAction_Redo + " " //$NON-NLS-1$
-				+ resource.getEditingDomain().getCommandStack()
-					.getRedoCommand().getLabel());
+					+ label);
 			setEnabled(true);
 		} else {
 			setText(Messages.RedoAction_Redo);
diff --git a/bundles/org.eclipse.e4.tools.emf.editor3x/src/org/eclipse/e4/tools/emf/editor3x/UndoAction.java b/bundles/org.eclipse.e4.tools.emf.editor3x/src/org/eclipse/e4/tools/emf/editor3x/UndoAction.java
index 28eebf0..26313dd 100644
--- a/bundles/org.eclipse.e4.tools.emf.editor3x/src/org/eclipse/e4/tools/emf/editor3x/UndoAction.java
+++ b/bundles/org.eclipse.e4.tools.emf.editor3x/src/org/eclipse/e4/tools/emf/editor3x/UndoAction.java
@@ -10,7 +10,15 @@
  ******************************************************************************/
 package org.eclipse.e4.tools.emf.editor3x;
 
+import java.util.Collection;
+
 import org.eclipse.e4.tools.emf.ui.common.IModelResource;
+import org.eclipse.e4.ui.model.application.ui.MUILabel;
+import org.eclipse.emf.common.command.Command;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.edit.command.AddCommand;
+import org.eclipse.emf.edit.command.DeleteCommand;
+import org.eclipse.emf.edit.command.SetCommand;
 import org.eclipse.jface.action.Action;
 
 public class UndoAction extends Action {
@@ -41,11 +49,15 @@
 		}
 	}
 
+	private static int cpt = 0;
+
 	private void update() {
 		if (resource.getEditingDomain().getCommandStack().canUndo()) {
+			Command undoCommand = resource.getEditingDomain().getCommandStack()
+					.getUndoCommand();
+			String label = getCommandLabel(undoCommand);
 			setText(Messages.UndoAction_Undo + " " //$NON-NLS-1$
-				+ resource.getEditingDomain().getCommandStack()
-					.getUndoCommand().getLabel());
+					+ label);
 			setEnabled(true);
 		} else {
 			setText(Messages.UndoAction_Undo);
@@ -54,6 +66,47 @@
 	}
 
 	/**
+	 * Compute a command label depending on the command for undo/redo label.
+	 *
+	 * For instance : Add Trimmedwindow or Delete 5 objects
+	 *
+	 * @param cmd
+	 * @return a description string for the command
+	 */
+	public static String getCommandLabel(Command cmd) {
+
+		if (cmd instanceof SetCommand) {
+			SetCommand sc = (SetCommand) cmd;
+			return sc.getLabel() + " " + sc.getFeature().getName() + " on " + sc.getOwner().eClass().getName(); //$NON-NLS-1$ //$NON-NLS-2$
+		} else if (cmd instanceof AddCommand) {
+			AddCommand ac = (AddCommand) cmd;
+			return ac.getLabel() + " " + getFirstClassName(ac.getCollection()); //$NON-NLS-1$
+		} else if (cmd instanceof DeleteCommand) {
+			DeleteCommand dc = (DeleteCommand) cmd;
+			Collection<?> deleted = dc.getCollection();
+			if (deleted.size() == 1) {
+				return dc.getLabel() + " " + getFirstClassName(deleted); //$NON-NLS-1$
+			}
+			return dc.getLabel() + " " + dc.getCollection().size() + " Objects"; //$NON-NLS-1$ //$NON-NLS-2$
+		}
+		return cmd.getLabel();
+	}
+
+	/**
+	 * Get the eClassname or empty string of the first element in the collection
+	 *
+	 * @param c
+	 * @return name of classname if object is an EObject else an empty string
+	 */
+	private static String getFirstClassName(Collection<?> c)
+	{
+		Object o = c.iterator().next();
+		String clname = (o instanceof EObject) ? ((EObject) o).eClass().getName() : ""; //$NON-NLS-1$
+		String dname = (o instanceof MUILabel) ? ((MUILabel) o).getLabel() : ""; //$NON-NLS-1$
+		return clname + " " + (dname == null ? "" : dname); //$NON-NLS-1$ //$NON-NLS-2$
+	}
+
+	/**
 	 * Clean up
 	 */
 	public void dispose() {
diff --git a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/Messages.java b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/Messages.java
index 8346eb0..86893c8 100644
--- a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/Messages.java
+++ b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/Messages.java
@@ -110,6 +110,7 @@
 	public String ModelTooling_Common_TabDefault;
 	public String ModelTooling_Common_TabSupplementary;
 	public String ModelEditor_AddChild;
+	public String ModelEditor_Move;
 	public String ModelTooling_Common_RuntimeContributionInstance;
 	public String ModelTooling_Common_RuntimeWidgetTree;
 
diff --git a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/Messages.properties b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/Messages.properties
index c45792d..fde97d5 100644
--- a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/Messages.properties
+++ b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/Messages.properties
@@ -44,6 +44,7 @@
 ModelTooling_Common_TabDefault=Default
 ModelTooling_Common_TabSupplementary=Supplementary
 ModelEditor_AddChild=Add child
+ModelEditor_Move=Move
 ModelTooling_Common_RuntimeContributionInstance=Contrib. Instance
 ModelTooling_Common_RuntimeWidgetTree=Widget Tree
 
diff --git a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/ModelEditor.java b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/ModelEditor.java
index 92d1433..ac05f04 100644
--- a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/ModelEditor.java
+++ b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/ModelEditor.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2010, 2017 BestSolution.at and others.
+ * Copyright (c) 2010, 2018 BestSolution.at 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
@@ -13,7 +13,8 @@
  * Steven Spungin <steven@spungin.tv> - Bug 396902, 431755, 431735, 424730, 424730, 391089, 437236, 437552, Ongoing
  * Maintenance
  * Simon Scholz <simon.scholz@vogella.com> - Bug 475365
- * Olivier Prouvost <olivier.prouvost@opcoach.com> - Bug 472706
+ * Olivier Prouvost <olivier.prouvost@opcoach.com> - Bug 472706, 429684
+ * Dmitry Spiridenok <d.spiridenok@gmail.com> - Bug 429684
  ******************************************************************************/
 package org.eclipse.e4.tools.emf.ui.internal.common;
 
@@ -157,6 +158,7 @@
 import org.eclipse.e4.ui.model.application.ui.MContext;
 import org.eclipse.e4.ui.model.application.ui.MElementContainer;
 import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.MUILabel;
 import org.eclipse.e4.ui.model.application.ui.advanced.impl.AdvancedPackageImpl;
 import org.eclipse.e4.ui.model.application.ui.basic.MPart;
 import org.eclipse.e4.ui.model.application.ui.basic.impl.BasicPackageImpl;
@@ -1835,7 +1837,7 @@
 				}
 
 				if (feature != null && parent != null) {
-					final Command cmd = AddCommand.create(domain, parent, feature, data);
+					final Command cmd = createRemoveAddCommand(data, feature, parent, CommandParameter.NO_INDEX);
 					if (cmd.canExecute()) {
 						domain.getCommandStack().execute(cmd);
 						if (isLiveModel()) {
@@ -1877,7 +1879,7 @@
 				if (feature == FragmentPackageImpl.Literals.MODEL_FRAGMENTS__IMPORTS && parent != null) {
 					final MApplicationElement el = (MApplicationElement) EcoreUtil.create(((EObject) data).eClass());
 					el.setElementId(((MApplicationElement) data).getElementId());
-					final Command cmd = AddCommand.create(domain, parent, feature, el);
+					final Command cmd = createRemoveAddCommand(data, feature, parent, CommandParameter.NO_INDEX);
 					if (cmd.canExecute()) {
 						domain.getCommandStack().execute(cmd);
 					}
@@ -1908,7 +1910,7 @@
 							data = EcoreUtil.copy((EObject) data);
 						}
 
-						final Command cmd = AddCommand.create(domain, parent, feature, data, index);
+						final Command cmd = createRemoveAddCommand(data, feature, parent, index);
 						if (cmd.canExecute()) {
 							domain.getCommandStack().execute(cmd);
 							if (isLiveModel()) {
@@ -1926,6 +1928,58 @@
 			return false;
 		}
 
+		/**
+		 * Create an internal Compound command containing a Remove and a Add so as to
+		 * allow the Undo
+		 *
+		 * @param data
+		 *            the object to be dragged and dropped
+		 * @param destFeature
+		 *            the target feature in the model where data must be dropped
+		 * @param parent
+		 *            the destination parent
+		 * @param index
+		 *            the index in the parent list
+		 * @see bug #429684
+		 * @return the compound command
+		 */
+		private Command createRemoveAddCommand(Object data, EStructuralFeature destFeature, EObject parent, int index) {
+
+			// Remark : this code could be replaced by a MoveCommand, but unfortunately I
+			// could not make it working (its canExecute() method always returns false
+			// because it is not prepared (see canExecute())...)...
+
+			List<Command> listOfCommands = new ArrayList<>();
+			EStructuralFeature sourceFeature = null;
+			if (data instanceof EObject) {
+				sourceFeature = ((EObject) data).eContainmentFeature();
+			}
+			Command removeCommand = RemoveCommand.create(domain, ((EObject) data).eContainer(), sourceFeature, data);
+			if (removeCommand.canExecute()) {
+				listOfCommands.add(removeCommand);
+			}
+
+			Command addCommand = AddCommand.create(domain, parent, destFeature, data, index);
+			listOfCommands.add(addCommand);
+			CompoundCommand compoundCommand = new CompoundCommand(listOfCommands);
+			compoundCommand.setLabel(messages.ModelEditor_Move + " " + getObjectNameForCommand(data)); //$NON-NLS-1$
+			return compoundCommand;
+
+		}
+
+		/**
+		 * compute a valid name for the undo/redo/paste of move commands
+		 *
+		 * @param data
+		 *            the object concerned by the command
+		 * @return a representative string for the object or 'Object' if nothing found
+		 */
+		private String getObjectNameForCommand(Object data) {
+			String clname = (data instanceof EObject) ? ((EObject) data).eClass().getName() : "Object"; //$NON-NLS-1$
+			String dname = (data instanceof MUILabel) ? ((MUILabel) data).getLabel() : ""; //$NON-NLS-1$
+			return clname + " " + dname; //$NON-NLS-1$
+		}
+
 		@Override
 		public boolean validateDrop(Object target, int operation, TransferData transferType) {
 			boolean rv = true;
diff --git a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/AddonsEditor.java b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/AddonsEditor.java
index 6390890..dd39f04 100644
--- a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/AddonsEditor.java
+++ b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/AddonsEditor.java
@@ -116,7 +116,6 @@
 		}
 
 		getMaster().setValue(object);
-		context.updateModels();
 		return composite;
 	}
 
diff --git a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/DynamicMenuContributionEditor.java b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/DynamicMenuContributionEditor.java
index be0e4f9..e96b68e 100644
--- a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/DynamicMenuContributionEditor.java
+++ b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/DynamicMenuContributionEditor.java
@@ -109,7 +109,6 @@
 		}
 
 		getMaster().setValue(object);
-		context.updateModels();
 
 		return composite;
 	}
diff --git a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/HandlerEditor.java b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/HandlerEditor.java
index c75e11f..43470ee 100644
--- a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/HandlerEditor.java
+++ b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/HandlerEditor.java
@@ -119,7 +119,6 @@
 		}
 
 		getMaster().setValue(object);
-		context.updateModels();
 		return composite;
 	}
 
diff --git a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/ImperativeExpressionEditor.java b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/ImperativeExpressionEditor.java
index 18d5f6a..58d8a1f 100644
--- a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/ImperativeExpressionEditor.java
+++ b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/ImperativeExpressionEditor.java
@@ -78,7 +78,6 @@
 			createForm(composite, context, getMaster());
 		}
 		getMaster().setValue(object);
-		context.updateModels();
 
 		return composite;
 	}
diff --git a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/MenuItemEditor.java b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/MenuItemEditor.java
index 9aede68..1c12475 100644
--- a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/MenuItemEditor.java
+++ b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/MenuItemEditor.java
@@ -147,7 +147,6 @@
 		getMaster().setValue(object);
 		enableIdGenerator(UiPackageImpl.Literals.UI_LABEL__LABEL,
 				ApplicationPackageImpl.Literals.APPLICATION_ELEMENT__ELEMENT_ID, null);
-		context.updateModels();
 
 		return composite;
 	}
diff --git a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/PartDescriptorEditor.java b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/PartDescriptorEditor.java
index d3bbd10..7c302e1 100644
--- a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/PartDescriptorEditor.java
+++ b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/PartDescriptorEditor.java
@@ -141,7 +141,6 @@
 		getMaster().setValue(object);
 		enableIdGenerator(UiPackageImpl.Literals.UI_LABEL__LABEL,
 				ApplicationPackageImpl.Literals.APPLICATION_ELEMENT__ELEMENT_ID, null);
-		context.updateModels();
 		return composite;
 	}
 
diff --git a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/PartEditor.java b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/PartEditor.java
index c42d026..e568cee 100644
--- a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/PartEditor.java
+++ b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/PartEditor.java
@@ -143,7 +143,6 @@
 		getMaster().setValue(object);
 		enableIdGenerator(UiPackageImpl.Literals.UI_LABEL__LABEL,
 				ApplicationPackageImpl.Literals.APPLICATION_ELEMENT__ELEMENT_ID, null);
-		context.updateModels();
 
 		return composite;
 	}
diff --git a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/ToolItemEditor.java b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/ToolItemEditor.java
index e37ecb6..4831fb7 100644
--- a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/ToolItemEditor.java
+++ b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/ToolItemEditor.java
@@ -129,7 +129,6 @@
 
 		getMaster().setValue(object);
 		enableIdGenerator(UiPackageImpl.Literals.UI_LABEL__LABEL, ApplicationPackageImpl.Literals.APPLICATION_ELEMENT__ELEMENT_ID, null);
-		context.updateModels();
 
 		return composite;
 	}