Index: plugins/todo/src/org/openstreetmap/josm/plugins/todo/TodoDialog.java
===================================================================
--- plugins/todo/src/org/openstreetmap/josm/plugins/todo/TodoDialog.java	(revision 119)
+++ plugins/todo/src/org/openstreetmap/josm/plugins/todo/TodoDialog.java	(working copy)
@@ -20,6 +20,8 @@
 import javax.swing.JList;
 import javax.swing.ListSelectionModel;
 import javax.swing.SwingUtilities;
+import javax.swing.event.ListDataEvent;
+import javax.swing.event.ListDataListener;
 import javax.swing.event.ListSelectionEvent;
 import javax.swing.event.ListSelectionListener;
 
@@ -27,7 +29,9 @@
 import org.openstreetmap.josm.actions.AutoScaleAction.AutoScaleMode;
 import org.openstreetmap.josm.data.osm.DataSelectionListener;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.event.DatasetEventManager;
 import org.openstreetmap.josm.data.osm.event.SelectionEventManager;
+import org.openstreetmap.josm.data.osm.event.DatasetEventManager.FireMode;
 import org.openstreetmap.josm.gui.MainApplication;
 import org.openstreetmap.josm.gui.SideButton;
 import org.openstreetmap.josm.gui.dialogs.ToggleDialog;
@@ -35,10 +39,13 @@
 import org.openstreetmap.josm.gui.layer.LayerManager.LayerChangeListener;
 import org.openstreetmap.josm.gui.layer.LayerManager.LayerOrderChangeEvent;
 import org.openstreetmap.josm.gui.layer.LayerManager.LayerRemoveEvent;
+import org.openstreetmap.josm.gui.util.HighlightHelper;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.gui.widgets.ListPopupMenu;
 import org.openstreetmap.josm.gui.widgets.PopupMenuLauncher;
+import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.tools.ImageProvider;
+import org.openstreetmap.josm.tools.InputMapUtils;
 import org.openstreetmap.josm.tools.Shortcut;
 
 /**
@@ -52,6 +59,7 @@
     private final TodoListModel model = new TodoListModel(selectionModel);
     private final JList<TodoListItem> lstPrimitives = new JList<>(model);
     private final AddAction actAdd = new AddAction(model);
+    private final SelectAction actSelect = new SelectAction(model);
     private final PassAction actPass = new PassAction(model);
     private final MarkAction actMark = new MarkAction(model);
     private final MarkSelectedAction actMarkSelected = new MarkSelectedAction(model);
@@ -72,10 +80,15 @@
                         KeyEvent.VK_T, Shortcut.CTRL_SHIFT), 150);
         buildContentPanel();
 
+        model.addListDataListener(new TitleUpdater());
+
         MainApplication.getLayerManager().addLayerChangeListener(this);
+        DatasetEventManager.getInstance().addDatasetListener(model, FireMode.IN_EDT);
         lstPrimitives.addMouseListener(new DblClickHandler());
         lstPrimitives.addMouseListener(new TodoPopupLauncher());
         toggleAction.addPropertyChangeListener(this);
+
+        InputMapUtils.addEnterAction(lstPrimitives, actSelect);
     }
 
     /**
@@ -83,14 +96,14 @@
      */
     protected void buildContentPanel() {
         lstPrimitives.setSelectionModel(selectionModel);
-        lstPrimitives.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+        lstPrimitives.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
         lstPrimitives.setCellRenderer(new TodoListItemRenderer());
         lstPrimitives.setTransferHandler(null);
 
         // the select action
-        SelectAction actSelect = new SelectAction(model);
         SideButton selectButton = new SideButton(actSelect);
         lstPrimitives.getSelectionModel().addListSelectionListener(actSelect);
+        actSelect.updateEnabledState();
 
         // the add button
         SideButton addButton = new SideButton(actAdd);
@@ -147,7 +160,9 @@
             }
             layer.data.setSelected(items);
         }
-        zoom(layer);
+        if (!layer.data.selectionEmpty()) {
+            zoom(layer);
+        }
     }
 
     protected void updateTitle() {
@@ -161,6 +176,12 @@
         actAdd.updateEnabledState();
     }
 
+    @Override
+    public void hideNotify() {
+        SelectionEventManager.getInstance().removeSelectionListener(actAdd);
+        SelectionEventManager.getInstance().removeSelectionListener(actMarkSelected);
+    }
+
     protected Collection<TodoListItem> getItems() {
         OsmDataLayer layer = MainApplication.getLayerManager().getEditLayer();
         if (layer == null)
@@ -186,7 +207,7 @@
         }
 
         public void updateEnabledState() {
-            setEnabled(model.getSelected() != null);
+            setEnabled(!model.isSelectionEmpty());
         }
 
         @Override
@@ -262,7 +283,6 @@
         @Override
         public void actionPerformed(ActionEvent e) {
             model.addItems(getItems());
-            updateTitle();
         }
 
         public void updateEnabledState() {
@@ -293,7 +313,6 @@
         @Override
         public void actionPerformed(ActionEvent e) {
             model.markItems(getItems());
-            updateTitle();
         }
 
         public void updateEnabledState() {
@@ -310,7 +329,7 @@
         }
     }
 
-    private class MarkAction extends AbstractAction implements ListSelectionListener {
+    private static class MarkAction extends AbstractAction implements ListSelectionListener {
 
         TodoListModel model;
 
@@ -324,13 +343,12 @@
 
         @Override
         public void actionPerformed(ActionEvent arg0) {
-            model.markSelected();
+            model.markItems(model.getSelected());
             selectAndZoom(model.getSelected());
-            updateTitle();
         }
 
         public void updateEnabledState() {
-            setEnabled(model.getSelected() != null);
+            setEnabled(!model.isSelectionEmpty());
         }
 
         @Override
@@ -339,7 +357,7 @@
         }
     }
 
-    private class MarkAllAction extends AbstractAction {
+    private static class MarkAllAction extends AbstractAction {
 
         TodoListModel model;
 
@@ -354,12 +372,10 @@
         public void actionPerformed(ActionEvent arg0) {
             model.markAll();
             selectAndZoom(model.getSelected());
-            updateTitle();
         }
-
     }
 
-    private class UnmarkAllAction extends AbstractAction {
+    private static class UnmarkAllAction extends AbstractAction {
 
         TodoListModel model;
 
@@ -373,11 +389,10 @@
         @Override
         public void actionPerformed(ActionEvent arg0) {
             model.unmarkAll();
-            updateTitle();
         }
     }
 
-    private class ClearAction extends AbstractAction {
+    private static class ClearAction extends AbstractAction {
 
         TodoListModel model;
 
@@ -391,7 +406,6 @@
         @Override
         public void actionPerformed(ActionEvent arg0) {
             model.clear();
-            updateTitle();
         }
     }
 
@@ -411,13 +425,27 @@
      * The popup menu launcher.
      */
     class TodoPopupLauncher extends PopupMenuLauncher {
+        private final HighlightHelper helper = new HighlightHelper();
+        private final boolean highlightEnabled = Config.getPref().getBoolean("draw.target-highlight", true);
+        
+        TodoPopupLauncher() {
+            super(popupMenu);
+        }
+
         @Override
-        public void launch(MouseEvent evt) {
-            int idx = lstPrimitives.locationToIndex(evt.getPoint());
-            if (idx >= 0)
-                model.setSelected(model.getElementAt(idx));
+        public void mouseClicked(MouseEvent e) {
+            int idx = lstPrimitives.locationToIndex(e.getPoint());
+            if (idx < 0) return;
+            if (highlightEnabled && MainApplication.isDisplayingMapView() && 
+                       helper.highlightOnly(model.getElementAt(idx).primitive)) {
+                MainApplication.getMap().mapView.repaint();
+            }
+        }
 
-            popupMenu.show(lstPrimitives, evt.getX(), evt.getY());
+        @Override
+        public void mouseExited(MouseEvent me) {
+            if (highlightEnabled) helper.clear();
+            super.mouseExited(me);
         }
     }
 
@@ -439,6 +467,26 @@
         }
     }
 
+    /**
+     * Updates the dialog title with a summary of the current todo list status
+     */
+    class TitleUpdater implements ListDataListener {
+        @Override
+        public void contentsChanged(ListDataEvent e) {
+            updateTitle();
+        }
+
+        @Override
+        public void intervalAdded(ListDataEvent e) {
+            updateTitle();
+        }
+
+        @Override
+        public void intervalRemoved(ListDataEvent e) {
+            updateTitle();
+        }
+    }
+
     @Override
     public void propertyChange(PropertyChangeEvent arg0) {
         actAdd.updateEnabledState();
@@ -448,6 +496,7 @@
     public void destroy() {
         super.destroy();
         MainApplication.getLayerManager().removeLayerChangeListener(this);
+        DatasetEventManager.getInstance().removeDatasetListener(model);
         MainApplication.unregisterActionShortcut(actPass, sctPass);
         MainApplication.unregisterActionShortcut(actMark, sctMark);
     }
@@ -460,9 +509,7 @@
     @Override
     public void layerRemoving(LayerRemoveEvent e) {
         if (e.getRemovedLayer() instanceof OsmDataLayer) {
-            if (model.purgeLayerItems((OsmDataLayer) e.getRemovedLayer())) {
-                updateTitle();
-            }
+            model.purgeLayerItems((OsmDataLayer) e.getRemovedLayer());
         }
     }
 
Index: plugins/todo/src/org/openstreetmap/josm/plugins/todo/TodoListModel.java
===================================================================
--- plugins/todo/src/org/openstreetmap/josm/plugins/todo/TodoListModel.java	(revision 119)
+++ plugins/todo/src/org/openstreetmap/josm/plugins/todo/TodoListModel.java	(working copy)
@@ -6,13 +6,32 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
 
 import javax.swing.AbstractListModel;
 import javax.swing.DefaultListSelectionModel;
 
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.event.AbstractDatasetChangedEvent;
+import org.openstreetmap.josm.data.osm.event.DataChangedEvent;
+import org.openstreetmap.josm.data.osm.event.DataSetListener;
+import org.openstreetmap.josm.data.osm.event.NodeMovedEvent;
+import org.openstreetmap.josm.data.osm.event.PrimitivesAddedEvent;
+import org.openstreetmap.josm.data.osm.event.PrimitivesRemovedEvent;
+import org.openstreetmap.josm.data.osm.event.RelationMembersChangedEvent;
+import org.openstreetmap.josm.data.osm.event.TagsChangedEvent;
+import org.openstreetmap.josm.data.osm.event.WayNodesChangedEvent;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.gui.util.TableHelper;
 
-public class TodoListModel extends AbstractListModel<TodoListItem> {
+/**
+ * The list model for the todo list items.
+ *
+ * The model also maintains a list of already completed items
+ *
+ */
+public class TodoListModel extends AbstractListModel<TodoListItem> implements DataSetListener {
 
     private final ArrayList<TodoListItem> todoList = new ArrayList<>();
     private final ArrayList<TodoListItem> doneList = new ArrayList<>();
@@ -32,16 +51,26 @@
         return todoList.size();
     }
 
+    public boolean isSelectionEmpty() {
+        return selectionModel.isSelectionEmpty();
+    }
+
     public int getDoneSize() {
         return doneList.size();
     }
 
-    public TodoListItem getSelected() {
-        if (getSize() == 0 || selectionModel.isSelectionEmpty() || selectionModel.getMinSelectionIndex() >= getSize())
-            return null;
-        return todoList.get(selectionModel.getMinSelectionIndex());
+    public synchronized Collection<TodoListItem> getSelected() {
+        return IntStream.range(0, getSize())
+                .filter(selectionModel::isSelectedIndex)
+                .mapToObj(todoList::get)
+                .collect(Collectors.toSet());
     }
 
+    public Collection<TodoListItem> getItemsForPrimitives(Collection<? extends OsmPrimitive> primitives) {
+        return todoList.stream().filter(i -> primitives.contains(i.primitive))
+            .collect(Collectors.toList());
+    }
+
     public List<TodoListItem> getTodoList() {
         return todoList;
     }
@@ -104,11 +133,9 @@
         selectionModel.setSelectionInterval(sel, sel);
     }
 
-    public void setSelected(TodoListItem element) {
-        int sel = todoList.indexOf(element);
-        if (sel == -1)
-            return;
-        selectionModel.setSelectionInterval(sel, sel);
+    public synchronized void setSelected(Collection<TodoListItem> sel) {
+        TableHelper.setSelectedIndices(selectionModel,
+                sel != null ? sel.stream().mapToInt(todoList::indexOf) : IntStream.empty());
     }
 
     public void markAll() {
@@ -120,6 +147,18 @@
         super.fireIntervalRemoved(this, 0, size-1);
     }
 
+    public void removeItems(Collection<TodoListItem> items) {
+        if (items == null || items.isEmpty())
+            return;
+
+        int size = getSize();
+
+        todoList.removeAll(items);
+        doneList.removeAll(items);
+
+        super.fireIntervalRemoved(this, 0, size-1);
+    }
+
     public void markItems(Collection<TodoListItem> items) {
         if (items == null || items.isEmpty())
             return;
@@ -175,4 +214,67 @@
         else return tr("Todo list {0}/{1} ({2}%)", getDoneSize(), totalSize, 100.0*getDoneSize()/totalSize);
     }
 
+    /**
+     * Triggers a refresh of the view for all items in {@code toUpdate}
+     * which are currently displayed in the view
+     *
+     * @param toUpdate the collection of items to update
+     */
+    public synchronized void update(Collection<? extends TodoListItem> toUpdate) {
+        if (toUpdate == null) return;
+        if (toUpdate.isEmpty()) return;
+        Collection<TodoListItem> sel = getSelected();
+        for (TodoListItem p: toUpdate) {
+            int i = todoList.indexOf(p);
+            if (i >= 0) {
+                super.fireContentsChanged(this, i, i);
+            }
+        }
+        setSelected(sel);
+    }
+
+    @Override
+    public void primitivesAdded(PrimitivesAddedEvent event) {
+        // ignored
+    }
+
+    @Override
+    public void primitivesRemoved(PrimitivesRemovedEvent event) {
+        removeItems(getItemsForPrimitives(event.getPrimitives()));
+    }
+
+    @Override
+    public void tagsChanged(TagsChangedEvent event) {
+        update(getItemsForPrimitives(event.getPrimitives()));
+    }
+
+    @Override
+    public void nodeMoved(NodeMovedEvent event) {
+        update(getItemsForPrimitives(event.getPrimitives()));
+    }
+
+    @Override
+    public void wayNodesChanged(WayNodesChangedEvent event) {
+        update(getItemsForPrimitives(event.getPrimitives()));
+    }
+
+    @Override
+    public void relationMembersChanged(RelationMembersChangedEvent event) {
+        update(getItemsForPrimitives(event.getPrimitives()));
+    }
+
+    @Override
+    public void otherDatasetChange(AbstractDatasetChangedEvent event) {
+        update(getItemsForPrimitives(event.getPrimitives()));
+    }
+
+    @Override
+    public void dataChanged(DataChangedEvent event) {
+        update(getItemsForPrimitives(event.getPrimitives()));
+        for (AbstractDatasetChangedEvent e : event.getEvents()) {
+            if (e instanceof PrimitivesRemovedEvent) {
+                primitivesRemoved((PrimitivesRemovedEvent) e);
+            }
+        }
+    }
 }
