Index: /trunk/.classpath
===================================================================
--- /trunk/.classpath	(revision 1649)
+++ /trunk/.classpath	(revision 1650)
@@ -2,5 +2,7 @@
 <classpath>
 	<classpathentry kind="src" path="src"/>
-	<classpathentry excluding="build/|dist/|src/|test/" including="images/|presets/|styles/" kind="src" path=""/>
+	<classpathentry kind="src" path="test/unit"/>
+	<classpathentry kind="src" path="test/functional"/>
+	<classpathentry excluding="build/|dist/|src/|test/|test/unit/|test/functional/" including="images/|presets/|styles/" kind="src" path=""/>
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
 	<classpathentry kind="lib" path="lib/metadata-extractor-2.3.1-nosun.jar"/>
@@ -9,4 +11,11 @@
 	<classpathentry kind="lib" path="lib/josm-translation.jar"/>
 	<classpathentry kind="lib" path="lib/gettext-commons-0.9.6.jar"/>
+	<classpathentry kind="lib" path="test/lib/fest/debug-1.0.jar"/>
+	<classpathentry kind="lib" path="test/lib/fest/fest-assert-1.0.jar"/>
+	<classpathentry kind="lib" path="test/lib/fest/fest-reflect-1.1.jar"/>
+	<classpathentry kind="lib" path="test/lib/fest/fest-swing-1.1.jar"/>
+	<classpathentry kind="lib" path="test/lib/fest/fest-util-1.0.jar"/>
+	<classpathentry kind="lib" path="test/lib/fest/jcip-annotations-1.0.jar"/>
+	<classpathentry kind="lib" path="test/lib/fest/MRJToolkitStubs-1.0.jar"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
Index: /trunk/.settings/org.eclipse.jdt.core.prefs
===================================================================
--- /trunk/.settings/org.eclipse.jdt.core.prefs	(revision 1649)
+++ /trunk/.settings/org.eclipse.jdt.core.prefs	(revision 1650)
@@ -1,3 +1,3 @@
-#Sun Sep 07 19:15:59 CEST 2008
+#Sat Jun 06 11:00:10 CEST 2009
 eclipse.preferences.version=1
 org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
@@ -101,10 +101,10 @@
 org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
 org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
-org.eclipse.jdt.core.formatter.comment.format_block_comments=false
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
 org.eclipse.jdt.core.formatter.comment.format_comments=true
 org.eclipse.jdt.core.formatter.comment.format_header=false
 org.eclipse.jdt.core.formatter.comment.format_html=false
-org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=false
-org.eclipse.jdt.core.formatter.comment.format_line_comments=false
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
 org.eclipse.jdt.core.formatter.comment.format_source_code=false
 org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
Index: /trunk/.settings/org.eclipse.jdt.ui.prefs
===================================================================
--- /trunk/.settings/org.eclipse.jdt.ui.prefs	(revision 1649)
+++ /trunk/.settings/org.eclipse.jdt.ui.prefs	(revision 1650)
@@ -1,5 +1,6 @@
-#Wed Apr 16 17:01:39 CEST 2008
+#Sat Jun 06 11:00:10 CEST 2009
 eclipse.preferences.version=1
 formatter_profile=_josm
-formatter_settings_version=10
-org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates><template autoinsert\="true" context\="gettercomment_context" deleted\="false" description\="Comment for getter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.gettercomment" name\="gettercomment">/**\n * @return the ${bare_field_name}\n */</template><template autoinsert\="true" context\="settercomment_context" deleted\="false" description\="Comment for setter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.settercomment" name\="settercomment">/**\n * @param ${param} the ${bare_field_name} to set\n */</template><template autoinsert\="true" context\="constructorcomment_context" deleted\="false" description\="Comment for created constructors" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorcomment" name\="constructorcomment">/**\n * ${tags}\n */</template><template autoinsert\="false" context\="filecomment_context" deleted\="false" description\="Comment for created Java files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.filecomment" name\="filecomment">// License\: GPL. \n</template><template autoinsert\="true" context\="typecomment_context" deleted\="false" description\="Comment for created types" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.typecomment" name\="typecomment">/**\n * @author ${user}\n *\n * ${tags}\n */</template><template autoinsert\="true" context\="fieldcomment_context" deleted\="false" description\="Comment for fields" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment">/**\n * \n */</template><template autoinsert\="true" context\="methodcomment_context" deleted\="false" description\="Comment for non-overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodcomment" name\="methodcomment">/**\n * ${tags}\n */</template><template autoinsert\="true" context\="overridecomment_context" deleted\="false" description\="Comment for overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.overridecomment" name\="overridecomment">/* (non-Javadoc)\n * ${see_to_overridden}\n */</template><template autoinsert\="true" context\="delegatecomment_context" deleted\="false" description\="Comment for delegate methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.delegatecomment" name\="delegatecomment">/**\n * ${tags}\n * ${see_to_target}\n */</template><template autoinsert\="false" context\="newtype_context" deleted\="false" description\="Newly created files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.newtype" name\="newtype">// License\: GPL. For details, see LICENSE file.\n${package_declaration}\n\n${typecomment}\n${type_declaration}</template><template autoinsert\="true" context\="classbody_context" deleted\="false" description\="Code in new class type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.classbody" name\="classbody">\n</template><template autoinsert\="true" context\="interfacebody_context" deleted\="false" description\="Code in new interface type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.interfacebody" name\="interfacebody">\n</template><template autoinsert\="true" context\="enumbody_context" deleted\="false" description\="Code in new enum type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.enumbody" name\="enumbody">\n</template><template autoinsert\="true" context\="annotationbody_context" deleted\="false" description\="Code in new annotation type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.annotationbody" name\="annotationbody">\n</template><template autoinsert\="true" context\="catchblock_context" deleted\="false" description\="Code in new catch blocks" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.catchblock" name\="catchblock">// ${todo} Auto-generated catch block\n${exception_var}.printStackTrace();</template><template autoinsert\="true" context\="methodbody_context" deleted\="false" description\="Code in created method stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodbody" name\="methodbody">// ${todo} Auto-generated method stub\n${body_statement}</template><template autoinsert\="true" context\="constructorbody_context" deleted\="false" description\="Code in created constructor stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorbody" name\="constructorbody">${body_statement}\n// ${todo} Auto-generated constructor stub</template><template autoinsert\="true" context\="getterbody_context" deleted\="false" description\="Code in created getters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.getterbody" name\="getterbody">return ${field};</template><template autoinsert\="true" context\="setterbody_context" deleted\="false" description\="Code in created setters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.setterbody" name\="setterbody">${field} \= ${param};</template></templates>
+formatter_settings_version=11
+org.eclipse.jdt.ui.javadoc=false
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates><template autoinsert\="true" context\="gettercomment_context" deleted\="false" description\="Comment for getter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.gettercomment" name\="gettercomment">/**\r\n * @return the ${bare_field_name}\r\n */</template><template autoinsert\="true" context\="settercomment_context" deleted\="false" description\="Comment for setter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.settercomment" name\="settercomment">/**\r\n * @param ${param} the ${bare_field_name} to set\r\n */</template><template autoinsert\="true" context\="constructorcomment_context" deleted\="false" description\="Comment for created constructors" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorcomment" name\="constructorcomment">/**\r\n * ${tags}\r\n */</template><template autoinsert\="false" context\="filecomment_context" deleted\="false" description\="Comment for created Java files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.filecomment" name\="filecomment">// License\: GPL. \r\n</template><template autoinsert\="true" context\="typecomment_context" deleted\="false" description\="Comment for created types" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.typecomment" name\="typecomment">/**\r\n * @author ${user}\r\n *\r\n * ${tags}\r\n */</template><template autoinsert\="true" context\="fieldcomment_context" deleted\="false" description\="Comment for fields" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment">/**\r\n * \r\n */</template><template autoinsert\="true" context\="methodcomment_context" deleted\="false" description\="Comment for non-overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodcomment" name\="methodcomment">/**\r\n * ${tags}\r\n */</template><template autoinsert\="true" context\="overridecomment_context" deleted\="false" description\="Comment for overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.overridecomment" name\="overridecomment">/* (non-Javadoc)\r\n * ${see_to_overridden}\r\n */</template><template autoinsert\="true" context\="delegatecomment_context" deleted\="false" description\="Comment for delegate methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.delegatecomment" name\="delegatecomment">/**\r\n * ${tags}\r\n * ${see_to_target}\r\n */</template><template autoinsert\="false" context\="newtype_context" deleted\="false" description\="Newly created files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.newtype" name\="newtype">// License\: GPL. For details, see LICENSE file.\r\n${package_declaration}\r\n\r\n${typecomment}\r\n${type_declaration}</template><template autoinsert\="true" context\="classbody_context" deleted\="false" description\="Code in new class type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.classbody" name\="classbody">\r\n</template><template autoinsert\="true" context\="interfacebody_context" deleted\="false" description\="Code in new interface type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.interfacebody" name\="interfacebody">\r\n</template><template autoinsert\="true" context\="enumbody_context" deleted\="false" description\="Code in new enum type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.enumbody" name\="enumbody">\r\n</template><template autoinsert\="true" context\="annotationbody_context" deleted\="false" description\="Code in new annotation type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.annotationbody" name\="annotationbody">\r\n</template><template autoinsert\="true" context\="catchblock_context" deleted\="false" description\="Code in new catch blocks" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.catchblock" name\="catchblock">// ${todo} Auto-generated catch block\r\n${exception_var}.printStackTrace();</template><template autoinsert\="true" context\="methodbody_context" deleted\="false" description\="Code in created method stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodbody" name\="methodbody">// ${todo} Auto-generated method stub\r\n${body_statement}</template><template autoinsert\="true" context\="constructorbody_context" deleted\="false" description\="Code in created constructor stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorbody" name\="constructorbody">${body_statement}\r\n// ${todo} Auto-generated constructor stub</template><template autoinsert\="true" context\="getterbody_context" deleted\="false" description\="Code in created getters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.getterbody" name\="getterbody">return ${field};</template><template autoinsert\="true" context\="setterbody_context" deleted\="false" description\="Code in created setters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.setterbody" name\="setterbody">${field} \= ${param};</template><template autoinsert\="true" context\="gettercomment_context" deleted\="false" description\="Comment for getter function" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.gettercomment" name\="gettercomment">/**\r\n * @return the ${bare_field_name}\r\n */</template><template autoinsert\="true" context\="settercomment_context" deleted\="false" description\="Comment for setter function" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.settercomment" name\="settercomment">/**\r\n * @param ${param} the ${bare_field_name} to set\r\n */</template><template autoinsert\="true" context\="constructorcomment_context" deleted\="false" description\="Comment for created constructors" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.constructorcomment" name\="constructorcomment">/**\r\n * ${tags}\r\n */</template><template autoinsert\="true" context\="filecomment_context" deleted\="false" description\="Comment for created JavaScript files" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.filecomment" name\="filecomment">/**\r\n * \r\n */</template><template autoinsert\="true" context\="typecomment_context" deleted\="false" description\="Comment for created types" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.typecomment" name\="typecomment">/**\r\n * @author ${user}\r\n *\r\n * ${tags}\r\n */</template><template autoinsert\="true" context\="fieldcomment_context" deleted\="false" description\="Comment for vars" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment">/**\r\n * \r\n */</template><template autoinsert\="true" context\="methodcomment_context" deleted\="false" description\="Comment for non-overriding function" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.methodcomment" name\="methodcomment">/**\r\n * ${tags}\r\n */</template><template autoinsert\="true" context\="overridecomment_context" deleted\="false" description\="Comment for overriding functions" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.overridecomment" name\="overridecomment">/* (non-Jsdoc)\r\n * ${see_to_overridden}\r\n */</template><template autoinsert\="true" context\="delegatecomment_context" deleted\="false" description\="Comment for delegate functions" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.delegatecomment" name\="delegatecomment">/**\r\n * ${tags}\r\n * ${see_to_target}\r\n */</template><template autoinsert\="true" context\="newtype_context" deleted\="false" description\="Newly created files" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.newtype" name\="newtype">${filecomment}\r\n${package_declaration}\r\n\r\n${typecomment}\r\n${type_declaration}</template><template autoinsert\="true" context\="classbody_context" deleted\="false" description\="Code in new class type bodies" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.classbody" name\="classbody">\r\n</template><template autoinsert\="true" context\="catchblock_context" deleted\="false" description\="Code in new catch blocks" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.catchblock" name\="catchblock">// ${todo} Auto-generated catch block\r\n${exception_var}.printStackTrace();</template><template autoinsert\="true" context\="methodbody_context" deleted\="false" description\="Code in created function stubs" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.methodbody" name\="methodbody">// ${todo} Auto-generated function stub\r\n${body_statement}</template><template autoinsert\="true" context\="constructorbody_context" deleted\="false" description\="Code in created constructor stubs" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.constructorbody" name\="constructorbody">${body_statement}\r\n// ${todo} Auto-generated constructor stub</template><template autoinsert\="true" context\="getterbody_context" deleted\="false" description\="Code in created getters" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.getterbody" name\="getterbody">return ${field};</template><template autoinsert\="true" context\="setterbody_context" deleted\="false" description\="Code in created setters" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.setterbody" name\="setterbody">${field} \= ${param};</template></templates>
Index: /trunk/build.xml
===================================================================
--- /trunk/build.xml	(revision 1649)
+++ /trunk/build.xml	(revision 1650)
@@ -96,4 +96,9 @@
 		<delete dir="dist" />
 	</target>
+	
+	<target name="dev-deploy" depends="dist">
+		<copy file="dist/josm-custom.jar" todir="C:\data\projekte\osm\tag-editor-plugin"/>
+	</target>
+
 
 </project>
Index: /trunk/src/org/openstreetmap/josm/gui/conflict/ComparePairListCellRenderer.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/conflict/ComparePairListCellRenderer.java	(revision 1650)
+++ /trunk/src/org/openstreetmap/josm/gui/conflict/ComparePairListCellRenderer.java	(revision 1650)
@@ -0,0 +1,30 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.conflict;
+
+import java.awt.Color;
+import java.awt.Component;
+
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.ListCellRenderer;
+
+public class ComparePairListCellRenderer extends JLabel implements ListCellRenderer {
+    public final static Color BGCOLOR_SELECTED = new Color(143,170,255);
+
+    public ComparePairListCellRenderer() {
+        setOpaque(true);
+    }
+    public Component getListCellRendererComponent(
+            JList list,
+            Object value,
+            int index,
+            boolean isSelected,
+            boolean cellHasFocus)
+    {
+        ComparePairType type = (ComparePairType)value;
+        setText(type.getDisplayName());
+        setBackground(isSelected ? BGCOLOR_SELECTED : Color.WHITE);
+        setForeground(Color.BLACK);
+        return this;
+    }
+}
Index: /trunk/src/org/openstreetmap/josm/gui/conflict/ComparePairType.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/conflict/ComparePairType.java	(revision 1650)
+++ /trunk/src/org/openstreetmap/josm/gui/conflict/ComparePairType.java	(revision 1650)
@@ -0,0 +1,88 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.conflict;
+import static org.openstreetmap.josm.gui.conflict.ListRole.MERGED_ENTRIES;
+import static org.openstreetmap.josm.gui.conflict.ListRole.MY_ENTRIES;
+import static org.openstreetmap.josm.gui.conflict.ListRole.THEIR_ENTRIES;
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+/**
+ * Enumeration of the possible comparison pairs
+ *
+ */
+public enum ComparePairType {
+
+    /**
+     * compare my version of an {@see OsmPrimitive} with their version
+     */
+    MY_WITH_THEIR (tr("My with Their"), new ListRole[] {MY_ENTRIES, THEIR_ENTRIES}),
+
+    /**
+     * compare my version of an {@see OsmPrimitive} with the merged version
+     */
+    MY_WITH_MERGED (tr("My with Merged"),  new ListRole[] {MY_ENTRIES, MERGED_ENTRIES}),
+
+    /**
+     * compare their version of an {@see OsmPrimitive} with the merged veresion
+     */
+    THEIR_WITH_MERGED(tr("Their with Merged"),  new ListRole[] {THEIR_ENTRIES, MERGED_ENTRIES});
+
+    /** the localized display name */
+    private final String displayName;
+    private ListRole[] participatingRoles;
+
+    ComparePairType(String displayName, ListRole[] participatingRoles) {
+        this.displayName = displayName;
+        this.participatingRoles = participatingRoles;
+    }
+
+    /**
+     * replies the display name
+     * 
+     * @return the display name
+     */
+    public String getDisplayName() {
+        return displayName;
+    }
+
+    /**
+     * replies true, if <code>role</code> is participating in this comparison
+     * pair
+     * 
+     * @param role  the list role
+     * @return true, if <code>role</code> is participating in this comparison
+     * pair; false, otherwise
+     */
+    public boolean isParticipatingIn(ListRole role) {
+        for (ListRole r: participatingRoles) {
+            if (r.equals(role)) return true;
+        }
+        return false;
+    }
+
+    /**
+     * replies the pair of {@see ListRole}s participating in this comparison
+     * pair
+     * 
+     * @return  the pair of list roles
+     */
+    public ListRole[] getParticipatingRoles() {
+        return participatingRoles;
+    }
+
+    /**
+     * replies the opposite role of <code>role</code> participating in this comparison
+     * pair
+     * 
+     * @param role one of the two roles in this pair
+     * @return the opposite role
+     * @exception IllegalStateException  if role is not participating in this pair
+     */
+    public ListRole getOppositeRole(ListRole role) {
+        if (!isParticipatingIn(role))
+            throw new IllegalStateException(tr("role {0} is not participating in compare pair {1}", role.toString(), this.toString()));
+        if (participatingRoles[0].equals(role))
+            return participatingRoles[1];
+        else
+            return participatingRoles[0];
+    }
+}
Index: /trunk/src/org/openstreetmap/josm/gui/conflict/ConflictResolver.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/conflict/ConflictResolver.java	(revision 1649)
+++ /trunk/src/org/openstreetmap/josm/gui/conflict/ConflictResolver.java	(revision 1650)
@@ -93,5 +93,5 @@
                 tabbedPane.setIconAt(0, mergeIncomplete);
             }
-        } else if (evt.getPropertyName().equals(ListMergeModel.PROP_FROZEN)) {
+        } else if (evt.getPropertyName().equals(ListMergeModel.FROZEN_PROP)) {
             boolean frozen = (Boolean)evt.getNewValue();
             if (frozen && evt.getSource() == nodeListMerger.getModel()) {
Index: /trunk/src/org/openstreetmap/josm/gui/conflict/ListMergeModel.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/conflict/ListMergeModel.java	(revision 1649)
+++ /trunk/src/org/openstreetmap/josm/gui/conflict/ListMergeModel.java	(revision 1650)
@@ -2,4 +2,10 @@
 package org.openstreetmap.josm.gui.conflict;
 
+import static org.openstreetmap.josm.gui.conflict.ComparePairType.MY_WITH_MERGED;
+import static org.openstreetmap.josm.gui.conflict.ComparePairType.MY_WITH_THEIR;
+import static org.openstreetmap.josm.gui.conflict.ComparePairType.THEIR_WITH_MERGED;
+import static org.openstreetmap.josm.gui.conflict.ListRole.MERGED_ENTRIES;
+import static org.openstreetmap.josm.gui.conflict.ListRole.MY_ENTRIES;
+import static org.openstreetmap.josm.gui.conflict.ListRole.THEIR_ENTRIES;
 import static org.openstreetmap.josm.tools.I18n.tr;
 
@@ -7,7 +13,10 @@
 import java.beans.PropertyChangeListener;
 import java.util.ArrayList;
-import java.util.List;
+import java.util.HashMap;
+import java.util.Observable;
 import java.util.logging.Logger;
 
+import javax.swing.AbstractListModel;
+import javax.swing.ComboBoxModel;
 import javax.swing.DefaultListSelectionModel;
 import javax.swing.table.DefaultTableModel;
@@ -36,5 +45,5 @@
  * ListMergeModel is an abstract class. Three methods have to be implemented by subclasses:
  * <ul>
- *   <li>{@see ListMergeModel#cloneEntry(Object)} - clones an entry of type T</li>
+ *   <li>{@see ListMergeModel#cloneEntryForMergedList(Object)} - clones an entry of type T</li>
  *   <li>{@see ListMergeModel#isEqualEntry(Object, Object)} - checks whether two entries are equals </li>
  *   <li>{@see ListMergeModel#setValueAt(DefaultTableModel, Object, int, int)} - handles values edited in
@@ -46,13 +55,10 @@
  * @see ListMerger
  */
-public abstract class ListMergeModel<T> {
+public abstract class ListMergeModel<T> extends Observable {
     private static final Logger logger = Logger.getLogger(ListMergeModel.class.getName());
 
-    public static final String PROP_FROZEN = ListMergeModel.class.getName() + ".frozen";
-
-    protected ArrayList<T> myEntries;
-    protected ArrayList<T> theirEntries;
-    protected ArrayList<T> mergedEntries;
-
+    public static final String FROZEN_PROP = ListMergeModel.class.getName() + ".frozen";
+
+    protected HashMap<ListRole, ArrayList<T>> entries;
 
     protected DefaultTableModel myEntriesTableModel;
@@ -60,17 +66,22 @@
     protected DefaultTableModel mergedEntriesTableModel;
 
-    protected EntriesSelectionModel<T> myEntriesSelectionModel;
-    protected EntriesSelectionModel<T> theirEntriesSelectionModel;
-    protected EntriesSelectionModel<T> mergedEntriesSelectionModel;
+    protected EntriesSelectionModel myEntriesSelectionModel;
+    protected EntriesSelectionModel theirEntriesSelectionModel;
+    protected EntriesSelectionModel mergedEntriesSelectionModel;
 
     private final ArrayList<PropertyChangeListener> listeners;
     private boolean isFrozen = false;
-
-    /**
-     * Clones an entry of type T
+    private final ComparePairListModel comparePairListModel;
+
+
+
+    /**
+     * Creates a clone of an entry of type T suitable to be included in the
+     * list of merged entries
+     * 
      * @param entry the entry
      * @return the cloned entry
      */
-    protected abstract T cloneEntry(T entry);
+    protected abstract T cloneEntryForMergedList(T entry);
 
     /**
@@ -99,19 +110,42 @@
 
     protected void buildMyEntriesTableModel() {
-        myEntriesTableModel = new EntriesTableModel<T>(myEntries);
+        myEntriesTableModel = new EntriesTableModel(MY_ENTRIES);
     }
 
     protected void buildTheirEntriesTableModel() {
-        theirEntriesTableModel = new EntriesTableModel<T>(theirEntries);
+        theirEntriesTableModel = new EntriesTableModel(THEIR_ENTRIES);
     }
 
     protected void buildMergedEntriesTableModel() {
-        mergedEntriesTableModel = new EntriesTableModel<T>(mergedEntries);
+        mergedEntriesTableModel = new EntriesTableModel(MERGED_ENTRIES);
+    }
+
+    protected ArrayList<T> getMergedEntries() {
+        return entries.get(MERGED_ENTRIES);
+    }
+    protected ArrayList<T> getMyEntries() {
+        return entries.get(MY_ENTRIES);
+    }
+    protected ArrayList<T> getTheirEntries() {
+        return entries.get(THEIR_ENTRIES);
+    }
+
+    public int getMyEntriesSize() {
+        return getMyEntries().size();
+    }
+
+    public int getMergedEntriesSize() {
+        return getMergedEntries().size();
+    }
+
+    public int getTheirEntriesSize() {
+        return getTheirEntries().size();
     }
 
     public ListMergeModel() {
-        myEntries = new ArrayList<T>();
-        theirEntries = new ArrayList<T>();
-        mergedEntries = new ArrayList<T>();
+        entries = new HashMap<ListRole, ArrayList<T>>();
+        for (ListRole role : ListRole.values()) {
+            entries.put(role, new ArrayList<T>());
+        }
 
         buildMyEntriesTableModel();
@@ -119,13 +153,13 @@
         buildMergedEntriesTableModel();
 
-        myEntriesSelectionModel = new EntriesSelectionModel<T>(myEntries);
-        theirEntriesSelectionModel = new EntriesSelectionModel<T>(theirEntries);
-        mergedEntriesSelectionModel =  new EntriesSelectionModel<T>(mergedEntries);
+        myEntriesSelectionModel = new EntriesSelectionModel(entries.get(MY_ENTRIES));
+        theirEntriesSelectionModel = new EntriesSelectionModel(entries.get(THEIR_ENTRIES));
+        mergedEntriesSelectionModel =  new EntriesSelectionModel(entries.get(MERGED_ENTRIES));
 
         listeners = new ArrayList<PropertyChangeListener>();
+        comparePairListModel = new ComparePairListModel();
 
         setFrozen(true);
     }
-
 
     public void addPropertyChangeListener(PropertyChangeListener listener) {
@@ -147,5 +181,5 @@
     protected void fireFrozenChanged(boolean oldValue, boolean newValue) {
         synchronized(listeners) {
-            PropertyChangeEvent evt = new PropertyChangeEvent(this, PROP_FROZEN, oldValue, newValue);
+            PropertyChangeEvent evt = new PropertyChangeEvent(this, FROZEN_PROP, oldValue, newValue);
             for (PropertyChangeListener listener: listeners) {
                 listener.propertyChange(evt);
@@ -188,18 +222,19 @@
     }
 
-
     protected void fireModelDataChanged() {
         myEntriesTableModel.fireTableDataChanged();
         theirEntriesTableModel.fireTableDataChanged();
         mergedEntriesTableModel.fireTableDataChanged();
-    }
-
-    protected void copyToTop(List<T> source, int []rows) {
+        setChanged();
+        notifyObservers();
+    }
+
+    protected void copyToTop(ListRole role, int []rows) {
         if (rows == null || rows.length == 0)
             return;
         for (int i = rows.length - 1; i >= 0; i--) {
             int row = rows[i];
-            T n = source.get(row);
-            mergedEntries.add(0, cloneEntry(n));
+            T n = entries.get(role).get(row);
+            entries.get(MERGED_ENTRIES).add(0, cloneEntryForMergedList(n));
         }
         fireModelDataChanged();
@@ -215,5 +250,5 @@
      */
     public void copyMyToTop(int [] rows) {
-        copyToTop(myEntries, rows);
+        copyToTop(MY_ENTRIES, rows);
     }
 
@@ -226,5 +261,5 @@
      */
     public void copyTheirToTop(int [] rows) {
-        copyToTop(theirEntries, rows);
+        copyToTop(THEIR_ENTRIES, rows);
     }
 
@@ -238,10 +273,11 @@
      */
 
-    public void copyToEnd(List<T> source, int [] rows) {
+    public void copyToEnd(ListRole source, int [] rows) {
         if (rows == null || rows.length == 0)
             return;
+        ArrayList<T> mergedEntries = getMergedEntries();
         for (int row : rows) {
-            T n = source.get(row);
-            mergedEntries.add(cloneEntry(n));
+            T n = entries.get(source).get(row);
+            mergedEntries.add(cloneEntryForMergedList(n));
         }
         fireModelDataChanged();
@@ -258,5 +294,5 @@
      */
     public void copyMyToEnd(int [] rows) {
-        copyToEnd(myEntries, rows);
+        copyToEnd(MY_ENTRIES, rows);
     }
 
@@ -269,5 +305,5 @@
      */
     public void copyTheirToEnd(int [] rows) {
-        copyToEnd(theirEntries, rows);
+        copyToEnd(THEIR_ENTRIES, rows);
     }
 
@@ -282,13 +318,14 @@
      * 
      */
-    protected void copyBeforeCurrent(List<T> source, int [] rows, int current) {
+    protected void copyBeforeCurrent(ListRole source, int [] rows, int current) {
         if (rows == null || rows.length == 0)
             return;
+        ArrayList<T> mergedEntries = getMergedEntries();
         if (current < 0 || current >= mergedEntries.size())
             throw new IllegalArgumentException(tr("parameter current out of range: got {0}", current));
         for (int i=rows.length -1; i>=0; i--) {
             int row = rows[i];
-            T n = source.get(row);
-            mergedEntries.add(current, cloneEntry(n));
+            T n = entries.get(source).get(row);
+            mergedEntries.add(current, cloneEntryForMergedList(n));
         }
         fireModelDataChanged();
@@ -306,5 +343,5 @@
      */
     public void copyMyBeforeCurrent(int [] rows, int current) {
-        copyBeforeCurrent(myEntries,rows,current);
+        copyBeforeCurrent(MY_ENTRIES,rows,current);
     }
 
@@ -319,5 +356,5 @@
      */
     public void copyTheirBeforeCurrent(int [] rows, int current) {
-        copyBeforeCurrent(theirEntries,rows,current);
+        copyBeforeCurrent(THEIR_ENTRIES,rows,current);
     }
 
@@ -332,24 +369,23 @@
      * 
      */
-    protected void copyAfterCurrent(List<T> source, int [] rows, int current) {
+    protected void copyAfterCurrent(ListRole source, int [] rows, int current) {
         if (rows == null || rows.length == 0)
             return;
+        ArrayList<T> mergedEntries = getMergedEntries();
+
         if (current < 0 || current >= mergedEntries.size())
             throw new IllegalArgumentException(tr("parameter current out of range: got {0}", current));
         if (current == mergedEntries.size() -1) {
-            if (source == myEntries) {
-                copyMyToEnd(rows);
-            } else if (source == theirEntries) {
-                copyTheirToEnd(rows);
-            }
+            copyToEnd(source, rows);
         } else {
             for (int i=rows.length -1; i>=0; i--) {
                 int row = rows[i];
-                T n = source.get(row);
-                mergedEntries.add(current+1, cloneEntry(n));
+                T n = entries.get(source).get(row);
+                mergedEntries.add(current+1, cloneEntryForMergedList(n));
             }
         }
         fireModelDataChanged();
         mergedEntriesSelectionModel.setSelectionInterval(current+1, current + rows.length-1);
+        notifyObservers();
     }
 
@@ -364,5 +400,5 @@
      */
     public void copyMyAfterCurrent(int [] rows, int current) {
-        copyAfterCurrent(myEntries, rows, current);
+        copyAfterCurrent(MY_ENTRIES, rows, current);
     }
 
@@ -377,5 +413,5 @@
      */
     public void copyTheirAfterCurrent(int [] rows, int current) {
-        copyAfterCurrent(theirEntries, rows, current);
+        copyAfterCurrent(THEIR_ENTRIES, rows, current);
     }
 
@@ -393,4 +429,5 @@
             // can't move up
             return;
+        ArrayList<T> mergedEntries = getMergedEntries();
         for (int row: rows) {
             T n = mergedEntries.get(row);
@@ -399,4 +436,5 @@
         }
         fireModelDataChanged();
+        notifyObservers();
         mergedEntriesSelectionModel.clearSelection();
         for (int row: rows) {
@@ -414,4 +452,5 @@
         if (rows == null || rows.length == 0)
             return;
+        ArrayList<T> mergedEntries = getMergedEntries();
         if (rows[rows.length -1] == mergedEntries.size() -1)
             // can't move down
@@ -424,4 +463,5 @@
         }
         fireModelDataChanged();
+        notifyObservers();
         mergedEntriesSelectionModel.clearSelection();
         for (int row: rows) {
@@ -439,8 +479,12 @@
         if (rows == null || rows.length == 0)
             return;
+
+        ArrayList<T> mergedEntries = getMergedEntries();
+
         for (int i = rows.length-1; i>=0;i--) {
             mergedEntries.remove(rows[i]);
         }
         fireModelDataChanged();
+        notifyObservers();
         mergedEntriesSelectionModel.clearSelection();
     }
@@ -454,8 +498,9 @@
      */
     protected boolean myAndTheirEntriesEqual() {
-        if (myEntries.size() != theirEntries.size())
+
+        if (getMyEntries().size() != getTheirEntries().size())
             return false;
-        for (int i=0; i < myEntries.size(); i++) {
-            if (! isEqualEntry(myEntries.get(i), theirEntries.get(i)))
+        for (int i=0; i < getMyEntries().size(); i++) {
+            if (! isEqualEntry(getMyEntries().get(i), getTheirEntries().get(i)))
                 return false;
         }
@@ -464,16 +509,30 @@
 
 
-    protected class EntriesTableModel<T1> extends DefaultTableModel {
-        private final ArrayList<T1> entries;
-
-        public EntriesTableModel(ArrayList<T1> nodes) {
-            this.entries = nodes;
+    /**
+     * This an adapter between a {@see JTable} and one of the three entry lists
+     * in the role {@see ListRole} managed by the {@see ListMergeModel}.
+     * 
+     * From the point of view of the {@see JTable} it is a {@see TableModel}.
+     *
+     * @param <T>
+     * @see ListMergeModel#getMyTableModel()
+     * @see ListMergeModel#getTheirTableModel()
+     * @see ListMergeModel#getMergedTableModel()
+     */
+    public class EntriesTableModel extends DefaultTableModel {
+        private final ListRole role;
+
+        /**
+         * 
+         * @param role the role
+         */
+        public EntriesTableModel(ListRole role) {
+            this.role = role;
         }
 
         @Override
         public int getRowCount() {
-            int count = myEntries.size();
-            count = Math.max(count, mergedEntries.size());
-            count = Math.max(count, theirEntries.size());
+            int count = Math.max(getMyEntries().size(), getMergedEntries().size());
+            count = Math.max(count, getTheirEntries().size());
             return count;
         }
@@ -481,6 +540,6 @@
         @Override
         public Object getValueAt(int row, int column) {
-            if (row < entries.size())
-                return entries.get(row);
+            if (row < entries.get(role).size())
+                return entries.get(role).get(row);
             return null;
         }
@@ -495,10 +554,108 @@
             ListMergeModel.this.setValueAt(this, value,row,col);
         }
-    }
-
-    protected class EntriesSelectionModel<T1> extends DefaultListSelectionModel {
-        private final ArrayList<T1> entries;
-
-        public EntriesSelectionModel(ArrayList<T1> nodes) {
+
+        public ListMergeModel getListMergeModel() {
+            return ListMergeModel.this;
+        }
+
+        /**
+         * replies true if the {@see ListRole} of this {@see EntriesTableModel}
+         * participates in the current {@see ComparePairType}
+         * 
+         * @return true, if the if the {@see ListRole} of this {@see EntriesTableModel}
+         * participates in the current {@see ComparePairType}
+         * 
+         * @see ComparePairListModel#getSelectedComparePair()
+         */
+        public boolean isParticipatingInCurrentComparePair() {
+            return getComparePairListModel()
+            .getSelectedComparePair()
+            .isParticipatingIn(role);
+        }
+
+        /**
+         * replies true if the entry at <code>row</code> is equal to the entry at the
+         * same position in the opposite list of the current {@see ComparePairType}.
+         * 
+         * @param row  the row number
+         * @return true if the entry at <code>row</code> is equal to the entry at the
+         * same position in the opposite list of the current {@see ComparePairType}
+         * @exception IllegalStateException thrown, if this model is not participating in the
+         *   current  {@see ComparePairType}
+         * @see ComparePairType#getOppositeRole(ListRole)
+         * @see #getRole()
+         * @see #getOppositeEntries()
+         */
+        public boolean isSamePositionInOppositeList(int row) {
+            if (!isParticipatingInCurrentComparePair())
+                throw new IllegalStateException(tr("list in role {0} is currently not participating in a compare pair", role.toString()));
+            if (row >= getEntries().size()) return false;
+            if (row >= getOppositeEntries().size()) return false;
+
+            T e1 = getEntries().get(row);
+            T e2 = getOppositeEntries().get(row);
+            return isEqualEntry(e1, e2);
+        }
+
+        /**
+         * replies true if the entry at the current position is present in the opposite list
+         * of the current {@see ComparePairType}.
+         * 
+         * @param row the current row
+         * @return true if the entry at the current position is present in the opposite list
+         * of the current {@see ComparePairType}.
+         * @exception IllegalStateException thrown, if this model is not participating in the
+         *   current  {@see ComparePairType}
+         * @see ComparePairType#getOppositeRole(ListRole)
+         * @see #getRole()
+         * @see #getOppositeEntries()
+         */
+        public boolean isIncludedInOppositeList(int row) {
+            if (!isParticipatingInCurrentComparePair())
+                throw new IllegalStateException(tr("list in role {0} is currently not participating in a compare pair", role.toString()));
+
+            if (row >= getEntries().size()) return false;
+            T e1 = getEntries().get(row);
+            for (T e2: getOppositeEntries()) {
+                if (isEqualEntry(e1, e2)) return true;
+            }
+            return false;
+        }
+
+        protected ArrayList<T> getEntries() {
+            return entries.get(role);
+        }
+
+        /**
+         * replies the opposite list of entries with respect to the current {@see ComparePairType}
+         * 
+         * @return the opposite list of entries
+         */
+        protected ArrayList<T> getOppositeEntries() {
+            ListRole opposite = getComparePairListModel().getSelectedComparePair().getOppositeRole(role);
+            return entries.get(opposite);
+        }
+
+        public ListRole getRole() {
+            return role;
+        }
+    }
+
+    /**
+     * This is the selection model to be used in a {@see JTable} which displays
+     * an entry list managed by {@see ListMergeModel}.
+     * 
+     * The model ensures that only rows displaying an entry in the entry list
+     * can be selected. "Empty" rows can't be selected.
+     * 
+     * @see ListMergeModel#getMySelectionModel()
+     * @see ListMergeModel#getMergedSelectionModel()
+     * @see ListMergeModel#getTheirSelectionModel()
+     *
+     */
+    protected class EntriesSelectionModel extends DefaultListSelectionModel {
+        private final ArrayList<T> entries;
+
+        public EntriesSelectionModel(ArrayList<T> nodes) {
             this.entries = nodes;
         }
@@ -584,3 +741,47 @@
         }
     }
+
+    public ComparePairListModel getComparePairListModel() {
+        return this.comparePairListModel;
+    }
+
+    public class ComparePairListModel extends AbstractListModel implements ComboBoxModel {
+
+        private  int selectedIdx;
+        private final ArrayList<ComparePairType> compareModes;
+
+        public ComparePairListModel() {
+            this.compareModes = new ArrayList<ComparePairType>();
+            compareModes.add(MY_WITH_THEIR);
+            compareModes.add(MY_WITH_MERGED);
+            compareModes.add(THEIR_WITH_MERGED);
+            selectedIdx = 0;
+        }
+
+        public Object getElementAt(int index) {
+            if (index < compareModes.size())
+                return compareModes.get(index);
+            throw new IllegalArgumentException(tr("unexpected value of parameter \"index\". Got {0}", index));
+        }
+
+        public int getSize() {
+            return compareModes.size();
+        }
+
+        public Object getSelectedItem() {
+            return compareModes.get(selectedIdx);
+        }
+
+        public void setSelectedItem(Object anItem) {
+            int i = compareModes.indexOf(anItem);
+            if (i < 0)
+                throw new IllegalStateException(tr("item {0} not found in list", anItem));
+            selectedIdx = i;
+            fireModelDataChanged();
+        }
+
+        public ComparePairType getSelectedComparePair() {
+            return compareModes.get(selectedIdx);
+        }
+    }
 }
Index: /trunk/src/org/openstreetmap/josm/gui/conflict/ListMerger.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/conflict/ListMerger.java	(revision 1649)
+++ /trunk/src/org/openstreetmap/josm/gui/conflict/ListMerger.java	(revision 1650)
@@ -2,4 +2,5 @@
 
 import static org.openstreetmap.josm.tools.I18n.tr;
+import static org.openstreetmap.josm.tools.I18n.trn;
 
 import java.awt.Adjustable;
@@ -26,4 +27,5 @@
 import javax.swing.JButton;
 import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
 import javax.swing.JLabel;
 import javax.swing.JPanel;
@@ -42,5 +44,5 @@
  * @see ListMergeModel
  */
-public abstract class ListMerger<T> extends JPanel implements PropertyChangeListener {
+public abstract class ListMerger<T> extends JPanel implements PropertyChangeListener, Observer {
     private static final Logger logger = Logger.getLogger(ListMerger.class.getName());
 
@@ -72,4 +74,11 @@
     private  JCheckBox cbLockMergedScrolling;
     private  JCheckBox cbLockTheirScrolling;
+
+    private  JLabel lblMyVersion;
+    private  JLabel lblMergedVersion;
+    private  JLabel lblTheirVersion;
+
+
+    private  JLabel lblFrozenState;
 
     abstract protected JScrollPane buildMyElementsTable();
@@ -204,15 +213,4 @@
         pnl.add(new JButton(removeMergedAction), gc);
 
-        gc.gridx = 0;
-        gc.gridy = 1;
-        gc.gridwidth = 3;
-        gc.weightx = 1.0;
-        freezeAction = new FreezeAction();
-        JToggleButton btn = new JToggleButton(freezeAction);
-        freezeAction.adapt(btn);
-        btn.setName("button.freeze");
-        btn.addItemListener(freezeAction);
-        pnl.add(btn, gc);
-
         return pnl;
     }
@@ -224,4 +222,28 @@
         panel.add(cb);
         return panel;
+    }
+
+    protected JPanel buildComparePairSelectionPanel() {
+        JPanel p = new JPanel();
+        p.setLayout(new FlowLayout(FlowLayout.LEFT));
+        p.add(new JLabel(tr("Compare ")));
+        JComboBox cbComparePair =new JComboBox(model.getComparePairListModel());
+        cbComparePair.setRenderer(new ComparePairListCellRenderer());
+        p.add(cbComparePair);
+        return p;
+    }
+
+    protected JPanel buildFrozeStateControlPanel() {
+        JPanel p = new JPanel();
+        p.setLayout(new FlowLayout(FlowLayout.LEFT));
+        lblFrozenState = new JLabel();
+        p.add(lblFrozenState);
+        freezeAction = new FreezeAction();
+        JToggleButton btn = new JToggleButton(freezeAction);
+        freezeAction.adapt(btn);
+        btn.setName("button.freeze");
+        p.add(btn);
+
+        return p;
     }
 
@@ -239,20 +261,20 @@
         gc.weightx = 0.0;
         gc.weighty = 0.0;
-        gc.insets = new Insets(10,0,10,0);
-        JLabel lbl = new JLabel(tr("My version"));
-        lbl.setToolTipText(tr("List of elements in my dataset, i.e. the local dataset"));
-        add(lbl, gc);
+        gc.insets = new Insets(10,0,0,0);
+        lblMyVersion = new JLabel(tr("My version"));
+        lblMyVersion.setToolTipText(tr("List of elements in my dataset, i.e. the local dataset"));
+        add(lblMyVersion, gc);
 
         gc.gridx = 2;
         gc.gridy = 0;
-        lbl = new JLabel(tr("Merged version"));
-        lbl.setToolTipText(tr("List of merged elements. They will replace the my elements when the merge decisions are applied."));
-        add(lbl, gc);
+        lblMergedVersion = new JLabel(tr("Merged version"));
+        lblMergedVersion.setToolTipText(tr("List of merged elements. They will replace the my elements when the merge decisions are applied."));
+        add(lblMergedVersion, gc);
 
         gc.gridx = 4;
         gc.gridy = 0;
-        lbl = new JLabel(tr("Their version"));
-        lbl.setToolTipText(tr("List of elements in their dataset, i.e. the server dataset"));
-        add(lbl, gc);
+        lblTheirVersion = new JLabel(tr("Their version"));
+        lblTheirVersion.setToolTipText(tr("List of elements in their dataset, i.e. the server dataset"));
+        add(lblTheirVersion, gc);
 
         // ------------------------------
@@ -343,4 +365,26 @@
         add(buildMergedListControlButtons(), gc);
 
+        // -----------------------------------
+        gc.gridx = 0;
+        gc.gridy = 4;
+        gc.gridwidth = 2;
+        gc.gridheight = 1;
+        gc.fill = GridBagConstraints.HORIZONTAL;
+        gc.anchor = GridBagConstraints.LINE_START;
+        gc.weightx = 0.0;
+        gc.weighty = 0.0;
+        add(buildComparePairSelectionPanel(), gc);
+
+        gc.gridx = 2;
+        gc.gridy = 4;
+        gc.gridwidth = 3;
+        gc.gridheight = 1;
+        gc.fill = GridBagConstraints.HORIZONTAL;
+        gc.anchor = GridBagConstraints.LINE_START;
+        gc.weightx = 0.0;
+        gc.weighty = 0.0;
+        add(buildFrozeStateControlPanel(), gc);
+
+
         wireActionsToSelectionModels();
     }
@@ -348,4 +392,5 @@
     public ListMerger(ListMergeModel<T> model) {
         this.model = model;
+        model.addObserver(this);
         build();
         model.addPropertyChangeListener(this);
@@ -714,11 +759,11 @@
             int state = e.getStateChange();
             if (state == ItemEvent.SELECTED) {
-                model.setFrozen(true);
                 putValue(Action.NAME, tr("Unfreeze"));
                 putValue(Action.SHORT_DESCRIPTION, tr("Unfreeze the list of merged elements and start merging"));
+                model.setFrozen(true);
             } else if (state == ItemEvent.DESELECTED) {
-                model.setFrozen(false);
                 putValue(Action.NAME, tr("Freeze"));
                 putValue(Action.SHORT_DESCRIPTION, tr("Freeze the current list of merged elements"));
+                model.setFrozen(false);
             }
             boolean isSelected = (Boolean)getValue(PROP_SELECTED);
@@ -737,10 +782,22 @@
         mergedEntriesTable.getSelectionModel().clearSelection();
         mergedEntriesTable.setEnabled(!newValue);
-        freezeAction.putValue(FreezeActionProperties.PROP_SELECTED, newValue);
-    }
-
+        if (freezeAction != null) {
+            freezeAction.putValue(FreezeActionProperties.PROP_SELECTED, newValue);
+        }
+        if (newValue) {
+            lblFrozenState.setText(
+                    tr("<html>Click <strong>{0}</strong> to start merging my and their entries</html>",
+                            freezeAction.getValue(Action.NAME))
+            );
+        } else {
+            lblFrozenState.setText(
+                    tr("<html>Click <strong>{0}</strong> to finish merging my and their entries</html>",
+                            freezeAction.getValue(Action.NAME))
+            );
+        }
+    }
 
     public void propertyChange(PropertyChangeEvent evt) {
-        if (evt.getPropertyName().equals(ListMergeModel.PROP_FROZEN)) {
+        if (evt.getPropertyName().equals(ListMergeModel.FROZEN_PROP)) {
             handlePropertyChangeFrozen((Boolean)evt.getOldValue(), (Boolean)evt.getNewValue());
         }
@@ -749,4 +806,20 @@
     public ListMergeModel<T> getModel() {
         return model;
+    }
+
+
+    public void update(Observable o, Object arg) {
+        lblMyVersion.setText(
+                tr("My version ")
+                + trn("({0} entry)", "({0} entries)", model.getMyEntriesSize(), model.getMyEntriesSize())
+        );
+        lblMergedVersion.setText(
+                tr("Merged version ")
+                + trn("({0} entry)", "({0} entries)", model.getMergedEntriesSize(), model.getMergedEntriesSize())
+        );
+        lblTheirVersion.setText(
+                tr("Their version ")
+                + trn("({0} entry)", "({0} entries)", model.getTheirEntriesSize(), model.getTheirEntriesSize())
+        );
     }
 
Index: /trunk/src/org/openstreetmap/josm/gui/conflict/ListRole.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/conflict/ListRole.java	(revision 1650)
+++ /trunk/src/org/openstreetmap/josm/gui/conflict/ListRole.java	(revision 1650)
@@ -0,0 +1,11 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.conflict;
+
+/**
+ * Enumeration of roles entry lists play in {@see ListMergeModel}
+ */
+public enum ListRole {
+    MY_ENTRIES,
+    MERGED_ENTRIES,
+    THEIR_ENTRIES
+}
Index: /trunk/src/org/openstreetmap/josm/gui/conflict/nodes/NodeListColumnModel.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/conflict/nodes/NodeListColumnModel.java	(revision 1649)
+++ /trunk/src/org/openstreetmap/josm/gui/conflict/nodes/NodeListColumnModel.java	(revision 1650)
@@ -17,7 +17,7 @@
         col = new TableColumn(0);
         col.setHeaderValue("");
-        col.setResizable(false);
+        col.setResizable(true);
         col.setWidth(30);
-        col.setMaxWidth(30);
+        col.setPreferredWidth(30);
         col.setCellRenderer(renderer);
         addColumn(col);
Index: /trunk/src/org/openstreetmap/josm/gui/conflict/nodes/NodeListMergeModel.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/conflict/nodes/NodeListMergeModel.java	(revision 1649)
+++ /trunk/src/org/openstreetmap/josm/gui/conflict/nodes/NodeListMergeModel.java	(revision 1650)
@@ -1,4 +1,6 @@
 // License: GPL. For details, see LICENSE file.
 package org.openstreetmap.josm.gui.conflict.nodes;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.util.ArrayList;
@@ -11,4 +13,5 @@
 import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.gui.conflict.ListMergeModel;
+import org.openstreetmap.josm.gui.conflict.ListRole;
 
 public class NodeListMergeModel extends ListMergeModel<Node>{
@@ -28,18 +31,18 @@
     public void populate(Way my, Way their) {
         if (my == null)
-            throw new IllegalArgumentException("parameter 'way' must not be null");
+            throw new IllegalArgumentException(tr("parameter \"way\" must not be null"));
         if (their == null)
-            throw new IllegalArgumentException("parameter 'their' must not be null");
-        mergedEntries.clear();
-        myEntries.clear();
-        theirEntries.clear();
+            throw new IllegalArgumentException(tr("parameter \"their\" must not be null"));
+        getMergedEntries().clear();
+        getMyEntries().clear();
+        getTheirEntries().clear();
         for (Node n : my.nodes) {
-            myEntries.add(n);
+            getMyEntries().add(n);
         }
         for (Node n : their.nodes) {
-            theirEntries.add(n);
+            getTheirEntries().add(n);
         }
         if (myAndTheirEntriesEqual()) {
-            mergedEntries = new ArrayList<Node>(myEntries);
+            entries.put(ListRole.MERGED_ENTRIES, new ArrayList<Node>(getMyEntries()));
             setFrozen(true);
         } else {
@@ -62,10 +65,10 @@
     public WayNodesConflictResolverCommand buildResolveCommand(Way my, Way their) {
         if (my == null)
-            throw new IllegalArgumentException("parameter my most not be null");
+            throw new IllegalArgumentException(tr("parameter \"my\" most not be null"));
         if (their == null)
-            throw new IllegalArgumentException("parameter my most not be null");
+            throw new IllegalArgumentException(tr("parameter \"my\" most not be null"));
         if (! isFrozen())
-            throw new IllegalArgumentException("merged nodes not frozen yet. Can't build resolution command");
-        return new WayNodesConflictResolverCommand(my, their, mergedEntries);
+            throw new IllegalArgumentException(tr("Merged nodes not frozen yet. Can't build resolution command"));
+        return new WayNodesConflictResolverCommand(my, their, getMergedEntries());
     }
 
@@ -73,5 +76,8 @@
     @Override
     public boolean isEqualEntry(Node e1, Node e2) {
-        return e1.id == e2.id;
+        if (e1.id > 0)
+            return e1.id == e2.id;
+        else
+            return e1 == e2;
     }
 
@@ -82,8 +88,6 @@
 
     @Override
-    protected Node cloneEntry(Node entry) {
-        Node n = new Node(entry.id);
-        n.cloneFrom(entry);
-        return n;
+    protected Node cloneEntryForMergedList(Node entry) {
+        return entry;
     }
 }
Index: /trunk/src/org/openstreetmap/josm/gui/conflict/nodes/NodeListTableCellRenderer.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/conflict/nodes/NodeListTableCellRenderer.java	(revision 1649)
+++ /trunk/src/org/openstreetmap/josm/gui/conflict/nodes/NodeListTableCellRenderer.java	(revision 1650)
@@ -7,4 +7,7 @@
 import java.awt.Component;
 import java.text.DecimalFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.logging.Logger;
 
 import javax.swing.BorderFactory;
@@ -16,4 +19,6 @@
 
 import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.gui.conflict.ListMergeModel;
 import org.openstreetmap.josm.tools.ImageProvider;
 
@@ -23,10 +28,18 @@
  */
 public  class NodeListTableCellRenderer extends JLabel implements TableCellRenderer {
+    static private final Logger logger = Logger.getLogger(NodeListTableCellRenderer.class.getName());
     private static DecimalFormat COORD_FORMATTER = new DecimalFormat("###0.0000");
     public final static Color BGCOLOR_SELECTED = new Color(143,170,255);
     public final static Color BGCOLOR_EMPTY_ROW = new Color(234,234,234);
-
-    private ImageIcon icon = null;
-    private Border rowNumberBorder = null;
+    public final static Color BGCOLOR_FROZEN = new Color(234,234,234);
+    public final static Color BGCOLOR_PARTICIPAING_IN_COMPARISON = Color.BLACK;
+    public final static Color FGCOLOR_PARTICIPAING_IN_COMPARISON = Color.WHITE;
+
+    public final static Color BGCOLOR_NOT_IN_OPPOSITE = new Color(255,197,197);
+    public final static Color BGCOLOR_IN_OPPOSITE = new Color(255,234,213);
+    public final static Color BGCOLOR_SAME_POSITION_IN_OPPOSITE = new Color(217,255,217);
+
+    private final ImageIcon icon;
+    private final Border rowNumberBorder;
 
     /**
@@ -68,4 +81,37 @@
     }
 
+
+    public String buildToolTipText(OsmPrimitive primitive) {
+        StringBuilder sb = new StringBuilder();
+        sb.append("<html>");
+        sb.append("<strong>id</strong>=")
+        .append(primitive.id)
+        .append("<br>");
+        ArrayList<String> keyList = new ArrayList<String>(primitive.keySet());
+        Collections.sort(keyList);
+        for (int i = 0; i < keyList.size(); i++) {
+            if (i > 0) {
+                sb.append("<br>");
+            }
+            String key = keyList.get(i);
+            sb.append("<strong>")
+            .append(key)
+            .append("</strong>")
+            .append("=");
+            String value = primitive.get(key);
+            while(value.length() != 0) {
+                sb.append(value.substring(0,Math.min(50, value.length())));
+                if (value.length() > 50) {
+                    sb.append("<br>");
+                    value = value.substring(50);
+                } else {
+                    value = "";
+                }
+            }
+        }
+        sb.append("</html>");
+        return sb.toString();
+    }
+
     /**
      * reset the renderer
@@ -76,18 +122,35 @@
     }
 
+
+
     /**
      * render a node
+     * @param model  the model
      * @param node the node
-     * @param isSelected
-     */
-    protected  void renderNode(Node node, boolean isSelected) {
+     * @param isSelected true, if the current row is selected
+     */
+    protected  void renderNode(ListMergeModel<Node>.EntriesTableModel model, Node node, int row, boolean isSelected) {
         setIcon(icon);
         setBorder(null);
-        if (isSelected) {
+        if (model.getListMergeModel().isFrozen()) {
+            setBackground(BGCOLOR_FROZEN);
+        } else if (isSelected) {
             setBackground(BGCOLOR_SELECTED);
+        } else if (model.isParticipatingInCurrentComparePair()) {
+            if (model.isSamePositionInOppositeList(row)) {
+                setBackground(BGCOLOR_SAME_POSITION_IN_OPPOSITE);
+            } else if (model.isIncludedInOppositeList(row)) {
+                setBackground(BGCOLOR_IN_OPPOSITE);
+            } else {
+                setBackground(BGCOLOR_NOT_IN_OPPOSITE);
+            }
         }
         setText(getDisplayName(node));
-    }
-
+        setToolTipText(buildToolTipText(node));
+    }
+
+    /**
+     * render an empty row
+     */
     protected void renderEmptyRow() {
         setIcon(null);
@@ -98,12 +161,16 @@
     /**
      * render the row id
+     * @param model  the model
      * @param row the row index
-     * @param isSelected
-     */
-    protected  void renderRowId(int row, boolean isSelected) {
+     * @param isSelected true, if the current row is selected
+     */
+    protected  void renderRowId( ListMergeModel<Node>.EntriesTableModel model, int row, boolean isSelected) {
         setIcon(null);
         setBorder(rowNumberBorder);
-        if (isSelected) {
-            setBackground(BGCOLOR_SELECTED);
+        if (model.getListMergeModel().isFrozen()) {
+            setBackground(BGCOLOR_FROZEN);
+        } else if (model.isParticipatingInCurrentComparePair()) {
+            setBackground(BGCOLOR_PARTICIPAING_IN_COMPARISON);
+            setForeground(FGCOLOR_PARTICIPAING_IN_COMPARISON);
         }
         setText(Integer.toString(row+1));
@@ -117,5 +184,5 @@
         switch(column) {
         case 0:
-            renderRowId(row, isSelected);
+            renderRowId(getModel(table),row, isSelected);
             break;
         case 1:
@@ -123,5 +190,5 @@
                 renderEmptyRow();
             } else {
-                renderNode(node,isSelected);
+                renderNode(getModel(table), node, row, isSelected);
             }
             break;
@@ -132,3 +199,12 @@
         return this;
     }
+
+    /**
+     * replies the model
+     * @param table  the table
+     * @return the table model
+     */
+    protected ListMergeModel<Node>.EntriesTableModel getModel(JTable table) {
+        return (ListMergeModel.EntriesTableModel)table.getModel();
+    }
 }
Index: /trunk/src/org/openstreetmap/josm/gui/conflict/relation/RelationMemberListColumnModel.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/conflict/relation/RelationMemberListColumnModel.java	(revision 1649)
+++ /trunk/src/org/openstreetmap/josm/gui/conflict/relation/RelationMemberListColumnModel.java	(revision 1650)
@@ -16,7 +16,7 @@
         col = new TableColumn(0);
         col.setHeaderValue("");
-        col.setResizable(false);
+        col.setResizable(true);
         col.setWidth(20);
-        col.setMaxWidth(20);
+        col.setPreferredWidth(20);
         col.setCellRenderer(renderer);
         addColumn(col);
Index: /trunk/src/org/openstreetmap/josm/gui/conflict/relation/RelationMemberListMergeModel.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/conflict/relation/RelationMemberListMergeModel.java	(revision 1649)
+++ /trunk/src/org/openstreetmap/josm/gui/conflict/relation/RelationMemberListMergeModel.java	(revision 1650)
@@ -9,9 +9,8 @@
 
 import org.openstreetmap.josm.command.RelationMemberConflictResolverCommand;
-import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.Relation;
 import org.openstreetmap.josm.data.osm.RelationMember;
-import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.gui.conflict.ListMergeModel;
+import org.openstreetmap.josm.gui.conflict.ListRole;
 /**
  * The model for merging two lists of relation members
@@ -25,9 +24,14 @@
     @Override
     public boolean isEqualEntry(RelationMember e1, RelationMember e2) {
-        return
-        (    (e1.role == null && e2.role == null)
-                || (e1.role != null && e1.role.equals(e2.role))
-        )
-        && e1.member.id == e2.member.id;
+        boolean ret =
+            (    (e1.role == null && e2.role == null)
+                    || (e1.role != null && e1.role.equals(e2.role))
+            );
+        if (e1.member.id > 0 ) {
+            ret = ret && (e1.member.id == e2.member.id);
+        } else {
+            ret = ret && (e1 == e2);
+        }
+        return ret;
     }
 
@@ -37,5 +41,5 @@
         // editing cells in the first column
         //
-        mergedEntriesTableModel = this.new EntriesTableModel<RelationMember>(mergedEntries) {
+        mergedEntriesTableModel = this.new EntriesTableModel(ListRole.MERGED_ENTRIES) {
             @Override
             public boolean isCellEditable(int row, int column) {
@@ -51,5 +55,5 @@
     protected void setValueAt(DefaultTableModel model, Object value, int row, int col) {
         if (model == getMergedTableModel() && col == 1) {
-            RelationMember member = mergedEntries.get(row);
+            RelationMember member = getMergedEntries().get(row);
             member.role = (String)value;
             fireModelDataChanged();
@@ -72,17 +76,17 @@
             throw new IllegalArgumentException(tr("parameter their must not be null"));
 
-        mergedEntries.clear();
-        myEntries.clear();
-        theirEntries.clear();
+        getMergedEntries().clear();
+        getMyEntries().clear();
+        getTheirEntries().clear();
 
         for (RelationMember n : my.members) {
-            myEntries.add(n);
+            getMyEntries().add(n);
         }
         for (RelationMember n : their.members) {
-            theirEntries.add(n);
+            getTheirEntries().add(n);
         }
         if (myAndTheirEntriesEqual()) {
-            for (RelationMember m : myEntries) {
-                mergedEntries.add(cloneEntry(m));
+            for (RelationMember m : getMyEntries()) {
+                getMergedEntries().add(cloneEntryForMergedList(m));
             }
             setFrozen(true);
@@ -95,15 +99,8 @@
 
     @Override
-    protected RelationMember cloneEntry(RelationMember entry) {
+    protected RelationMember cloneEntryForMergedList(RelationMember entry) {
         RelationMember member = new RelationMember();
         member.role = entry.role;
-        if (entry.member instanceof Node) {
-            member.member = new Node(entry.member.id);
-        } else if (entry.member instanceof Way) {
-            member.member = new Way(entry.member.id);
-        } else if (entry.member instanceof Relation) {
-            member.member = new Relation(entry.member.id);
-        }
-        member.member.cloneFrom(entry.member);
+        member.member = entry.member;
         return member;
     }
@@ -126,5 +123,5 @@
         if (! isFrozen())
             throw new IllegalArgumentException(tr("merged nodes not frozen yet. Can't build resolution command"));
-        return new RelationMemberConflictResolverCommand(my, their, mergedEntries);
+        return new RelationMemberConflictResolverCommand(my, their, getMergedEntries());
     }
 }
Index: /trunk/src/org/openstreetmap/josm/gui/conflict/relation/RelationMemberTableCellRenderer.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/conflict/relation/RelationMemberTableCellRenderer.java	(revision 1649)
+++ /trunk/src/org/openstreetmap/josm/gui/conflict/relation/RelationMemberTableCellRenderer.java	(revision 1650)
@@ -1,10 +1,10 @@
 // License: GPL. For details, see LICENSE file.
 package org.openstreetmap.josm.gui.conflict.relation;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.Color;
 import java.awt.Component;
 import java.text.DecimalFormat;
+import java.util.ArrayList;
+import java.util.Collections;
 
 import javax.swing.BorderFactory;
@@ -20,4 +20,5 @@
 import org.openstreetmap.josm.data.osm.RelationMember;
 import org.openstreetmap.josm.data.osm.Way;
+import org.openstreetmap.josm.gui.conflict.ListMergeModel;
 import org.openstreetmap.josm.tools.ImageProvider;
 
@@ -31,4 +32,13 @@
     public final static Color BGCOLOR_EMPTY_ROW = new Color(234,234,234);
 
+    public final static Color BGCOLOR_NOT_IN_OPPOSITE = new Color(255,197,197);
+    public final static Color BGCOLOR_IN_OPPOSITE = new Color(255,234,213);
+    public final static Color BGCOLOR_SAME_POSITION_IN_OPPOSITE = new Color(217,255,217);
+
+    public final static Color BGCOLOR_PARTICIPAING_IN_COMPARISON = Color.BLACK;
+    public final static Color FGCOLOR_PARTICIPAING_IN_COMPARISON = Color.WHITE;
+
+    public final static Color BGCOLOR_FROZEN = new Color(234,234,234);
+
     private ImageIcon nodeIcon;
     private ImageIcon wayIcon;
@@ -57,4 +67,37 @@
     }
 
+
+    public String buildToolTipText(OsmPrimitive primitive) {
+        StringBuilder sb = new StringBuilder();
+        sb.append("<html>");
+        sb.append("<strong>id</strong>=")
+        .append(primitive.id)
+        .append("<br>");
+        ArrayList<String> keyList = new ArrayList<String>(primitive.keySet());
+        Collections.sort(keyList);
+        for (int i = 0; i < keyList.size(); i++) {
+            if (i > 0) {
+                sb.append("<br>");
+            }
+            String key = keyList.get(i);
+            sb.append("<strong>")
+            .append(key)
+            .append("</strong>")
+            .append("=");
+            String value = primitive.get(key);
+            while(value.length() != 0) {
+                sb.append(value.substring(0,Math.min(50, value.length())));
+                if (value.length() > 50) {
+                    sb.append("<br>");
+                    value = value.substring(50);
+                } else {
+                    value = "";
+                }
+            }
+        }
+        sb.append("</html>");
+        return sb.toString();
+    }
+
     /**
      * creates the display name for a node. The name is derived from the nodes id,
@@ -67,12 +110,4 @@
         StringBuilder sb = new StringBuilder();
         OsmPrimitive primitive = member.member;
-        if (primitive instanceof Node) {
-            sb.append(tr("Node"));
-        } else if (primitive instanceof Way) {
-            sb.append(tr("Way"));
-        } else if (primitive instanceof Relation) {
-            sb.append(tr("Relation"));
-        }
-        sb.append(" ");
         if (primitive.get("name") != null) {
             sb.append(primitive.get("name"));
@@ -110,7 +145,42 @@
 
 
-    protected void setBackground(boolean isSelected) {
-        Color bgc = isSelected ?  BGCOLOR_SELECTED : Color.WHITE;
+    protected void renderBackground(ListMergeModel<Node>.EntriesTableModel model, RelationMember member, int row, int col, boolean isSelected) {
+        Color bgc = Color.WHITE;
+        if (col == 0) {
+            if (model.getListMergeModel().isFrozen()) {
+                bgc = BGCOLOR_FROZEN;
+            } else if (model.isParticipatingInCurrentComparePair()) {
+                bgc = BGCOLOR_PARTICIPAING_IN_COMPARISON;
+            } else if (isSelected) {
+                bgc = BGCOLOR_SELECTED;
+            }
+        } else {
+            if (model.getListMergeModel().isFrozen()) {
+                bgc = BGCOLOR_FROZEN;
+            } else if (member == null) {
+                bgc = BGCOLOR_EMPTY_ROW;
+            } else if (isSelected) {
+                bgc = BGCOLOR_SELECTED;
+            } else {
+                if (model.isParticipatingInCurrentComparePair()) {
+                    if (model.isSamePositionInOppositeList(row)) {
+                        bgc = BGCOLOR_SAME_POSITION_IN_OPPOSITE;
+                    } else if (model.isIncludedInOppositeList(row)) {
+                        bgc = BGCOLOR_IN_OPPOSITE;
+                    } else {
+                        bgc = BGCOLOR_NOT_IN_OPPOSITE;
+                    }
+                }
+            }
+        }
         setBackground(bgc);
+    }
+
+    protected void renderForeground(ListMergeModel<Node>.EntriesTableModel model, RelationMember member, int row, int col, boolean isSelected) {
+        Color fgc = Color.BLACK;
+        if (col == 0 && model.isParticipatingInCurrentComparePair() && ! model.getListMergeModel().isFrozen()) {
+            fgc = Color.WHITE;
+        }
+        setForeground(fgc);
     }
 
@@ -123,5 +193,5 @@
         String displayName = getDisplayName(member);
         setText(displayName);
-        setToolTipText(displayName);
+        setToolTipText(buildToolTipText(member.member));
         if (member.member instanceof Node) {
             setIcon(nodeIcon);
@@ -141,5 +211,5 @@
      * @param isSelected
      */
-    protected  void renderRowId(int row, boolean isSelected) {
+    protected  void renderRowId(int row) {
         setBorder(rowNumberBorder);
         setText(Integer.toString(row+1));
@@ -158,8 +228,9 @@
         RelationMember member = (RelationMember)value;
         reset();
-        setBackground(isSelected);
+        renderBackground(getModel(table), member, row, column, isSelected);
+        renderForeground(getModel(table), member, row, column, isSelected);
         switch(column) {
         case 0:
-            renderRowId(row, isSelected);
+            renderRowId(row);
             break;
         case 1:
@@ -183,3 +254,11 @@
     }
 
+    /**
+     * replies the model
+     * @param table  the table
+     * @return the table model
+     */
+    protected ListMergeModel<Node>.EntriesTableModel getModel(JTable table) {
+        return (ListMergeModel.EntriesTableModel)table.getModel();
+    }
 }
Index: /trunk/test/unit/org/openstreetmap/josm/gui/conflict/nodes/NodeListMergeModelTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/gui/conflict/nodes/NodeListMergeModelTest.java	(revision 1649)
+++ /trunk/test/unit/org/openstreetmap/josm/gui/conflict/nodes/NodeListMergeModelTest.java	(revision 1650)
@@ -3,4 +3,5 @@
 
 import static org.fest.reflect.core.Reflection.field;
+import static org.fest.reflect.core.Reflection.method;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
@@ -21,7 +22,8 @@
 
     protected List<Node> inspectNodeList(NodeListMergeModel model, String name) {
-        return field(name).ofType(ArrayList.class)
+        return method("get" + name + "Entries")
+        .withReturnType(List.class)
         .in(model)
-        .get();
+        .invoke();
     }
 
@@ -69,5 +71,5 @@
         model.copyMyToTop(new int[]{0});
 
-        List<Node> mergedNodes = inspectNodeList(model, "mergedEntries");
+        List<Node> mergedNodes = inspectNodeList(model, "Merged");
 
         assertEquals(1, mergedNodes.size());
@@ -92,10 +94,10 @@
         model.populate(myWay, theirWay);
 
-        List<Node> mergedNodes = inspectNodeList(model, "mergedEntries");
+        List<Node> mergedNodes = inspectNodeList(model, "Merged");
         mergedNodes.add(new Node(1));
 
         model.copyMyToTop(new int[]{0});
 
-        mergedNodes = inspectNodeList(model, "mergedEntries");
+        mergedNodes = inspectNodeList(model, "Merged");
         assertEquals(2, mergedNodes.size());
         assertEquals(2, mergedNodes.get(0).id);
@@ -123,10 +125,10 @@
         model.populate(myWay, theirWay);
 
-        List<Node> mergedNodes = inspectNodeList(model, "mergedEntries");
+        List<Node> mergedNodes = inspectNodeList(model, "Merged");
         mergedNodes.add(new Node(1));
 
         model.copyMyToTop(new int[]{1}); // copy node 3
 
-        mergedNodes = inspectNodeList(model, "mergedEntries");
+        mergedNodes = inspectNodeList(model, "Merged");
         assertEquals(2, mergedNodes.size());
         assertEquals(3, mergedNodes.get(0).id); // my node 3 at position 0
@@ -150,10 +152,10 @@
         model.populate(myWay, theirWay);
 
-        List<Node> mergedNodes = inspectNodeList(model, "mergedEntries");
+        List<Node> mergedNodes = inspectNodeList(model, "Merged");
         mergedNodes.add(new Node(1));
 
         model.copyMyToTop(new int[]{1,2}); // copy node 3 and 4
 
-        mergedNodes = inspectNodeList(model, "mergedEntries");
+        mergedNodes = inspectNodeList(model, "Merged");
         assertEquals(3, mergedNodes.size());
         assertEquals(3, mergedNodes.get(0).id); // my node 3 at position 0
@@ -178,5 +180,5 @@
         model.copyMyToEnd(new int[]{0});
 
-        List<Node> mergedNodes = inspectNodeList(model, "mergedEntries");
+        List<Node> mergedNodes = inspectNodeList(model, "Merged");
 
         assertEquals(1, mergedNodes.size());
@@ -198,10 +200,10 @@
         model.populate(myWay, theirWay);
 
-        List<Node> mergedNodes = inspectNodeList(model, "mergedEntries");
+        List<Node> mergedNodes = inspectNodeList(model, "Merged");
         mergedNodes.add(new Node(1));
 
         model.copyMyToEnd(new int[]{0});
 
-        mergedNodes = inspectNodeList(model, "mergedEntries");
+        mergedNodes = inspectNodeList(model, "Merged");
         assertEquals(2, mergedNodes.size());
         assertEquals(1, mergedNodes.get(0).id); // already merged node 1 at position 0
@@ -224,10 +226,10 @@
         model.populate(myWay, theirWay);
 
-        List<Node> mergedNodes = inspectNodeList(model, "mergedEntries");
+        List<Node> mergedNodes = inspectNodeList(model, "Merged");
         mergedNodes.add(new Node(1));
 
         model.copyMyToEnd(new int[]{1}); // copy node 3
 
-        mergedNodes = inspectNodeList(model, "mergedEntries");
+        mergedNodes = inspectNodeList(model, "Merged");
         assertEquals(2, mergedNodes.size());
         assertEquals(1, mergedNodes.get(0).id); // already merged node 1 at position 0
@@ -252,10 +254,10 @@
         model.populate(myWay, theirWay);
 
-        List<Node> mergedNodes = inspectNodeList(model, "mergedEntries");
+        List<Node> mergedNodes = inspectNodeList(model, "Merged");
         mergedNodes.add(new Node(1));
 
         model.copyMyToEnd(new int[]{1,2}); // copy node 3 and 4
 
-        mergedNodes = inspectNodeList(model, "mergedEntries");
+        mergedNodes = inspectNodeList(model, "Merged");
         assertEquals(3, mergedNodes.size());
         assertEquals(1, mergedNodes.get(0).id); // already merged node 1 at position 0
@@ -282,5 +284,5 @@
 
         model.populate(myWay, theirWay);
-        List<Node> mergedNodes = inspectNodeList(model, "mergedEntries");
+        List<Node> mergedNodes = inspectNodeList(model, "Merged");
         mergedNodes.add(new Node(10));
         mergedNodes.add(new Node(11));
@@ -310,5 +312,5 @@
 
         model.populate(myWay, theirWay);
-        List<Node> mergedNodes = inspectNodeList(model, "mergedEntries");
+        List<Node> mergedNodes = inspectNodeList(model, "Merged");
         mergedNodes.add(new Node(10));
         mergedNodes.add(new Node(11));
@@ -338,5 +340,5 @@
 
         model.populate(myWay, theirWay);
-        List<Node> mergedNodes = inspectNodeList(model, "mergedEntries");
+        List<Node> mergedNodes = inspectNodeList(model, "Merged");
         mergedNodes.add(new Node(10));
         mergedNodes.add(new Node(11));
@@ -371,5 +373,5 @@
 
         model.populate(myWay, theirWay);
-        List<Node> mergedNodes = inspectNodeList(model, "mergedEntries");
+        List<Node> mergedNodes = inspectNodeList(model, "Merged");
         mergedNodes.add(new Node(10));
         mergedNodes.add(new Node(11));
@@ -400,5 +402,5 @@
 
         model.populate(myWay, theirWay);
-        List<Node> mergedNodes = inspectNodeList(model, "mergedEntries");
+        List<Node> mergedNodes = inspectNodeList(model, "Merged");
         mergedNodes.add(new Node(10));
         mergedNodes.add(new Node(11));
@@ -430,5 +432,5 @@
 
         model.populate(myWay, theirWay);
-        List<Node> mergedNodes = inspectNodeList(model, "mergedEntries");
+        List<Node> mergedNodes = inspectNodeList(model, "Merged");
         mergedNodes.add(new Node(10));
         mergedNodes.add(new Node(11));
@@ -458,5 +460,5 @@
 
         model.populate(myWay, theirWay);
-        List<Node> mergedNodes = inspectNodeList(model, "mergedEntries");
+        List<Node> mergedNodes = inspectNodeList(model, "Merged");
         mergedNodes.add(new Node(10));
         mergedNodes.add(new Node(11));
@@ -491,5 +493,5 @@
 
         model.populate(myWay, theirWay);
-        List<Node> mergedNodes = inspectNodeList(model, "mergedEntries");
+        List<Node> mergedNodes = inspectNodeList(model, "Merged");
         mergedNodes.add(new Node(10));
         mergedNodes.add(new Node(11));
@@ -517,5 +519,5 @@
 
         model.populate(myWay, theirWay);
-        List<Node> mergedNodes = inspectNodeList(model, "mergedEntries");
+        List<Node> mergedNodes = inspectNodeList(model, "Merged");
         mergedNodes.add(new Node(10));
         mergedNodes.add(new Node(11));
@@ -547,5 +549,5 @@
 
         model.populate(myWay, theirWay);
-        List<Node> mergedNodes = inspectNodeList(model, "mergedEntries");
+        List<Node> mergedNodes = inspectNodeList(model, "Merged");
         mergedNodes.add(new Node(10));
         mergedNodes.add(new Node(11));
@@ -580,5 +582,5 @@
 
         model.populate(myWay, theirWay);
-        List<Node> mergedNodes = inspectNodeList(model, "mergedEntries");
+        List<Node> mergedNodes = inspectNodeList(model, "Merged");
         mergedNodes.add(new Node(10));
         mergedNodes.add(new Node(11));
@@ -606,5 +608,5 @@
 
         model.populate(myWay, theirWay);
-        List<Node> mergedNodes = inspectNodeList(model, "mergedEntries");
+        List<Node> mergedNodes = inspectNodeList(model, "Merged");
         mergedNodes.add(new Node(10));
         mergedNodes.add(new Node(11));
@@ -636,5 +638,5 @@
 
         model.populate(myWay, theirWay);
-        List<Node> mergedNodes = inspectNodeList(model, "mergedEntries");
+        List<Node> mergedNodes = inspectNodeList(model, "Merged");
         mergedNodes.add(new Node(10));
         mergedNodes.add(new Node(11));
