[560861] Swapping content merge viewer don't swap phantoms

The target side when revealing phantom decorators don't return the
correct MergeViewerSide when the compare configuration is mirrored.

- Fix the method PhantomManager#getTargetSide(Match, View)

- Refactor DiagramContentMergeViewer class

- Creating Unit tests

Bug: 560861
Change-Id: I437293113ad2e5fe91ffb4977aaa52c975167d73
Signed-off-by: Glenn Plouhinec <glenn.plouhinec@obeo.fr>
diff --git a/org.eclipse.emf.compare-parent/pom.xml b/org.eclipse.emf.compare-parent/pom.xml
index 62d805f..2e95ea6 100644
--- a/org.eclipse.emf.compare-parent/pom.xml
+++ b/org.eclipse.emf.compare-parent/pom.xml
@@ -120,6 +120,7 @@
     <module>../plugins/org.eclipse.emf.compare.diagram</module>
     <module>../plugins/org.eclipse.emf.compare.diagram.edit</module>
     <module>../plugins/org.eclipse.emf.compare.diagram.ide.ui</module>
+    <module>../plugins/org.eclipse.emf.compare.diagram.ide.ui.tests</module>
     
     <module>../packaging/org.eclipse.emf.compare.tests-feature</module>
   </modules>
diff --git a/packaging/org.eclipse.emf.compare.tests-feature/feature.xml b/packaging/org.eclipse.emf.compare.tests-feature/feature.xml
index 44f8c14..b33eeb7 100644
--- a/packaging/org.eclipse.emf.compare.tests-feature/feature.xml
+++ b/packaging/org.eclipse.emf.compare.tests-feature/feature.xml
@@ -113,4 +113,11 @@
          version="0.0.0"
          unpack="false"/>
 
+   <plugin
+         id="org.eclipse.emf.compare.diagram.ide.ui.tests"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
 </feature>
diff --git a/plugins/org.eclipse.emf.compare.diagram.ide.ui.tests/.checkstyle b/plugins/org.eclipse.emf.compare.diagram.ide.ui.tests/.checkstyle
new file mode 100644
index 0000000..2684ff1
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.diagram.ide.ui.tests/.checkstyle
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<fileset-config file-format-version="1.2.0" simple-config="true" sync-formatter="false">
+  <local-check-config name="EMF Compare" location="/org.eclipse.emf.compare-parent/codeStyle/EMFCompareCheckstyle6Configuration.xml" type="project" description="">
+    <additional-data name="protect-config-file" value="false"/>
+  </local-check-config>
+  <fileset name="all" enabled="true" check-config-name="EMF Compare" local="true">
+    <file-match-pattern match-pattern="." include-pattern="true"/>
+  </fileset>
+</fileset-config>
diff --git a/plugins/org.eclipse.emf.compare.diagram.ide.ui.tests/.classpath b/plugins/org.eclipse.emf.compare.diagram.ide.ui.tests/.classpath
new file mode 100644
index 0000000..3e5654f
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.diagram.ide.ui.tests/.classpath
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="src" path="src">
+		<attributes>
+			<attribute name="test" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/plugins/org.eclipse.emf.compare.diagram.ide.ui.tests/.project b/plugins/org.eclipse.emf.compare.diagram.ide.ui.tests/.project
new file mode 100644
index 0000000..4a23ac7
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.diagram.ide.ui.tests/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.emf.compare.diagram.ide.ui.tests</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/plugins/org.eclipse.emf.compare.diagram.ide.ui.tests/.settings/org.eclipse.jdt.core.prefs b/plugins/org.eclipse.emf.compare.diagram.ide.ui.tests/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..0c68a61
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.diagram.ide.ui.tests/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/plugins/org.eclipse.emf.compare.diagram.ide.ui.tests/META-INF/MANIFEST.MF b/plugins/org.eclipse.emf.compare.diagram.ide.ui.tests/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..ddf3579
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.diagram.ide.ui.tests/META-INF/MANIFEST.MF
@@ -0,0 +1,19 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %pluginName
+Bundle-SymbolicName: org.eclipse.emf.compare.diagram.ide.ui.tests
+Bundle-Version: 3.4.3.qualifier
+Bundle-Vendor: %providerName
+Automatic-Module-Name: org.eclipse.emf.compare.diagram.ide.ui.tests
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Bundle-Localization: plugin
+Require-Bundle: org.junit,
+ org.eclipse.compare,
+ org.mockito,
+ org.hamcrest,
+ org.eclipse.emf.compare,
+ org.eclipse.emf.compare.diagram.ide.ui,
+ org.eclipse.emf.compare.ide.ui,
+ org.eclipse.emf.compare.tests,
+ org.eclipse.emf.compare.rcp.ui,
+ org.eclipse.gmf.runtime.notation
diff --git a/plugins/org.eclipse.emf.compare.diagram.ide.ui.tests/about.html b/plugins/org.eclipse.emf.compare.diagram.ide.ui.tests/about.html
new file mode 100644
index 0000000..670d108
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.diagram.ide.ui.tests/about.html
@@ -0,0 +1,106 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
+<html xmlns="http://www.w3.org/1999/xhtml"> 
+<head> 
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" /> 
+<title>Eclipse Foundation Software User Agreement</title> 
+</head> 
+ 
+<body lang="EN-US"> 
+<h2>Eclipse Foundation Software User Agreement</h2> 
+<p>April 14, 2010</p> 
+ 
+<h3>Usage Of Content</h3> 
+ 
+<p>THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR OTHER MATERIALS FOR OPEN SOURCE PROJECTS
+   (COLLECTIVELY &quot;CONTENT&quot;).  USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS AGREEMENT AND/OR THE TERMS AND
+   CONDITIONS OF LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW.  BY USING THE CONTENT, YOU AGREE THAT YOUR USE
+   OF THE CONTENT IS GOVERNED BY THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR
+   NOTICES INDICATED OR REFERENCED BELOW.  IF YOU DO NOT AGREE TO THE TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND
+   CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW, THEN YOU MAY NOT USE THE CONTENT.</p> 
+ 
+<h3>Applicable Licenses</h3> 
+ 
+<p>Unless otherwise indicated, all Content made available by the Eclipse Foundation is provided to you under the terms and conditions of the Eclipse Public License Version 1.0
+   (&quot;EPL&quot;).  A copy of the EPL is provided with this Content and is also available at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+   For purposes of the EPL, &quot;Program&quot; will mean the Content.</p> 
+ 
+<p>Content includes, but is not limited to, source code, object code, documentation and other files maintained in the Eclipse Foundation source code
+   repository (&quot;Repository&quot;) in software modules (&quot;Modules&quot;) and made available as downloadable archives (&quot;Downloads&quot;).</p> 
+ 
+<ul> 
+       <li>Content may be structured and packaged into modules to facilitate delivering, extending, and upgrading the Content.  Typical modules may include plug-ins (&quot;Plug-ins&quot;), plug-in fragments (&quot;Fragments&quot;), and features (&quot;Features&quot;).</li> 
+       <li>Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java&trade; ARchive) in a directory named &quot;plugins&quot;.</li> 
+       <li>A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material.  Each Feature may be packaged as a sub-directory in a directory named &quot;features&quot;.  Within a Feature, files named &quot;feature.xml&quot; may contain a list of the names and version numbers of the Plug-ins
+      and/or Fragments associated with that Feature.</li> 
+       <li>Features may also include other Features (&quot;Included Features&quot;). Within a Feature, files named &quot;feature.xml&quot; may contain a list of the names and version numbers of Included Features.</li> 
+</ul> 
+ 
+<p>The terms and conditions governing Plug-ins and Fragments should be contained in files named &quot;about.html&quot; (&quot;Abouts&quot;). The terms and conditions governing Features and
+Included Features should be contained in files named &quot;license.html&quot; (&quot;Feature Licenses&quot;).  Abouts and Feature Licenses may be located in any directory of a Download or Module
+including, but not limited to the following locations:</p> 
+ 
+<ul> 
+       <li>The top-level (root) directory</li> 
+       <li>Plug-in and Fragment directories</li> 
+       <li>Inside Plug-ins and Fragments packaged as JARs</li> 
+       <li>Sub-directories of the directory named &quot;src&quot; of certain Plug-ins</li> 
+       <li>Feature directories</li> 
+</ul> 
+ 
+<p>Note: if a Feature made available by the Eclipse Foundation is installed using the Provisioning Technology (as defined below), you must agree to a license (&quot;Feature Update License&quot;) during the
+installation process.  If the Feature contains Included Features, the Feature Update License should either provide you with the terms and conditions governing the Included Features or
+inform you where you can locate them.  Feature Update Licenses may be found in the &quot;license&quot; property of files named &quot;feature.properties&quot; found within a Feature.
+Such Abouts, Feature Licenses, and Feature Update Licenses contain the terms and conditions (or references to such terms and conditions) that govern your use of the associated Content in
+that directory.</p> 
+ 
+<p>THE ABOUTS, FEATURE LICENSES, AND FEATURE UPDATE LICENSES MAY REFER TO THE EPL OR OTHER LICENSE AGREEMENTS, NOTICES OR TERMS AND CONDITIONS.  SOME OF THESE
+OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):</p> 
+ 
+<ul> 
+       <li>Common Public License Version 1.0 (available at <a href="http://www.eclipse.org/legal/cpl-v10.html">http://www.eclipse.org/legal/cpl-v10.html</a>)</li> 
+       <li>Apache Software License 1.1 (available at <a href="http://www.apache.org/licenses/LICENSE">http://www.apache.org/licenses/LICENSE</a>)</li> 
+       <li>Apache Software License 2.0 (available at <a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>)</li> 
+       <li>Metro Link Public License 1.00 (available at <a href="http://www.opengroup.org/openmotif/supporters/metrolink/license.html">http://www.opengroup.org/openmotif/supporters/metrolink/license.html</a>)</li> 
+       <li>Mozilla Public License Version 1.1 (available at <a href="http://www.mozilla.org/MPL/MPL-1.1.html">http://www.mozilla.org/MPL/MPL-1.1.html</a>)</li> 
+</ul> 
+ 
+<p>IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR TO USE OF THE CONTENT.  If no About, Feature License, or Feature Update License is provided, please
+contact the Eclipse Foundation to determine what terms and conditions govern that particular Content.</p> 
+ 
+ 
+<h3>Use of Provisioning Technology</h3> 
+ 
+<p>The Eclipse Foundation makes available provisioning software, examples of which include, but are not limited to, p2 and the Eclipse
+   Update Manager (&quot;Provisioning Technology&quot;) for the purpose of allowing users to install software, documentation, information and/or
+   other materials (collectively &quot;Installable Software&quot;). This capability is provided with the intent of allowing such users to
+   install, extend and update Eclipse-based products. Information about packaging Installable Software is available at <a 
+       href="http://eclipse.org/equinox/p2/repository_packaging.html">http://eclipse.org/equinox/p2/repository_packaging.html</a> 
+   (&quot;Specification&quot;).</p> 
+ 
+<p>You may use Provisioning Technology to allow other parties to install Installable Software. You shall be responsible for enabling the
+   applicable license agreements relating to the Installable Software to be presented to, and accepted by, the users of the Provisioning Technology
+   in accordance with the Specification. By using Provisioning Technology in such a manner and making it available in accordance with the
+   Specification, you further acknowledge your agreement to, and the acquisition of all necessary rights to permit the following:</p> 
+ 
+<ol> 
+       <li>A series of actions may occur (&quot;Provisioning Process&quot;) in which a user may execute the Provisioning Technology
+       on a machine (&quot;Target Machine&quot;) with the intent of installing, extending or updating the functionality of an Eclipse-based
+       product.</li> 
+       <li>During the Provisioning Process, the Provisioning Technology may cause third party Installable Software or a portion thereof to be
+       accessed and copied to the Target Machine.</li> 
+       <li>Pursuant to the Specification, you will provide to the user the terms and conditions that govern the use of the Installable
+       Software (&quot;Installable Software Agreement&quot;) and such Installable Software Agreement shall be accessed from the Target
+       Machine in accordance with the Specification. Such Installable Software Agreement must inform the user of the terms and conditions that govern
+       the Installable Software and must solicit acceptance by the end user in the manner prescribed in such Installable Software Agreement. Upon such
+       indication of agreement by the user, the provisioning Technology will complete installation of the Installable Software.</li> 
+</ol> 
+ 
+<h3>Cryptography</h3> 
+ 
+<p>Content may contain encryption software. The country in which you are currently may have restrictions on the import, possession, and use, and/or re-export to
+   another country, of encryption software. BEFORE using any encryption software, please check the country's laws, regulations and policies concerning the import,
+   possession, or use, and re-export of encryption software, to see if this is permitted.</p> 
+ 
+<p><small>Java and all Java-based trademarks are trademarks of Oracle Corporation in the United States, other countries, or both.</small></p> 
+</body> 
+</html> 
\ No newline at end of file
diff --git a/plugins/org.eclipse.emf.compare.diagram.ide.ui.tests/build.properties b/plugins/org.eclipse.emf.compare.diagram.ide.ui.tests/build.properties
new file mode 100644
index 0000000..0fb7ee6
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.diagram.ide.ui.tests/build.properties
@@ -0,0 +1,7 @@
+source.. = src/
+output.. = target/
+bin.includes = META-INF/,\
+               .,\
+               about.html,\
+               plugin.properties
+src.includes = about.html
diff --git a/plugins/org.eclipse.emf.compare.diagram.ide.ui.tests/plugin.properties b/plugins/org.eclipse.emf.compare.diagram.ide.ui.tests/plugin.properties
new file mode 100644
index 0000000..0d9f2c4
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.diagram.ide.ui.tests/plugin.properties
@@ -0,0 +1,12 @@
+################################################################################
+# Copyright (c) 2020 Obeo.
+# 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:
+#     Obeo - initial API and implementation
+################################################################################
+pluginName = EMF Compare IDE UI Diagram integration Tests
+providerName = Eclipse Modeling Project
diff --git a/plugins/org.eclipse.emf.compare.diagram.ide.ui.tests/pom.xml b/plugins/org.eclipse.emf.compare.diagram.ide.ui.tests/pom.xml
new file mode 100644
index 0000000..2199fe8
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.diagram.ide.ui.tests/pom.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <artifactId>emf.compare-test-parent</artifactId>
+    <groupId>org.eclipse.emf.compare</groupId>
+    <version>1.0.0-SNAPSHOT</version>
+    <relativePath>../../org.eclipse.emf.compare-parent/test-parent</relativePath>
+  </parent>
+  <groupId>org.eclipse.emf.compare</groupId>
+  <artifactId>org.eclipse.emf.compare.diagram.ide.ui.tests</artifactId>
+  <version>3.4.3-SNAPSHOT</version>
+  <packaging>eclipse-test-plugin</packaging>
+
+  <build>
+    <plugins>
+  	  <plugin>
+        <groupId>org.eclipse.tycho</groupId>
+        <artifactId>tycho-surefire-plugin</artifactId>
+        <configuration>
+          <includes>
+            <include>org/eclipse/emf/compare/diagram/ide/ui/tests/suite/AllTests.class</include>
+          </includes>
+          <useUIHarness>true</useUIHarness>
+		</configuration>
+	  </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/plugins/org.eclipse.emf.compare.diagram.ide.ui.tests/src/org/eclipse/emf/compare/diagram/ide/ui/internal/contentmergeviewer/diagram/TestBug560861.java b/plugins/org.eclipse.emf.compare.diagram.ide.ui.tests/src/org/eclipse/emf/compare/diagram/ide/ui/internal/contentmergeviewer/diagram/TestBug560861.java
new file mode 100644
index 0000000..46bf099
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.diagram.ide.ui.tests/src/org/eclipse/emf/compare/diagram/ide/ui/internal/contentmergeviewer/diagram/TestBug560861.java
@@ -0,0 +1,130 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Obeo.
+ * 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:
+ *     Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+
+import org.eclipse.compare.CompareConfiguration;
+import org.eclipse.emf.compare.Comparison;
+import org.eclipse.emf.compare.EMFCompare;
+import org.eclipse.emf.compare.Match;
+import org.eclipse.emf.compare.ide.ui.internal.configuration.EMFCompareConfiguration;
+import org.eclipse.emf.compare.rcp.ui.mergeviewer.IMergeViewer.MergeViewerSide;
+import org.eclipse.emf.compare.scope.DefaultComparisonScope;
+import org.eclipse.emf.compare.tests.framework.AbstractInputData;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * This test is related to the bug <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=560861">560861</a>
+ * 
+ * @author <a href="mailto:glenn.plouhinec@obeo.fr">Glenn Plouhinec</a>
+ */
+@SuppressWarnings("restriction")
+public class TestBug560861 {
+
+	private Comparison comparison;
+
+	private CompareConfiguration cc;
+
+	private EMFCompareConfiguration emfcc;
+
+	private PhantomManager phantomManager;
+
+	private boolean mirrored;
+
+	/**
+	 * Set up the two test models.
+	 * <p>
+	 * <ul>
+	 * <li>left.nodes: In this model we have a tree nodes structured like this:
+	 * 
+	 * <pre>
+	 * Root - DeletedNode
+	 * </pre>
+	 * 
+	 * </li>
+	 * <li>right.nodes: In this model "DeletedNode" has been deleted.</li>
+	 * </ul>
+	 * </p>
+	 * <p>
+	 * A 2-way comparison between left.nodes (left input) and right.nodes (right input) gives the resulting
+	 * comparison model:
+	 * <li>A difference for the deletion of "DeletedNode".</li>
+	 * </p>
+	 * 
+	 * @throws IOException
+	 */
+	@Before
+	public void setUp() throws IOException {
+		Bug560861InputData inputData = new Bug560861InputData();
+		Resource left = inputData.getResource("left.nodes"); //$NON-NLS-1$
+		Resource right = inputData.getResource("right.nodes"); //$NON-NLS-1$
+		Resource origin = null;
+
+		DefaultComparisonScope scope = new DefaultComparisonScope(left, right, origin);
+		comparison = EMFCompare.builder().build().compare(scope);
+		cc = new CompareConfiguration();
+		emfcc = new EMFCompareConfiguration(cc);
+	}
+
+	/**
+	 * Tests that the side returned by the getTargetSide() method is correct before swapping.
+	 */
+	@Test
+	public void testSideBeforeSwappingLeftAndRight() {
+		mirrored = false;
+		cc.setProperty(EMFCompareConfiguration.MIRRORED, mirrored);
+		Match match = comparison.getMatches().get(0).getSubmatches().get(0);
+		phantomManager = new PhantomManager(emfcc, null, null, null, null);
+		MergeViewerSide phantomSide = phantomManager.getTargetSide(match, null);
+
+		assertFalse(emfcc.isMirrored());
+		assertEquals(phantomSide, MergeViewerSide.RIGHT);
+	}
+
+	/**
+	 * Tests that the side returned by the getTargetSide() method is correct after swapping.
+	 */
+	@Test
+	public void testSideAfterSwappingLeftAndRight() {
+		mirrored = true;
+		cc.setProperty(EMFCompareConfiguration.MIRRORED, mirrored);
+		Match match = comparison.getMatches().get(0).getSubmatches().get(0);
+		phantomManager = new PhantomManager(emfcc, null, null, null, null);
+		MergeViewerSide phantomSide = phantomManager.getTargetSide(match, null);
+
+		assertTrue(emfcc.isMirrored());
+		assertEquals(phantomSide, MergeViewerSide.LEFT);
+	}
+
+	/**
+	 * Input data for this bug.
+	 * 
+	 * @author <a href="mailto:glenn.plouhinec@obeo.fr">Glenn Plouhinec</a>
+	 */
+	public class Bug560861InputData extends AbstractInputData {
+
+		private static final String PATH_PREFIX = "data/_560861/"; //$NON-NLS-1$
+
+		public Resource getResource(String resourceName) throws IOException {
+			StringBuilder resourceURL = new StringBuilder(PATH_PREFIX);
+			resourceURL.append(resourceName);
+			return loadFromClassLoader(resourceURL.toString());
+		}
+	}
+
+}
diff --git a/plugins/org.eclipse.emf.compare.diagram.ide.ui.tests/src/org/eclipse/emf/compare/diagram/ide/ui/internal/contentmergeviewer/diagram/data/_560861/left.nodes b/plugins/org.eclipse.emf.compare.diagram.ide.ui.tests/src/org/eclipse/emf/compare/diagram/ide/ui/internal/contentmergeviewer/diagram/data/_560861/left.nodes
new file mode 100644
index 0000000..b26ea13
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.diagram.ide.ui.tests/src/org/eclipse/emf/compare/diagram/ide/ui/internal/contentmergeviewer/diagram/data/_560861/left.nodes
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<nodes:Node xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:nodes="http://www.eclipse.org/emf/compare/tests/nodes" xmi:id="_yWc_0JUeEeGiestbncRZoQ" name="Root">
+  <containmentRef1 xmi:id="_MPLmoN82EeO5ttKSQEjHCQ" name="DeletedNode"/>
+</nodes:Node>
diff --git a/plugins/org.eclipse.emf.compare.diagram.ide.ui.tests/src/org/eclipse/emf/compare/diagram/ide/ui/internal/contentmergeviewer/diagram/data/_560861/right.nodes b/plugins/org.eclipse.emf.compare.diagram.ide.ui.tests/src/org/eclipse/emf/compare/diagram/ide/ui/internal/contentmergeviewer/diagram/data/_560861/right.nodes
new file mode 100644
index 0000000..f249db8
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.diagram.ide.ui.tests/src/org/eclipse/emf/compare/diagram/ide/ui/internal/contentmergeviewer/diagram/data/_560861/right.nodes
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<nodes:Node xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:nodes="http://www.eclipse.org/emf/compare/tests/nodes" xmi:id="_yWc_0JUeEeGiestbncRZoQ" name="Root"/>
diff --git a/plugins/org.eclipse.emf.compare.diagram.ide.ui.tests/src/org/eclipse/emf/compare/diagram/ide/ui/tests/suite/AllTests.java b/plugins/org.eclipse.emf.compare.diagram.ide.ui.tests/src/org/eclipse/emf/compare/diagram/ide/ui/tests/suite/AllTests.java
new file mode 100644
index 0000000..9401ad4
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.diagram.ide.ui.tests/src/org/eclipse/emf/compare/diagram/ide/ui/tests/suite/AllTests.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Obeo.
+ * 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:
+ *     Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.compare.diagram.ide.ui.tests.suite;
+
+import org.eclipse.emf.compare.ComparePackage;
+import org.eclipse.emf.compare.diagram.ide.ui.tests.suite.BugsTestSuite;
+import org.eclipse.emf.compare.tests.nodes.NodesPackage;
+import org.eclipse.emf.compare.tests.nodes.util.NodesResourceFactoryImpl;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.junit.BeforeClass;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+
+@RunWith(Suite.class)
+@SuiteClasses({BugsTestSuite.class })
+public class AllTests {
+
+	@BeforeClass
+	public static void fillEMFRegistries() {
+		EPackage.Registry.INSTANCE.put(ComparePackage.eNS_URI, ComparePackage.eINSTANCE);
+		EPackage.Registry.INSTANCE.put(NodesPackage.eNS_URI, NodesPackage.eINSTANCE);
+
+		Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().put("nodes", //$NON-NLS-1$
+				new NodesResourceFactoryImpl());
+	}
+}
diff --git a/plugins/org.eclipse.emf.compare.diagram.ide.ui.tests/src/org/eclipse/emf/compare/diagram/ide/ui/tests/suite/BugsTestSuite.java b/plugins/org.eclipse.emf.compare.diagram.ide.ui.tests/src/org/eclipse/emf/compare/diagram/ide/ui/tests/suite/BugsTestSuite.java
new file mode 100644
index 0000000..69ac115
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.diagram.ide.ui.tests/src/org/eclipse/emf/compare/diagram/ide/ui/tests/suite/BugsTestSuite.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Obeo.
+ * 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:
+ *     Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.compare.diagram.ide.ui.tests.suite;
+
+import org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.TestBug560861;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+
+@RunWith(Suite.class)
+@SuiteClasses({TestBug560861.class })
+public class BugsTestSuite {
+}
diff --git a/plugins/org.eclipse.emf.compare.diagram.ide.ui/src/org/eclipse/emf/compare/diagram/ide/ui/internal/contentmergeviewer/diagram/AbstractDecoratorManager.java b/plugins/org.eclipse.emf.compare.diagram.ide.ui/src/org/eclipse/emf/compare/diagram/ide/ui/internal/contentmergeviewer/diagram/AbstractDecoratorManager.java
new file mode 100644
index 0000000..1043020
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.diagram.ide.ui/src/org/eclipse/emf/compare/diagram/ide/ui/internal/contentmergeviewer/diagram/AbstractDecoratorManager.java
@@ -0,0 +1,796 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Obeo.
+ * 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:
+ *     Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram;
+
+import com.google.common.base.Predicate;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.eclipse.compare.CompareConfiguration;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.emf.compare.Diff;
+import org.eclipse.emf.compare.Match;
+import org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.figures.DecoratorFigure;
+import org.eclipse.emf.compare.diagram.internal.extensions.DiagramDiff;
+import org.eclipse.emf.compare.ide.ui.internal.configuration.EMFCompareConfiguration;
+import org.eclipse.emf.compare.rcp.ui.mergeviewer.ICompareColor;
+import org.eclipse.emf.compare.rcp.ui.mergeviewer.IMergeViewer.MergeViewerSide;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.gef.EditPart;
+import org.eclipse.gef.GraphicalEditPart;
+import org.eclipse.gef.LayerConstants;
+import org.eclipse.gef.editparts.LayerManager;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.ListCompartmentEditPart;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.ListItemEditPart;
+import org.eclipse.gmf.runtime.notation.Diagram;
+import org.eclipse.gmf.runtime.notation.Edge;
+import org.eclipse.gmf.runtime.notation.View;
+
+/**
+ * Decorator manager to create, hide or reveal decorator figures related to deleted or added graphical
+ * objects.
+ * 
+ * @author <a href="mailto:cedric.notot@obeo.fr">Cedric Notot</a>
+ */
+public abstract class AbstractDecoratorManager implements IDecoratorManager {
+
+	/**
+	 * Decorator represented by a <code>figure</code> on a <code>layer</code>, from the given
+	 * <code>side</code> of the merge viewer. An edit part may be linked to the <code>figure</code> in some
+	 * cases.<br>
+	 * The decorator is related to a <code>difference</code> and it is binded with the reference view and
+	 * figure.
+	 * 
+	 * @author <a href="mailto:cedric.notot@obeo.fr">Cedric Notot</a>
+	 */
+	protected abstract class AbstractDecorator {
+
+		/** The reference <code>View</code> for this decorator. */
+		protected View fOriginView;
+
+		/** The reference <code>IFigure</code> for this decorator. */
+		protected IFigure fOriginFigure;
+
+		/** The <code>IFigure</code> representing this decorator. */
+		protected IFigure fFigure;
+
+		/**
+		 * The <code>DecoratorFigure</code> representing this decorator. It references
+		 * {@link AbstractDecorator#fFigure} through the accessor {@link DecoratorFigure#getMainFigure()}.
+		 */
+		protected DecoratorFigure fDecoratorFigure;
+
+		/** The layer on which the <code>figure</code> has to be drawn. */
+		protected IFigure fLayer;
+
+		/** The side of the merge viewer on which the <code>figure</code> has to be drawn. */
+		protected MergeViewerSide fSide;
+
+		/** The difference related to this phantom. */
+		protected Diff fDifference;
+
+		/** The edit part of the figure representing this phantom. May be null. */
+		protected EditPart fEditPart;
+
+		/**
+		 * Getter.
+		 * 
+		 * @return the originView {@link AbstractDecorator#fOriginView}.
+		 */
+		public View getOriginView() {
+			return fOriginView;
+		}
+
+		/**
+		 * Setter.
+		 * 
+		 * @param originView
+		 *            {@link AbstractDecorator#fOriginView}.
+		 */
+		public void setOriginView(View originView) {
+			this.fOriginView = originView;
+		}
+
+		/**
+		 * Getter.
+		 * 
+		 * @return the originFigure {@link AbstractDecorator#fOriginFigure}.
+		 */
+		public IFigure getOriginFigure() {
+			return fOriginFigure;
+		}
+
+		/**
+		 * Setter.
+		 * 
+		 * @param originFigure
+		 *            {@link AbstractDecorator#fOriginFigure}.
+		 */
+		public void setOriginFigure(IFigure originFigure) {
+			this.fOriginFigure = originFigure;
+		}
+
+		/**
+		 * Getter.
+		 * 
+		 * @return the figure {@link AbstractDecorator#fFigure}.
+		 */
+		public IFigure getFigure() {
+			return fFigure;
+		}
+
+		/**
+		 * Getter.
+		 * 
+		 * @return the decorator figure {@link AbstractDecorator#fDecoratorFigure}.
+		 */
+		public DecoratorFigure getDecoratorFigure() {
+			return fDecoratorFigure;
+		}
+
+		/**
+		 * Setter.
+		 * 
+		 * @param figure
+		 *            {@link AbstractDecorator#fFigure}.
+		 */
+		public void setFigure(IFigure figure) {
+			this.fFigure = figure;
+		}
+
+		/**
+		 * Setter.
+		 * 
+		 * @param figure
+		 *            {@link AbstractDecorator#fFigure}.
+		 */
+		public void setDecoratorFigure(DecoratorFigure figure) {
+			this.fDecoratorFigure = figure;
+			setFigure(figure.getMainFigure());
+		}
+
+		/**
+		 * Getter.
+		 * 
+		 * @return the layer {@link AbstractDecorator#fLayer}.
+		 */
+		public IFigure getLayer() {
+			return fLayer;
+		}
+
+		/**
+		 * Setter.
+		 * 
+		 * @param layer
+		 *            {@link AbstractDecorator#fLayer}.
+		 */
+		public void setLayer(IFigure layer) {
+			this.fLayer = layer;
+		}
+
+		/**
+		 * Getter.
+		 * 
+		 * @return the side {@link AbstractDecorator#fSide}.
+		 */
+		public MergeViewerSide getSide() {
+			return fSide;
+		}
+
+		/**
+		 * Setter.
+		 * 
+		 * @param side
+		 *            {@link AbstractDecorator#fSide}.
+		 */
+		public void setSide(MergeViewerSide side) {
+			this.fSide = side;
+		}
+
+		/**
+		 * Getter.
+		 * 
+		 * @return the difference {@link AbstractDecorator#fDifference}.
+		 */
+		public Diff getDifference() {
+			return fDifference;
+		}
+
+		/**
+		 * Setter.
+		 * 
+		 * @param difference
+		 *            {@link AbstractDecorator#fDifference}.
+		 */
+		public void setDifference(Diff difference) {
+			this.fDifference = difference;
+		}
+
+		/**
+		 * Getter.
+		 * 
+		 * @return the editPart {@link AbstractDecorator#fEditPart}.
+		 */
+		public EditPart getEditPart() {
+			return fEditPart;
+		}
+
+		/**
+		 * Setter.
+		 * 
+		 * @param editPart
+		 *            {@link AbstractDecorator#fEditPart}.
+		 */
+		public void setEditPart(EditPart editPart) {
+			this.fEditPart = editPart;
+		}
+
+	}
+
+	/**
+	 * The compare configuration of the viewer.
+	 */
+	private EMFCompareConfiguration fCompareConfiguration;
+
+	/**
+	 * The left area of the viewer.
+	 */
+	private DiagramMergeViewer fLeft;
+
+	/**
+	 * The right area of the viewer.
+	 */
+	private DiagramMergeViewer fRight;
+
+	/**
+	 * The ancestor area of the viewer.
+	 */
+	private DiagramMergeViewer fAncestor;
+
+	/**
+	 * The color of the difference.
+	 */
+	private ICompareColor fColor;
+
+	/**
+	 * Constructor.
+	 * 
+	 * @param compareConfiguration
+	 *            The compare configuration of the viewer.
+	 * @param left
+	 *            The left area of the viewer.
+	 * @param right
+	 *            The right area of the viewer.
+	 * @param ancestor
+	 *            The ancestor area of the viewer.
+	 * @param color
+	 *            The color of the difference.
+	 */
+	protected AbstractDecoratorManager(EMFCompareConfiguration compareConfiguration, DiagramMergeViewer left,
+			DiagramMergeViewer right, DiagramMergeViewer ancestor, ICompareColor color) {
+		fCompareConfiguration = compareConfiguration;
+		fLeft = left;
+		fRight = right;
+		fAncestor = ancestor;
+		fColor = color;
+	}
+
+	/**
+	 * Returns the compare configuration of this viewer.
+	 *
+	 * @return the compare configuration, never <code>null</code>
+	 */
+	protected EMFCompareConfiguration getCompareConfiguration() {
+		return fCompareConfiguration;
+	}
+
+	/**
+	 * Returns the left area of the viewer.
+	 * 
+	 * @return the fLeft
+	 */
+	protected DiagramMergeViewer getLeftMergeViewer() {
+		return fLeft;
+	}
+
+	/**
+	 * Returns the right area of the viewer.
+	 * 
+	 * @return the fRight
+	 */
+	protected DiagramMergeViewer getRightMergeViewer() {
+		return fRight;
+	}
+
+	/**
+	 * Returns the ancestor area of the viewer.
+	 * 
+	 * @return the fAncestor
+	 */
+	protected DiagramMergeViewer getAncestorMergeViewer() {
+		return fAncestor;
+	}
+
+	/**
+	 * Return whether the input is a three-way comparison.
+	 * 
+	 * @return whether the input is a three-way comparison
+	 */
+	protected boolean isThreeWay() {
+		return getCompareConfiguration().getComparison().isThreeWay();
+	}
+
+	/**
+	 * Returns the ICompareColor.
+	 * 
+	 * @return the ICompareColor.
+	 */
+	public ICompareColor getCompareColor() {
+		return fColor;
+	}
+
+	/**
+	 * From a given difference, it hides the related decorators.
+	 * 
+	 * @param difference
+	 *            The difference.
+	 */
+	public void hideDecorators(Diff difference) {
+		Collection<? extends AbstractDecorator> oldDecorators = getDecorators(difference);
+		if (oldDecorators != null && !oldDecorators.isEmpty()
+				&& getCompareConfiguration().getComparison() != null) {
+			handleDecorators(oldDecorators, false, true);
+		}
+	}
+
+	/**
+	 * From a given difference, it reveals the related decorators.
+	 * 
+	 * @param difference
+	 *            The difference.
+	 */
+	public void revealDecorators(Diff difference) {
+
+		Collection<? super AbstractDecorator> decorators = (Collection<? super AbstractDecorator>)getDecorators(
+				difference);
+
+		// Create decorators only if they do not already exist and if the selected difference is a good
+		// candidate for that.
+		if ((decorators == null || decorators.isEmpty()) && isGoodCandidate(difference)) {
+
+			DiagramDiff diagramDiff = (DiagramDiff)difference;
+
+			List<View> referenveViews = getReferenceViews(diagramDiff);
+
+			for (View referenceView : referenveViews) {
+				IFigure referenceFigure = getFigure(referenceView);
+
+				if (referenceFigure != null) {
+					MergeViewerSide targetSide = getTargetSide(
+							getCompareConfiguration().getComparison().getMatch(referenceView), referenceView);
+
+					if (decorators == null) {
+						decorators = new ArrayList<AbstractDecorator>();
+					}
+
+					AbstractDecorator decorator = createAndRegisterDecorator(difference, referenceView,
+							referenceFigure, targetSide);
+					if (decorator != null) {
+						decorators.add(decorator);
+					}
+				}
+
+			}
+
+		}
+
+		// The selected difference is a good candidate and decorators exist for it
+		if (decorators != null && !decorators.isEmpty()) {
+			revealDecorators((Collection<? extends AbstractDecorator>)decorators);
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.IDecoratorManager#removeDecorators(org.eclipse.emf.compare.Diff)
+	 */
+	public abstract void removeDecorators(Diff difference);
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.IDecoratorManager#removeAll()
+	 */
+	public abstract void removeAll();
+
+	/**
+	 * It reveals the given decorators.
+	 * 
+	 * @param decorators
+	 *            The main decorators.
+	 */
+	protected void revealDecorators(Collection<? extends AbstractDecorator> decorators) {
+		handleDecorators(decorators, true, true);
+	}
+
+	/**
+	 * Get the figure related to the given view.
+	 * 
+	 * @param view
+	 *            The view.
+	 * @return the figure.
+	 */
+	protected IFigure getFigure(View view) {
+		MergeViewerSide side = getSide(view);
+		GraphicalEditPart originEditPart = (GraphicalEditPart)getViewer(side).getEditPart(view);
+		if (originEditPart != null) {
+			return originEditPart.getFigure();
+		}
+		return null;
+	}
+
+	/**
+	 * It manages the display of the given decorators.<br>
+	 * 
+	 * @param decorators
+	 *            The decorators to handle.
+	 * @param isAdd
+	 *            True if it has to be revealed, False otherwise.
+	 * @param areMain
+	 *            It indicates if the given decorators to handle are considered as the main ones (the ones
+	 *            directly linked to the selected difference).
+	 */
+	protected void handleDecorators(Collection<? extends AbstractDecorator> decorators, boolean isAdd,
+			boolean areMain) {
+		for (AbstractDecorator decorator : decorators) {
+			handleDecorator(decorator, isAdd, areMain);
+		}
+	}
+
+	/**
+	 * It manages the display of the given decorator.
+	 * 
+	 * @param decorator
+	 *            The decorator to handle.
+	 * @param isAdd
+	 *            True if it has to be revealed, False otherwise.
+	 * @param isMain
+	 *            It indicates if the given decorator to handle is considered as the main one (the one
+	 *            directly linked to the selected difference).
+	 */
+	protected void handleDecorator(AbstractDecorator decorator, boolean isAdd, boolean isMain) {
+		IFigure layer = decorator.getLayer();
+		IFigure figure = decorator.getFigure();
+		if (isAdd) {
+			handleAddDecorator(decorator, layer, figure, isMain);
+		} else if (layer.getChildren().contains(figure)) {
+			handleDeleteDecorator(decorator, layer, figure);
+		}
+	}
+
+	/**
+	 * It manages the reveal of the given decorator.
+	 * 
+	 * @param decorator
+	 *            The decorator.
+	 * @param parent
+	 *            The parent figure which has to get the figure to reveal (<code>toAdd</code>)
+	 * @param toAdd
+	 *            The figure to reveal.
+	 * @param isMain
+	 *            It indicates if the given decorator to reveal is considered as the main one (the one
+	 *            directly linked to the selected difference).
+	 */
+	protected void handleAddDecorator(AbstractDecorator decorator, IFigure parent, IFigure toAdd,
+			boolean isMain) {
+		if (decorator.getEditPart() != null) {
+			decorator.getEditPart().activate();
+		}
+		if (!parent.getChildren().contains(toAdd)) {
+			parent.add(toAdd);
+		}
+	}
+
+	/**
+	 * It manages the hiding of the given decorator.
+	 * 
+	 * @param decorator
+	 *            The decorator.
+	 * @param parent
+	 *            The parent figure which has to get the figure to hide (<code>toDelete</code>)
+	 * @param toDelete
+	 *            The figure to hide.
+	 */
+	protected void handleDeleteDecorator(AbstractDecorator decorator, IFigure parent, IFigure toDelete) {
+		if (decorator.getEditPart() != null) {
+			decorator.getEditPart().deactivate();
+		}
+		if (parent.getChildren().contains(toDelete)) {
+			parent.remove(toDelete);
+		}
+	}
+
+	/**
+	 * It checks if the given difference is a good candidate to manage decorators.<br>
+	 * 
+	 * @see {@link PhantomManager#goodCandidate()}.
+	 * @param difference
+	 *            The difference.
+	 * @return True if it is a good candidate, False otherwise.
+	 */
+	private boolean isGoodCandidate(Diff difference) {
+		return goodCandidate().apply(difference);
+	}
+
+	/**
+	 * Get the layer on the given side, from the reference view.<br>
+	 * 
+	 * @see @ link {@link PhantomManager#getIDLayer(View)}.
+	 * @param referenceView
+	 *            The reference view.
+	 * @param side
+	 *            The side where the layer has to be found.
+	 * @return The layer figure or null if the edit part of the diagram is not found.
+	 */
+	protected IFigure getLayer(View referenceView, MergeViewerSide side) {
+		Diagram referenceDiagram = referenceView.getDiagram();
+		Diagram targetDiagram = (Diagram)getMatchView(referenceDiagram, getEffectiveSide(side));
+		DiagramMergeViewer targetViewer = getViewer(side);
+		EditPart editPart = targetViewer.getEditPart(targetDiagram);
+		if (editPart != null) {
+			return LayerManager.Helper.find(editPart).getLayer(getIDLayer(referenceView));
+		}
+		return null;
+	}
+
+	/**
+	 * Get the layer ID to use from the reference view.<br>
+	 * If the reference view is an edge, it is the {@link LayerConstants.CONNECTION_LAYER} which is used,
+	 * {@link LayerConstants.SCALABLE_LAYERS} otherwise.
+	 * 
+	 * @param referenceView
+	 *            The reference view.
+	 * @return The ID of the layer.
+	 */
+	protected Object getIDLayer(View referenceView) {
+		if (referenceView instanceof Edge) {
+			return LayerConstants.CONNECTION_LAYER;
+		} else {
+			return LayerConstants.SCALABLE_LAYERS;
+		}
+	}
+
+	/**
+	 * It translates the coordinates of the given bounds, from the reference figure and the root of this one,
+	 * to absolute coordinates.
+	 * 
+	 * @param referenceFigure
+	 *            The reference figure.
+	 * @param rootReferenceFigure
+	 *            The root of the reference figure.
+	 * @param boundsToTranslate
+	 *            The bounds to translate.
+	 */
+	protected void translateCoordinates(IFigure referenceFigure, IFigure rootReferenceFigure,
+			Rectangle boundsToTranslate) {
+		IFigure referenceParentFigure = referenceFigure.getParent();
+		if (referenceParentFigure != null && referenceFigure != rootReferenceFigure) {
+			// rootReferenceFigure may be located to (-x,0)... We consider that the root reference is
+			// always (0,0)
+			if (referenceParentFigure.isCoordinateSystem() && referenceParentFigure != rootReferenceFigure) {
+				boundsToTranslate.x += referenceParentFigure.getBounds().x;
+				boundsToTranslate.y += referenceParentFigure.getBounds().y;
+			}
+			translateCoordinates(referenceParentFigure, rootReferenceFigure, boundsToTranslate);
+		}
+	}
+
+	/**
+	 * It checks that the given view represents an element of a list.
+	 * 
+	 * @param view
+	 *            The view.
+	 * @return True it it is an element of a list.
+	 */
+	protected boolean isNodeList(View view) {
+		DiagramMergeViewer viewer = getViewer(getSide(view));
+		EditPart part = viewer.getEditPart(view);
+		return isNodeList(part);
+	}
+
+	/**
+	 * It checks that the given part represents an element of a list.
+	 * 
+	 * @param part
+	 *            The part.
+	 * @return True it it represents an element of a list.
+	 */
+	private boolean isNodeList(EditPart part) {
+		return part instanceof ListItemEditPart || isInListContainer(part);
+
+	}
+
+	/**
+	 * It checks that the given part is in one representing a list container.
+	 * 
+	 * @param part
+	 *            The part.
+	 * @return True it it is in a part representing a list container.
+	 */
+	private boolean isInListContainer(EditPart part) {
+		EditPart parent = part.getParent();
+		while (parent != null) {
+			if (parent instanceof ListCompartmentEditPart) {
+				return true;
+			}
+			parent = parent.getParent();
+		}
+		return false;
+	}
+
+	/**
+	 * Utility method to retrieve the {@link DiagramMergeViewer} from the given side.
+	 * 
+	 * @param side
+	 *            The side to focus.
+	 * @return The viewer.
+	 */
+	public DiagramMergeViewer getViewer(MergeViewerSide side) {
+		DiagramMergeViewer result = null;
+		switch (side) {
+			case LEFT:
+				result = getLeftMergeViewer();
+				break;
+			case RIGHT:
+				result = getRightMergeViewer();
+				break;
+			case ANCESTOR:
+				result = getAncestorMergeViewer();
+				break;
+			default:
+		}
+		return result;
+	}
+
+	/**
+	 * Utility method to know the side where is located the given view.
+	 * 
+	 * @param view
+	 *            The view.
+	 * @return The side of the view.
+	 */
+	public MergeViewerSide getSide(View view) {
+		MergeViewerSide result = null;
+		Match match = getCompareConfiguration().getComparison().getMatch(view);
+		if (match.getLeft() == view) {
+			result = MergeViewerSide.LEFT;
+		} else if (match.getRight() == view) {
+			result = MergeViewerSide.RIGHT;
+		} else if (match.getOrigin() == view) {
+			result = MergeViewerSide.ANCESTOR;
+		}
+		return getEffectiveSide(result);
+	}
+
+	/**
+	 * Returns the effective side taking into account {@link CompareConfiguration#isMirrored()} to switch left
+	 * and right.
+	 * 
+	 * @param side
+	 *            The side where the potential matching object has to be retrieved.
+	 * @return the effective side with respect to mirroring.
+	 */
+	protected MergeViewerSide getEffectiveSide(MergeViewerSide side) {
+		if (side != null && getCompareConfiguration().isMirrored()) {
+			return side.opposite();
+		}
+		return side;
+	}
+
+	/**
+	 * Utility method to get the object matching with the given one, to the given side.
+	 * 
+	 * @param object
+	 *            The object as base of the lookup.
+	 * @param side
+	 *            The side where the potential matching object has to be retrieved.
+	 * @return The matching object.
+	 */
+	public EObject getMatchView(EObject object, MergeViewerSide side) {
+		Match match = getCompareConfiguration().getComparison().getMatch(object);
+		return getMatchView(match, side);
+	}
+
+	/**
+	 * Utility method to get the object in the given side from the given match.
+	 * 
+	 * @param match
+	 *            The match.
+	 * @param side
+	 *            The side where the potential matching object has to be retrieved.
+	 * @return The matching object.
+	 */
+	private EObject getMatchView(Match match, MergeViewerSide side) {
+		EObject result = null;
+		switch (side) {
+			case LEFT:
+				result = match.getLeft();
+				break;
+			case RIGHT:
+				result = match.getRight();
+				break;
+			case ANCESTOR:
+				result = match.getOrigin();
+				break;
+			default:
+		}
+		return result;
+	}
+
+	/**
+	 * Get the predicate to know the differences concerned by the display of decorators.
+	 * 
+	 * @return The predicate.
+	 */
+	protected abstract Predicate<Diff> goodCandidate();
+
+	/**
+	 * Get the views which have to be used as reference to build the related decorators from the given
+	 * difference of the value concerned by the difference.<br>
+	 * 
+	 * @param difference
+	 *            The difference.
+	 * @return The list of reference views.
+	 */
+	protected abstract List<View> getReferenceViews(DiagramDiff difference);
+
+	/**
+	 * Get the side where decorators have to be drawn, according to the given reference view and its
+	 * match.<br>
+	 * 
+	 * @param match
+	 *            The match of the reference view.
+	 * @param referenceView
+	 *            The reference view.
+	 * @return The side for phantoms.
+	 */
+	protected abstract MergeViewerSide getTargetSide(Match match, View referenceView);
+
+	/**
+	 * It creates new decorators and registers them.
+	 * 
+	 * @param diff
+	 *            The related difference used as index for the main decorator.
+	 * @param referenceView
+	 *            The reference view as base for creation of the decorator.
+	 * @param referenceFigure
+	 *            The reference figure as base for creation of the decorator.
+	 * @param targetSide
+	 *            The side where the decorator has to be created.
+	 * @return The list of main decorators.
+	 */
+	protected abstract AbstractDecorator createAndRegisterDecorator(Diff diff, View referenceView,
+			IFigure referenceFigure, MergeViewerSide targetSide);
+
+	/**
+	 * Get the main decorators related to the given difference.
+	 * 
+	 * @param difference
+	 *            The difference.
+	 * @return The list of main decorators.
+	 */
+	protected abstract Collection<? extends AbstractDecorator> getDecorators(Diff difference);
+
+}
diff --git a/plugins/org.eclipse.emf.compare.diagram.ide.ui/src/org/eclipse/emf/compare/diagram/ide/ui/internal/contentmergeviewer/diagram/DecoratorsManager.java b/plugins/org.eclipse.emf.compare.diagram.ide.ui/src/org/eclipse/emf/compare/diagram/ide/ui/internal/contentmergeviewer/diagram/DecoratorsManager.java
new file mode 100644
index 0000000..7b8ebb3
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.diagram.ide.ui/src/org/eclipse/emf/compare/diagram/ide/ui/internal/contentmergeviewer/diagram/DecoratorsManager.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Obeo.
+ * 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:
+ *     Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram;
+
+import org.eclipse.emf.compare.Diff;
+import org.eclipse.emf.compare.ide.ui.internal.configuration.EMFCompareConfiguration;
+import org.eclipse.emf.compare.rcp.ui.mergeviewer.ICompareColor;
+
+/**
+ * Decorator manager to create, hide or reveal all decorator figures related to graphical changes.
+ * 
+ * @author <a href="mailto:cedric.notot@obeo.fr">Cedric Notot</a>
+ */
+public class DecoratorsManager implements IDecoratorManager {
+	/** Phantoms manager. */
+	private IDecoratorManager fPhantomManager;
+
+	/** Markers manager. */
+	private IDecoratorManager fMarkerManager;
+
+	/**
+	 * Constructor.
+	 * 
+	 * @param compareConfiguration
+	 *            The compare configuration of the viewer.
+	 * @param left
+	 *            The left area of the viewer.
+	 * @param right
+	 *            The right area of the viewer.
+	 * @param ancestor
+	 *            The ancestor area of the viewer.
+	 * @param color
+	 *            The color of the difference.
+	 */
+	public DecoratorsManager(EMFCompareConfiguration compareConfiguration, DiagramMergeViewer left,
+			DiagramMergeViewer right, DiagramMergeViewer ancestor, ICompareColor color) {
+		fPhantomManager = new PhantomManager(compareConfiguration, left, right, ancestor, color);
+		fMarkerManager = new MarkerManager(compareConfiguration, left, right, ancestor, color);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.IDecoratorManager#hideDecorators(org.eclipse.emf.compare.Diff)
+	 */
+	public void hideDecorators(Diff difference) {
+		fMarkerManager.hideDecorators(difference);
+		fPhantomManager.hideDecorators(difference);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.IDecoratorManager#revealDecorators(org.eclipse.emf.compare.Diff)
+	 */
+	public void revealDecorators(Diff difference) {
+		fMarkerManager.revealDecorators(difference);
+		fPhantomManager.revealDecorators(difference);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.IDecoratorManager#hideAll()
+	 */
+	public void hideAll() {
+		fMarkerManager.hideAll();
+		fPhantomManager.hideAll();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.IDecoratorManager#removeDecorators(org.eclipse.emf.compare.Diff)
+	 */
+	public void removeDecorators(Diff difference) {
+		fMarkerManager.removeDecorators(difference);
+		fPhantomManager.removeDecorators(difference);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.IDecoratorManager#removeAll()
+	 */
+	public void removeAll() {
+		fMarkerManager.removeAll();
+		fPhantomManager.removeAll();
+	}
+
+}
diff --git a/plugins/org.eclipse.emf.compare.diagram.ide.ui/src/org/eclipse/emf/compare/diagram/ide/ui/internal/contentmergeviewer/diagram/DiagramContentMergeViewer.java b/plugins/org.eclipse.emf.compare.diagram.ide.ui/src/org/eclipse/emf/compare/diagram/ide/ui/internal/contentmergeviewer/diagram/DiagramContentMergeViewer.java
index a8a49e8..7280677 100644
--- a/plugins/org.eclipse.emf.compare.diagram.ide.ui/src/org/eclipse/emf/compare/diagram/ide/ui/internal/contentmergeviewer/diagram/DiagramContentMergeViewer.java
+++ b/plugins/org.eclipse.emf.compare.diagram.ide.ui/src/org/eclipse/emf/compare/diagram/ide/ui/internal/contentmergeviewer/diagram/DiagramContentMergeViewer.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2013, 2018 Obeo and others.
+ * Copyright (c) 2013, 2020 Obeo 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,80 +13,32 @@
  *******************************************************************************/
 package org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram;
 
-import static com.google.common.base.Predicates.and;
-import static com.google.common.base.Predicates.instanceOf;
-import static com.google.common.base.Predicates.or;
 import static org.eclipse.emf.compare.merge.AbstractMerger.isInTerminalState;
-import static org.eclipse.emf.compare.utils.EMFComparePredicates.ofKind;
-import static org.eclipse.emf.compare.utils.EMFComparePredicates.onFeature;
-import static org.eclipse.emf.compare.utils.EMFComparePredicates.valueIs;
 
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
-import com.google.common.collect.Collections2;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Iterables;
 import com.google.common.collect.Iterators;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Multimap;
 
-import java.util.ArrayList;
-import java.util.Collection;
 import java.util.EventObject;
-import java.util.HashMap;
 import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
 import java.util.ResourceBundle;
 
-import org.eclipse.draw2d.IFigure;
-import org.eclipse.draw2d.Polyline;
-import org.eclipse.draw2d.PolylineConnection;
-import org.eclipse.draw2d.RectangleFigure;
-import org.eclipse.draw2d.geometry.Point;
-import org.eclipse.draw2d.geometry.Rectangle;
 import org.eclipse.emf.common.command.Command;
 import org.eclipse.emf.common.command.CommandStack;
 import org.eclipse.emf.compare.Diff;
-import org.eclipse.emf.compare.DifferenceKind;
-import org.eclipse.emf.compare.DifferenceState;
-import org.eclipse.emf.compare.Match;
 import org.eclipse.emf.compare.command.impl.CopyCommand;
 import org.eclipse.emf.compare.diagram.ide.ui.internal.accessor.IDiagramDiffAccessor;
 import org.eclipse.emf.compare.diagram.ide.ui.internal.accessor.IDiagramNodeAccessor;
-import org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.figures.DecoratorFigure;
-import org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.figures.EdgeFigure;
-import org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.figures.NodeFigure;
-import org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.figures.NodeListFigure;
-import org.eclipse.emf.compare.diagram.internal.extensions.CoordinatesChange;
 import org.eclipse.emf.compare.diagram.internal.extensions.DiagramDiff;
-import org.eclipse.emf.compare.diagram.internal.extensions.Hide;
-import org.eclipse.emf.compare.diagram.internal.extensions.Show;
 import org.eclipse.emf.compare.ide.ui.internal.configuration.EMFCompareConfiguration;
 import org.eclipse.emf.compare.ide.ui.internal.contentmergeviewer.EMFCompareContentMergeViewer;
 import org.eclipse.emf.compare.ide.ui.internal.contentmergeviewer.tree.TreeContentMergeViewerContentProvider;
-import org.eclipse.emf.compare.internal.utils.DiffUtil;
 import org.eclipse.emf.compare.rcp.ui.mergeviewer.IMergeViewer;
 import org.eclipse.emf.compare.rcp.ui.mergeviewer.IMergeViewer.MergeViewerSide;
-import org.eclipse.emf.compare.utils.ReferenceUtil;
 import org.eclipse.emf.ecore.EObject;
-import org.eclipse.gef.ConnectionEditPart;
-import org.eclipse.gef.EditPart;
-import org.eclipse.gef.GraphicalEditPart;
-import org.eclipse.gef.LayerConstants;
 import org.eclipse.gef.RootEditPart;
-import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
-import org.eclipse.gef.editparts.LayerManager;
 import org.eclipse.gef.editparts.ZoomListener;
 import org.eclipse.gef.editparts.ZoomManager;
 import org.eclipse.gef.ui.actions.ZoomComboContributionItem;
 import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramRootEditPart;
-import org.eclipse.gmf.runtime.diagram.ui.editparts.ListCompartmentEditPart;
-import org.eclipse.gmf.runtime.diagram.ui.editparts.ListItemEditPart;
-import org.eclipse.gmf.runtime.notation.Diagram;
-import org.eclipse.gmf.runtime.notation.Edge;
-import org.eclipse.gmf.runtime.notation.NotationPackage;
-import org.eclipse.gmf.runtime.notation.View;
 import org.eclipse.jface.action.ToolBarManager;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.graphics.GC;
@@ -104,1642 +56,12 @@
 public class DiagramContentMergeViewer extends EMFCompareContentMergeViewer implements ZoomListener {
 
 	/**
-	 * Interface for the management of decorators.
-	 * 
-	 * @author <a href="mailto:cedric.notot@obeo.fr">Cedric Notot</a>
-	 */
-	private interface IDecoratorManager {
-
-		/**
-		 * It hides the revealed decorators.
-		 */
-		void hideAll();
-
-		/**
-		 * From a given difference, it hides the related decorators.
-		 * 
-		 * @param difference
-		 *            The difference.
-		 */
-		void hideDecorators(Diff difference);
-
-		/**
-		 * From a given difference, it reveals the related decorators.
-		 * 
-		 * @param difference
-		 *            The difference.
-		 */
-		void revealDecorators(Diff difference);
-
-		/**
-		 * From a given difference, it removes the related decorators from cash.
-		 * 
-		 * @param difference
-		 *            The difference.
-		 */
-		void removeDecorators(Diff difference);
-
-		/**
-		 * It removes all the displayed decorators from cache.
-		 */
-		void removeAll();
-	}
-
-	/**
-	 * Decorator manager to create, hide or reveal decorator figures related to deleted or added graphical
-	 * objects.
-	 * 
-	 * @author <a href="mailto:cedric.notot@obeo.fr">Cedric Notot</a>
-	 */
-	private abstract class AbstractDecoratorManager implements IDecoratorManager {
-
-		/**
-		 * Decorator represented by a <code>figure</code> on a <code>layer</code>, from the given
-		 * <code>side</code> of the merge viewer. An edit part may be linked to the <code>figure</code> in
-		 * some cases.<br>
-		 * The decorator is related to a <code>difference</code> and it is binded with the reference view and
-		 * figure.
-		 * 
-		 * @author <a href="mailto:cedric.notot@obeo.fr">Cedric Notot</a>
-		 */
-		protected abstract class AbstractDecorator {
-
-			/** The reference <code>View</code> for this decorator. */
-			protected View fOriginView;
-
-			/** The reference <code>IFigure</code> for this decorator. */
-			protected IFigure fOriginFigure;
-
-			/** The <code>IFigure</code> representing this decorator. */
-			protected IFigure fFigure;
-
-			/**
-			 * The <code>DecoratorFigure</code> representing this decorator. It references
-			 * {@link AbstractDecorator#fFigure} through the accessor {@link DecoratorFigure#getMainFigure()}.
-			 */
-			protected DecoratorFigure fDecoratorFigure;
-
-			/** The layer on which the <code>figure</code> has to be drawn. */
-			protected IFigure fLayer;
-
-			/** The side of the merge viewer on which the <code>figure</code> has to be drawn. */
-			protected MergeViewerSide fSide;
-
-			/** The difference related to this phantom. */
-			protected Diff fDifference;
-
-			/** The edit part of the figure representing this phantom. May be null. */
-			protected EditPart fEditPart;
-
-			/**
-			 * Getter.
-			 * 
-			 * @return the originView {@link AbstractDecorator#fOriginView}.
-			 */
-			public View getOriginView() {
-				return fOriginView;
-			}
-
-			/**
-			 * Setter.
-			 * 
-			 * @param originView
-			 *            {@link AbstractDecorator#fOriginView}.
-			 */
-			public void setOriginView(View originView) {
-				this.fOriginView = originView;
-			}
-
-			/**
-			 * Getter.
-			 * 
-			 * @return the originFigure {@link AbstractDecorator#fOriginFigure}.
-			 */
-			public IFigure getOriginFigure() {
-				return fOriginFigure;
-			}
-
-			/**
-			 * Setter.
-			 * 
-			 * @param originFigure
-			 *            {@link AbstractDecorator#fOriginFigure}.
-			 */
-			public void setOriginFigure(IFigure originFigure) {
-				this.fOriginFigure = originFigure;
-			}
-
-			/**
-			 * Getter.
-			 * 
-			 * @return the figure {@link AbstractDecorator#fFigure}.
-			 */
-			public IFigure getFigure() {
-				return fFigure;
-			}
-
-			/**
-			 * Getter.
-			 * 
-			 * @return the decorator figure {@link AbstractDecorator#fDecoratorFigure}.
-			 */
-			public DecoratorFigure getDecoratorFigure() {
-				return fDecoratorFigure;
-			}
-
-			/**
-			 * Setter.
-			 * 
-			 * @param figure
-			 *            {@link AbstractDecorator#fFigure}.
-			 */
-			public void setFigure(IFigure figure) {
-				this.fFigure = figure;
-			}
-
-			/**
-			 * Setter.
-			 * 
-			 * @param figure
-			 *            {@link AbstractDecorator#fFigure}.
-			 */
-			public void setDecoratorFigure(DecoratorFigure figure) {
-				this.fDecoratorFigure = figure;
-				setFigure(figure.getMainFigure());
-			}
-
-			/**
-			 * Getter.
-			 * 
-			 * @return the layer {@link AbstractDecorator#fLayer}.
-			 */
-			public IFigure getLayer() {
-				return fLayer;
-			}
-
-			/**
-			 * Setter.
-			 * 
-			 * @param layer
-			 *            {@link AbstractDecorator#fLayer}.
-			 */
-			public void setLayer(IFigure layer) {
-				this.fLayer = layer;
-			}
-
-			/**
-			 * Getter.
-			 * 
-			 * @return the side {@link AbstractDecorator#fSide}.
-			 */
-			public MergeViewerSide getSide() {
-				return fSide;
-			}
-
-			/**
-			 * Setter.
-			 * 
-			 * @param side
-			 *            {@link AbstractDecorator#fSide}.
-			 */
-			public void setSide(MergeViewerSide side) {
-				this.fSide = side;
-			}
-
-			/**
-			 * Getter.
-			 * 
-			 * @return the difference {@link AbstractDecorator#fDifference}.
-			 */
-			public Diff getDifference() {
-				return fDifference;
-			}
-
-			/**
-			 * Setter.
-			 * 
-			 * @param difference
-			 *            {@link AbstractDecorator#fDifference}.
-			 */
-			public void setDifference(Diff difference) {
-				this.fDifference = difference;
-			}
-
-			/**
-			 * Getter.
-			 * 
-			 * @return the editPart {@link AbstractDecorator#fEditPart}.
-			 */
-			public EditPart getEditPart() {
-				return fEditPart;
-			}
-
-			/**
-			 * Setter.
-			 * 
-			 * @param editPart
-			 *            {@link AbstractDecorator#fEditPart}.
-			 */
-			public void setEditPart(EditPart editPart) {
-				this.fEditPart = editPart;
-			}
-
-		}
-
-		/**
-		 * From a given difference, it hides the related decorators.
-		 * 
-		 * @param difference
-		 *            The difference.
-		 */
-		public void hideDecorators(Diff difference) {
-			Collection<? extends AbstractDecorator> oldDecorators = getDecorators(difference);
-			if (oldDecorators != null && !oldDecorators.isEmpty()
-					&& getCompareConfiguration().getComparison() != null) {
-				handleDecorators(oldDecorators, false, true);
-			}
-		}
-
-		/**
-		 * From a given difference, it reveals the related decorators.
-		 * 
-		 * @param difference
-		 *            The difference.
-		 */
-		public void revealDecorators(Diff difference) {
-
-			Collection<? super AbstractDecorator> decorators = (Collection<? super AbstractDecorator>)getDecorators(
-					difference);
-
-			// Create decorators only if they do not already exist and if the selected difference is a good
-			// candidate for that.
-			if ((decorators == null || decorators.isEmpty()) && isGoodCandidate(difference)) {
-
-				DiagramDiff diagramDiff = (DiagramDiff)difference;
-
-				List<View> referenveViews = getReferenceViews(diagramDiff);
-
-				for (View referenceView : referenveViews) {
-					IFigure referenceFigure = getFigure(referenceView);
-
-					if (referenceFigure != null) {
-						MergeViewerSide targetSide = getTargetSide(
-								getCompareConfiguration().getComparison().getMatch(referenceView),
-								referenceView);
-
-						if (decorators == null) {
-							decorators = new ArrayList<AbstractDecorator>();
-						}
-
-						AbstractDecorator decorator = createAndRegisterDecorator(difference, referenceView,
-								referenceFigure, targetSide);
-						if (decorator != null) {
-							decorators.add(decorator);
-						}
-					}
-
-				}
-
-			}
-
-			// The selected difference is a good candidate and decorators exist for it
-			if (decorators != null && !decorators.isEmpty()) {
-				revealDecorators((Collection<? extends AbstractDecorator>)decorators);
-			}
-		}
-
-		/**
-		 * {@inheritDoc}
-		 * 
-		 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.DiagramContentMergeViewer.IDecoratorManager#removeDecorators(org.eclipse.emf.compare.Diff)
-		 */
-		public abstract void removeDecorators(Diff difference);
-
-		/**
-		 * {@inheritDoc}
-		 * 
-		 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.DiagramContentMergeViewer.IDecoratorManager#removeAll()
-		 */
-		public abstract void removeAll();
-
-		/**
-		 * It reveals the given decorators.
-		 * 
-		 * @param decorators
-		 *            The main decorators.
-		 */
-		protected void revealDecorators(Collection<? extends AbstractDecorator> decorators) {
-			handleDecorators(decorators, true, true);
-		}
-
-		/**
-		 * Get the figure related to the given view.
-		 * 
-		 * @param view
-		 *            The view.
-		 * @return the figure.
-		 */
-		protected IFigure getFigure(View view) {
-			MergeViewerSide side = getSide(view);
-			GraphicalEditPart originEditPart = (GraphicalEditPart)getViewer(side).getEditPart(view);
-			if (originEditPart != null) {
-				return originEditPart.getFigure();
-			}
-			return null;
-		}
-
-		/**
-		 * It manages the display of the given decorators.<br>
-		 * 
-		 * @param decorators
-		 *            The decorators to handle.
-		 * @param isAdd
-		 *            True if it has to be revealed, False otherwise.
-		 * @param areMain
-		 *            It indicates if the given decorators to handle are considered as the main ones (the ones
-		 *            directly linked to the selected difference).
-		 */
-		protected void handleDecorators(Collection<? extends AbstractDecorator> decorators, boolean isAdd,
-				boolean areMain) {
-			for (AbstractDecorator decorator : decorators) {
-				handleDecorator(decorator, isAdd, areMain);
-			}
-		}
-
-		/**
-		 * It manages the display of the given decorator.
-		 * 
-		 * @param decorator
-		 *            The decorator to handle.
-		 * @param isAdd
-		 *            True if it has to be revealed, False otherwise.
-		 * @param isMain
-		 *            It indicates if the given decorator to handle is considered as the main one (the one
-		 *            directly linked to the selected difference).
-		 */
-		protected void handleDecorator(AbstractDecorator decorator, boolean isAdd, boolean isMain) {
-			IFigure layer = decorator.getLayer();
-			IFigure figure = decorator.getFigure();
-			if (isAdd) {
-				handleAddDecorator(decorator, layer, figure, isMain);
-			} else if (layer.getChildren().contains(figure)) {
-				handleDeleteDecorator(decorator, layer, figure);
-			}
-		}
-
-		/**
-		 * It manages the reveal of the given decorator.
-		 * 
-		 * @param decorator
-		 *            The decorator.
-		 * @param parent
-		 *            The parent figure which has to get the figure to reveal (<code>toAdd</code>)
-		 * @param toAdd
-		 *            The figure to reveal.
-		 * @param isMain
-		 *            It indicates if the given decorator to reveal is considered as the main one (the one
-		 *            directly linked to the selected difference).
-		 */
-		protected void handleAddDecorator(AbstractDecorator decorator, IFigure parent, IFigure toAdd,
-				boolean isMain) {
-			if (decorator.getEditPart() != null) {
-				decorator.getEditPart().activate();
-			}
-			if (!parent.getChildren().contains(toAdd)) {
-				parent.add(toAdd);
-			}
-		}
-
-		/**
-		 * It manages the hiding of the given decorator.
-		 * 
-		 * @param decorator
-		 *            The decorator.
-		 * @param parent
-		 *            The parent figure which has to get the figure to hide (<code>toDelete</code>)
-		 * @param toDelete
-		 *            The figure to hide.
-		 */
-		protected void handleDeleteDecorator(AbstractDecorator decorator, IFigure parent, IFigure toDelete) {
-			if (decorator.getEditPart() != null) {
-				decorator.getEditPart().deactivate();
-			}
-			if (parent.getChildren().contains(toDelete)) {
-				parent.remove(toDelete);
-			}
-		}
-
-		/**
-		 * It checks if the given difference is a good candidate to manage decorators.<br>
-		 * 
-		 * @see {@link PhantomManager#goodCandidate()}.
-		 * @param difference
-		 *            The difference.
-		 * @return True if it is a good candidate, False otherwise.
-		 */
-		private boolean isGoodCandidate(Diff difference) {
-			return goodCandidate().apply(difference);
-		}
-
-		/**
-		 * Get the layer on the given side, from the reference view.<br>
-		 * 
-		 * @see @ link PhantomManager#getIDLayer(View)} .
-		 * @param referenceView
-		 *            The reference view.
-		 * @param side
-		 *            The side where the layer has to be found.
-		 * @return The layer figure or null if the edit part of the diagram is not found.
-		 */
-		protected IFigure getLayer(View referenceView, MergeViewerSide side) {
-			Diagram referenceDiagram = referenceView.getDiagram();
-			Diagram targetDiagram = (Diagram)getMatchView(referenceDiagram, getEffectiveSide(side));
-			DiagramMergeViewer targetViewer = getViewer(side);
-			EditPart editPart = targetViewer.getEditPart(targetDiagram);
-			if (editPart != null) {
-				return LayerManager.Helper.find(editPart).getLayer(getIDLayer(referenceView));
-			}
-			return null;
-		}
-
-		/**
-		 * Get the layer ID to use from the reference view.<br>
-		 * If the reference view is an edge, it is the {@link LayerConstants.CONNECTION_LAYER} which is used,
-		 * {@link LayerConstants.SCALABLE_LAYERS} otherwise.
-		 * 
-		 * @param referenceView
-		 *            The reference view.
-		 * @return The ID of the layer.
-		 */
-		protected Object getIDLayer(View referenceView) {
-			if (referenceView instanceof Edge) {
-				return LayerConstants.CONNECTION_LAYER;
-			} else {
-				return LayerConstants.SCALABLE_LAYERS;
-			}
-		}
-
-		/**
-		 * It translates the coordinates of the given bounds, from the reference figure and the root of this
-		 * one, to absolute coordinates.
-		 * 
-		 * @param referenceFigure
-		 *            The reference figure.
-		 * @param rootReferenceFigure
-		 *            The root of the reference figure.
-		 * @param boundsToTranslate
-		 *            The bounds to translate.
-		 */
-		protected void translateCoordinates(IFigure referenceFigure, IFigure rootReferenceFigure,
-				Rectangle boundsToTranslate) {
-			IFigure referenceParentFigure = referenceFigure.getParent();
-			if (referenceParentFigure != null && referenceFigure != rootReferenceFigure) {
-				// rootReferenceFigure may be located to (-x,0)... We consider that the root reference is
-				// always (0,0)
-				if (referenceParentFigure.isCoordinateSystem()
-						&& referenceParentFigure != rootReferenceFigure) {
-					boundsToTranslate.x += referenceParentFigure.getBounds().x;
-					boundsToTranslate.y += referenceParentFigure.getBounds().y;
-				}
-				translateCoordinates(referenceParentFigure, rootReferenceFigure, boundsToTranslate);
-			}
-		}
-
-		/**
-		 * It checks that the given view represents an element of a list.
-		 * 
-		 * @param view
-		 *            The view.
-		 * @return True it it is an element of a list.
-		 */
-		protected boolean isNodeList(View view) {
-			DiagramMergeViewer viewer = getViewer(getSide(view));
-			EditPart part = viewer.getEditPart(view);
-			return isNodeList(part);
-		}
-
-		/**
-		 * It checks that the given part represents an element of a list.
-		 * 
-		 * @param part
-		 *            The part.
-		 * @return True it it represents an element of a list.
-		 */
-		private boolean isNodeList(EditPart part) {
-			return part instanceof ListItemEditPart || isInListContainer(part);
-
-		}
-
-		/**
-		 * It checks that the given part is in one representing a list container.
-		 * 
-		 * @param part
-		 *            The part.
-		 * @return True it it is in a part representing a list container.
-		 */
-		private boolean isInListContainer(EditPart part) {
-			EditPart parent = part.getParent();
-			while (parent != null) {
-				if (parent instanceof ListCompartmentEditPart) {
-					return true;
-				}
-				parent = parent.getParent();
-			}
-			return false;
-		}
-
-		/**
-		 * Get the predicate to know the differences concerned by the display of decorators.
-		 * 
-		 * @return The predicate.
-		 */
-		protected abstract Predicate<Diff> goodCandidate();
-
-		/**
-		 * Get the views which have to be used as reference to build the related decorators from the given
-		 * difference of the value concerned by the difference.<br>
-		 * 
-		 * @param difference
-		 *            The difference.
-		 * @return The list of reference views.
-		 */
-		protected abstract List<View> getReferenceViews(DiagramDiff difference);
-
-		/**
-		 * Get the side where decorators have to be drawn, according to the given reference view and its
-		 * match.<br>
-		 * 
-		 * @param match
-		 *            The match of the reference view.
-		 * @param referenceView
-		 *            The reference view.
-		 * @return The side for phantoms.
-		 */
-		protected abstract MergeViewerSide getTargetSide(Match match, View referenceView);
-
-		/**
-		 * It creates new decorators and registers them.
-		 * 
-		 * @param diff
-		 *            The related difference used as index for the main decorator.
-		 * @param referenceView
-		 *            The reference view as base for creation of the decorator.
-		 * @param referenceFigure
-		 *            The reference figure as base for creation of the decorator.
-		 * @param targetSide
-		 *            The side where the decorator has to be created.
-		 * @return The list of main decorators.
-		 */
-		protected abstract AbstractDecorator createAndRegisterDecorator(Diff diff, View referenceView,
-				IFigure referenceFigure, MergeViewerSide targetSide);
-
-		/**
-		 * Get the main decorators related to the given difference.
-		 * 
-		 * @param difference
-		 *            The difference.
-		 * @return The list of main decorators.
-		 */
-		protected abstract Collection<? extends AbstractDecorator> getDecorators(Diff difference);
-
-	}
-
-	/**
-	 * Phantom manager to create, hide or reveal phantom figures related to deleted or added graphical
-	 * objects.
-	 * 
-	 * @author <a href="mailto:cedric.notot@obeo.fr">Cedric Notot</a>
-	 */
-	private class PhantomManager extends AbstractDecoratorManager {
-
-		/**
-		 * Phantom represented by a <code>figure</code> on a <code>layer</code>, from the given
-		 * <code>side</code> of the merge viewer. An edit part may be linked to the <code>figure</code> in
-		 * some cases.<br>
-		 * The phantom is related to a <code>difference</code> and it is binded with the reference view and
-		 * figure.
-		 * 
-		 * @author <a href="mailto:cedric.notot@obeo.fr">Cedric Notot</a>
-		 */
-		private class Phantom extends AbstractDecorator {
-
-			/**
-			 * Constructor.
-			 * 
-			 * @param layer
-			 *            {@link Phantom#fLayer}.
-			 * @param side
-			 *            {@link Phantom#fSide}.
-			 * @param originView
-			 *            {@link Phantom#fOriginView}.
-			 * @param originFigure
-			 *            {@link Phantom#fOriginFigure}.
-			 * @param diff
-			 *            {@link Phantom#fDifference}.
-			 */
-			Phantom(IFigure layer, MergeViewerSide side, View originView, IFigure originFigure, Diff diff) {
-				setLayer(layer);
-				setSide(side);
-				setOriginView(originView);
-				setOriginFigure(originFigure);
-				setDifference(diff);
-			}
-
-			/**
-			 * Get the decorator dependencies of this one. The dependencies are the decorator ancestors plus
-			 * the extremities of an edge decorator.<br>
-			 * DO NOT CALL in an iterate of {@link PhantomManager#fPhantomRegistry}
-			 * 
-			 * @return The list of found decorators.
-			 */
-			public List<? extends AbstractDecorator> getDependencies() {
-				List<AbstractDecorator> result = new ArrayList<AbstractDecorator>();
-				result.addAll(getAncestors());
-				if (fOriginView instanceof Edge) {
-					View source = ((Edge)fOriginView).getSource();
-					View target = ((Edge)fOriginView).getTarget();
-					result.addAll(getOrCreateRelatedPhantoms(source, fSide));
-					result.addAll(getOrCreateRelatedPhantoms(target, fSide));
-				}
-				return result;
-			}
-
-			/**
-			 * Get the ancestor decorators of this one.
-			 * 
-			 * @return The list of the ancestors.
-			 */
-			private List<? extends AbstractDecorator> getAncestors() {
-				List<AbstractDecorator> result = new ArrayList<AbstractDecorator>();
-				EObject parentOriginView = fOriginView.eContainer();
-				while (parentOriginView != null) {
-					result.addAll(getOrCreateRelatedPhantoms(parentOriginView, fSide));
-					parentOriginView = parentOriginView.eContainer();
-				}
-				return result;
-			}
-		}
-
-		/** Registry of created phantoms, indexed by difference. */
-		private final Map<Diff, Phantom> fPhantomRegistry = new HashMap<Diff, Phantom>();
-
-		/** Predicate witch checks that the given difference is an ADD or DELETE of a graphical object. */
-		private Predicate<Diff> isAddOrDelete = and(instanceOf(DiagramDiff.class),
-				or(ofKind(DifferenceKind.ADD), ofKind(DifferenceKind.DELETE)));
-
-		/** Predicate witch checks that the given difference is a HIDE or REVEAL of a graphical object. */
-		private Predicate<Diff> isHideOrReveal = or(instanceOf(Show.class), instanceOf(Hide.class));
-
-		/**
-		 * {@inheritDoc}
-		 * 
-		 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.
-		 *      DiagramContentMergeViewer.AbstractDecoratorManager#goodCandidate()<br>
-		 *      Only the diagram differences ADD/REVEAL or DELETE/HIDE are concerned by this display.
-		 */
-		@Override
-		protected Predicate<Diff> goodCandidate() {
-			return new Predicate<Diff>() {
-				public boolean apply(Diff difference) {
-					return Predicates.or(isAddOrDelete, isHideOrReveal).apply(difference)
-							&& difference.getState() == DifferenceState.UNRESOLVED;
-				}
-			};
-		}
-
-		/**
-		 * From the given view, get or create the related phantoms in the given side.
-		 * 
-		 * @param referenceView
-		 *            The given view.
-		 * @param side
-		 *            The given side.
-		 * @return The list of phantoms.
-		 */
-		private List<Phantom> getOrCreateRelatedPhantoms(EObject referenceView, MergeViewerSide side) {
-			List<Phantom> result = new ArrayList<Phantom>();
-			Collection<Diff> changes = Collections2.filter(
-					getCompareConfiguration().getComparison().getDifferences(referenceView), goodCandidate());
-			for (Diff change : changes) {
-				Phantom phantom = fPhantomRegistry.get(change);
-				if (phantom == null) {
-					IFigure referenceFigure = PhantomManager.this.getFigure((View)referenceView);
-					if (referenceFigure != null) {
-						phantom = createAndRegisterDecorator(change, (View)referenceView, referenceFigure,
-								side);
-					}
-				}
-				if (phantom != null) {
-					result.add(phantom);
-				}
-			}
-			return result;
-		}
-
-		/**
-		 * {@inheritDoc}
-		 * 
-		 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.DiagramContentMergeViewer.AbstractDecoratorManager#getReferenceViews(org.eclipse.emf.compare.diagram.DiagramDiff)
-		 */
-		@Override
-		protected List<View> getReferenceViews(DiagramDiff difference) {
-			List<View> result = new ArrayList<View>();
-
-			Match match = getCompareConfiguration().getComparison().getMatch(difference.getView());
-
-			EObject originObj = match.getOrigin();
-			EObject leftObj = match.getLeft();
-			EObject rightObj = match.getRight();
-
-			if (leftObj instanceof View || rightObj instanceof View) {
-				View referenceView = getReferenceView((View)originObj, (View)leftObj, (View)rightObj);
-				// It may be null if it is hidden
-				if (referenceView != null) {
-					result.add(referenceView);
-				}
-			}
-
-			return result;
-		}
-
-		/**
-		 * {@inheritDoc}
-		 * 
-		 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.
-		 *      DiagramContentMergeViewer.AbstractDecoratorManager#getTargetSide(org.eclipse.emf.compare.
-		 *      Match, org.eclipse.gmf.runtime.notation.View)<br>
-		 *      If the left object is null, a phantom should be drawn instead. Else, it means that the right
-		 *      object is null and a phantom should be displayed on the right side.
-		 */
-		@Override
-		protected MergeViewerSide getTargetSide(Match match, View referenceView) {
-			MergeViewerSide targetSide = null;
-			if (!isFigureExist((View)match.getLeft())) {
-				targetSide = MergeViewerSide.LEFT;
-			} else {
-				targetSide = MergeViewerSide.RIGHT;
-			}
-			return targetSide;
-		}
-
-		/**
-		 * {@inheritDoc}
-		 * 
-		 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.DiagramContentMergeViewer.AbstractDecoratorManager#createAndRegisterDecorator(org.eclipse.emf.compare.Diff,
-		 *      org.eclipse.gmf.runtime.notation.View, org.eclipse.draw2d.IFigure,
-		 *      org.eclipse.emf.compare.rcp.ui.mergeviewer.IMergeViewer.MergeViewerSide)
-		 */
-		@Override
-		protected Phantom createAndRegisterDecorator(Diff diff, View referenceView, IFigure referenceFigure,
-				MergeViewerSide targetSide) {
-			Phantom phantom = createPhantom(diff, referenceView, referenceFigure, targetSide);
-			if (phantom != null) {
-				fPhantomRegistry.put(diff, phantom);
-			}
-			return phantom;
-		}
-
-		/**
-		 * {@inheritDoc}
-		 * 
-		 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.DiagramContentMergeViewer.AbstractDecoratorManager#removeDecorators(org.eclipse.emf.compare.Diff)
-		 */
-		@Override
-		public void removeDecorators(Diff difference) {
-			fPhantomRegistry.remove(difference);
-		}
-
-		/**
-		 * {@inheritDoc}
-		 * 
-		 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.DiagramContentMergeViewer.AbstractDecoratorManager#removeAll()
-		 */
-		@Override
-		public void removeAll() {
-			fPhantomRegistry.clear();
-		}
-
-		/**
-		 * {@inheritDoc}
-		 * 
-		 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.DiagramContentMergeViewer.AbstractDecoratorManager#getDecorators(org.eclipse.emf.compare.Diff)
-		 */
-		@Override
-		protected List<Phantom> getDecorators(Diff difference) {
-			List<Phantom> result = new ArrayList<DiagramContentMergeViewer.PhantomManager.Phantom>();
-			Phantom phantom = fPhantomRegistry.get(difference);
-			if (phantom != null) {
-				result.add(phantom);
-			}
-			return result;
-		}
-
-		/**
-		 * {@inheritDoc}.<br>
-		 * DO NOT CALL on a phantom within an iteration on the phantom registry.
-		 * {@link PhantomManager#fPhantomRegistry}
-		 * 
-		 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.DiagramContentMergeViewer.AbstractDecoratorManager#handleDecorator(org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.DiagramContentMergeViewer.AbstractDecoratorManager.AbstractDecorator,
-		 *      boolean)
-		 */
-		@Override
-		protected void handleDecorator(AbstractDecorator decorator, boolean isAdd, boolean isMain) {
-			super.handleDecorator(decorator, isAdd, isMain);
-			// Display the dependencies (context) of this decorator
-			for (AbstractDecorator ancestor : ((Phantom)decorator).getDependencies()) {
-				super.handleDecorator(ancestor, isAdd, false);
-			}
-		}
-
-		@Override
-		protected void handleAddDecorator(AbstractDecorator decorator, IFigure parent, IFigure toAdd,
-				boolean isMain) {
-			super.handleAddDecorator(decorator, parent, toAdd, isMain);
-			// Set the highlight of the figure
-			if (isMain) {
-				decorator.getDecoratorFigure().highlight();
-				getViewer(decorator.getSide()).getGraphicalViewer().reveal(toAdd);
-			} else {
-				decorator.getDecoratorFigure().unhighlight();
-			}
-		}
-
-		/**
-		 * It checks that the given view graphically exists.
-		 * 
-		 * @param view
-		 *            The view.
-		 * @return True if it exists.
-		 */
-		private boolean isFigureExist(View view) {
-			return view != null && view.isVisible();
-		}
-
-		/**
-		 * Get the view which has to be used as reference to build a phantom.<br>
-		 * The reference is the non null object among the given objects. In case of delete object, in the
-		 * context of three-way comparison, the reference will be the ancestor one (<code>originObj</code>).
-		 * 
-		 * @param originObj
-		 *            The ancestor object.
-		 * @param leftView
-		 *            The left object.
-		 * @param rightView
-		 *            The right object.
-		 * @return The reference object.
-		 */
-		private View getReferenceView(View originObj, View leftView, View rightView) {
-			View referenceView;
-			if (isFigureExist(originObj)) {
-				referenceView = originObj;
-			} else if (isFigureExist(leftView)) {
-				referenceView = leftView;
-			} else {
-				referenceView = rightView;
-			}
-			return referenceView;
-		}
-
-		/**
-		 * It creates a new phantom from the given difference, view and figure.
-		 * 
-		 * @param diff
-		 *            The related difference used as index for the main phantom.
-		 * @param referenceView
-		 *            The reference view as base for creation of the phantom.
-		 * @param referenceFigure
-		 *            The reference figure as base for creation of the phantom.
-		 * @param side
-		 *            The side where the phantom has to be created.
-		 * @return The phantom or null if the target layer is not found.
-		 */
-		private Phantom createPhantom(Diff diff, View referenceView, IFigure referenceFigure,
-				MergeViewerSide side) {
-			IFigure targetLayer = getLayer(referenceView, side);
-			if (targetLayer != null) {
-				MergeViewerSide referenceSide = getSide(referenceView);
-
-				Rectangle rect = referenceFigure.getBounds().getCopy();
-
-				IFigure referenceLayer = getLayer(referenceView, referenceSide);
-				translateCoordinates(referenceFigure, referenceLayer, rect);
-
-				DecoratorFigure ghost = null;
-
-				Phantom phantom = new Phantom(targetLayer, side, referenceView, referenceFigure, diff);
-
-				// Container "list" case
-				if (isNodeList(referenceView)) {
-
-					int index = getIndex(diff, referenceView, side);
-
-					IFigure referenceParentFigure = referenceFigure.getParent();
-					Rectangle referenceParentBounds = referenceParentFigure.getBounds().getCopy();
-					translateCoordinates(referenceParentFigure, referenceLayer, referenceParentBounds);
-
-					View parentView = (View)getMatchView(referenceView.eContainer(), side);
-					if (parentView != null) {
-						int nbElements = getVisibleViews(parentView).size();
-						// CHECKSTYLE:OFF
-						if (index > nbElements) {
-							// CHECKSTYLE:ON
-							index = nbElements;
-						}
-					}
-
-					// FIXME: The add of decorators modifies the physical coordinates of elements
-					// FIXME: Compute position from the y position of the first child + sum of height of the
-					// children.
-					int pos = rect.height * index + referenceParentBounds.y + 1;
-					Map<String, Object> parameters = new HashMap<String, Object>();
-					parameters.put(NodeListFigure.PARAM_Y_POS, Integer.valueOf(pos));
-
-					ghost = new NodeListFigure(diff, isThreeWay(), getCompareColor(), referenceFigure, rect,
-							true, parameters);
-
-					// Edge case
-				} else if (referenceView instanceof Edge) {
-					// If the edge phantom ties shapes where their coordinates changed
-					if (hasAnExtremityChange((Edge)referenceView, side)) {
-						EditPart edgeEditPart = createEdgeEditPart((Edge)referenceView, referenceSide, side);
-						// CHECKSTYLE:OFF
-						if (edgeEditPart instanceof GraphicalEditPart) {
-							// CHECKSTYLE:ON
-							phantom.setEditPart(edgeEditPart);
-
-							IFigure fig = ((GraphicalEditPart)edgeEditPart).getFigure();
-							fig.getChildren().clear();
-							ghost = new DecoratorFigure(diff, isThreeWay(), getCompareColor(),
-									referenceFigure, fig, true);
-
-						}
-						// Else, it creates only a polyline connection figure with the same properties as the
-						// reference
-					} else {
-						if (referenceFigure instanceof PolylineConnection) {
-							ghost = new EdgeFigure(diff, isThreeWay(), getCompareColor(), referenceFigure,
-									rect, true);
-						}
-					}
-				}
-
-				// Default case: Nodes
-				if (ghost == null) {
-					ghost = new NodeFigure(diff, isThreeWay(), getCompareColor(), referenceFigure, rect,
-							true);
-				}
-
-				phantom.setDecoratorFigure(ghost);
-
-				translateWhenInsideContainerChange(phantom);
-
-				return phantom;
-			}
-
-			return null;
-
-		}
-
-		/**
-		 * Get the index of the phantom to draw.
-		 * 
-		 * @param diff
-		 *            The related difference used as index for the main phantom.
-		 * @param referenceView
-		 *            The reference view to compute the phantom.
-		 * @param side
-		 *            The side where the phantom has to be drawn.
-		 * @return The index in the list where the phantom has to be drawn.
-		 */
-		private int getIndex(Diff diff, View referenceView, MergeViewerSide side) {
-			// Case for invisible objects
-			if (diff instanceof Hide || diff instanceof Show) {
-				List<Object> source = null;
-				List<Object> target = null;
-				Object newElement = null;
-				Match match = diff.getMatch();
-				List<Object> leftList = ReferenceUtil.getAsList(match.getLeft().eContainer(),
-						NotationPackage.Literals.VIEW__PERSISTED_CHILDREN);
-				List<Object> rightList = ReferenceUtil.getAsList(match.getRight().eContainer(),
-						NotationPackage.Literals.VIEW__PERSISTED_CHILDREN);
-				if (diff instanceof Hide) {
-					source = rightList;
-					target = leftList;
-					newElement = diff.getMatch().getRight();
-				} else {
-					source = leftList;
-					target = rightList;
-					newElement = diff.getMatch().getLeft();
-				}
-				Iterable<Object> ignoredElements = Iterables.filter(target, new Predicate() {
-					public boolean apply(Object input) {
-						return input instanceof View && !((View)input).isVisible();
-					}
-				});
-				return DiffUtil.findInsertionIndex(getCompareConfiguration().getComparison(), ignoredElements,
-						source, target, newElement);
-			}
-			// Case for deleted objects
-			Diff refiningDiff = Iterators.find(diff.getRefinedBy().iterator(), and(valueIs(referenceView),
-					onFeature(NotationPackage.Literals.VIEW__PERSISTED_CHILDREN.getName())));
-
-			return DiffUtil.findInsertionIndex(getCompareConfiguration().getComparison(), refiningDiff,
-					side == MergeViewerSide.LEFT);
-		}
-
-		/**
-		 * Get the visible view under the given parent view.
-		 * 
-		 * @param parent
-		 *            The parent view.
-		 * @return The list of views.
-		 */
-		private List<View> getVisibleViews(View parent) {
-			return (List<View>)Lists
-					.newArrayList(Iterators.filter(parent.getChildren().iterator(), new Predicate<Object>() {
-						public boolean apply(Object input) {
-							return input instanceof View && ((View)input).isVisible();
-						}
-					}));
-		}
-
-		/**
-		 * It translates and resizes the figure of the given phantom when this one is nested in a container
-		 * which is subjected to a coordinates change.
-		 * 
-		 * @param phantom
-		 *            The phantom.
-		 */
-		private void translateWhenInsideContainerChange(Phantom phantom) {
-			boolean isCandidate = false;
-			Diff diff = phantom.getDifference();
-			if (diff instanceof DiagramDiff) {
-				EObject parent = ((DiagramDiff)diff).getView().eContainer();
-				while (parent instanceof View && !isCandidate) {
-					isCandidate = Iterables.any(
-							getCompareConfiguration().getComparison().getDifferences(parent),
-							instanceOf(CoordinatesChange.class));
-					parent = parent.eContainer();
-				}
-			}
-			if (isCandidate) {
-				View referenceView = phantom.getOriginView();
-				View parentReferenceView = (View)referenceView.eContainer();
-				if (parentReferenceView != null) {
-					View parentView = (View)getMatchView(parentReferenceView, phantom.getSide());
-					IFigure parentFigure = getFigure(parentView);
-					if (parentFigure != null) {
-						Rectangle parentRect = parentFigure.getBounds().getCopy();
-						translateCoordinates(parentFigure, getLayer(parentReferenceView, getSide(parentView)),
-								parentRect);
-
-						IFigure parentReferenceFigure = getFigure(parentReferenceView);
-						// CHECKSTYLE:OFF
-						if (parentReferenceFigure != null) {
-							Rectangle parentReferenceRect = parentReferenceFigure.getBounds().getCopy();
-							translateCoordinates(parentReferenceFigure,
-									getLayer(parentReferenceView, getSide(parentReferenceView)),
-									parentReferenceRect);
-
-							int deltaX = parentRect.x - parentReferenceRect.x;
-							int deltaY = parentRect.y - parentReferenceRect.y;
-							int deltaWidth = parentRect.width - parentReferenceRect.width;
-							int deltaHeight = parentRect.height - parentReferenceRect.height;
-
-							IFigure figure = phantom.getFigure();
-
-							Rectangle rect = figure.getBounds().getCopy();
-							rect.x += deltaX;
-							rect.y += deltaY;
-							rect.width += deltaWidth;
-							if (!(figure instanceof Polyline)) {
-								rect.height += deltaHeight;
-							}
-							figure.setBounds(rect);
-
-							if (figure instanceof Polyline) {
-
-								Point firstPoint = ((Polyline)figure).getPoints().getFirstPoint().getCopy();
-								Point lastPoint = ((Polyline)figure).getPoints().getLastPoint().getCopy();
-
-								firstPoint.x += deltaX;
-								firstPoint.y += deltaY;
-
-								lastPoint.x += deltaX + deltaWidth;
-								lastPoint.y += deltaY;
-
-								((Polyline)figure).setEndpoints(firstPoint, lastPoint);
-
-							}
-						}
-						// CHECKSTYLE:ON
-					}
-				}
-			}
-		}
-
-		/**
-		 * It checks that the given edge is linked to graphical objects subjected to coordinate changes, on
-		 * the given side.
-		 * 
-		 * @param edge
-		 *            The edge to check.
-		 * @param targetSide
-		 *            The side to check extremities (side of the phantom).
-		 * @return True if an extremity at least changed its location, False otherwise.
-		 */
-		private boolean hasAnExtremityChange(Edge edge, MergeViewerSide targetSide) {
-			View referenceSource = edge.getSource();
-			View referenceTarget = edge.getTarget();
-			return hasChange(referenceSource, targetSide) || hasChange(referenceTarget, targetSide);
-		}
-
-		/**
-		 * It checks that the coordinates of the given view changed between left and right, from the given
-		 * side.
-		 * 
-		 * @param referenceView
-		 *            The view to check.
-		 * @param targetSide
-		 *            The side to focus.
-		 * @return True if the view changed its location, False otherwise.
-		 */
-		private boolean hasChange(View referenceView, MergeViewerSide targetSide) {
-			View extremity = (View)getMatchView(referenceView, targetSide);
-			// Look for a related change coordinates on the extremity of the edge reference.
-			Collection<Diff> diffs = Collections2.filter(
-					getCompareConfiguration().getComparison().getDifferences(referenceView),
-					instanceOf(CoordinatesChange.class));
-			if (diffs.isEmpty()) {
-				// Look for a related change coordinates on the matching extremity (other side) of the edge
-				// reference.
-				diffs = Collections2.filter(
-						getCompareConfiguration().getComparison().getDifferences(extremity),
-						instanceOf(CoordinatesChange.class));
-			}
-			return !diffs.isEmpty();
-		}
-
-		/**
-		 * It creates and returns a new edit part from the given edge. This edit part listens to the reference
-		 * edge but is attached to the controllers of the target (phantom) side.
-		 * 
-		 * @param referenceEdge
-		 *            The edge as base of the edit part.
-		 * @param referenceSide
-		 *            The side of this edge.
-		 * @param targetSide
-		 *            The side where the edit part has to be created to draw the related phantom.
-		 * @return The new edit part.
-		 */
-		private EditPart createEdgeEditPart(Edge referenceEdge, MergeViewerSide referenceSide,
-				MergeViewerSide targetSide) {
-			EditPart edgeEditPartReference = getViewer(referenceSide).getEditPart(referenceEdge);
-			EditPart edgeEditPart = null;
-			if (edgeEditPartReference instanceof ConnectionEditPart) {
-
-				edgeEditPart = getOrCreatePhantomEditPart(referenceEdge, referenceSide, targetSide);
-
-				if (edgeEditPart instanceof ConnectionEditPart) {
-					EditPart edgeSourceEp = getOrCreateExtremityPhantomEditPart(
-							((ConnectionEditPart)edgeEditPartReference).getSource(), referenceSide,
-							targetSide);
-
-					((ConnectionEditPart)edgeEditPart).setSource(edgeSourceEp);
-
-					EditPart edgeTargetEp = getOrCreateExtremityPhantomEditPart(
-							((ConnectionEditPart)edgeEditPartReference).getTarget(), referenceSide,
-							targetSide);
-
-					((ConnectionEditPart)edgeEditPart).setTarget(edgeTargetEp);
-				}
-			}
-			return edgeEditPart;
-		}
-
-		/**
-		 * From the given edit part, it retrieves the matched one, from the given target side. If the
-		 * retrieved edit part is not linked to a GMF object, in the target side, a phantom GEF edit part is
-		 * returned which will locate a rectangle invisible figure in the same location as the related
-		 * phantom.
-		 * 
-		 * @param referenceEdgeExtremityEp
-		 *            The reference edit part for one of the extremities of an edge.
-		 * @param referenceSide
-		 *            The side of the reference.
-		 * @param targetSide
-		 *            The other side, where the phantom has to be drawn.
-		 * @return The phantom edit part used to attach the extremity of an edge phantom.
-		 */
-		private EditPart getOrCreateExtremityPhantomEditPart(EditPart referenceEdgeExtremityEp,
-				MergeViewerSide referenceSide, MergeViewerSide targetSide) {
-			View referenceExtremityView = (View)referenceEdgeExtremityEp.getModel();
-
-			EditPart edgeExtremityEp = getOrCreatePhantomEditPart(referenceExtremityView, referenceSide,
-					targetSide);
-
-			if (isPhantomEditPart((AbstractGraphicalEditPart)edgeExtremityEp)) {
-
-				final AbstractGraphicalEditPart edgeExtremityEpParent = (AbstractGraphicalEditPart)edgeExtremityEp
-						.getParent();
-
-				List<Phantom> phantoms = getOrCreateRelatedPhantoms(referenceExtremityView, targetSide);
-				if (!phantoms.isEmpty()) {
-					Phantom phantomToTarget = phantoms.get(0);
-					final IFigure figureToTarget = phantomToTarget.getFigure();
-
-					edgeExtremityEp = new org.eclipse.gmf.runtime.diagram.ui.editparts.GraphicalEditPart(
-							referenceExtremityView) {
-						@Override
-						protected void createDefaultEditPolicies() {
-						}
-
-						@Override
-						protected IFigure createFigure() {
-							RectangleFigure fig = new RectangleFigure();
-							fig.setBounds(figureToTarget.getBounds());
-							fig.setParent(edgeExtremityEpParent.getFigure());
-							return fig;
-						}
-					};
-
-					edgeExtremityEp.setParent(edgeExtremityEpParent);
-				}
-
-				((AbstractGraphicalEditPart)edgeExtremityEp).activate();
-				((AbstractGraphicalEditPart)edgeExtremityEp).getFigure();
-			}
-
-			return edgeExtremityEp;
-		}
-
-		/**
-		 * It checks if the given edit part is related to a phantom edit part (created for nothing, without
-		 * link to a GMF object in the target side).
-		 * 
-		 * @param editPart
-		 *            The edit part to check.
-		 * @return True if it is a phantom edit part, false otherwise.
-		 */
-		private boolean isPhantomEditPart(AbstractGraphicalEditPart editPart) {
-			Rectangle targetBounds = editPart.getFigure().getBounds();
-			return targetBounds.x == 0 && targetBounds.y == 0 && targetBounds.width == 0
-					&& targetBounds.height == 0;
-		}
-
-		/**
-		 * It creates and returns a new edit part from the given view. This edit part listens the reference
-		 * view but is attached to the controllers of the target (phantom) side.
-		 * 
-		 * @param referenceView
-		 *            The view as base of the edit part.
-		 * @param referenceSide
-		 *            The side of this view.
-		 * @param targetSide
-		 *            The side where the edit part has to be created to draw the related phantom.
-		 * @return The new edit part.
-		 */
-		private EditPart getOrCreatePhantomEditPart(EObject referenceView, MergeViewerSide referenceSide,
-				MergeViewerSide targetSide) {
-			EditPart editPartParent = null;
-			EditPart editPart = null;
-			EditPart editPartReference = getViewer(referenceSide).getEditPart(referenceView);
-			EditPart editPartReferenceParent = editPartReference.getParent();
-			Object referenceViewParent = editPartReferenceParent.getModel();
-			if (!(referenceViewParent instanceof EObject)) {
-				referenceViewParent = referenceView.eContainer();
-			}
-			View viewParent = (View)getMatchView((EObject)referenceViewParent, targetSide);
-			if (viewParent != null) {
-				editPartParent = getViewer(targetSide).getEditPart(viewParent);
-			}
-			if (editPartParent == null) {
-				editPartParent = getOrCreatePhantomEditPart((EObject)referenceViewParent, referenceSide,
-						targetSide);
-
-			}
-			if (editPartParent != null) {
-				View view = (View)getMatchView(referenceView, targetSide);
-				if (view != null) {
-					editPart = getViewer(targetSide).getEditPart(view);
-				}
-				if (editPart == null) {
-
-					editPart = getViewer(targetSide).getGraphicalViewer().getEditPartFactory()
-							.createEditPart(editPartParent, referenceView);
-					editPart.setParent(editPartParent);
-					getViewer(targetSide).getGraphicalViewer().getEditPartRegistry().put(referenceView,
-							editPart);
-
-				}
-
-			}
-			return editPart;
-		}
-
-		/**
-		 * {@inheritDoc}
-		 * 
-		 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.DiagramContentMergeViewer.IDecoratorManager#hideAll()
-		 */
-		public void hideAll() {
-			for (Phantom phantom : fPhantomRegistry.values()) {
-				handleDeleteDecorator(phantom, phantom.getLayer(), phantom.getFigure());
-			}
-		}
-	}
-
-	/**
-	 * Marker manager to create, hide or reveal marker figures related to deleted or added graphical objects.
-	 * 
-	 * @author <a href="mailto:cedric.notot@obeo.fr">Cedric Notot</a>
-	 */
-	private class MarkerManager extends AbstractDecoratorManager {
-
-		/**
-		 * Marker represented by a <code>figure</code> on a <code>layer</code>, from the given
-		 * <code>side</code> of the merge viewer. An edit part may be linked to the <code>figure</code> in
-		 * some cases.<br>
-		 * The marker is related to a <code>difference</code> and it is binded with the reference view and
-		 * figure.
-		 * 
-		 * @author <a href="mailto:cedric.notot@obeo.fr">Cedric Notot</a>
-		 */
-		private class Marker extends AbstractDecorator {
-
-			/**
-			 * Constructor.
-			 * 
-			 * @param layer
-			 *            {@link Marker#fLayer}.
-			 * @param side
-			 *            {@link Marker#fSide}.
-			 * @param originView
-			 *            {@link Marker#fOriginView}.
-			 * @param originFigure
-			 *            {@link Marker#fOriginFigure}.
-			 * @param diff
-			 *            {@link Marker#fDifference}.
-			 */
-			Marker(IFigure layer, MergeViewerSide side, View originView, IFigure originFigure, Diff diff) {
-				setLayer(layer);
-				setSide(side);
-				setOriginView(originView);
-				setOriginFigure(originFigure);
-				setDifference(diff);
-			}
-		}
-
-		/** Registry of created markers, indexed by difference. */
-		private Multimap<Diff, Marker> fMarkerRegistry = HashMultimap.create();
-
-		/**
-		 * {@inheritDoc}
-		 * 
-		 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.DiagramContentMergeViewer.AbstractDecoratorManager#getReferenceViews(org.eclipse.emf.compare.diagram.DiagramDiff)
-		 */
-		@Override
-		protected List<View> getReferenceViews(DiagramDiff difference) {
-			List<View> result = new ArrayList<View>();
-			Match matchValue = getCompareConfiguration().getComparison().getMatch(difference.getView());
-			if (matchValue != null) {
-				if (matchValue.getLeft() != null) {
-					result.add((View)matchValue.getLeft());
-				}
-				if (matchValue.getRight() != null) {
-					result.add((View)matchValue.getRight());
-				}
-				if (getCompareConfiguration().getComparison().isThreeWay()) {
-					switch (difference.getKind()) {
-						case DELETE:
-						case CHANGE:
-						case MOVE:
-							result.add((View)matchValue.getOrigin());
-							break;
-						default:
-							break;
-					}
-				}
-			}
-			return result;
-		}
-
-		/**
-		 * {@inheritDoc}
-		 * 
-		 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.DiagramContentMergeViewer.AbstractDecoratorManager#getTargetSide(org.eclipse.emf.compare.Match,
-		 *      org.eclipse.gmf.runtime.notation.View)
-		 */
-		@Override
-		protected MergeViewerSide getTargetSide(Match match, View referenceView) {
-			return getSide(referenceView);
-		}
-
-		/**
-		 * {@inheritDoc}
-		 * 
-		 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.DiagramContentMergeViewer.AbstractDecoratorManager#createAndRegisterDecorator(org.eclipse.emf.compare.Diff,
-		 *      org.eclipse.gmf.runtime.notation.View, org.eclipse.draw2d.IFigure,
-		 *      org.eclipse.emf.compare.rcp.ui.mergeviewer.IMergeViewer.MergeViewerSide)
-		 */
-		@Override
-		protected Marker createAndRegisterDecorator(Diff diff, View referenceView, IFigure referenceFigure,
-				MergeViewerSide targetSide) {
-			Marker marker = createMarker(diff, referenceView, referenceFigure, targetSide);
-			if (marker != null) {
-				fMarkerRegistry.put(diff, marker);
-			}
-			return marker;
-		}
-
-		/**
-		 * {@inheritDoc}
-		 * 
-		 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.DiagramContentMergeViewer.AbstractDecoratorManager#removeDecorators(org.eclipse.emf.compare.Diff)
-		 */
-		@Override
-		public void removeDecorators(Diff difference) {
-			fMarkerRegistry.removeAll(difference);
-		}
-
-		/**
-		 * {@inheritDoc}
-		 * 
-		 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.DiagramContentMergeViewer.AbstractDecoratorManager#removeAll()
-		 */
-		@Override
-		public void removeAll() {
-			fMarkerRegistry.clear();
-		}
-
-		/**
-		 * {@inheritDoc}
-		 * 
-		 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.DiagramContentMergeViewer.AbstractDecoratorManager#getDecorators(org.eclipse.emf.compare.Diff)
-		 */
-		@Override
-		protected Collection<Marker> getDecorators(Diff difference) {
-			return fMarkerRegistry.get(difference);
-		}
-
-		@Override
-		protected void handleAddDecorator(AbstractDecorator decorator, IFigure parent, IFigure toAdd,
-				boolean isMain) {
-			super.handleAddDecorator(decorator, parent, toAdd, isMain);
-			DiagramMergeViewer viewer = getViewer(decorator.getSide());
-			EditPart editPart = viewer.getEditPart(decorator.getOriginView());
-			if (editPart != null) {
-				viewer.getGraphicalViewer().reveal(editPart);
-			}
-		}
-
-		/**
-		 * {@inheritDoc}
-		 * 
-		 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.
-		 *      DiagramContentMergeViewer.AbstractDecoratorManager#goodCandidate()<br>
-		 *      All graphical differences are concerned.
-		 */
-		@Override
-		protected Predicate<Diff> goodCandidate() {
-			return new Predicate<Diff>() {
-				public boolean apply(Diff difference) {
-					return instanceOf(DiagramDiff.class).apply(difference);
-				}
-			};
-		}
-
-		/**
-		 * It creates a new marker from the given difference, view and figure.
-		 * 
-		 * @param diff
-		 *            The related difference used as index for the main marker.
-		 * @param referenceView
-		 *            The reference view as base for creation of the marker.
-		 * @param referenceFigure
-		 *            The reference figure as base for creation of the marker.
-		 * @param side
-		 *            The side where the marker has to be created.
-		 * @return The phantom or null if the target layer is not found.
-		 */
-		private Marker createMarker(Diff diff, View referenceView, IFigure referenceFigure,
-				MergeViewerSide side) {
-
-			IFigure referenceLayer = getLayer(referenceView, side);
-			if (referenceLayer != null) {
-				Rectangle referenceBounds = referenceFigure.getBounds().getCopy();
-				translateCoordinates(referenceFigure, referenceLayer, referenceBounds);
-
-				DecoratorFigure markerFigure = null;
-
-				Marker marker = new Marker(referenceLayer, side, referenceView, referenceFigure, diff);
-
-				if (isNodeList(referenceView)) {
-					markerFigure = new NodeListFigure(diff, isThreeWay(), getCompareColor(), referenceFigure,
-							referenceBounds, false);
-				} else if (referenceView instanceof Edge && referenceFigure instanceof PolylineConnection) {
-					markerFigure = new EdgeFigure(diff, isThreeWay(), getCompareColor(), referenceFigure,
-							referenceBounds, false);
-				}
-
-				// Default case: Nodes
-				if (markerFigure == null) {
-					markerFigure = new NodeFigure(diff, isThreeWay(), getCompareColor(), referenceFigure,
-							referenceBounds, false);
-				}
-
-				marker.setDecoratorFigure(markerFigure);
-				return marker;
-			}
-
-			return null;
-
-		}
-
-		/**
-		 * {@inheritDoc}
-		 * 
-		 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.DiagramContentMergeViewer.IDecoratorManager#hideAll()
-		 */
-		public void hideAll() {
-			for (Marker marker : fMarkerRegistry.values()) {
-				handleDeleteDecorator(marker, marker.getLayer(), marker.getFigure());
-			}
-		}
-
-	}
-
-	/**
-	 * Decorator manager to create, hide or reveal all decorator figures related to graphical changes.
-	 * 
-	 * @author <a href="mailto:cedric.notot@obeo.fr">Cedric Notot</a>
-	 */
-	private class DecoratorsManager implements IDecoratorManager {
-		/** Phantoms manager. */
-		private IDecoratorManager fPhantomManager = new PhantomManager();
-
-		/** Markers manager. */
-		private IDecoratorManager fMarkerManager = new MarkerManager();
-
-		/**
-		 * {@inheritDoc}
-		 * 
-		 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.DiagramContentMergeViewer.IDecoratorManager#hideDecorators(org.eclipse.emf.compare.Diff)
-		 */
-		public void hideDecorators(Diff difference) {
-			fMarkerManager.hideDecorators(difference);
-			fPhantomManager.hideDecorators(difference);
-		}
-
-		/**
-		 * {@inheritDoc}
-		 * 
-		 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.DiagramContentMergeViewer.IDecoratorManager#revealDecorators(org.eclipse.emf.compare.Diff)
-		 */
-		public void revealDecorators(Diff difference) {
-			fMarkerManager.revealDecorators(difference);
-			fPhantomManager.revealDecorators(difference);
-		}
-
-		/**
-		 * {@inheritDoc}
-		 * 
-		 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.DiagramContentMergeViewer.IDecoratorManager#hideAll()
-		 */
-		public void hideAll() {
-			fMarkerManager.hideAll();
-			fPhantomManager.hideAll();
-		}
-
-		/**
-		 * {@inheritDoc}
-		 * 
-		 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.DiagramContentMergeViewer.IDecoratorManager#removeDecorators(org.eclipse.emf.compare.Diff)
-		 */
-		public void removeDecorators(Diff difference) {
-			fMarkerManager.removeDecorators(difference);
-			fPhantomManager.removeDecorators(difference);
-		}
-
-		/**
-		 * {@inheritDoc}
-		 * 
-		 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.DiagramContentMergeViewer.IDecoratorManager#removeAll()
-		 */
-		public void removeAll() {
-			fMarkerManager.removeAll();
-			fPhantomManager.removeAll();
-		}
-
-	}
-
-	/**
 	 * Bundle name of the property file containing all displayed strings.
 	 */
 	private static final String BUNDLE_NAME = DiagramContentMergeViewer.class.getName();
 
 	/** The phantom manager to use in the context of this viewer. */
-	private final DecoratorsManager fDecoratorsManager = new DecoratorsManager();
+	private DecoratorsManager fDecoratorsManager;
 
 	/** The current "opened" difference. */
 	private Diff fCurrentSelectedDiff;
@@ -1819,7 +141,7 @@
 	/**
 	 * {@inheritDoc}
 	 * 
-	 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.DiagramCompareContentMergeViewer#createMergeViewer(org.eclipse.swt.widgets.Composite,
+	 * @see org.eclipse.emf.compare.ide.ui.internal.contentmergeviewer.EMFCompareContentMergeViewer#createMergeViewer(org.eclipse.swt.widgets.Composite,
 	 *      org.eclipse.emf.compare.rcp.ui.mergeviewer.IMergeViewer.MergeViewerSide)
 	 */
 	@Override
@@ -1832,7 +154,7 @@
 	/**
 	 * {@inheritDoc}
 	 * 
-	 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.DiagramCompareContentMergeViewer#paintCenter(org.eclipse.swt.graphics.GC)
+	 * @see org.eclipse.emf.compare.ide.ui.internal.contentmergeviewer.EMFCompareContentMergeViewer#paintCenter(org.eclipse.swt.graphics.GC)
 	 */
 	@Override
 	protected void paintCenter(GC g) {
@@ -1842,12 +164,15 @@
 	/**
 	 * {@inheritDoc}
 	 * 
-	 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.DiagramCompareContentMergeViewer#updateContent(java.lang.Object,
+	 * @see org.eclipse.emf.compare.ide.ui.internal.contentmergeviewer.EMFCompareContentMergeViewer#updateContent(java.lang.Object,
 	 *      java.lang.Object, java.lang.Object)
 	 */
 	@Override
 	protected void updateContent(Object ancestor, Object left, Object right) {
 
+		fDecoratorsManager = new DecoratorsManager(getCompareConfiguration(), getLeftMergeViewer(),
+				getRightMergeViewer(), getAncestorMergeViewer(), getCompareColor());
+
 		// Delete decorators at each selection of a difference (force the computation)
 		fDecoratorsManager.hideAll();
 		fDecoratorsManager.removeAll();
@@ -1933,6 +258,11 @@
 		return null;
 	}
 
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.compare.ide.ui.internal.contentmergeviewer.EMFCompareContentMergeViewer#createToolItems(org.eclipse.jface.action.ToolBarManager)
+	 */
 	@Override
 	protected void createToolItems(ToolBarManager toolBarManager) {
 		super.createToolItems(toolBarManager);
@@ -1943,6 +273,8 @@
 
 	/**
 	 * {@inheritDoc} When the zoom on any of the sides changes, the same zoom level is applied to other sides.
+	 * 
+	 * @see org.eclipse.gef.editparts.ZoomListener#zoomChanged(double)
 	 */
 	@Override
 	public void zoomChanged(double zoom) {
@@ -1970,7 +302,7 @@
 
 		// Delete decorators at each change of the input models (after merging or CTRL-Z, CTRL-Y)
 		Object source = event.getSource();
-		if (source instanceof CommandStack) {
+		if (source instanceof CommandStack && fDecoratorsManager != null) {
 			Command command = ((CommandStack)source).getMostRecentCommand();
 			if (command instanceof CopyCommand) {
 				Iterator<DiagramDiff> diffs = Iterators.filter(command.getAffectedObjects().iterator(),
@@ -2007,88 +339,4 @@
 		getRightMergeViewer().removeSelectionChangedListener(this);
 	}
 
-	/**
-	 * Utility method to retrieve the {@link DiagramMergeViewer} from the given side.
-	 * 
-	 * @param side
-	 *            The side to focus.
-	 * @return The viewer.
-	 */
-	private DiagramMergeViewer getViewer(MergeViewerSide side) {
-		DiagramMergeViewer result = null;
-		switch (side) {
-			case LEFT:
-				result = getLeftMergeViewer();
-				break;
-			case RIGHT:
-				result = getRightMergeViewer();
-				break;
-			case ANCESTOR:
-				result = getAncestorMergeViewer();
-				break;
-			default:
-		}
-		return result;
-	}
-
-	/**
-	 * Utility method to know the side where is located the given view.
-	 * 
-	 * @param view
-	 *            The view.
-	 * @return The side of the view.
-	 */
-	private MergeViewerSide getSide(View view) {
-		MergeViewerSide result = null;
-		Match match = getCompareConfiguration().getComparison().getMatch(view);
-		if (match.getLeft() == view) {
-			result = MergeViewerSide.LEFT;
-		} else if (match.getRight() == view) {
-			result = MergeViewerSide.RIGHT;
-		} else if (match.getOrigin() == view) {
-			result = MergeViewerSide.ANCESTOR;
-		}
-		return getEffectiveSide(result);
-	}
-
-	/**
-	 * Utility method to get the object matching with the given one, to the given side.
-	 * 
-	 * @param object
-	 *            The object as base of the lookup.
-	 * @param side
-	 *            The side where the potential matching object has to be retrieved.
-	 * @return The matching object.
-	 */
-	private EObject getMatchView(EObject object, MergeViewerSide side) {
-		Match match = getCompareConfiguration().getComparison().getMatch(object);
-		return getMatchView(match, side);
-	}
-
-	/**
-	 * Utility method to get the object in the given side from the given match.
-	 * 
-	 * @param match
-	 *            The match.
-	 * @param side
-	 *            The side where the potential matching object has to be retrieved.
-	 * @return The matching object.
-	 */
-	private EObject getMatchView(Match match, MergeViewerSide side) {
-		EObject result = null;
-		switch (side) {
-			case LEFT:
-				result = match.getLeft();
-				break;
-			case RIGHT:
-				result = match.getRight();
-				break;
-			case ANCESTOR:
-				result = match.getOrigin();
-				break;
-			default:
-		}
-		return result;
-	}
-
 }
diff --git a/plugins/org.eclipse.emf.compare.diagram.ide.ui/src/org/eclipse/emf/compare/diagram/ide/ui/internal/contentmergeviewer/diagram/IDecoratorManager.java b/plugins/org.eclipse.emf.compare.diagram.ide.ui/src/org/eclipse/emf/compare/diagram/ide/ui/internal/contentmergeviewer/diagram/IDecoratorManager.java
new file mode 100644
index 0000000..f5e3a5b
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.diagram.ide.ui/src/org/eclipse/emf/compare/diagram/ide/ui/internal/contentmergeviewer/diagram/IDecoratorManager.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Obeo.
+ * 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:
+ *     Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram;
+
+import org.eclipse.emf.compare.Diff;
+
+/**
+ * Interface for the management of decorators.
+ * 
+ * @author <a href="mailto:cedric.notot@obeo.fr">Cedric Notot</a>
+ */
+public interface IDecoratorManager {
+
+	/**
+	 * It hides the revealed decorators.
+	 */
+	void hideAll();
+
+	/**
+	 * From a given difference, it hides the related decorators.
+	 * 
+	 * @param difference
+	 *            The difference.
+	 */
+	void hideDecorators(Diff difference);
+
+	/**
+	 * From a given difference, it reveals the related decorators.
+	 * 
+	 * @param difference
+	 *            The difference.
+	 */
+	void revealDecorators(Diff difference);
+
+	/**
+	 * From a given difference, it removes the related decorators from cash.
+	 * 
+	 * @param difference
+	 *            The difference.
+	 */
+	void removeDecorators(Diff difference);
+
+	/**
+	 * It removes all the displayed decorators from cache.
+	 */
+	void removeAll();
+
+}
diff --git a/plugins/org.eclipse.emf.compare.diagram.ide.ui/src/org/eclipse/emf/compare/diagram/ide/ui/internal/contentmergeviewer/diagram/MarkerManager.java b/plugins/org.eclipse.emf.compare.diagram.ide.ui/src/org/eclipse/emf/compare/diagram/ide/ui/internal/contentmergeviewer/diagram/MarkerManager.java
new file mode 100644
index 0000000..0075fe6
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.diagram.ide.ui/src/org/eclipse/emf/compare/diagram/ide/ui/internal/contentmergeviewer/diagram/MarkerManager.java
@@ -0,0 +1,282 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Obeo.
+ * 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:
+ *     Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram;
+
+import static com.google.common.base.Predicates.instanceOf;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimap;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.PolylineConnection;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.emf.compare.Diff;
+import org.eclipse.emf.compare.Match;
+import org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.figures.DecoratorFigure;
+import org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.figures.EdgeFigure;
+import org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.figures.NodeFigure;
+import org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.figures.NodeListFigure;
+import org.eclipse.emf.compare.diagram.internal.extensions.DiagramDiff;
+import org.eclipse.emf.compare.ide.ui.internal.configuration.EMFCompareConfiguration;
+import org.eclipse.emf.compare.rcp.ui.mergeviewer.ICompareColor;
+import org.eclipse.emf.compare.rcp.ui.mergeviewer.IMergeViewer.MergeViewerSide;
+import org.eclipse.gef.EditPart;
+import org.eclipse.gmf.runtime.notation.Edge;
+import org.eclipse.gmf.runtime.notation.View;
+
+/**
+ * Marker manager to create, hide or reveal marker figures related to deleted or added graphical objects.
+ * 
+ * @author <a href="mailto:cedric.notot@obeo.fr">Cedric Notot</a>
+ */
+public class MarkerManager extends AbstractDecoratorManager {
+
+	/**
+	 * Marker represented by a <code>figure</code> on a <code>layer</code>, from the given <code>side</code>
+	 * of the merge viewer. An edit part may be linked to the <code>figure</code> in some cases.<br>
+	 * The marker is related to a <code>difference</code> and it is binded with the reference view and figure.
+	 * 
+	 * @author <a href="mailto:cedric.notot@obeo.fr">Cedric Notot</a>
+	 */
+	private class Marker extends AbstractDecorator {
+
+		/**
+		 * Constructor.
+		 * 
+		 * @param layer
+		 *            {@link Marker#fLayer}.
+		 * @param side
+		 *            {@link Marker#fSide}.
+		 * @param originView
+		 *            {@link Marker#fOriginView}.
+		 * @param originFigure
+		 *            {@link Marker#fOriginFigure}.
+		 * @param diff
+		 *            {@link Marker#fDifference}.
+		 */
+		Marker(IFigure layer, MergeViewerSide side, View originView, IFigure originFigure, Diff diff) {
+			setLayer(layer);
+			setSide(side);
+			setOriginView(originView);
+			setOriginFigure(originFigure);
+			setDifference(diff);
+		}
+	}
+
+	/** Registry of created markers, indexed by difference. */
+	private Multimap<Diff, Marker> fMarkerRegistry = HashMultimap.create();
+
+	/**
+	 * Constructor.
+	 * 
+	 * @param compareConfiguration
+	 *            The compare configuration of the viewer.
+	 * @param left
+	 *            The left area of the viewer.
+	 * @param right
+	 *            The right area of the viewer.
+	 * @param ancestor
+	 *            The ancestor area of the viewer.
+	 * @param color
+	 *            The color of the difference.
+	 */
+	public MarkerManager(EMFCompareConfiguration compareConfiguration, DiagramMergeViewer left,
+			DiagramMergeViewer right, DiagramMergeViewer ancestor, ICompareColor color) {
+		super(compareConfiguration, left, right, ancestor, color);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.AbstractDecoratorManager#getReferenceViews(
+	 *      org.eclipse.emf.compare.diagram.internal.extensions.DiagramDiff)
+	 */
+	@Override
+	protected List<View> getReferenceViews(DiagramDiff difference) {
+		List<View> result = new ArrayList<View>();
+		Match matchValue = getCompareConfiguration().getComparison().getMatch(difference.getView());
+		if (matchValue != null) {
+			if (matchValue.getLeft() != null) {
+				result.add((View)matchValue.getLeft());
+			}
+			if (matchValue.getRight() != null) {
+				result.add((View)matchValue.getRight());
+			}
+			if (getCompareConfiguration().getComparison().isThreeWay()) {
+				switch (difference.getKind()) {
+					case DELETE:
+					case CHANGE:
+					case MOVE:
+						result.add((View)matchValue.getOrigin());
+						break;
+					default:
+						break;
+				}
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.AbstractDecoratorManager#getTargetSide(org.eclipse.emf.compare.Match,
+	 *      org.eclipse.gmf.runtime.notation.View)
+	 */
+	@Override
+	public MergeViewerSide getTargetSide(Match match, View referenceView) {
+		return getSide(referenceView);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.AbstractDecoratorManager#createAndRegisterDecorator(org.eclipse.emf.compare.Diff,
+	 *      org.eclipse.gmf.runtime.notation.View, org.eclipse.draw2d.IFigure,
+	 *      org.eclipse.emf.compare.rcp.ui.mergeviewer.IMergeViewer.MergeViewerSide)
+	 */
+	@Override
+	protected Marker createAndRegisterDecorator(Diff diff, View referenceView, IFigure referenceFigure,
+			MergeViewerSide targetSide) {
+		Marker marker = createMarker(diff, referenceView, referenceFigure, targetSide);
+		if (marker != null) {
+			fMarkerRegistry.put(diff, marker);
+		}
+		return marker;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.AbstractDecoratorManager#removeDecorators(org.eclipse.emf.compare.Diff)
+	 */
+	@Override
+	public void removeDecorators(Diff difference) {
+		fMarkerRegistry.removeAll(difference);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.AbstractDecoratorManager#removeAll()
+	 */
+	@Override
+	public void removeAll() {
+		fMarkerRegistry.clear();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.AbstractDecoratorManager#getDecorators(org.eclipse.emf.compare.Diff)
+	 */
+	@Override
+	protected Collection<Marker> getDecorators(Diff difference) {
+		return fMarkerRegistry.get(difference);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.AbstractDecoratorManager#handleAddDecorator(org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.AbstractDecoratorManager.AbstractDecorator,
+	 *      org.eclipse.draw2d.IFigure, org.eclipse.draw2d.IFigure, boolean)
+	 */
+	@Override
+	protected void handleAddDecorator(AbstractDecorator decorator, IFigure parent, IFigure toAdd,
+			boolean isMain) {
+		super.handleAddDecorator(decorator, parent, toAdd, isMain);
+		DiagramMergeViewer viewer = getViewer(decorator.getSide());
+		EditPart editPart = viewer.getEditPart(decorator.getOriginView());
+		if (editPart != null) {
+			viewer.getGraphicalViewer().reveal(editPart);
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.AbstractDecoratorManager#goodCandidate()
+	 *      <br>
+	 *      All graphical differences are concerned.
+	 */
+	@Override
+	protected Predicate<Diff> goodCandidate() {
+		return new Predicate<Diff>() {
+			public boolean apply(Diff difference) {
+				return instanceOf(DiagramDiff.class).apply(difference);
+			}
+		};
+	}
+
+	/**
+	 * It creates a new marker from the given difference, view and figure.
+	 * 
+	 * @param diff
+	 *            The related difference used as index for the main marker.
+	 * @param referenceView
+	 *            The reference view as base for creation of the marker.
+	 * @param referenceFigure
+	 *            The reference figure as base for creation of the marker.
+	 * @param side
+	 *            The side where the marker has to be created.
+	 * @return The phantom or null if the target layer is not found.
+	 */
+	private Marker createMarker(Diff diff, View referenceView, IFigure referenceFigure,
+			MergeViewerSide side) {
+
+		IFigure referenceLayer = getLayer(referenceView, side);
+		if (referenceLayer != null) {
+			Rectangle referenceBounds = referenceFigure.getBounds().getCopy();
+			translateCoordinates(referenceFigure, referenceLayer, referenceBounds);
+
+			DecoratorFigure markerFigure = null;
+
+			Marker marker = new Marker(referenceLayer, side, referenceView, referenceFigure, diff);
+
+			if (isNodeList(referenceView)) {
+				markerFigure = new NodeListFigure(diff, isThreeWay(), getCompareColor(), referenceFigure,
+						referenceBounds, false);
+			} else if (referenceView instanceof Edge && referenceFigure instanceof PolylineConnection) {
+				markerFigure = new EdgeFigure(diff, isThreeWay(), getCompareColor(), referenceFigure,
+						referenceBounds, false);
+			}
+
+			// Default case: Nodes
+			if (markerFigure == null) {
+				markerFigure = new NodeFigure(diff, isThreeWay(), getCompareColor(), referenceFigure,
+						referenceBounds, false);
+			}
+
+			marker.setDecoratorFigure(markerFigure);
+			return marker;
+		}
+
+		return null;
+
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.IDecoratorManager#hideAll()
+	 */
+	public void hideAll() {
+		for (Marker marker : fMarkerRegistry.values()) {
+			handleDeleteDecorator(marker, marker.getLayer(), marker.getFigure());
+		}
+	}
+
+}
diff --git a/plugins/org.eclipse.emf.compare.diagram.ide.ui/src/org/eclipse/emf/compare/diagram/ide/ui/internal/contentmergeviewer/diagram/PhantomManager.java b/plugins/org.eclipse.emf.compare.diagram.ide.ui/src/org/eclipse/emf/compare/diagram/ide/ui/internal/contentmergeviewer/diagram/PhantomManager.java
new file mode 100644
index 0000000..e72faa7
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.diagram.ide.ui/src/org/eclipse/emf/compare/diagram/ide/ui/internal/contentmergeviewer/diagram/PhantomManager.java
@@ -0,0 +1,824 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Obeo.
+ * 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:
+ *     Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram;
+
+import static com.google.common.base.Predicates.and;
+import static com.google.common.base.Predicates.instanceOf;
+import static com.google.common.base.Predicates.or;
+import static org.eclipse.emf.compare.utils.EMFComparePredicates.ofKind;
+import static org.eclipse.emf.compare.utils.EMFComparePredicates.onFeature;
+import static org.eclipse.emf.compare.utils.EMFComparePredicates.valueIs;
+
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Iterators;
+import com.google.common.collect.Lists;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.Polyline;
+import org.eclipse.draw2d.PolylineConnection;
+import org.eclipse.draw2d.RectangleFigure;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.emf.compare.Diff;
+import org.eclipse.emf.compare.DifferenceKind;
+import org.eclipse.emf.compare.DifferenceState;
+import org.eclipse.emf.compare.Match;
+import org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.figures.DecoratorFigure;
+import org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.figures.EdgeFigure;
+import org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.figures.NodeFigure;
+import org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.figures.NodeListFigure;
+import org.eclipse.emf.compare.diagram.internal.extensions.CoordinatesChange;
+import org.eclipse.emf.compare.diagram.internal.extensions.DiagramDiff;
+import org.eclipse.emf.compare.diagram.internal.extensions.Hide;
+import org.eclipse.emf.compare.diagram.internal.extensions.Show;
+import org.eclipse.emf.compare.ide.ui.internal.configuration.EMFCompareConfiguration;
+import org.eclipse.emf.compare.internal.utils.DiffUtil;
+import org.eclipse.emf.compare.rcp.ui.mergeviewer.ICompareColor;
+import org.eclipse.emf.compare.rcp.ui.mergeviewer.IMergeViewer.MergeViewerSide;
+import org.eclipse.emf.compare.utils.ReferenceUtil;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.gef.ConnectionEditPart;
+import org.eclipse.gef.EditPart;
+import org.eclipse.gef.GraphicalEditPart;
+import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
+import org.eclipse.gmf.runtime.notation.Edge;
+import org.eclipse.gmf.runtime.notation.NotationPackage;
+import org.eclipse.gmf.runtime.notation.View;
+
+/**
+ * Phantom manager to create, hide or reveal phantom figures related to deleted or added graphical objects.
+ * 
+ * @author <a href="mailto:cedric.notot@obeo.fr">Cedric Notot</a>
+ */
+public class PhantomManager extends AbstractDecoratorManager {
+
+	/**
+	 * Phantom represented by a <code>figure</code> on a <code>layer</code>, from the given <code>side</code>
+	 * of the merge viewer. An edit part may be linked to the <code>figure</code> in some cases.<br>
+	 * The phantom is related to a <code>difference</code> and it is binded with the reference view and
+	 * figure.
+	 * 
+	 * @author <a href="mailto:cedric.notot@obeo.fr">Cedric Notot</a>
+	 */
+	private class Phantom extends AbstractDecorator {
+
+		/**
+		 * Constructor.
+		 * 
+		 * @param layer
+		 *            {@link Phantom#fLayer}.
+		 * @param side
+		 *            {@link Phantom#fSide}.
+		 * @param originView
+		 *            {@link Phantom#fOriginView}.
+		 * @param originFigure
+		 *            {@link Phantom#fOriginFigure}.
+		 * @param diff
+		 *            {@link Phantom#fDifference}.
+		 */
+		Phantom(IFigure layer, MergeViewerSide side, View originView, IFigure originFigure, Diff diff) {
+			setLayer(layer);
+			setSide(side);
+			setOriginView(originView);
+			setOriginFigure(originFigure);
+			setDifference(diff);
+		}
+
+		/**
+		 * Get the decorator dependencies of this one. The dependencies are the decorator ancestors plus the
+		 * extremities of an edge decorator.<br>
+		 * DO NOT CALL in an iterate of {@link PhantomManager#fPhantomRegistry}
+		 * 
+		 * @return The list of found decorators.
+		 */
+		public List<? extends AbstractDecorator> getDependencies() {
+			List<AbstractDecorator> result = new ArrayList<AbstractDecorator>();
+			result.addAll(getAncestors());
+			if (fOriginView instanceof Edge) {
+				View source = ((Edge)fOriginView).getSource();
+				View target = ((Edge)fOriginView).getTarget();
+				result.addAll(getOrCreateRelatedPhantoms(source, fSide));
+				result.addAll(getOrCreateRelatedPhantoms(target, fSide));
+			}
+			return result;
+		}
+
+		/**
+		 * Get the ancestor decorators of this one.
+		 * 
+		 * @return The list of the ancestors.
+		 */
+		private List<? extends AbstractDecorator> getAncestors() {
+			List<AbstractDecorator> result = new ArrayList<AbstractDecorator>();
+			EObject parentOriginView = fOriginView.eContainer();
+			while (parentOriginView != null) {
+				result.addAll(getOrCreateRelatedPhantoms(parentOriginView, fSide));
+				parentOriginView = parentOriginView.eContainer();
+			}
+			return result;
+		}
+	}
+
+	/** Registry of created phantoms, indexed by difference. */
+	private final Map<Diff, Phantom> fPhantomRegistry = new HashMap<Diff, Phantom>();
+
+	/** Predicate witch checks that the given difference is an ADD or DELETE of a graphical object. */
+	private Predicate<Diff> isAddOrDelete = and(instanceOf(DiagramDiff.class),
+			or(ofKind(DifferenceKind.ADD), ofKind(DifferenceKind.DELETE)));
+
+	/** Predicate witch checks that the given difference is a HIDE or REVEAL of a graphical object. */
+	private Predicate<Diff> isHideOrReveal = or(instanceOf(Show.class), instanceOf(Hide.class));
+
+	/**
+	 * Constructor.
+	 * 
+	 * @param compareConfiguration
+	 *            The compare configuration of the viewer.
+	 * @param left
+	 *            The left area of the viewer.
+	 * @param right
+	 *            The right area of the viewer.
+	 * @param ancestor
+	 *            The ancestor area of the viewer.
+	 * @param color
+	 *            The color of the difference.
+	 */
+	public PhantomManager(EMFCompareConfiguration compareConfiguration, DiagramMergeViewer left,
+			DiagramMergeViewer right, DiagramMergeViewer ancestor, ICompareColor color) {
+		super(compareConfiguration, left, right, ancestor, color);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.AbstractDecoratorManager#goodCandidate()
+	 *      <br>
+	 *      Only the diagram differences ADD/REVEAL or DELETE/HIDE are concerned by this display.
+	 */
+	@Override
+	protected Predicate<Diff> goodCandidate() {
+		return new Predicate<Diff>() {
+			public boolean apply(Diff difference) {
+				return Predicates.or(isAddOrDelete, isHideOrReveal).apply(difference)
+						&& difference.getState() == DifferenceState.UNRESOLVED;
+			}
+		};
+	}
+
+	/**
+	 * From the given view, get or create the related phantoms in the given side.
+	 * 
+	 * @param referenceView
+	 *            The given view.
+	 * @param side
+	 *            The given side.
+	 * @return The list of phantoms.
+	 */
+	private List<Phantom> getOrCreateRelatedPhantoms(EObject referenceView, MergeViewerSide side) {
+		List<Phantom> result = new ArrayList<Phantom>();
+		Collection<Diff> changes = Collections2.filter(
+				getCompareConfiguration().getComparison().getDifferences(referenceView), goodCandidate());
+		for (Diff change : changes) {
+			Phantom phantom = fPhantomRegistry.get(change);
+			if (phantom == null) {
+				IFigure referenceFigure = PhantomManager.this.getFigure((View)referenceView);
+				if (referenceFigure != null) {
+					phantom = createAndRegisterDecorator(change, (View)referenceView, referenceFigure, side);
+				}
+			}
+			if (phantom != null) {
+				result.add(phantom);
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.AbstractDecoratorManager#getReferenceViews(
+	 *      org.eclipse.emf.compare.diagram.internal.extensions.DiagramDiff)
+	 */
+	@Override
+	protected List<View> getReferenceViews(DiagramDiff difference) {
+		List<View> result = new ArrayList<View>();
+
+		Match match = getCompareConfiguration().getComparison().getMatch(difference.getView());
+
+		EObject originObj = match.getOrigin();
+		EObject leftObj = match.getLeft();
+		EObject rightObj = match.getRight();
+
+		if (leftObj instanceof View || rightObj instanceof View) {
+			View referenceView = getReferenceView((View)originObj, (View)leftObj, (View)rightObj);
+			// It may be null if it is hidden
+			if (referenceView != null) {
+				result.add(referenceView);
+			}
+		}
+
+		return result;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.AbstractDecoratorManager#getTargetSide(org.eclipse.emf.compare.
+	 *      Match, org.eclipse.gmf.runtime.notation.View) <br>
+	 *      If the left object is null, a phantom should be drawn instead. Else, it means that the right
+	 *      object is null and a phantom should be displayed on the right side.
+	 */
+	@Override
+	public MergeViewerSide getTargetSide(Match match, View referenceView) {
+		MergeViewerSide targetSide = null;
+		EObject leftMatch = match.getLeft();
+
+		if (leftMatch == null || (leftMatch instanceof View && !isFigureExist((View)leftMatch))) {
+			targetSide = MergeViewerSide.LEFT;
+		} else {
+			targetSide = MergeViewerSide.RIGHT;
+		}
+		return getEffectiveSide(targetSide);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.AbstractDecoratorManager#createAndRegisterDecorator(org.eclipse.emf.compare.Diff,
+	 *      org.eclipse.gmf.runtime.notation.View, org.eclipse.draw2d.IFigure,
+	 *      org.eclipse.emf.compare.rcp.ui.mergeviewer.IMergeViewer.MergeViewerSide)
+	 */
+	@Override
+	protected Phantom createAndRegisterDecorator(Diff diff, View referenceView, IFigure referenceFigure,
+			MergeViewerSide targetSide) {
+		Phantom phantom = createPhantom(diff, referenceView, referenceFigure, targetSide);
+		if (phantom != null) {
+			fPhantomRegistry.put(diff, phantom);
+		}
+		return phantom;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.AbstractDecoratorManager#removeDecorators(org.eclipse.emf.compare.Diff)
+	 */
+	@Override
+	public void removeDecorators(Diff difference) {
+		fPhantomRegistry.remove(difference);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.AbstractDecoratorManager#removeAll()
+	 */
+	@Override
+	public void removeAll() {
+		fPhantomRegistry.clear();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.AbstractDecoratorManager#getDecorators(org.eclipse.emf.compare.Diff)
+	 */
+	@Override
+	protected List<Phantom> getDecorators(Diff difference) {
+		List<Phantom> result = new ArrayList<PhantomManager.Phantom>();
+		Phantom phantom = fPhantomRegistry.get(difference);
+		if (phantom != null) {
+			result.add(phantom);
+		}
+		return result;
+	}
+
+	/**
+	 * {@inheritDoc}.<br>
+	 * DO NOT CALL on a phantom within an iteration on the phantom registry.
+	 * {@link PhantomManager#fPhantomRegistry}
+	 * 
+	 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.AbstractDecoratorManager#handleDecorator(org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.AbstractDecoratorManager.AbstractDecorator,
+	 *      boolean, boolean)
+	 */
+	@Override
+	protected void handleDecorator(AbstractDecorator decorator, boolean isAdd, boolean isMain) {
+		super.handleDecorator(decorator, isAdd, isMain);
+		// Display the dependencies (context) of this decorator
+		for (AbstractDecorator ancestor : ((Phantom)decorator).getDependencies()) {
+			super.handleDecorator(ancestor, isAdd, false);
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.AbstractDecoratorManager#handleAddDecorator(org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.AbstractDecoratorManager.AbstractDecorator,
+	 *      org.eclipse.draw2d.IFigure, org.eclipse.draw2d.IFigure, boolean)
+	 */
+	@Override
+	protected void handleAddDecorator(AbstractDecorator decorator, IFigure parent, IFigure toAdd,
+			boolean isMain) {
+		super.handleAddDecorator(decorator, parent, toAdd, isMain);
+		// Set the highlight of the figure
+		if (isMain) {
+			decorator.getDecoratorFigure().highlight();
+			getViewer(decorator.getSide()).getGraphicalViewer().reveal(toAdd);
+		} else {
+			decorator.getDecoratorFigure().unhighlight();
+		}
+	}
+
+	/**
+	 * It checks that the given view graphically exists.
+	 * 
+	 * @param view
+	 *            The view.
+	 * @return True if it exists.
+	 */
+	private boolean isFigureExist(View view) {
+		return view != null && view.isVisible();
+	}
+
+	/**
+	 * Get the view which has to be used as reference to build a phantom.<br>
+	 * The reference is the non null object among the given objects. In case of delete object, in the context
+	 * of three-way comparison, the reference will be the ancestor one (<code>originObj</code>).
+	 * 
+	 * @param originObj
+	 *            The ancestor object.
+	 * @param leftView
+	 *            The left object.
+	 * @param rightView
+	 *            The right object.
+	 * @return The reference object.
+	 */
+	private View getReferenceView(View originObj, View leftView, View rightView) {
+		View referenceView;
+		if (isFigureExist(originObj)) {
+			referenceView = originObj;
+		} else if (isFigureExist(leftView)) {
+			referenceView = leftView;
+		} else {
+			referenceView = rightView;
+		}
+		return referenceView;
+	}
+
+	/**
+	 * It creates a new phantom from the given difference, view and figure.
+	 * 
+	 * @param diff
+	 *            The related difference used as index for the main phantom.
+	 * @param referenceView
+	 *            The reference view as base for creation of the phantom.
+	 * @param referenceFigure
+	 *            The reference figure as base for creation of the phantom.
+	 * @param side
+	 *            The side where the phantom has to be created.
+	 * @return The phantom or null if the target layer is not found.
+	 */
+	private Phantom createPhantom(Diff diff, View referenceView, IFigure referenceFigure,
+			MergeViewerSide side) {
+		IFigure targetLayer = getLayer(referenceView, side);
+		if (targetLayer != null) {
+			MergeViewerSide referenceSide = getSide(referenceView);
+
+			Rectangle rect = referenceFigure.getBounds().getCopy();
+
+			IFigure referenceLayer = getLayer(referenceView, referenceSide);
+			translateCoordinates(referenceFigure, referenceLayer, rect);
+
+			DecoratorFigure ghost = null;
+
+			Phantom phantom = new Phantom(targetLayer, side, referenceView, referenceFigure, diff);
+
+			// Container "list" case
+			if (isNodeList(referenceView)) {
+
+				int index = getIndex(diff, referenceView, side);
+
+				IFigure referenceParentFigure = referenceFigure.getParent();
+				Rectangle referenceParentBounds = referenceParentFigure.getBounds().getCopy();
+				translateCoordinates(referenceParentFigure, referenceLayer, referenceParentBounds);
+
+				View parentView = (View)getMatchView(referenceView.eContainer(), side);
+				if (parentView != null) {
+					int nbElements = getVisibleViews(parentView).size();
+					// CHECKSTYLE:OFF
+					if (index > nbElements) {
+						// CHECKSTYLE:ON
+						index = nbElements;
+					}
+				}
+
+				// FIXME: The add of decorators modifies the physical coordinates of elements
+				// FIXME: Compute position from the y position of the first child + sum of height of the
+				// children.
+				int pos = rect.height * index + referenceParentBounds.y + 1;
+				Map<String, Object> parameters = new HashMap<String, Object>();
+				parameters.put(NodeListFigure.PARAM_Y_POS, Integer.valueOf(pos));
+
+				ghost = new NodeListFigure(diff, isThreeWay(), getCompareColor(), referenceFigure, rect, true,
+						parameters);
+
+				// Edge case
+			} else if (referenceView instanceof Edge) {
+				// If the edge phantom ties shapes where their coordinates changed
+				if (hasAnExtremityChange((Edge)referenceView, side)) {
+					EditPart edgeEditPart = createEdgeEditPart((Edge)referenceView, referenceSide, side);
+					// CHECKSTYLE:OFF
+					if (edgeEditPart instanceof GraphicalEditPart) {
+						// CHECKSTYLE:ON
+						phantom.setEditPart(edgeEditPart);
+
+						IFigure fig = ((GraphicalEditPart)edgeEditPart).getFigure();
+						fig.getChildren().clear();
+						ghost = new DecoratorFigure(diff, isThreeWay(), getCompareColor(), referenceFigure,
+								fig, true);
+
+					}
+					// Else, it creates only a polyline connection figure with the same properties as the
+					// reference
+				} else {
+					if (referenceFigure instanceof PolylineConnection) {
+						ghost = new EdgeFigure(diff, isThreeWay(), getCompareColor(), referenceFigure, rect,
+								true);
+					}
+				}
+			}
+
+			// Default case: Nodes
+			if (ghost == null) {
+				ghost = new NodeFigure(diff, isThreeWay(), getCompareColor(), referenceFigure, rect, true);
+			}
+
+			phantom.setDecoratorFigure(ghost);
+
+			translateWhenInsideContainerChange(phantom);
+
+			return phantom;
+		}
+
+		return null;
+
+	}
+
+	/**
+	 * Get the index of the phantom to draw.
+	 * 
+	 * @param diff
+	 *            The related difference used as index for the main phantom.
+	 * @param referenceView
+	 *            The reference view to compute the phantom.
+	 * @param side
+	 *            The side where the phantom has to be drawn.
+	 * @return The index in the list where the phantom has to be drawn.
+	 */
+	private int getIndex(Diff diff, View referenceView, MergeViewerSide side) {
+		// Case for invisible objects
+		if (diff instanceof Hide || diff instanceof Show) {
+			List<Object> source = null;
+			List<Object> target = null;
+			Object newElement = null;
+			Match match = diff.getMatch();
+			List<Object> leftList = ReferenceUtil.getAsList(match.getLeft().eContainer(),
+					NotationPackage.Literals.VIEW__PERSISTED_CHILDREN);
+			List<Object> rightList = ReferenceUtil.getAsList(match.getRight().eContainer(),
+					NotationPackage.Literals.VIEW__PERSISTED_CHILDREN);
+			if (diff instanceof Hide) {
+				source = rightList;
+				target = leftList;
+				newElement = diff.getMatch().getRight();
+			} else {
+				source = leftList;
+				target = rightList;
+				newElement = diff.getMatch().getLeft();
+			}
+			Iterable<Object> ignoredElements = Iterables.filter(target, new Predicate() {
+				public boolean apply(Object input) {
+					return input instanceof View && !((View)input).isVisible();
+				}
+			});
+			return DiffUtil.findInsertionIndex(getCompareConfiguration().getComparison(), ignoredElements,
+					source, target, newElement);
+		}
+		// Case for deleted objects
+		Diff refiningDiff = Iterators.find(diff.getRefinedBy().iterator(), and(valueIs(referenceView),
+				onFeature(NotationPackage.Literals.VIEW__PERSISTED_CHILDREN.getName())));
+
+		return DiffUtil.findInsertionIndex(getCompareConfiguration().getComparison(), refiningDiff,
+				side == MergeViewerSide.LEFT);
+	}
+
+	/**
+	 * Get the visible view under the given parent view.
+	 * 
+	 * @param parent
+	 *            The parent view.
+	 * @return The list of views.
+	 */
+	private List<View> getVisibleViews(View parent) {
+		return (List<View>)Lists
+				.newArrayList(Iterators.filter(parent.getChildren().iterator(), new Predicate<Object>() {
+					public boolean apply(Object input) {
+						return input instanceof View && ((View)input).isVisible();
+					}
+				}));
+	}
+
+	/**
+	 * It translates and resizes the figure of the given phantom when this one is nested in a container which
+	 * is subjected to a coordinates change.
+	 * 
+	 * @param phantom
+	 *            The phantom.
+	 */
+	private void translateWhenInsideContainerChange(Phantom phantom) {
+		boolean isCandidate = false;
+		Diff diff = phantom.getDifference();
+		if (diff instanceof DiagramDiff) {
+			EObject parent = ((DiagramDiff)diff).getView().eContainer();
+			while (parent instanceof View && !isCandidate) {
+				isCandidate = Iterables.any(getCompareConfiguration().getComparison().getDifferences(parent),
+						instanceOf(CoordinatesChange.class));
+				parent = parent.eContainer();
+			}
+		}
+		if (isCandidate) {
+			View referenceView = phantom.getOriginView();
+			View parentReferenceView = (View)referenceView.eContainer();
+			if (parentReferenceView != null) {
+				View parentView = (View)getMatchView(parentReferenceView, phantom.getSide());
+				IFigure parentFigure = getFigure(parentView);
+				if (parentFigure != null) {
+					Rectangle parentRect = parentFigure.getBounds().getCopy();
+					translateCoordinates(parentFigure, getLayer(parentReferenceView, getSide(parentView)),
+							parentRect);
+
+					IFigure parentReferenceFigure = getFigure(parentReferenceView);
+					// CHECKSTYLE:OFF
+					if (parentReferenceFigure != null) {
+						Rectangle parentReferenceRect = parentReferenceFigure.getBounds().getCopy();
+						translateCoordinates(parentReferenceFigure,
+								getLayer(parentReferenceView, getSide(parentReferenceView)),
+								parentReferenceRect);
+
+						int deltaX = parentRect.x - parentReferenceRect.x;
+						int deltaY = parentRect.y - parentReferenceRect.y;
+						int deltaWidth = parentRect.width - parentReferenceRect.width;
+						int deltaHeight = parentRect.height - parentReferenceRect.height;
+
+						IFigure figure = phantom.getFigure();
+
+						Rectangle rect = figure.getBounds().getCopy();
+						rect.x += deltaX;
+						rect.y += deltaY;
+						rect.width += deltaWidth;
+						if (!(figure instanceof Polyline)) {
+							rect.height += deltaHeight;
+						}
+						figure.setBounds(rect);
+
+						if (figure instanceof Polyline) {
+
+							Point firstPoint = ((Polyline)figure).getPoints().getFirstPoint().getCopy();
+							Point lastPoint = ((Polyline)figure).getPoints().getLastPoint().getCopy();
+
+							firstPoint.x += deltaX;
+							firstPoint.y += deltaY;
+
+							lastPoint.x += deltaX + deltaWidth;
+							lastPoint.y += deltaY;
+
+							((Polyline)figure).setEndpoints(firstPoint, lastPoint);
+
+						}
+					}
+					// CHECKSTYLE:ON
+				}
+			}
+		}
+	}
+
+	/**
+	 * It checks that the given edge is linked to graphical objects subjected to coordinate changes, on the
+	 * given side.
+	 * 
+	 * @param edge
+	 *            The edge to check.
+	 * @param targetSide
+	 *            The side to check extremities (side of the phantom).
+	 * @return True if an extremity at least changed its location, False otherwise.
+	 */
+	private boolean hasAnExtremityChange(Edge edge, MergeViewerSide targetSide) {
+		View referenceSource = edge.getSource();
+		View referenceTarget = edge.getTarget();
+		return hasChange(referenceSource, targetSide) || hasChange(referenceTarget, targetSide);
+	}
+
+	/**
+	 * It checks that the coordinates of the given view changed between left and right, from the given side.
+	 * 
+	 * @param referenceView
+	 *            The view to check.
+	 * @param targetSide
+	 *            The side to focus.
+	 * @return True if the view changed its location, False otherwise.
+	 */
+	private boolean hasChange(View referenceView, MergeViewerSide targetSide) {
+		View extremity = (View)getMatchView(referenceView, targetSide);
+		// Look for a related change coordinates on the extremity of the edge reference.
+		Collection<Diff> diffs = Collections2.filter(
+				getCompareConfiguration().getComparison().getDifferences(referenceView),
+				instanceOf(CoordinatesChange.class));
+		if (diffs.isEmpty()) {
+			// Look for a related change coordinates on the matching extremity (other side) of the edge
+			// reference.
+			diffs = Collections2.filter(getCompareConfiguration().getComparison().getDifferences(extremity),
+					instanceOf(CoordinatesChange.class));
+		}
+		return !diffs.isEmpty();
+	}
+
+	/**
+	 * It creates and returns a new edit part from the given edge. This edit part listens to the reference
+	 * edge but is attached to the controllers of the target (phantom) side.
+	 * 
+	 * @param referenceEdge
+	 *            The edge as base of the edit part.
+	 * @param referenceSide
+	 *            The side of this edge.
+	 * @param targetSide
+	 *            The side where the edit part has to be created to draw the related phantom.
+	 * @return The new edit part.
+	 */
+	private EditPart createEdgeEditPart(Edge referenceEdge, MergeViewerSide referenceSide,
+			MergeViewerSide targetSide) {
+		EditPart edgeEditPartReference = getViewer(referenceSide).getEditPart(referenceEdge);
+		EditPart edgeEditPart = null;
+		if (edgeEditPartReference instanceof ConnectionEditPart) {
+
+			edgeEditPart = getOrCreatePhantomEditPart(referenceEdge, referenceSide, targetSide);
+
+			if (edgeEditPart instanceof ConnectionEditPart) {
+				EditPart edgeSourceEp = getOrCreateExtremityPhantomEditPart(
+						((ConnectionEditPart)edgeEditPartReference).getSource(), referenceSide, targetSide);
+
+				((ConnectionEditPart)edgeEditPart).setSource(edgeSourceEp);
+
+				EditPart edgeTargetEp = getOrCreateExtremityPhantomEditPart(
+						((ConnectionEditPart)edgeEditPartReference).getTarget(), referenceSide, targetSide);
+
+				((ConnectionEditPart)edgeEditPart).setTarget(edgeTargetEp);
+			}
+		}
+		return edgeEditPart;
+	}
+
+	/**
+	 * From the given edit part, it retrieves the matched one, from the given target side. If the retrieved
+	 * edit part is not linked to a GMF object, in the target side, a phantom GEF edit part is returned which
+	 * will locate a rectangle invisible figure in the same location as the related phantom.
+	 * 
+	 * @param referenceEdgeExtremityEp
+	 *            The reference edit part for one of the extremities of an edge.
+	 * @param referenceSide
+	 *            The side of the reference.
+	 * @param targetSide
+	 *            The other side, where the phantom has to be drawn.
+	 * @return The phantom edit part used to attach the extremity of an edge phantom.
+	 */
+	private EditPart getOrCreateExtremityPhantomEditPart(EditPart referenceEdgeExtremityEp,
+			MergeViewerSide referenceSide, MergeViewerSide targetSide) {
+		View referenceExtremityView = (View)referenceEdgeExtremityEp.getModel();
+
+		EditPart edgeExtremityEp = getOrCreatePhantomEditPart(referenceExtremityView, referenceSide,
+				targetSide);
+
+		if (isPhantomEditPart((AbstractGraphicalEditPart)edgeExtremityEp)) {
+
+			final AbstractGraphicalEditPart edgeExtremityEpParent = (AbstractGraphicalEditPart)edgeExtremityEp
+					.getParent();
+
+			List<Phantom> phantoms = getOrCreateRelatedPhantoms(referenceExtremityView, targetSide);
+			if (!phantoms.isEmpty()) {
+				Phantom phantomToTarget = phantoms.get(0);
+				final IFigure figureToTarget = phantomToTarget.getFigure();
+
+				edgeExtremityEp = new org.eclipse.gmf.runtime.diagram.ui.editparts.GraphicalEditPart(
+						referenceExtremityView) {
+					@Override
+					protected void createDefaultEditPolicies() {
+					}
+
+					@Override
+					protected IFigure createFigure() {
+						RectangleFigure fig = new RectangleFigure();
+						fig.setBounds(figureToTarget.getBounds());
+						fig.setParent(edgeExtremityEpParent.getFigure());
+						return fig;
+					}
+				};
+
+				edgeExtremityEp.setParent(edgeExtremityEpParent);
+			}
+
+			((AbstractGraphicalEditPart)edgeExtremityEp).activate();
+			((AbstractGraphicalEditPart)edgeExtremityEp).getFigure();
+		}
+
+		return edgeExtremityEp;
+	}
+
+	/**
+	 * It checks if the given edit part is related to a phantom edit part (created for nothing, without link
+	 * to a GMF object in the target side).
+	 * 
+	 * @param editPart
+	 *            The edit part to check.
+	 * @return True if it is a phantom edit part, false otherwise.
+	 */
+	private boolean isPhantomEditPart(AbstractGraphicalEditPart editPart) {
+		Rectangle targetBounds = editPart.getFigure().getBounds();
+		return targetBounds.x == 0 && targetBounds.y == 0 && targetBounds.width == 0
+				&& targetBounds.height == 0;
+	}
+
+	/**
+	 * It creates and returns a new edit part from the given view. This edit part listens the reference view
+	 * but is attached to the controllers of the target (phantom) side.
+	 * 
+	 * @param referenceView
+	 *            The view as base of the edit part.
+	 * @param referenceSide
+	 *            The side of this view.
+	 * @param targetSide
+	 *            The side where the edit part has to be created to draw the related phantom.
+	 * @return The new edit part.
+	 */
+	private EditPart getOrCreatePhantomEditPart(EObject referenceView, MergeViewerSide referenceSide,
+			MergeViewerSide targetSide) {
+		EditPart editPartParent = null;
+		EditPart editPart = null;
+		EditPart editPartReference = getViewer(referenceSide).getEditPart(referenceView);
+		EditPart editPartReferenceParent = editPartReference.getParent();
+		Object referenceViewParent = editPartReferenceParent.getModel();
+		if (!(referenceViewParent instanceof EObject)) {
+			referenceViewParent = referenceView.eContainer();
+		}
+		View viewParent = (View)getMatchView((EObject)referenceViewParent, targetSide);
+		if (viewParent != null) {
+			editPartParent = getViewer(targetSide).getEditPart(viewParent);
+		}
+		if (editPartParent == null) {
+			editPartParent = getOrCreatePhantomEditPart((EObject)referenceViewParent, referenceSide,
+					targetSide);
+
+		}
+		if (editPartParent != null) {
+			View view = (View)getMatchView(referenceView, targetSide);
+			if (view != null) {
+				editPart = getViewer(targetSide).getEditPart(view);
+			}
+			if (editPart == null) {
+
+				editPart = getViewer(targetSide).getGraphicalViewer().getEditPartFactory()
+						.createEditPart(editPartParent, referenceView);
+				editPart.setParent(editPartParent);
+				getViewer(targetSide).getGraphicalViewer().getEditPartRegistry().put(referenceView, editPart);
+
+			}
+
+		}
+		return editPart;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram.IDecoratorManager#hideAll()
+	 */
+	public void hideAll() {
+		for (Phantom phantom : fPhantomRegistry.values()) {
+			handleDeleteDecorator(phantom, phantom.getLayer(), phantom.getFigure());
+		}
+	}
+}