Index: applications/editors/josm/plugins/conflation/src/org/openstreetmap/josm/plugins/conflation/ConflationAction.java
===================================================================
--- applications/editors/josm/plugins/conflation/src/org/openstreetmap/josm/plugins/conflation/ConflationAction.java	(revision 27852)
+++ 	(revision )
@@ -1,46 +1,0 @@
-// License: GPL. Copyright 2011 by Josh Doe and others
-// Connects from JOSM menu action to Plugin
-package org.openstreetmap.josm.plugins.conflation;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.event.ActionEvent;
-import java.awt.event.InputEvent;
-import java.awt.event.KeyEvent;
-import java.util.List;
-import javax.swing.JOptionPane;
-import org.openstreetmap.josm.Main;
-
-import org.openstreetmap.josm.actions.JosmAction;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
-import org.openstreetmap.josm.tools.Shortcut;
-
-//@SuppressWarnings("serial")
-public class ConflationAction extends JosmAction {
-    public ConflationAction() {
-        super(tr("Conflation"), "conflation", tr("Conflation tool for merging data"),
-                Shortcut.registerShortcut("tool:conflation", tr("Tool: {0}", tr("Conflation")),
-                KeyEvent.VK_A, Shortcut.CTRL_SHIFT), true);
-        //setEnabled(false);
-        //DataSet.selListeners.add(this);
-
-    }
-
-    public void actionPerformed(ActionEvent e) {
-        // get list of OsmDataLayers
-        List<OsmDataLayer> layerList = null;
-        if (Main.map != null && Main.map.mapView != null) {
-            layerList = Main.map.mapView.getLayersOfType(OsmDataLayer.class);
-        }
-        if (layerList == null || layerList.isEmpty()) {
-            JOptionPane.showMessageDialog(Main.parent, tr("There are no data layers "
-                    + "present. Please open or create at least one data layer and try again."),
-                    tr("Cannot perform conflation"), JOptionPane.ERROR_MESSAGE);
-            return;
-        }
-
-        // show options dialog
-        ConflationOptionsDialog conflationDialog = new ConflationOptionsDialog(Main.parent, layerList);
-        conflationDialog.setVisible(true);
-    }
-}
Index: applications/editors/josm/plugins/conflation/src/org/openstreetmap/josm/plugins/conflation/ConflationCandidate.java
===================================================================
--- applications/editors/josm/plugins/conflation/src/org/openstreetmap/josm/plugins/conflation/ConflationCandidate.java	(revision 27959)
+++ applications/editors/josm/plugins/conflation/src/org/openstreetmap/josm/plugins/conflation/ConflationCandidate.java	(revision 27959)
@@ -0,0 +1,59 @@
+package org.openstreetmap.josm.plugins.conflation;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+
+/**
+ * This class represents a potential match, i.e. a pair of primitives and
+ * related information.
+ */
+public class ConflationCandidate {
+
+    OsmPrimitive sourcePrimitive;
+    OsmDataLayer sourceLayer;
+    OsmPrimitive targetPrimitive;
+    OsmDataLayer targetLayer;
+    double cost;
+    double distance;
+
+    public ConflationCandidate(OsmPrimitive source, OsmDataLayer sourceLayer,
+            OsmPrimitive target, OsmDataLayer targetLayer, double cost) {
+        if (source == null || target == null) {
+            throw new IllegalArgumentException("Invalid source or target");
+        }
+        this.sourcePrimitive = source;
+        this.sourceLayer = sourceLayer;
+        this.targetPrimitive = target;
+        this.targetLayer = targetLayer;
+        this.cost = cost;
+        // TODO: use distance calculated in cost function, and make sure it's in meters?
+        this.distance = ConflationUtils.getCenter(source).distance(ConflationUtils.getCenter(target));
+    }
+
+    public OsmPrimitive getSourcePrimitive() {
+        return sourcePrimitive;
+    }
+    
+    public OsmDataLayer getSourceLayer() {
+        return sourceLayer;
+    }
+    
+    public OsmDataLayer getTargetLayer() {
+        return targetLayer;
+    }
+
+    public OsmPrimitive getTargetPrimitive() {
+        return targetPrimitive;
+    }
+
+    public Object getCost() {
+        return cost;
+    }
+
+    public Object getDistance() {
+        return distance;
+    }
+}
Index: applications/editors/josm/plugins/conflation/src/org/openstreetmap/josm/plugins/conflation/ConflationCandidateList.java
===================================================================
--- applications/editors/josm/plugins/conflation/src/org/openstreetmap/josm/plugins/conflation/ConflationCandidateList.java	(revision 27959)
+++ applications/editors/josm/plugins/conflation/src/org/openstreetmap/josm/plugins/conflation/ConflationCandidateList.java	(revision 27959)
@@ -0,0 +1,102 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.openstreetmap.josm.plugins.conflation;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+
+/**
+ *  Holds a list of conflation candidates and provides convenience functions.
+ */
+public class ConflationCandidateList implements Iterable<ConflationCandidate> {
+    private CopyOnWriteArrayList<ConflationListChangedListener> listeners = new CopyOnWriteArrayList<ConflationListChangedListener>();
+
+    List<ConflationCandidate> candidates;
+
+    public ConflationCandidateList() {
+        candidates = new LinkedList<ConflationCandidate>();
+    }
+
+    public boolean hasCandidate(ConflationCandidate c) {
+        return hasCandidateForSource(c.getSourcePrimitive());
+    }
+
+    public boolean hasCandidate(OsmPrimitive src, OsmPrimitive tgt) {
+        return hasCandidateForSource(src) || hasCandidateForTarget(tgt);
+    }
+
+    public boolean hasCandidateForSource(OsmPrimitive src) {
+        return getCandidateBySource(src) != null;
+    }
+
+    public boolean hasCandidateForTarget(OsmPrimitive tgt) {
+        return getCandidateByTarget(tgt) != null;
+    }
+
+    public ConflationCandidate getCandidateBySource(OsmPrimitive src) {
+        for (ConflationCandidate c : candidates) {
+            if (c.getSourcePrimitive() == src) {
+                return c;
+            }
+        }
+        return null;
+    }
+
+    public ConflationCandidate getCandidateByTarget(OsmPrimitive tgt) {
+        for (ConflationCandidate c : candidates) {
+            if (c.getTargetPrimitive() == tgt) {
+                return c;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public Iterator<ConflationCandidate> iterator() {
+        return candidates.iterator();
+    }
+
+    public void add(ConflationCandidate c) {
+        candidates.add(c);
+        fireSelectionChanged();
+    }
+
+    public int size() {
+        return candidates.size();
+    }
+
+    public ConflationCandidate get(int index) {
+        return candidates.get(index);
+    }
+
+    public ConflationCandidate remove(int index) {
+        return candidates.remove(index);
+    }
+    
+    public void clear() {
+        candidates.clear();
+        fireSelectionChanged();
+    }
+
+    public boolean remove(ConflationCandidate c) {
+        boolean ret = candidates.remove(c);
+        fireSelectionChanged();
+        return ret;
+    }
+    
+    public void addConflationListChangedListener(ConflationListChangedListener listener) {
+        listeners.addIfAbsent(listener);
+    }
+
+    public void fireSelectionChanged(){
+        for (ConflationListChangedListener l : listeners) {
+            l.conflationListChanged(this);
+        }
+    }
+}
Index: applications/editors/josm/plugins/conflation/src/org/openstreetmap/josm/plugins/conflation/ConflationLayer.java
===================================================================
--- applications/editors/josm/plugins/conflation/src/org/openstreetmap/josm/plugins/conflation/ConflationLayer.java	(revision 27852)
+++ applications/editors/josm/plugins/conflation/src/org/openstreetmap/josm/plugins/conflation/ConflationLayer.java	(revision 27959)
@@ -4,22 +4,16 @@
 import java.awt.BasicStroke;
 import java.awt.Color;
-import javax.swing.Action;
-import javax.swing.Icon;
-import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
-import static org.openstreetmap.josm.tools.I18n.tr;
-
 import java.awt.Graphics2D;
 import java.awt.Point;
 import java.awt.geom.GeneralPath;
 import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
+import javax.swing.Action;
+import javax.swing.Icon;
 import org.openstreetmap.josm.actions.RenameLayerAction;
-
-
 import org.openstreetmap.josm.data.Bounds;
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
 import org.openstreetmap.josm.gui.MapView;
 import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
@@ -28,5 +22,5 @@
 import org.openstreetmap.josm.gui.layer.Layer;
 import org.openstreetmap.josm.gui.layer.Layer.SeparatorLayerAction;
-import org.openstreetmap.josm.plugins.conflation.ConflationOptionsPanel.ConflationCandidate;
+import static org.openstreetmap.josm.tools.I18n.tr;
 import org.openstreetmap.josm.tools.ImageProvider;
 
@@ -37,8 +31,8 @@
  */
 public class ConflationLayer extends Layer implements LayerChangeListener {
-    protected List<ConflationCandidate> candidates;
+    protected ConflationCandidateList candidates;
     protected ConflationCandidate selectedCandidate = null;
     
-    public ConflationLayer(DataSet ds, List<ConflationCandidate> candidates) {
+    public ConflationLayer(DataSet ds, ConflationCandidateList candidates) {
         super(tr("Conflation"));
         MapView.addLayerChangeListener(this);
@@ -66,11 +60,11 @@
                 g2.setColor(Color.cyan);
             }
-            OsmPrimitive src = candidate.getSource();
-            OsmPrimitive tgt = candidate.getTarget();
+            OsmPrimitive src = candidate.getSourcePrimitive();
+            OsmPrimitive tgt = candidate.getTargetPrimitive();
             if (src != null && tgt != null) {
                 GeneralPath path = new GeneralPath();
                 // we have a pair, so draw line between them, FIXME: not good to use getCenter() from here, move to utils?
-                Point p1 = mv.getPoint(ConflationOptionsPanel.getCenter(src));
-                Point p2 = mv.getPoint(ConflationOptionsPanel.getCenter(tgt));
+                Point p1 = mv.getPoint(ConflationUtils.getCenter(src));
+                Point p2 = mv.getPoint(ConflationUtils.getCenter(tgt));
                 path.moveTo(p1.x, p1.y);
                 path.lineTo(p2.x, p2.y);
@@ -124,6 +118,6 @@
         for (Iterator<ConflationCandidate> it = this.candidates.iterator(); it.hasNext();) {
             ConflationCandidate candidate = it.next();
-            OsmPrimitive src = candidate.getSource();
-            OsmPrimitive tgt = candidate.getTarget();
+            OsmPrimitive src = candidate.getSourcePrimitive();
+            OsmPrimitive tgt = candidate.getTargetPrimitive();
             if (src != null && src instanceof Node)
                 v.visit((Node)src);
@@ -166,5 +160,5 @@
      * @return the set of conflicts currently managed in this layer
      */
-    public List<ConflationCandidate> getCandidates() {
+    public ConflationCandidateList getCandidates() {
         return this.candidates;
     }
Index: applications/editors/josm/plugins/conflation/src/org/openstreetmap/josm/plugins/conflation/ConflationListChangedListener.java
===================================================================
--- applications/editors/josm/plugins/conflation/src/org/openstreetmap/josm/plugins/conflation/ConflationListChangedListener.java	(revision 27959)
+++ applications/editors/josm/plugins/conflation/src/org/openstreetmap/josm/plugins/conflation/ConflationListChangedListener.java	(revision 27959)
@@ -0,0 +1,15 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.openstreetmap.josm.plugins.conflation;
+
+public interface ConflationListChangedListener {
+
+    /**
+     * Informs the listener that the conflation list has changed.
+     *
+     * @param list The new list.
+     */
+    public void conflationListChanged(ConflationCandidateList list);
+}
Index: applications/editors/josm/plugins/conflation/src/org/openstreetmap/josm/plugins/conflation/ConflationOptionsDialog.java
===================================================================
--- applications/editors/josm/plugins/conflation/src/org/openstreetmap/josm/plugins/conflation/ConflationOptionsDialog.java	(revision 27852)
+++ 	(revision )
@@ -1,68 +1,0 @@
-// License: GPL. Copyright 2011 by Josh Doe and others
-package org.openstreetmap.josm.plugins.conflation;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.BorderLayout;
-import java.awt.Component;
-import java.awt.event.ActionEvent;
-import java.awt.event.KeyEvent;
-import java.util.List;
-import javax.swing.AbstractAction;
-import javax.swing.JComponent;
-import javax.swing.JDialog;
-import javax.swing.JOptionPane;
-import javax.swing.KeyStroke;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
-import org.openstreetmap.josm.tools.ImageProvider;
-
-/**
- *
- * @author Josh Doe <josh@joshdoe.com>
- */
-public class ConflationOptionsDialog extends JDialog {
-    private boolean canceled = false;
-    private ConflationOptionsPanel panel;
-
-    public ConflationOptionsDialog(Component parent, List<OsmDataLayer> layers) {
-        super(JOptionPane.getFrameForComponent(parent),tr("Conflation Options"), ModalityType.MODELESS);
-        getContentPane().setLayout(new BorderLayout());
-        panel = new ConflationOptionsPanel(this, layers);
-        getContentPane().add(panel, BorderLayout.CENTER);
-
-        pack();
-
-        // make dialog respond to ESCAPE
-        getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE,0), "escape");
-        getRootPane().getActionMap().put("escape", new CancelAction());
-
-        // make dialog respond to F1
-        // TODO: set help context, whatever that means
-        //HelpUtil.setHelpContext(getRootPane(), help);
-    }
-
-    public void setCanceled(boolean canceled) {
-        this.canceled = canceled;
-    }
-
-    public boolean isCanceled() {
-        return canceled;
-    }
-
-    class CancelAction extends AbstractAction {
-        public CancelAction() {
-            putValue(NAME, tr("Cancel"));
-            putValue(SHORT_DESCRIPTION, tr("Close the dialog, do not perform conflation"));
-            putValue(SMALL_ICON, ImageProvider.get("cancel"));
-        }
-
-        public void actionPerformed(ActionEvent e) {
-            setCanceled(true);
-            setVisible(false);
-        }
-    }
-
-    public ConflationOptionsPanel getPanel() {
-        return panel;
-    }
-}
Index: applications/editors/josm/plugins/conflation/src/org/openstreetmap/josm/plugins/conflation/ConflationOptionsPanel.form
===================================================================
--- applications/editors/josm/plugins/conflation/src/org/openstreetmap/josm/plugins/conflation/ConflationOptionsPanel.form	(revision 27852)
+++ 	(revision )
@@ -1,400 +1,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-
-<Form version="1.6" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
-  <AuxValues>
-    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
-    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
-    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
-    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
-    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
-    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
-    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
-    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
-    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
-    <AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,24,0,0,1,-80"/>
-  </AuxValues>
-
-  <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout"/>
-  <SubComponents>
-    <Container class="javax.swing.JTabbedPane" name="resultsTabPanel">
-
-      <Layout class="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout"/>
-      <SubComponents>
-        <Container class="javax.swing.JPanel" name="objectTabPanel">
-          <Constraints>
-            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription">
-              <JTabbedPaneConstraints tabName="Object selection">
-                <Property name="tabTitle" type="java.lang.String" value="Object selection"/>
-              </JTabbedPaneConstraints>
-            </Constraint>
-          </Constraints>
-
-          <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout">
-            <Property name="axis" type="int" value="3"/>
-          </Layout>
-          <SubComponents>
-            <Container class="javax.swing.JPanel" name="refSetPanel">
-              <Properties>
-                <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
-                  <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
-                    <TitledBorder title="Target Selection"/>
-                  </Border>
-                </Property>
-              </Properties>
-
-              <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout"/>
-              <SubComponents>
-                <Component class="javax.swing.JButton" name="freezeMySetButton">
-                  <Properties>
-                    <Property name="text" type="java.lang.String" value="Freeze Selection"/>
-                  </Properties>
-                  <Events>
-                    <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="freezeTargetSelectionActionPerformed"/>
-                  </Events>
-                </Component>
-                <Container class="javax.swing.JPanel" name="jPanel3">
-
-                  <Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridLayout">
-                    <Property name="columns" type="int" value="2"/>
-                    <Property name="horizontalGap" type="int" value="2"/>
-                    <Property name="rows" type="int" value="0"/>
-                  </Layout>
-                  <SubComponents>
-                    <Component class="javax.swing.JLabel" name="jLabel2">
-                      <Properties>
-                        <Property name="text" type="java.lang.String" value="Layer"/>
-                      </Properties>
-                    </Component>
-                    <Component class="javax.swing.JLabel" name="myLayerLabel">
-                      <Properties>
-                        <Property name="text" type="java.lang.String" value="(invalid)"/>
-                      </Properties>
-                    </Component>
-                    <Component class="javax.swing.JLabel" name="jLabel1">
-                      <Properties>
-                        <Property name="text" type="java.lang.String" value="Nodes"/>
-                      </Properties>
-                    </Component>
-                    <Component class="javax.swing.JLabel" name="myNodeCountLabel">
-                      <Properties>
-                        <Property name="text" type="java.lang.String" value="0"/>
-                      </Properties>
-                    </Component>
-                    <Component class="javax.swing.JLabel" name="jLabel3">
-                      <Properties>
-                        <Property name="text" type="java.lang.String" value="Ways"/>
-                      </Properties>
-                    </Component>
-                    <Component class="javax.swing.JLabel" name="myWayCountLabel">
-                      <Properties>
-                        <Property name="text" type="java.lang.String" value="0"/>
-                      </Properties>
-                    </Component>
-                    <Component class="javax.swing.JLabel" name="jLabel4">
-                      <Properties>
-                        <Property name="text" type="java.lang.String" value="Relations"/>
-                      </Properties>
-                    </Component>
-                    <Component class="javax.swing.JLabel" name="myRelationCountLabel">
-                      <Properties>
-                        <Property name="text" type="java.lang.String" value="0"/>
-                      </Properties>
-                    </Component>
-                  </SubComponents>
-                </Container>
-                <Component class="javax.swing.JButton" name="restoreMySetButton">
-                  <Properties>
-                    <Property name="text" type="java.lang.String" value="Restore Selection"/>
-                  </Properties>
-                  <Events>
-                    <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="restoreMySetButtonActionPerformed"/>
-                  </Events>
-                </Component>
-              </SubComponents>
-            </Container>
-            <Container class="javax.swing.JPanel" name="nonRefSetPanel">
-              <Properties>
-                <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
-                  <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
-                    <TitledBorder title="Source Selection"/>
-                  </Border>
-                </Property>
-              </Properties>
-
-              <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout"/>
-              <SubComponents>
-                <Component class="javax.swing.JButton" name="freezeTheirSelectionButton">
-                  <Properties>
-                    <Property name="text" type="java.lang.String" value="Freeze Selection"/>
-                  </Properties>
-                  <Events>
-                    <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="freezeSourceSelectionActionPerformed"/>
-                  </Events>
-                </Component>
-                <Container class="javax.swing.JPanel" name="jPanel4">
-
-                  <Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridLayout">
-                    <Property name="columns" type="int" value="2"/>
-                    <Property name="horizontalGap" type="int" value="2"/>
-                    <Property name="rows" type="int" value="0"/>
-                  </Layout>
-                  <SubComponents>
-                    <Component class="javax.swing.JLabel" name="jLabel6">
-                      <Properties>
-                        <Property name="text" type="java.lang.String" value="Layer"/>
-                      </Properties>
-                    </Component>
-                    <Component class="javax.swing.JLabel" name="theirLayerLabel">
-                      <Properties>
-                        <Property name="text" type="java.lang.String" value="(invalid)"/>
-                      </Properties>
-                    </Component>
-                    <Component class="javax.swing.JLabel" name="jLabel7">
-                      <Properties>
-                        <Property name="text" type="java.lang.String" value="Nodes"/>
-                      </Properties>
-                    </Component>
-                    <Component class="javax.swing.JLabel" name="theirNodeCountLabel">
-                      <Properties>
-                        <Property name="text" type="java.lang.String" value="0"/>
-                      </Properties>
-                    </Component>
-                    <Component class="javax.swing.JLabel" name="jLabel9">
-                      <Properties>
-                        <Property name="text" type="java.lang.String" value="Ways"/>
-                      </Properties>
-                    </Component>
-                    <Component class="javax.swing.JLabel" name="theirWayCountLabel">
-                      <Properties>
-                        <Property name="text" type="java.lang.String" value="0"/>
-                      </Properties>
-                    </Component>
-                    <Component class="javax.swing.JLabel" name="jLabel5">
-                      <Properties>
-                        <Property name="text" type="java.lang.String" value="Relations"/>
-                      </Properties>
-                    </Component>
-                    <Component class="javax.swing.JLabel" name="theirRelationCountLabel">
-                      <Properties>
-                        <Property name="text" type="java.lang.String" value="0"/>
-                      </Properties>
-                    </Component>
-                  </SubComponents>
-                </Container>
-                <Component class="javax.swing.JButton" name="restoreTheirSetButton">
-                  <Properties>
-                    <Property name="text" type="java.lang.String" value="Restore Selection"/>
-                  </Properties>
-                  <Events>
-                    <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="restoreTheirSetButtonActionPerformed"/>
-                  </Events>
-                </Component>
-              </SubComponents>
-            </Container>
-            <Component class="javax.swing.JButton" name="objectTabCancelButton">
-              <Properties>
-                <Property name="text" type="java.lang.String" value="Cancel"/>
-              </Properties>
-              <Events>
-                <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="objectTabCancelButtonActionPerformed"/>
-              </Events>
-            </Component>
-            <Component class="javax.swing.JButton" name="objectTabNextButton">
-              <Properties>
-                <Property name="mnemonic" type="int" value="78"/>
-                <Property name="text" type="java.lang.String" value="Next"/>
-              </Properties>
-              <Events>
-                <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="objectTabNextButtonActionPerformed"/>
-              </Events>
-            </Component>
-          </SubComponents>
-        </Container>
-        <Container class="javax.swing.JPanel" name="criteriaTabPanel">
-          <Constraints>
-            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription">
-              <JTabbedPaneConstraints tabName="Matching criteria">
-                <Property name="tabTitle" type="java.lang.String" value="Matching criteria"/>
-              </JTabbedPaneConstraints>
-            </Constraint>
-          </Constraints>
-
-          <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout">
-            <Property name="axis" type="int" value="3"/>
-          </Layout>
-          <SubComponents>
-            <Container class="javax.swing.JPanel" name="jPanel2">
-              <Properties>
-                <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
-                  <Border info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
-                    <EtchetBorder/>
-                  </Border>
-                </Property>
-              </Properties>
-
-              <Layout>
-                <DimensionLayout dim="0">
-                  <Group type="103" groupAlignment="0" attributes="0">
-                      <Group type="102" attributes="0">
-                          <EmptySpace max="-2" attributes="0"/>
-                          <Component id="jCheckBox1" min="-2" max="-2" attributes="0"/>
-                          <EmptySpace pref="350" max="32767" attributes="0"/>
-                      </Group>
-                  </Group>
-                </DimensionLayout>
-                <DimensionLayout dim="1">
-                  <Group type="103" groupAlignment="0" attributes="0">
-                      <Group type="102" alignment="0" attributes="0">
-                          <EmptySpace max="-2" attributes="0"/>
-                          <Component id="jCheckBox1" min="-2" max="-2" attributes="0"/>
-                          <EmptySpace pref="195" max="32767" attributes="0"/>
-                      </Group>
-                  </Group>
-                </DimensionLayout>
-              </Layout>
-              <SubComponents>
-                <Component class="javax.swing.JCheckBox" name="jCheckBox1">
-                  <Properties>
-                    <Property name="selected" type="boolean" value="true"/>
-                    <Property name="text" type="java.lang.String" value="Distance"/>
-                    <Property name="enabled" type="boolean" value="false"/>
-                  </Properties>
-                  <Events>
-                    <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jCheckBox1ActionPerformed"/>
-                  </Events>
-                </Component>
-              </SubComponents>
-            </Container>
-            <Component class="javax.swing.JButton" name="criteriaTabConflateButton">
-              <Properties>
-                <Property name="mnemonic" type="int" value="102"/>
-                <Property name="text" type="java.lang.String" value="Conflate"/>
-              </Properties>
-              <Events>
-                <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="criteriaTabConflateButtonActionPerformed"/>
-              </Events>
-            </Component>
-          </SubComponents>
-        </Container>
-        <Container class="javax.swing.JPanel" name="resultsPanel">
-          <Constraints>
-            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription">
-              <JTabbedPaneConstraints tabName="Results">
-                <Property name="tabTitle" type="java.lang.String" value="Results"/>
-              </JTabbedPaneConstraints>
-            </Constraint>
-          </Constraints>
-
-          <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout">
-            <Property name="axis" type="int" value="3"/>
-          </Layout>
-          <SubComponents>
-            <Container class="javax.swing.JScrollPane" name="jScrollPane1">
-              <AuxValues>
-                <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
-              </AuxValues>
-
-              <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
-              <SubComponents>
-                <Component class="javax.swing.JTable" name="resultsTable">
-                  <Properties>
-                    <Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.editors2.TableModelEditor">
-                      <Table columnCount="5" rowCount="4">
-                        <Column editable="true" title="Mine" type="java.lang.Object"/>
-                        <Column editable="true" title="Theirs" type="java.lang.Object"/>
-                        <Column editable="true" title="Distance (m)" type="java.lang.Object"/>
-                        <Column editable="true" title="Cost" type="java.lang.Object"/>
-                        <Column editable="true" title="Tags" type="java.lang.Object"/>
-                      </Table>
-                    </Property>
-                    <Property name="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor">
-                      <JTableSelectionModel selectionMode="2"/>
-                    </Property>
-                  </Properties>
-                </Component>
-              </SubComponents>
-            </Container>
-            <Container class="javax.swing.JPanel" name="jPanel1">
-              <Properties>
-                <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
-                  <Border info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
-                    <EtchetBorder/>
-                  </Border>
-                </Property>
-              </Properties>
-
-              <Layout>
-                <DimensionLayout dim="0">
-                  <Group type="103" groupAlignment="0" attributes="0">
-                      <Group type="102" alignment="0" attributes="0">
-                          <EmptySpace max="-2" attributes="0"/>
-                          <Component id="jLabel8" min="-2" max="-2" attributes="0"/>
-                          <EmptySpace type="unrelated" max="-2" attributes="0"/>
-                          <Component id="replaceGeometryButton" min="-2" max="-2" attributes="0"/>
-                          <EmptySpace type="unrelated" max="-2" attributes="0"/>
-                          <Component id="useTheirTagsButton" min="-2" max="-2" attributes="0"/>
-                          <EmptySpace type="unrelated" max="-2" attributes="0"/>
-                          <Component id="jButton1" min="-2" max="-2" attributes="0"/>
-                          <EmptySpace pref="14" max="32767" attributes="0"/>
-                      </Group>
-                  </Group>
-                </DimensionLayout>
-                <DimensionLayout dim="1">
-                  <Group type="103" groupAlignment="0" attributes="0">
-                      <Group type="102" alignment="0" attributes="0">
-                          <EmptySpace max="-2" attributes="0"/>
-                          <Group type="103" groupAlignment="3" attributes="0">
-                              <Component id="jLabel8" alignment="3" min="-2" max="-2" attributes="0"/>
-                              <Component id="replaceGeometryButton" alignment="3" min="-2" max="-2" attributes="0"/>
-                              <Component id="useTheirTagsButton" alignment="3" min="-2" max="-2" attributes="0"/>
-                              <Component id="jButton1" alignment="3" min="-2" max="-2" attributes="0"/>
-                          </Group>
-                          <EmptySpace max="32767" attributes="0"/>
-                      </Group>
-                  </Group>
-                </DimensionLayout>
-              </Layout>
-              <SubComponents>
-                <Component class="javax.swing.JButton" name="replaceGeometryButton">
-                  <Properties>
-                    <Property name="text" type="java.lang.String" value="Replace Geometry"/>
-                  </Properties>
-                  <Events>
-                    <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="replaceGeometryButtonActionPerformed"/>
-                  </Events>
-                </Component>
-                <Component class="javax.swing.JLabel" name="jLabel8">
-                  <Properties>
-                    <Property name="text" type="java.lang.String" value="Resolve using:"/>
-                  </Properties>
-                </Component>
-                <Component class="javax.swing.JButton" name="useTheirTagsButton">
-                  <Properties>
-                    <Property name="text" type="java.lang.String" value="Merge tags"/>
-                  </Properties>
-                  <Events>
-                    <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="useTheirTagsButtonActionPerformed"/>
-                  </Events>
-                </Component>
-                <Component class="javax.swing.JButton" name="jButton1">
-                  <Properties>
-                    <Property name="text" type="java.lang.String" value="Not a match"/>
-                    <Property name="enabled" type="boolean" value="false"/>
-                  </Properties>
-                </Component>
-              </SubComponents>
-            </Container>
-            <Component class="javax.swing.JButton" name="resolveButton">
-              <Properties>
-                <Property name="text" type="java.lang.String" value="Resolve"/>
-              </Properties>
-              <Events>
-                <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="resolveButtonActionPerformed"/>
-              </Events>
-            </Component>
-          </SubComponents>
-        </Container>
-      </SubComponents>
-    </Container>
-  </SubComponents>
-</Form>
Index: applications/editors/josm/plugins/conflation/src/org/openstreetmap/josm/plugins/conflation/ConflationOptionsPanel.java
===================================================================
--- applications/editors/josm/plugins/conflation/src/org/openstreetmap/josm/plugins/conflation/ConflationOptionsPanel.java	(revision 27852)
+++ 	(revision )
@@ -1,828 +1,0 @@
-// License: GPL. Copyright 2011 by Josh Doe and others
-
-/*
- * ConflationPanel.java
- *
- * Created on Apr 26, 2011, 10:47:18 PM
- */
-
-package org.openstreetmap.josm.plugins.conflation;
-
-import java.awt.Component;
-import java.util.*;
-import javax.swing.DefaultListCellRenderer;
-import javax.swing.Icon;
-import javax.swing.JLabel;
-import javax.swing.JList;
-import javax.swing.JOptionPane;
-import javax.swing.JTable;
-import javax.swing.ListSelectionModel;
-import javax.swing.event.ListSelectionEvent;
-import javax.swing.event.ListSelectionListener;
-import javax.swing.table.AbstractTableModel;
-import javax.swing.table.TableCellRenderer;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.command.Command;
-import org.openstreetmap.josm.data.conflict.ConflictCollection;
-import org.openstreetmap.josm.data.conflict.IConflictListener;
-import org.openstreetmap.josm.data.coor.EastNorth;
-import org.openstreetmap.josm.data.coor.LatLon;
-import org.openstreetmap.josm.data.osm.DataSet;
-import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.data.osm.TagCollection;
-import org.openstreetmap.josm.data.osm.event.*;
-import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
-import org.openstreetmap.josm.gui.OsmPrimitivRenderer;
-import org.openstreetmap.josm.gui.layer.Layer;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
-
-import utilsplugin2.dumbutils.ReplaceGeometryAction;
-
-/**
- *
- * @author Josh
- */
-public class ConflationOptionsPanel extends javax.swing.JPanel implements DataSetListener {
-    ConflationOptionsDialog dlg = null;
-    ConflationLayer conflationLayer = null;
-    DataSet targetDataSet = null;
-    DataSet sourceDataSet = null;
-    ArrayList<OsmPrimitive> targetSelection = null;
-    ArrayList<OsmPrimitive> sourceSelection = null;
-    OsmDataLayer targetLayer = null;
-    OsmDataLayer sourceLayer = null;
-    MatchTableModel tableModel;
-    List<ConflationCandidate> candidates = null;
-
-    /** Creates new form ConflationPanel */
-    public ConflationOptionsPanel(ConflationOptionsDialog dlg, List<OsmDataLayer> layers) {
-        initComponents();
-
-        // add selection handler, to center/zoom view
-        resultsTable.getSelectionModel().addListSelectionListener(
-                new MatchListSelectionHandler());
-        resultsTable.getColumnModel().getSelectionModel().addListSelectionListener(
-                new MatchListSelectionHandler());
-
-        // FIXME: doesn't work right now
-        resultsTable.getColumnModel().getColumn(0).setCellRenderer(new OsmPrimitivRenderer());
-        resultsTable.getColumnModel().getColumn(1).setCellRenderer(new OsmPrimitivRenderer());
-        resultsTable.getColumnModel().getColumn(4).setCellRenderer(new ColorTableCellRenderer("Tags"));
-
-        this.dlg = dlg;
-
-        // set layer names to comboboxes
-//        if (layers != null && layers.size() > 0) {
-//            refLayerComboBox.setModel(new javax.swing.DefaultComboBoxModel(layers.toArray()));
-//            refLayerComboBox.setRenderer(new LayerListCellRenderer());
-//            nonRefLayerComboBox.setModel(new javax.swing.DefaultComboBoxModel(layers.toArray()));
-//            nonRefLayerComboBox.setRenderer(new LayerListCellRenderer());
-//        }
-
-    }
-
-    /** This method is called from within the constructor to
-     * initialize the form.
-     * WARNING: Do NOT modify this code. The content of this method is
-     * always regenerated by the Form Editor.
-     */
-    @SuppressWarnings("unchecked")
-    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
-    private void initComponents() {
-
-        resultsTabPanel = new javax.swing.JTabbedPane();
-        objectTabPanel = new javax.swing.JPanel();
-        refSetPanel = new javax.swing.JPanel();
-        freezeMySetButton = new javax.swing.JButton();
-        jPanel3 = new javax.swing.JPanel();
-        jLabel2 = new javax.swing.JLabel();
-        myLayerLabel = new javax.swing.JLabel();
-        jLabel1 = new javax.swing.JLabel();
-        myNodeCountLabel = new javax.swing.JLabel();
-        jLabel3 = new javax.swing.JLabel();
-        myWayCountLabel = new javax.swing.JLabel();
-        jLabel4 = new javax.swing.JLabel();
-        myRelationCountLabel = new javax.swing.JLabel();
-        restoreMySetButton = new javax.swing.JButton();
-        nonRefSetPanel = new javax.swing.JPanel();
-        freezeTheirSelectionButton = new javax.swing.JButton();
-        jPanel4 = new javax.swing.JPanel();
-        jLabel6 = new javax.swing.JLabel();
-        theirLayerLabel = new javax.swing.JLabel();
-        jLabel7 = new javax.swing.JLabel();
-        theirNodeCountLabel = new javax.swing.JLabel();
-        jLabel9 = new javax.swing.JLabel();
-        theirWayCountLabel = new javax.swing.JLabel();
-        jLabel5 = new javax.swing.JLabel();
-        theirRelationCountLabel = new javax.swing.JLabel();
-        restoreTheirSetButton = new javax.swing.JButton();
-        objectTabCancelButton = new javax.swing.JButton();
-        objectTabNextButton = new javax.swing.JButton();
-        criteriaTabPanel = new javax.swing.JPanel();
-        jPanel2 = new javax.swing.JPanel();
-        jCheckBox1 = new javax.swing.JCheckBox();
-        criteriaTabConflateButton = new javax.swing.JButton();
-        resultsPanel = new javax.swing.JPanel();
-        jScrollPane1 = new javax.swing.JScrollPane();
-        resultsTable = new javax.swing.JTable();
-        jPanel1 = new javax.swing.JPanel();
-        replaceGeometryButton = new javax.swing.JButton();
-        jLabel8 = new javax.swing.JLabel();
-        useTheirTagsButton = new javax.swing.JButton();
-        jButton1 = new javax.swing.JButton();
-        resolveButton = new javax.swing.JButton();
-
-        setLayout(new javax.swing.BoxLayout(this, javax.swing.BoxLayout.LINE_AXIS));
-
-        objectTabPanel.setLayout(new javax.swing.BoxLayout(objectTabPanel, javax.swing.BoxLayout.PAGE_AXIS));
-
-        refSetPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Target Selection"));
-        refSetPanel.setLayout(new javax.swing.BoxLayout(refSetPanel, javax.swing.BoxLayout.LINE_AXIS));
-
-        freezeMySetButton.setText("Freeze Selection");
-        freezeMySetButton.addActionListener(new java.awt.event.ActionListener() {
-            public void actionPerformed(java.awt.event.ActionEvent evt) {
-                freezeTargetSelectionActionPerformed(evt);
-            }
-        });
-        refSetPanel.add(freezeMySetButton);
-
-        jPanel3.setLayout(new java.awt.GridLayout(0, 2, 2, 0));
-
-        jLabel2.setText("Layer");
-        jPanel3.add(jLabel2);
-
-        myLayerLabel.setText("(invalid)");
-        jPanel3.add(myLayerLabel);
-
-        jLabel1.setText("Nodes");
-        jPanel3.add(jLabel1);
-
-        myNodeCountLabel.setText("0");
-        jPanel3.add(myNodeCountLabel);
-
-        jLabel3.setText("Ways");
-        jPanel3.add(jLabel3);
-
-        myWayCountLabel.setText("0");
-        jPanel3.add(myWayCountLabel);
-
-        jLabel4.setText("Relations");
-        jPanel3.add(jLabel4);
-
-        myRelationCountLabel.setText("0");
-        jPanel3.add(myRelationCountLabel);
-
-        refSetPanel.add(jPanel3);
-
-        restoreMySetButton.setText("Restore Selection");
-        restoreMySetButton.addActionListener(new java.awt.event.ActionListener() {
-            public void actionPerformed(java.awt.event.ActionEvent evt) {
-                restoreMySetButtonActionPerformed(evt);
-            }
-        });
-        refSetPanel.add(restoreMySetButton);
-
-        objectTabPanel.add(refSetPanel);
-
-        nonRefSetPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Source Selection"));
-        nonRefSetPanel.setLayout(new javax.swing.BoxLayout(nonRefSetPanel, javax.swing.BoxLayout.LINE_AXIS));
-
-        freezeTheirSelectionButton.setText("Freeze Selection");
-        freezeTheirSelectionButton.addActionListener(new java.awt.event.ActionListener() {
-            public void actionPerformed(java.awt.event.ActionEvent evt) {
-                freezeSourceSelectionActionPerformed(evt);
-            }
-        });
-        nonRefSetPanel.add(freezeTheirSelectionButton);
-
-        jPanel4.setLayout(new java.awt.GridLayout(0, 2, 2, 0));
-
-        jLabel6.setText("Layer");
-        jPanel4.add(jLabel6);
-
-        theirLayerLabel.setText("(invalid)");
-        jPanel4.add(theirLayerLabel);
-
-        jLabel7.setText("Nodes");
-        jPanel4.add(jLabel7);
-
-        theirNodeCountLabel.setText("0");
-        jPanel4.add(theirNodeCountLabel);
-
-        jLabel9.setText("Ways");
-        jPanel4.add(jLabel9);
-
-        theirWayCountLabel.setText("0");
-        jPanel4.add(theirWayCountLabel);
-
-        jLabel5.setText("Relations");
-        jPanel4.add(jLabel5);
-
-        theirRelationCountLabel.setText("0");
-        jPanel4.add(theirRelationCountLabel);
-
-        nonRefSetPanel.add(jPanel4);
-
-        restoreTheirSetButton.setText("Restore Selection");
-        restoreTheirSetButton.addActionListener(new java.awt.event.ActionListener() {
-            public void actionPerformed(java.awt.event.ActionEvent evt) {
-                restoreTheirSetButtonActionPerformed(evt);
-            }
-        });
-        nonRefSetPanel.add(restoreTheirSetButton);
-
-        objectTabPanel.add(nonRefSetPanel);
-
-        objectTabCancelButton.setText("Cancel");
-        objectTabCancelButton.addActionListener(new java.awt.event.ActionListener() {
-            public void actionPerformed(java.awt.event.ActionEvent evt) {
-                objectTabCancelButtonActionPerformed(evt);
-            }
-        });
-        objectTabPanel.add(objectTabCancelButton);
-
-        objectTabNextButton.setMnemonic('N');
-        objectTabNextButton.setText("Next");
-        objectTabNextButton.addActionListener(new java.awt.event.ActionListener() {
-            public void actionPerformed(java.awt.event.ActionEvent evt) {
-                objectTabNextButtonActionPerformed(evt);
-            }
-        });
-        objectTabPanel.add(objectTabNextButton);
-
-        resultsTabPanel.addTab("Object selection", objectTabPanel);
-
-        criteriaTabPanel.setLayout(new javax.swing.BoxLayout(criteriaTabPanel, javax.swing.BoxLayout.PAGE_AXIS));
-
-        jPanel2.setBorder(javax.swing.BorderFactory.createEtchedBorder());
-
-        jCheckBox1.setSelected(true);
-        jCheckBox1.setText("Distance");
-        jCheckBox1.setEnabled(false);
-        jCheckBox1.addActionListener(new java.awt.event.ActionListener() {
-            public void actionPerformed(java.awt.event.ActionEvent evt) {
-                jCheckBox1ActionPerformed(evt);
-            }
-        });
-
-        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
-        jPanel2.setLayout(jPanel2Layout);
-        jPanel2Layout.setHorizontalGroup(
-            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(jPanel2Layout.createSequentialGroup()
-                .addContainerGap()
-                .addComponent(jCheckBox1)
-                .addContainerGap(350, Short.MAX_VALUE))
-        );
-        jPanel2Layout.setVerticalGroup(
-            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(jPanel2Layout.createSequentialGroup()
-                .addContainerGap()
-                .addComponent(jCheckBox1)
-                .addContainerGap(195, Short.MAX_VALUE))
-        );
-
-        criteriaTabPanel.add(jPanel2);
-
-        criteriaTabConflateButton.setMnemonic('f');
-        criteriaTabConflateButton.setText("Conflate");
-        criteriaTabConflateButton.addActionListener(new java.awt.event.ActionListener() {
-            public void actionPerformed(java.awt.event.ActionEvent evt) {
-                criteriaTabConflateButtonActionPerformed(evt);
-            }
-        });
-        criteriaTabPanel.add(criteriaTabConflateButton);
-
-        resultsTabPanel.addTab("Matching criteria", criteriaTabPanel);
-
-        resultsPanel.setLayout(new javax.swing.BoxLayout(resultsPanel, javax.swing.BoxLayout.PAGE_AXIS));
-
-        resultsTable.setModel(new javax.swing.table.DefaultTableModel(
-            new Object [][] {
-                {null, null, null, null, null},
-                {null, null, null, null, null},
-                {null, null, null, null, null},
-                {null, null, null, null, null}
-            },
-            new String [] {
-                "Mine", "Theirs", "Distance (m)", "Cost", "Tags"
-            }
-        ));
-        resultsTable.setSelectionMode(javax.swing.ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
-        jScrollPane1.setViewportView(resultsTable);
-
-        resultsPanel.add(jScrollPane1);
-
-        jPanel1.setBorder(javax.swing.BorderFactory.createEtchedBorder());
-
-        replaceGeometryButton.setText("Replace Geometry");
-        replaceGeometryButton.addActionListener(new java.awt.event.ActionListener() {
-            public void actionPerformed(java.awt.event.ActionEvent evt) {
-                replaceGeometryButtonActionPerformed(evt);
-            }
-        });
-
-        jLabel8.setText("Resolve using:");
-
-        useTheirTagsButton.setText("Merge tags");
-        useTheirTagsButton.addActionListener(new java.awt.event.ActionListener() {
-            public void actionPerformed(java.awt.event.ActionEvent evt) {
-                useTheirTagsButtonActionPerformed(evt);
-            }
-        });
-
-        jButton1.setText("Not a match");
-        jButton1.setEnabled(false);
-
-        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
-        jPanel1.setLayout(jPanel1Layout);
-        jPanel1Layout.setHorizontalGroup(
-            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(jPanel1Layout.createSequentialGroup()
-                .addContainerGap()
-                .addComponent(jLabel8)
-                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
-                .addComponent(replaceGeometryButton)
-                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
-                .addComponent(useTheirTagsButton)
-                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
-                .addComponent(jButton1)
-                .addContainerGap(14, Short.MAX_VALUE))
-        );
-        jPanel1Layout.setVerticalGroup(
-            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(jPanel1Layout.createSequentialGroup()
-                .addContainerGap()
-                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
-                    .addComponent(jLabel8)
-                    .addComponent(replaceGeometryButton)
-                    .addComponent(useTheirTagsButton)
-                    .addComponent(jButton1))
-                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
-        );
-
-        resultsPanel.add(jPanel1);
-
-        resolveButton.setText("Resolve");
-        resolveButton.addActionListener(new java.awt.event.ActionListener() {
-            public void actionPerformed(java.awt.event.ActionEvent evt) {
-                resolveButtonActionPerformed(evt);
-            }
-        });
-        resultsPanel.add(resolveButton);
-
-        resultsTabPanel.addTab("Results", resultsPanel);
-
-        add(resultsTabPanel);
-    }// </editor-fold>//GEN-END:initComponents
-
-    private void objectTabCancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_objectTabCancelButtonActionPerformed
-        dlg.setCanceled(true);
-        dlg.setVisible(false);
-    }//GEN-LAST:event_objectTabCancelButtonActionPerformed
-
-    private void criteriaTabConflateButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_criteriaTabConflateButtonActionPerformed
-
-        // some initialization
-        int n = targetSelection.size();
-        int m = sourceSelection.size();
-        int maxLen = Math.max(n, m);
-        double cost[][] = new double[maxLen][maxLen];
-
-        // calculate cost matrix
-        for (int i = 0; i < n; i++) {
-            for (int j = 0; j < m; j++) {
-                cost[i][j] = calcCost(targetSelection.get(i), sourceSelection.get(j));
-            }
-        }
-
-        // perform assignment using Hungarian algorithm
-        int[][] assignment = HungarianAlgorithm.hgAlgorithm(cost, "min");
-        OsmPrimitive target, source;
-        candidates = new LinkedList<ConflationCandidate>();
-        for (int i = 0; i < maxLen; i++) {
-            int tgtIdx = assignment[i][0];
-            int srcIdx = assignment[i][1];
-            if (tgtIdx < n)
-                target = targetSelection.get(tgtIdx);
-            else
-                target = null;
-            if (srcIdx < m)
-                source = sourceSelection.get(srcIdx);
-            else
-                source = null;
-
-            if (target != null && source != null) {
-                // TODO: do something!
-                candidates.add(new ConflationCandidate(source, target, cost[tgtIdx][srcIdx]));
-            }
-        }
-
-        // add conflation layer
-        try {
-            conflationLayer = new ConflationLayer(targetLayer.data, candidates);
-            Main.main.addLayer(conflationLayer);
-        } catch (Exception ex) {
-            JOptionPane.showMessageDialog(Main.parent, ex.toString(),
-                    "Error adding conflation layer", JOptionPane.ERROR_MESSAGE);
-        }
-        tableModel = new MatchTableModel();
-        resultsTable.setModel(tableModel);
-
-        // print list of matched pairsalong with distance
-        // upon selection of one pair, highlight them and draw arrow
-        
-        if (resultsPanel != null)
-            resultsTabPanel.setSelectedComponent(resultsPanel);
-    }//GEN-LAST:event_criteriaTabConflateButtonActionPerformed
-
-    private void objectTabNextButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_objectTabNextButtonActionPerformed
-        if (criteriaTabPanel != null)
-            resultsTabPanel.setSelectedComponent(criteriaTabPanel);
-    }//GEN-LAST:event_objectTabNextButtonActionPerformed
-
-    private void restoreMySetButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_restoreMySetButtonActionPerformed
-        if (targetLayer != null && targetDataSet != null && targetSelection != null && !targetSelection.isEmpty()) {
-            Main.map.mapView.setActiveLayer(targetLayer);
-            targetLayer.setVisible(true);
-            targetDataSet.setSelected(targetSelection);
-        }
-    }//GEN-LAST:event_restoreMySetButtonActionPerformed
-
-    private void restoreTheirSetButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_restoreTheirSetButtonActionPerformed
-        if (sourceLayer != null && sourceDataSet != null && sourceSelection != null && !sourceSelection.isEmpty()) {
-            Main.map.mapView.setActiveLayer(sourceLayer);
-            sourceLayer.setVisible(true);
-            sourceDataSet.setSelected(sourceSelection);
-        }
-    }//GEN-LAST:event_restoreTheirSetButtonActionPerformed
-
-    private void freezeTargetSelectionActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_freezeTargetSelectionActionPerformed
-        if (targetDataSet != null && targetDataSet == Main.main.getCurrentDataSet()) {
-            targetDataSet.removeDataSetListener(this);
-        }
-        targetDataSet = Main.main.getCurrentDataSet();
-        targetDataSet.addDataSetListener(this);
-        targetLayer = Main.main.getEditLayer();
-        if (targetDataSet == null || targetLayer == null) {
-            JOptionPane.showMessageDialog(Main.parent, tr("No valid OSM data layer present."),
-                    tr("Error freezing selection"), JOptionPane.ERROR_MESSAGE);
-            return;
-        }
-        targetSelection = new ArrayList<OsmPrimitive>(targetDataSet.getSelected());
-        if (targetSelection.isEmpty()) {
-            JOptionPane.showMessageDialog(Main.parent, tr("Nothing is selected, please try again."),
-                    tr("Empty selection"), JOptionPane.ERROR_MESSAGE);
-            return;
-        }
-
-        int numNodes = 0;
-        int numWays = 0;
-        int numRelations = 0;
-        for (OsmPrimitive p: targetSelection) {
-            switch(p.getType()) {
-            case NODE: numNodes++; break;
-            case WAY: numWays++; break;
-            case RELATION: numRelations++; break;
-            }
-        }
-
-        myLayerLabel.setText(targetLayer.getName());
-        myNodeCountLabel.setText(Integer.toString(numNodes));
-        myWayCountLabel.setText(Integer.toString(numWays));
-        myRelationCountLabel.setText(Integer.toString(numRelations));
-    }//GEN-LAST:event_freezeTargetSelectionActionPerformed
-
-    private void freezeSourceSelectionActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_freezeSourceSelectionActionPerformed
-        if (sourceDataSet != null && sourceDataSet == Main.main.getCurrentDataSet()) {
-            sourceDataSet.removeDataSetListener(this);
-        }
-        sourceDataSet = Main.main.getCurrentDataSet();
-        sourceDataSet.addDataSetListener(this);
-        sourceLayer = Main.main.getEditLayer();
-        if (sourceDataSet == null || sourceLayer == null) {
-            JOptionPane.showMessageDialog(Main.parent, tr("No valid OSM data layer present."),
-                    tr("Error freezing selection"), JOptionPane.ERROR_MESSAGE);
-            return;
-        }
-        sourceSelection = new ArrayList<OsmPrimitive>(sourceDataSet.getSelected());
-        if (sourceSelection.isEmpty()) {
-            JOptionPane.showMessageDialog(Main.parent, tr("Nothing is selected, please try again."),
-                    tr("Empty selection"), JOptionPane.ERROR_MESSAGE);
-            return;
-        }
-
-        int numNodes = 0;
-        int numWays = 0;
-        int numRelations = 0;
-        for (OsmPrimitive p: sourceSelection) {
-            switch(p.getType()) {
-            case NODE: numNodes++; break;
-            case WAY: numWays++; break;
-            case RELATION: numRelations++; break;
-            }
-        }
-
-        theirLayerLabel.setText(sourceLayer.getName());
-        theirNodeCountLabel.setText(Integer.toString(numNodes));
-        theirWayCountLabel.setText(Integer.toString(numWays));
-        theirRelationCountLabel.setText(Integer.toString(numRelations));
-    }//GEN-LAST:event_freezeSourceSelectionActionPerformed
-
-    private void jCheckBox1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jCheckBox1ActionPerformed
-        // TODO add your handling code here:
-    }//GEN-LAST:event_jCheckBox1ActionPerformed
-
-    private void resolveButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_resolveButtonActionPerformed
-        // FIXME: perform replace geometry
-        //Main.main.undoRedo.add(cmd);
-    }//GEN-LAST:event_resolveButtonActionPerformed
-
-    private void replaceGeometryButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_replaceGeometryButtonActionPerformed
-        ReplaceGeometryAction rg = new ReplaceGeometryAction();
-        ConflationCandidate c = conflationLayer.getSelectedCandidate();
-        rg.replace(c.getSource(), c.getTarget());
-    }//GEN-LAST:event_replaceGeometryButtonActionPerformed
-
-    private void useTheirTagsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_useTheirTagsButtonActionPerformed
-        // TODO add your handling code here:
-    }//GEN-LAST:event_useTheirTagsButtonActionPerformed
-
-    static public class LayerListCellRenderer extends DefaultListCellRenderer {
-        @Override
-        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
-                boolean cellHasFocus) {
-            Layer layer = (Layer) value;
-            JLabel label = (JLabel) super.getListCellRendererComponent(list, layer.getName(), index, isSelected,
-                    cellHasFocus);
-            Icon icon = layer.getIcon();
-            label.setIcon(icon);
-            label.setToolTipText(layer.getToolTipText());
-            return label;
-        }
-    }
-
-
-    public static EastNorth getCenter(OsmPrimitive prim) {
-            LatLon center = prim.getBBox().getTopLeft().getCenter(prim.getBBox().getBottomRight());
-            return Main.map.mapView.getProjection().latlon2eastNorth(center);
-    }
-
-    /**
-     * Calculate the cost of a pair of <code>OsmPrimitive</code>'s. A
-     * simple cost consisting of the Euclidean distance is used
-     * now, later we can also use dissimilarity between tags.
-     *
-     * @param   source      the reference <code>OsmPrimitive</code>.
-     * @param   target   the non-reference <code>OsmPrimitive</code>.
-     */
-    public double calcCost(OsmPrimitive source, OsmPrimitive target) {
-        double dist;
-        try {
-            dist = getCenter(source).distance(getCenter(target));
-        } catch (Exception e) {
-            dist = 1000; // FIXME: what number to use?
-        }
-
-        // TODO: use other "distance" measures, i.e. matching tags
-        return dist;
-    }
-
-    class MatchTableModel extends AbstractTableModel {
-
-        private String[] columnNames = {"Mine", "Theirs", "Distance (m)", "Cost", "Tags"};
-
-        public int getColumnCount() {
-            return columnNames.length;
-        }
-
-        public int getRowCount() {
-            return candidates.size();
-        }
-
-        @Override
-        public String getColumnName(int col) {
-            return columnNames[col];
-        }
-
-        public Object getValueAt(int row, int col) {
-            ConflationCandidate c = candidates.get(row);
-            if (col == 0)
-                return c.getSource();
-            else if (col == 1)
-                return c.getTarget();
-            else if (col == 2)
-                return c.getDistance();
-            else if (col == 3)
-                return c.getCost();
-            if (col == 4) {
-                HashSet<OsmPrimitive> set = new HashSet<OsmPrimitive>();
-                set.add(c.getSource());
-                set.add(c.getTarget());
-                TagCollection tags = TagCollection.unionOfAllPrimitives(set);
-                Set<String> keys = tags.getKeysWithMultipleValues();
-                if (keys.isEmpty())
-                    return "No conflicts!";
-                else
-                    return "Conflicts!";
-
-            }
-            else
-                return 0;
-        }
-
-        @Override
-        public Class getColumnClass(int c) {
-            return getValueAt(0, c).getClass();
-        }
-    }
-
-    class ColorTableCellRenderer extends JLabel implements TableCellRenderer {
-        private String columnName;
-
-        public ColorTableCellRenderer(String column) {
-            this.columnName = column;
-            setOpaque(true);
-        }
-
-        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
-            Object columnValue = table.getValueAt(row, table.getColumnModel().getColumnIndex(columnName));
-
-            if (value != null) {
-                setText(value.toString());
-            }
-            if (isSelected) {
-                setBackground(table.getSelectionBackground());
-                setForeground(table.getSelectionForeground());
-            } else {
-                setBackground(table.getBackground());
-                setForeground(table.getForeground());
-                if (columnValue.equals("Conflicts!")) {
-                    setBackground(java.awt.Color.red);
-                }
-                else {
-                    setBackground(java.awt.Color.green);
-                }
-            }
-            return this;
-        }
-    }
-
-    class MatchListSelectionHandler implements ListSelectionListener {
-
-        public void valueChanged(ListSelectionEvent e) {
-            ListSelectionModel lsm = (ListSelectionModel) e.getSource();
-
-            int firstIndex = lsm.getMinSelectionIndex();
-            int lastIndex = lsm.getMaxSelectionIndex();
-            boolean isAdjusting = e.getValueIsAdjusting();
-            if (isAdjusting)
-                return;
-
-            // only one item selected, show tags and zoom/center map
-            if (!lsm.isSelectionEmpty() && firstIndex == lastIndex && firstIndex < candidates.size()) {
-                ConflationCandidate c = candidates.get(firstIndex);
-                
-                conflationLayer.setSelectedCandidate(c);
-                
-                targetDataSet.setSelected(Arrays.asList(c.getTarget(), c.getSource()));
-                
-                ArrayList<OsmPrimitive> sel = new ArrayList<OsmPrimitive>();
-                sel.add(c.getSource());
-                sel.add(c.getTarget());
-
-                BoundingXYVisitor box = new BoundingXYVisitor();
-                box.computeBoundingBox(sel);
-                if (box.getBounds() == null) {
-                    return;
-                }
-                box.enlargeBoundingBox();
-                Main.map.mapView.recalculateCenterScale(box);
-            }
-
-        }
-    }
-
-    public final void refreshView() {
-        // TODO: should tell what rows changed
-        tableModel.fireTableDataChanged();
-    }
-
-    @Override
-    public void primitivesAdded(PrimitivesAddedEvent event) {
-    }
-
-    @Override
-    public void primitivesRemoved(PrimitivesRemovedEvent event) {
-        List<? extends OsmPrimitive> prims = event.getPrimitives();
-        for (OsmPrimitive p : prims) {
-            for (ConflationCandidate c : candidates) {
-                if (c.getSource().equals(p) || c.getTarget().equals(p)) {
-                    candidates.remove(c);
-                    break;
-                }
-            }
-        }
-        refreshView();
-    }
-    
-    @Override
-    public void tagsChanged(TagsChangedEvent event) {}
-    
-    @Override
-    public void nodeMoved(NodeMovedEvent event) {}
-        
-    @Override
-    public void wayNodesChanged(WayNodesChangedEvent event) {}
-
-    @Override
-    public void relationMembersChanged(RelationMembersChangedEvent event) {}
-
-    @Override
-    public void otherDatasetChange(AbstractDatasetChangedEvent event) {}
-
-    @Override
-    public void dataChanged(DataChangedEvent event) {}
-
-    public class ConflationCandidate {
-        protected OsmPrimitive source;
-        protected OsmPrimitive target;
-        protected double cost;
-        protected double distance;
-        
-        public ConflationCandidate(OsmPrimitive source, OsmPrimitive target, double cost) {
-            if (source == null || target == null) {
-                throw new IllegalArgumentException("Invalid source or target");
-            }
-            this.source = source;
-            this.target = target;
-            this.cost = cost;
-            // TODO: use distance calculated in cost function, and make sure it's in meters?
-            this.distance = getCenter(source).distance(getCenter(target));
-        }
-        
-        public OsmPrimitive getSource() {
-            return source;
-        }
-        
-        public OsmPrimitive getTarget() {
-            return target;
-        }
-
-        private Object getCost() {
-            return cost;
-        }
-
-        private Object getDistance() {
-            return distance;
-        }
-    }
-
-    // Variables declaration - do not modify//GEN-BEGIN:variables
-    private javax.swing.JButton criteriaTabConflateButton;
-    private javax.swing.JPanel criteriaTabPanel;
-    private javax.swing.JButton freezeMySetButton;
-    private javax.swing.JButton freezeTheirSelectionButton;
-    private javax.swing.JButton jButton1;
-    private javax.swing.JCheckBox jCheckBox1;
-    private javax.swing.JLabel jLabel1;
-    private javax.swing.JLabel jLabel2;
-    private javax.swing.JLabel jLabel3;
-    private javax.swing.JLabel jLabel4;
-    private javax.swing.JLabel jLabel5;
-    private javax.swing.JLabel jLabel6;
-    private javax.swing.JLabel jLabel7;
-    private javax.swing.JLabel jLabel8;
-    private javax.swing.JLabel jLabel9;
-    private javax.swing.JPanel jPanel1;
-    private javax.swing.JPanel jPanel2;
-    private javax.swing.JPanel jPanel3;
-    private javax.swing.JPanel jPanel4;
-    private javax.swing.JScrollPane jScrollPane1;
-    private javax.swing.JLabel myLayerLabel;
-    private javax.swing.JLabel myNodeCountLabel;
-    private javax.swing.JLabel myRelationCountLabel;
-    private javax.swing.JLabel myWayCountLabel;
-    private javax.swing.JPanel nonRefSetPanel;
-    private javax.swing.JButton objectTabCancelButton;
-    private javax.swing.JButton objectTabNextButton;
-    private javax.swing.JPanel objectTabPanel;
-    private javax.swing.JPanel refSetPanel;
-    private javax.swing.JButton replaceGeometryButton;
-    private javax.swing.JButton resolveButton;
-    private javax.swing.JButton restoreMySetButton;
-    private javax.swing.JButton restoreTheirSetButton;
-    private javax.swing.JPanel resultsPanel;
-    private javax.swing.JTabbedPane resultsTabPanel;
-    private javax.swing.JTable resultsTable;
-    private javax.swing.JLabel theirLayerLabel;
-    private javax.swing.JLabel theirNodeCountLabel;
-    private javax.swing.JLabel theirRelationCountLabel;
-    private javax.swing.JLabel theirWayCountLabel;
-    private javax.swing.JButton useTheirTagsButton;
-    // End of variables declaration//GEN-END:variables
-
-}
Index: applications/editors/josm/plugins/conflation/src/org/openstreetmap/josm/plugins/conflation/ConflationPlugin.java
===================================================================
--- applications/editors/josm/plugins/conflation/src/org/openstreetmap/josm/plugins/conflation/ConflationPlugin.java	(revision 27852)
+++ applications/editors/josm/plugins/conflation/src/org/openstreetmap/josm/plugins/conflation/ConflationPlugin.java	(revision 27959)
@@ -2,24 +2,15 @@
 package org.openstreetmap.josm.plugins.conflation;
 
-import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
-import static org.openstreetmap.josm.tools.I18n.marktr;
-import static org.openstreetmap.josm.tools.I18n.tr;
-
 import java.awt.event.KeyEvent;
-import java.io.IOException;
-import java.util.logging.FileHandler;
-import java.util.logging.Logger;
-import javax.swing.JMenu;
-import javax.swing.JOptionPane;
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.gui.MainMenu;
+import org.openstreetmap.josm.gui.MapFrame;
 import org.openstreetmap.josm.plugins.Plugin;
 import org.openstreetmap.josm.plugins.PluginInformation;
+import org.openstreetmap.josm.tools.Shortcut;
 
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 public class ConflationPlugin extends Plugin {
 
-    ConflationAction action = null;
-    Logger logger;
+    private ConflationToggleDialog dialog = null;
 
     /**
@@ -28,24 +19,19 @@
     public ConflationPlugin(PluginInformation info) {
         super(info);
+    }
 
-        try {
-            logger = Logger.getLogger(ConflationPlugin.class.getName());
-            FileHandler fh = new FileHandler("C:/temp/log.txt");
-            logger.addHandler(fh);
-        }
-        catch (IOException e) {
-            JOptionPane.showMessageDialog(Main.parent, "Failed to create log file",
-                    "Failed to create logger", JOptionPane.ERROR_MESSAGE);
-        }
-
-        try {
-            JMenu conflationMenu = Main.main.menu.addMenu(marktr("Conflation"), KeyEvent.VK_R,
-                    Main.main.menu.defaultMenuPos, ht("/Plugin/Conflation"));
-            MainMenu.add(conflationMenu, new ConflationAction());
-
-
-        } catch (Exception e) {
-            JOptionPane.showMessageDialog(Main.parent, e.toString(),
-                    "Error adding conflation menu item", JOptionPane.ERROR_MESSAGE);
+    // add dialog the first time the mapframe is loaded
+    @Override
+    public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) {
+        if (oldFrame == null && newFrame != null) {
+            if (dialog == null) {
+                Shortcut shortcut = Shortcut.registerShortcut("Conflation", tr("Toggle: {0}", tr("Open Conflation")),
+                        KeyEvent.VK_0, Shortcut.ALT_SHIFT);
+                String name = "Conflation";
+                String tooltip = "Activates the conflation plugin";
+                dialog = new ConflationToggleDialog(tr(name), "conflation.png", tr(tooltip),
+                        shortcut, 150, this);
+            }
+            newFrame.addToggleDialog(dialog);
         }
     }
Index: applications/editors/josm/plugins/conflation/src/org/openstreetmap/josm/plugins/conflation/ConflationToggleDialog.java
===================================================================
--- applications/editors/josm/plugins/conflation/src/org/openstreetmap/josm/plugins/conflation/ConflationToggleDialog.java	(revision 27959)
+++ applications/editors/josm/plugins/conflation/src/org/openstreetmap/josm/plugins/conflation/ConflationToggleDialog.java	(revision 27959)
@@ -0,0 +1,564 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.openstreetmap.josm.plugins.conflation;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Dialog;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.KeyEvent;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import javax.swing.*;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.table.TableCellRenderer;
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.JosmAction;
+import org.openstreetmap.josm.data.SelectionChangedListener;
+import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.event.*;
+import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
+import org.openstreetmap.josm.gui.ExtendedDialog;
+import org.openstreetmap.josm.gui.MapView.EditLayerChangeListener;
+import org.openstreetmap.josm.gui.OsmPrimitivRenderer;
+import org.openstreetmap.josm.gui.SideButton;
+import org.openstreetmap.josm.gui.dialogs.ToggleDialog;
+import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.tools.GBC;
+import static org.openstreetmap.josm.tools.I18n.tr;
+import org.openstreetmap.josm.tools.Shortcut;
+import utilsplugin2.dumbutils.ReplaceGeometryAction;
+
+public class ConflationToggleDialog extends ToggleDialog
+        implements EditLayerChangeListener, SelectionChangedListener, DataSetListener,
+        ConflationListChangedListener {
+
+    public final static String PREF_PREFIX = "conflation";
+    JTable resultsTable;
+    ConflationLayer conflationLayer;
+    MatchTableModel tableModel;
+    ConflationCandidateList candidates;
+    ConflationOptionsDialog optionsDialog;
+
+    public ConflationToggleDialog(String name, String iconName, String tooltip,
+            Shortcut shortcut, int preferredHeight, ConflationPlugin conflationPlugin) {
+        super(tr(name), iconName, tr(tooltip), shortcut, preferredHeight);
+
+        candidates = new ConflationCandidateList();
+//        candidates.addConflationListChangedListener(this);
+
+        optionsDialog = new ConflationOptionsDialog();
+        optionsDialog.setModalityType(Dialog.ModalityType.MODELESS);
+
+        tableModel = new MatchTableModel();
+        tableModel.setCandidates(candidates);
+        candidates.addConflationListChangedListener(tableModel);
+
+        resultsTable = new JTable(tableModel);
+
+        // add selection handler, to center/zoom view
+        resultsTable.getSelectionModel().addListSelectionListener(
+                new MatchListSelectionHandler());
+        resultsTable.getColumnModel().getSelectionModel().addListSelectionListener(
+                new MatchListSelectionHandler());
+
+        // FIXME: doesn't work right now
+        resultsTable.getColumnModel().getColumn(0).setCellRenderer(new OsmPrimitivRenderer());
+        resultsTable.getColumnModel().getColumn(1).setCellRenderer(new OsmPrimitivRenderer());
+        resultsTable.getColumnModel().getColumn(4).setCellRenderer(new ColorTableCellRenderer("Tags"));
+
+        resultsTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+
+        createLayout(resultsTable, true, Arrays.asList(new SideButton[]{
+                    new SideButton(new ConfigureAction(), true),
+                    new SideButton(new ConflationAction(), true)
+//                    new SideButton("Replace Geometry", false),
+//                    new SideButton("Merge Tags", false),
+//                    new SideButton("Remove", false)
+                }));
+    }
+
+    @Override
+    public void conflationListChanged(ConflationCandidateList list) {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    public class ConfigureAction extends JosmAction {
+
+        public ConfigureAction() {
+            super(tr("Configure"), null, tr("Configure conflation"),
+                    Shortcut.registerShortcut("conflation:configure", tr("Conflation: {0}", tr("Conflation")),
+                    KeyEvent.VK_F, Shortcut.ALT_CTRL), false);
+        }
+
+        @Override
+        public void actionPerformed(ActionEvent e) {
+            optionsDialog.setVisible(true);
+        }
+    }
+
+    @Override
+    public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) {
+        // TODO
+    }
+
+    @Override
+    public void selectionChanged(Collection<? extends OsmPrimitive> newSelection) {
+        // TODO
+    }
+
+    class MatchListSelectionHandler implements ListSelectionListener {
+
+        @Override
+        public void valueChanged(ListSelectionEvent e) {
+            ListSelectionModel lsm = (ListSelectionModel) e.getSource();
+
+            int firstIndex = lsm.getMinSelectionIndex();
+            int lastIndex = lsm.getMaxSelectionIndex();
+            boolean isAdjusting = e.getValueIsAdjusting();
+            if (isAdjusting) {
+                return;
+            }
+
+            // only one item selected, show tags and zoom/center map
+            if (!lsm.isSelectionEmpty() && firstIndex == lastIndex && firstIndex < candidates.size()) {
+                ConflationCandidate c = candidates.get(firstIndex);
+                OsmPrimitive src = c.getSourcePrimitive();
+                OsmPrimitive tgt = c.getTargetPrimitive();
+
+                conflationLayer.setSelectedCandidate(c);
+
+                src.getDataSet().clearSelection();
+                tgt.getDataSet().clearSelection();
+                src.getDataSet().addSelected(src);
+                tgt.getDataSet().addSelected(tgt);
+
+                // zoom/center on pair
+                BoundingXYVisitor box = new BoundingXYVisitor();
+                box.computeBoundingBox(Arrays.asList(src, tgt));
+                if (box.getBounds() == null) {
+                    return;
+                }
+                box.enlargeBoundingBox();
+                Main.map.mapView.recalculateCenterScale(box);
+            }
+
+        }
+    }
+
+    class ColorTableCellRenderer extends JLabel implements TableCellRenderer {
+
+        private String columnName;
+
+        public ColorTableCellRenderer(String column) {
+            this.columnName = column;
+            setOpaque(true);
+        }
+
+        @Override
+        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
+            Object columnValue = table.getValueAt(row, table.getColumnModel().getColumnIndex(columnName));
+
+            if (value != null) {
+                setText(value.toString());
+            }
+            if (isSelected) {
+                setBackground(table.getSelectionBackground());
+                setForeground(table.getSelectionForeground());
+            } else {
+                setBackground(table.getBackground());
+                setForeground(table.getForeground());
+                if (columnValue.equals("Conflicts!")) {
+                    setBackground(java.awt.Color.red);
+                } else {
+                    setBackground(java.awt.Color.green);
+                }
+            }
+            return this;
+        }
+    }
+
+    static public class LayerListCellRenderer extends DefaultListCellRenderer {
+
+        @Override
+        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
+                boolean cellHasFocus) {
+            Layer layer = (Layer) value;
+            JLabel label = (JLabel) super.getListCellRendererComponent(list, layer.getName(), index, isSelected,
+                    cellHasFocus);
+            Icon icon = layer.getIcon();
+            label.setIcon(icon);
+            label.setToolTipText(layer.getToolTipText());
+            return label;
+        }
+    }
+    
+    class ConflationAction extends JosmAction {
+        public ConflationAction() {
+            super(tr("Replace Geometry"), null, tr("Replace geometry"),
+                    Shortcut.registerShortcut("conflation:replace", tr("Conflation: {0}", tr("Replace")),
+                    KeyEvent.VK_F, Shortcut.ALT_CTRL), false);
+        }
+        @Override
+        public void actionPerformed(ActionEvent e) {
+            ReplaceGeometryAction rg = new ReplaceGeometryAction();
+            ConflationCandidate c = conflationLayer.getSelectedCandidate();
+            if (rg.replace(c.getSourcePrimitive(), c.getTargetPrimitive())) {
+                candidates.remove(c);
+            }
+        }
+    }
+    
+    public class ConflationOptionsDialog extends ExtendedDialog {
+
+        private JPanel costsPanel;
+        private JCheckBox distanceCheckBox;
+        private JButton freezeSourceButton;
+        private JButton freezeTargetButton;
+        private JPanel jPanel3;
+        private JPanel jPanel5;
+        private JButton restoreSourceButton;
+        private JButton restoreTargetButton;
+        private JLabel sourceLayerLabel;
+        private JPanel sourcePanel;
+        private JLabel sourceSelectionLabel;
+        private JLabel targetLayerLabel;
+        private JPanel targetPanel;
+        private JLabel targetSelectionLabel;
+        ArrayList<OsmPrimitive> tgtSelection = null;
+        ArrayList<OsmPrimitive> srcSelection = null;
+        OsmDataLayer srcLayer;
+        DataSet tgtDataSet;
+        OsmDataLayer tgtLayer;
+        DataSet srcDataSet;
+        private boolean canceled = false;
+
+        public ConflationOptionsDialog() {
+            super(Main.parent,
+                    tr("Configure conflation options"),
+                    new String[]{tr("Conflate"), tr("Cancel")},
+                    false);
+            initComponents();
+        }
+
+        private void initComponents() {
+            sourcePanel = new JPanel();
+            sourceLayerLabel = new JLabel();
+            sourceSelectionLabel = new JLabel();
+            jPanel3 = new JPanel();
+            restoreSourceButton = new JButton(new RestoreSourceAction());
+            freezeSourceButton = new JButton(new FreezeSourceAction());
+            targetPanel = new JPanel();
+            targetLayerLabel = new JLabel();
+            targetSelectionLabel = new JLabel();
+            jPanel5 = new JPanel();
+            restoreTargetButton = new JButton(new RestoreTargetAction());
+            freezeTargetButton = new JButton(new FreezeTargetAction());
+            costsPanel = new JPanel();
+            distanceCheckBox = new JCheckBox();
+
+            JPanel pnl = new JPanel();
+            pnl.setLayout(new BoxLayout(pnl, BoxLayout.PAGE_AXIS));
+
+            sourcePanel.setBorder(BorderFactory.createTitledBorder("Source"));
+            sourcePanel.setLayout(new BoxLayout(sourcePanel, BoxLayout.PAGE_AXIS));
+
+            sourceLayerLabel.setText("layer");
+            sourcePanel.add(sourceLayerLabel);
+
+            sourceSelectionLabel.setText("Rel.:0 / Ways:0 / Nodes: 0");
+            sourcePanel.add(sourceSelectionLabel);
+
+            jPanel3.setLayout(new BoxLayout(jPanel3, BoxLayout.LINE_AXIS));
+
+            restoreSourceButton.setText("Restore");
+            jPanel3.add(restoreSourceButton);
+
+            jPanel3.add(freezeSourceButton);
+
+            sourcePanel.add(jPanel3);
+
+            pnl.add(sourcePanel);
+
+            targetPanel.setBorder(BorderFactory.createTitledBorder("Target"));
+            targetPanel.setLayout(new BoxLayout(targetPanel, BoxLayout.PAGE_AXIS));
+
+            targetLayerLabel.setText("layer");
+            targetPanel.add(targetLayerLabel);
+
+            targetSelectionLabel.setText("Rel.:0 / Ways:0 / Nodes: 0");
+            targetPanel.add(targetSelectionLabel);
+
+            jPanel5.setLayout(new BoxLayout(jPanel5, BoxLayout.LINE_AXIS));
+
+            restoreTargetButton.setText("Restore");
+            jPanel5.add(restoreTargetButton);
+
+            freezeTargetButton.setText("Freeze");
+            jPanel5.add(freezeTargetButton);
+
+            targetPanel.add(jPanel5);
+
+            pnl.add(targetPanel);
+
+            costsPanel.setBorder(BorderFactory.createTitledBorder("Costs"));
+            costsPanel.setLayout(new BoxLayout(costsPanel, BoxLayout.LINE_AXIS));
+
+            distanceCheckBox.setSelected(true);
+            distanceCheckBox.setText("Distance");
+            distanceCheckBox.setEnabled(false);
+            costsPanel.add(distanceCheckBox);
+
+            pnl.add(costsPanel);
+
+            setContent(pnl);
+            setupDialog();
+        }
+
+        @Override
+        protected void buttonAction(int buttonIndex, ActionEvent evt) {
+            super.buttonAction(buttonIndex, evt);
+            if (buttonIndex == 0) {
+                criteriaTabConflateButtonActionPerformed();
+            }
+        }
+
+        private void criteriaTabConflateButtonActionPerformed() {
+
+            // some initialization
+            int n = tgtSelection.size();
+            int m = srcSelection.size();
+            int maxLen = Math.max(n, m);
+            double cost[][] = new double[maxLen][maxLen];
+
+            // calculate cost matrix
+            for (int i = 0; i < n; i++) {
+                for (int j = 0; j < m; j++) {
+                    cost[i][j] = ConflationUtils.calcCost(tgtSelection.get(i), srcSelection.get(j));
+                }
+            }
+
+            // perform assignment using Hungarian algorithm
+            int[][] assignment = HungarianAlgorithm.hgAlgorithm(cost, "min");
+            OsmPrimitive tgt, src;
+            candidates.clear();
+            for (int i = 0; i < maxLen; i++) {
+                int tgtIdx = assignment[i][0];
+                int srcIdx = assignment[i][1];
+                if (tgtIdx < n) {
+                    tgt = tgtSelection.get(tgtIdx);
+                } else {
+                    tgt = null;
+                }
+                if (srcIdx < m) {
+                    src = srcSelection.get(srcIdx);
+                } else {
+                    src = null;
+                }
+
+                if (tgt != null && src != null) {
+                    // TODO: do something!
+                    if (!(candidates.hasCandidate(src, tgt) || candidates.hasCandidate(tgt, src))) {
+                        candidates.add(new ConflationCandidate(src, srcLayer, tgt, tgtLayer, cost[tgtIdx][srcIdx]));
+                    }
+                }
+            }
+
+            // add conflation layer
+            try {
+                conflationLayer = new ConflationLayer(tgtLayer.data, candidates);
+                Main.main.addLayer(conflationLayer);
+            } catch (Exception ex) {
+                JOptionPane.showMessageDialog(Main.parent, ex.toString(),
+                        "Error adding conflation layer", JOptionPane.ERROR_MESSAGE);
+            }
+
+            // print list of matched pairsalong with distance
+            // upon selection of one pair, highlight them and draw arrow
+
+//            if (resultsPanel != null) {
+//                resultsTabPanel.setSelectedComponent(resultsPanel);
+//            }
+        }
+
+        class RestoreTargetAction extends JosmAction {
+
+            public RestoreTargetAction() {
+                super(tr("Restore"), null, tr("Restore target selection"), null, false);
+            }
+
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                if (tgtLayer != null && tgtDataSet != null && tgtSelection != null && !tgtSelection.isEmpty()) {
+                    Main.map.mapView.setActiveLayer(tgtLayer);
+                    tgtLayer.setVisible(true);
+                    tgtDataSet.setSelected(tgtSelection);
+                }
+            }
+        }
+
+        class RestoreSourceAction extends JosmAction {
+
+            public RestoreSourceAction() {
+                super(tr("Restore"), null, tr("Restore source selection"), null, false);
+            }
+
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                if (srcLayer != null && srcDataSet != null && srcSelection != null && !srcSelection.isEmpty()) {
+                    Main.map.mapView.setActiveLayer(srcLayer);
+                    srcLayer.setVisible(true);
+                    srcDataSet.setSelected(srcSelection);
+                }
+            }
+        }
+
+        class FreezeTargetAction extends JosmAction {
+
+            public FreezeTargetAction() {
+                super(tr("Freeze"), null, tr("Freeze target selection"), null, false);
+            }
+
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                if (tgtDataSet != null && tgtDataSet == Main.main.getCurrentDataSet()) {
+//                targetDataSet.removeDataSetListener(this); FIXME:
+                }
+                tgtDataSet = Main.main.getCurrentDataSet();
+//            targetDataSet.addDataSetListener(tableModel); FIXME:
+                tgtLayer = Main.main.getEditLayer();
+                if (tgtDataSet == null || tgtLayer == null) {
+                    JOptionPane.showMessageDialog(Main.parent, tr("No valid OSM data layer present."),
+                            tr("Error freezing selection"), JOptionPane.ERROR_MESSAGE);
+                    return;
+                }
+                tgtSelection = new ArrayList<OsmPrimitive>(tgtDataSet.getSelected());
+                if (tgtSelection.isEmpty()) {
+                    JOptionPane.showMessageDialog(Main.parent, tr("Nothing is selected, please try again."),
+                            tr("Empty selection"), JOptionPane.ERROR_MESSAGE);
+                    return;
+                }
+
+                int numNodes = 0;
+                int numWays = 0;
+                int numRelations = 0;
+                for (OsmPrimitive p : tgtSelection) {
+                    switch (p.getType()) {
+                        case NODE:
+                            numNodes++;
+                            break;
+                        case WAY:
+                            numWays++;
+                            break;
+                        case RELATION:
+                            numRelations++;
+                            break;
+                    }
+                }
+
+                // FIXME: translate correctly
+                targetLayerLabel.setText(tgtLayer.getName());
+                targetSelectionLabel.setText(String.format("Rel.: %d / Ways: %d / Nodes: %d", numRelations, numWays, numNodes));
+            }
+        }
+
+        class FreezeSourceAction extends JosmAction {
+
+            public FreezeSourceAction() {
+                super(tr("Freeze"), null, tr("Freeze target selection"), null, false);
+            }
+
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                if (srcDataSet != null && srcDataSet == Main.main.getCurrentDataSet()) {
+//                sourceDataSet.removeDataSetListener(this); FIXME:
+                }
+                srcDataSet = Main.main.getCurrentDataSet();
+//            sourceDataSet.addDataSetListener(this); FIXME:
+                srcLayer = Main.main.getEditLayer();
+                if (srcDataSet == null || srcLayer == null) {
+                    JOptionPane.showMessageDialog(Main.parent, tr("No valid OSM data layer present."),
+                            tr("Error freezing selection"), JOptionPane.ERROR_MESSAGE);
+                    return;
+                }
+                srcSelection = new ArrayList<OsmPrimitive>(srcDataSet.getSelected());
+                if (srcSelection.isEmpty()) {
+                    JOptionPane.showMessageDialog(Main.parent, tr("Nothing is selected, please try again."),
+                            tr("Empty selection"), JOptionPane.ERROR_MESSAGE);
+                    return;
+                }
+
+                int numNodes = 0;
+                int numWays = 0;
+                int numRelations = 0;
+                for (OsmPrimitive p : srcSelection) {
+                    switch (p.getType()) {
+                        case NODE:
+                            numNodes++;
+                            break;
+                        case WAY:
+                            numWays++;
+                            break;
+                        case RELATION:
+                            numRelations++;
+                            break;
+                    }
+                }
+
+                // FIXME: translate correctly
+                sourceLayerLabel.setText(srcLayer.getName());
+                sourceSelectionLabel.setText(String.format("Rel.: %d / Ways: %d / Nodes: %d", numRelations, numWays, numNodes));
+            }
+        }
+    }
+
+    @Override
+    public void primitivesAdded(PrimitivesAddedEvent event) {
+    }
+
+    @Override
+    public void primitivesRemoved(PrimitivesRemovedEvent event) {
+        List<? extends OsmPrimitive> prims = event.getPrimitives();
+        for (OsmPrimitive p : prims) {
+            for (ConflationCandidate c : candidates) {
+                if (c.getSourcePrimitive().equals(p) || c.getTargetPrimitive().equals(p)) {
+                    candidates.remove(c);
+                    break;
+                }
+            }
+        }
+        tableModel.fireTableDataChanged();
+    }
+
+    @Override
+    public void tagsChanged(TagsChangedEvent event) {
+    }
+
+    @Override
+    public void nodeMoved(NodeMovedEvent event) {
+    }
+
+    @Override
+    public void wayNodesChanged(WayNodesChangedEvent event) {
+    }
+
+    @Override
+    public void relationMembersChanged(RelationMembersChangedEvent event) {
+    }
+
+    @Override
+    public void otherDatasetChange(AbstractDatasetChangedEvent event) {
+    }
+
+    @Override
+    public void dataChanged(DataChangedEvent event) {
+    }
+}
Index: applications/editors/josm/plugins/conflation/src/org/openstreetmap/josm/plugins/conflation/ConflationUtils.java
===================================================================
--- applications/editors/josm/plugins/conflation/src/org/openstreetmap/josm/plugins/conflation/ConflationUtils.java	(revision 27959)
+++ applications/editors/josm/plugins/conflation/src/org/openstreetmap/josm/plugins/conflation/ConflationUtils.java	(revision 27959)
@@ -0,0 +1,45 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.openstreetmap.josm.plugins.conflation;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.coor.EastNorth;
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+
+/**
+ *
+ * @author Josh
+ */
+public final class ConflationUtils {
+    private final static double MAX_COST = Double.MAX_VALUE;
+        
+    public static EastNorth getCenter(OsmPrimitive prim) {
+            LatLon center = prim.getBBox().getTopLeft().getCenter(prim.getBBox().getBottomRight());
+            return Main.map.mapView.getProjection().latlon2eastNorth(center);
+    }
+    
+    /**
+     * Calculate the cost of a pair of <code>OsmPrimitive</code>'s. A
+     * simple cost consisting of the Euclidean distance is used
+     * now, later we can also use dissimilarity between tags.
+     *
+     * @param   source      the reference <code>OsmPrimitive</code>.
+     * @param   target   the non-reference <code>OsmPrimitive</code>.
+     */
+    public static double calcCost(OsmPrimitive source, OsmPrimitive target) {
+        if (source==target) {
+            return MAX_COST;
+        }
+        
+        try {
+            return getCenter(source).distance(getCenter(target));
+        } catch (Exception e) {
+            return MAX_COST;
+        }
+
+        // TODO: use other "distance" measures, i.e. matching tags
+    }
+}
Index: applications/editors/josm/plugins/conflation/src/org/openstreetmap/josm/plugins/conflation/MatchTableModel.java
===================================================================
--- applications/editors/josm/plugins/conflation/src/org/openstreetmap/josm/plugins/conflation/MatchTableModel.java	(revision 27959)
+++ applications/editors/josm/plugins/conflation/src/org/openstreetmap/josm/plugins/conflation/MatchTableModel.java	(revision 27959)
@@ -0,0 +1,93 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.openstreetmap.josm.plugins.conflation;
+
+import java.util.HashSet;
+import java.util.Set;
+import javax.swing.table.AbstractTableModel;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.TagCollection;
+
+/**
+ * Model for the conflation results table.
+ */
+class MatchTableModel extends AbstractTableModel implements ConflationListChangedListener {
+
+    private ConflationCandidateList candidates = null;
+    private final static String[] columnNames = {"Mine", "Theirs", "Distance (m)", "Cost", "Tags"};
+
+    @Override
+    public int getColumnCount() {
+        return columnNames.length;
+    }
+
+    @Override
+    public int getRowCount() {
+        if (candidates == null)
+            return 0;
+        return candidates.size();
+    }
+
+    @Override
+    public String getColumnName(int col) {
+        return columnNames[col];
+    }
+
+    public Object getValueAt(int row, int col) {
+        if (candidates == null)
+            return null;
+        
+        ConflationCandidate c = candidates.get(row);
+        if (col == 0) {
+            return c.getSourcePrimitive();
+        } else if (col == 1) {
+            return c.getTargetPrimitive();
+        } else if (col == 2) {
+            return c.getDistance();
+        } else if (col == 3) {
+            return c.getCost();
+        }
+        if (col == 4) {
+            HashSet<OsmPrimitive> set = new HashSet<OsmPrimitive>();
+            set.add(c.getSourcePrimitive());
+            set.add(c.getTargetPrimitive());
+            TagCollection tags = TagCollection.unionOfAllPrimitives(set);
+            Set<String> keys = tags.getKeysWithMultipleValues();
+            if (keys.isEmpty()) {
+                return "No conflicts!";
+            } else {
+                return "Conflicts!";
+            }
+
+        } else {
+            return 0;
+        }
+    }
+
+    @Override
+    public Class getColumnClass(int c) {
+        return getValueAt(0, c).getClass();
+    }
+
+    /**
+     * @return the candidates
+     */
+    public ConflationCandidateList getCandidates() {
+        return candidates;
+    }
+
+    /**
+     * @param candidates the candidates to set
+     */
+    public void setCandidates(ConflationCandidateList candidates) {
+        this.candidates = candidates;
+        fireTableDataChanged();
+    }
+
+    @Override
+    public void conflationListChanged(ConflationCandidateList list) {
+        fireTableDataChanged();
+    }
+}
