Index: trunk/src/org/openstreetmap/josm/actions/AutoScaleAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/AutoScaleAction.java	(revision 5957)
+++ trunk/src/org/openstreetmap/josm/actions/AutoScaleAction.java	(revision 5958)
@@ -13,4 +13,8 @@
 
 import javax.swing.JOptionPane;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.event.TreeSelectionEvent;
+import javax.swing.event.TreeSelectionListener;
 
 import org.openstreetmap.josm.Main;
@@ -19,6 +23,10 @@
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
+import org.openstreetmap.josm.data.validation.TestError;
+import org.openstreetmap.josm.gui.MapFrame;
+import org.openstreetmap.josm.gui.MapFrameListener;
 import org.openstreetmap.josm.gui.MapView;
 import org.openstreetmap.josm.gui.dialogs.LayerListDialog;
+import org.openstreetmap.josm.gui.dialogs.ValidatorDialog.ValidatorBoundingXYVisitor;
 import org.openstreetmap.josm.gui.layer.Layer;
 import org.openstreetmap.josm.tools.Shortcut;
@@ -36,6 +44,12 @@
         marktr("conflict"),
         marktr("download"),
+        marktr("problem"),
         marktr("previous"),
         marktr("next")};
+    
+    private final String mode;
+
+    protected ZoomChangeAdapter zoomChangeAdapter;
+    protected MapFrameAdapter mapFrameAdapter;
 
     /**
@@ -77,6 +91,4 @@
     }
 
-    private final String mode;
-
     private static int getModeShortcut(String mode) {
         int shortcut = -1;
@@ -88,4 +100,5 @@
         else if (mode.equals("conflict")) { shortcut = KeyEvent.VK_4; }
         else if (mode.equals("download")) { shortcut = KeyEvent.VK_5; }
+        else if (mode.equals("problem")) { shortcut = KeyEvent.VK_6; }
         else if (mode.equals("previous")) { shortcut = KeyEvent.VK_8; }
         else if (mode.equals("next")) { shortcut = KeyEvent.VK_9; }
@@ -95,6 +108,6 @@
 
     /**
-     *
-     * @param mode
+     * Constructs a new {@code AutoScaleAction}.
+     * @param mode The autoscale mode (one of {@link AutoScaleAction#MODES})
      * @param marker Used only to differentiate from default constructor
      */
@@ -104,8 +117,12 @@
     }
 
-
-    public AutoScaleAction(String mode) {
+    /**
+     * Constructs a new {@code AutoScaleAction}.
+     * @param mode The autoscale mode (one of {@link AutoScaleAction#MODES})
+     */
+    public AutoScaleAction(final String mode) {
         super(tr("Zoom to {0}", tr(mode)), "dialogs/autoscale/" + mode, tr("Zoom the view to {0}.", tr(mode)),
-                Shortcut.registerShortcut("view:zoom"+mode, tr("View: {0}", tr("Zoom to {0}", tr(mode))), getModeShortcut(mode), Shortcut.DIRECT), true);
+                Shortcut.registerShortcut("view:zoom"+mode, tr("View: {0}", tr("Zoom to {0}", tr(mode))), getModeShortcut(mode), Shortcut.DIRECT), 
+                true, null, false);
         String modeHelp = Character.toUpperCase(mode.charAt(0)) + mode.substring(1);
         putValue("help", "Action/AutoScale/" + modeHelp);
@@ -119,4 +136,6 @@
         } else if (mode.equals("conflict")) {
             putValue("help", ht("/Action/ZoomToConflict"));
+        } else if (mode.equals("problem")) {
+            putValue("help", ht("/Action/ZoomToProblem"));
         } else if (mode.equals("download")) {
             putValue("help", ht("/Action/ZoomToDownload"));
@@ -125,5 +144,8 @@
         } else if (mode.equals("next")) {
             putValue("help", ht("/Action/ZoomToNext"));
-        }
+        } else {
+            throw new IllegalArgumentException("Unknown mode: "+mode);
+        }
+        installAdapters();
     }
 
@@ -171,6 +193,13 @@
 
     private BoundingXYVisitor getBoundingBox() {
-        BoundingXYVisitor v = new BoundingXYVisitor();
-        if (mode.equals("data")) {
+        BoundingXYVisitor v = mode.equals("problem") ? new ValidatorBoundingXYVisitor() : new BoundingXYVisitor();
+
+        if (mode.equals("problem")) {
+            TestError error = Main.map.validatorDialog.getSelectedError();
+            if (error == null) return null;
+            ((ValidatorBoundingXYVisitor) v).visit(error);
+            if (v.getBounds() == null) return null;
+            v.enlargeBoundingBox(Main.pref.getDouble("validator.zoom-enlarge-bbox", 0.0002));
+        } else if (mode.equals("data")) {
             for (Layer l : Main.map.mapView.getAllLayers()) {
                 l.visitBoundingBox(v);
@@ -236,4 +265,8 @@
                 setEnabled(true);
             }
+        } else if ("conflict".equals(mode)) {
+            setEnabled(Main.map != null && Main.map.conflictDialog.getSelectedConflict() != null);
+        } else if ("problem".equals(mode)) {
+            setEnabled(Main.map != null && Main.map.validatorDialog.getSelectedError() != null);
         } else if ("previous".equals(mode)) {
             setEnabled(Main.isDisplayingMapView() && Main.map.mapView.hasZoomUndoEntries());
@@ -258,14 +291,13 @@
     protected void installAdapters() {
         super.installAdapters();
-        // make this action listen to zoom change events
+        // make this action listen to zoom and mapframe change events
         //
-        zoomChangeAdapter = new ZoomChangeAdapter();
-        MapView.addZoomChangeListener(zoomChangeAdapter);
+        MapView.addZoomChangeListener(zoomChangeAdapter = new ZoomChangeAdapter());
+        Main.addMapFrameListener(mapFrameAdapter = new MapFrameAdapter());
         initEnabledState();
     }
 
     /**
-     * Adapter for selection change events
-     *
+     * Adapter for zoom change events
      */
     private class ZoomChangeAdapter implements MapView.ZoomChangeListener {
@@ -275,4 +307,42 @@
     }
 
-    private ZoomChangeAdapter zoomChangeAdapter;
+    /**
+     * Adapter for MapFrame change events
+     */
+    private class MapFrameAdapter implements MapFrameListener {
+        private ListSelectionListener conflictSelectionListener;
+        private TreeSelectionListener validatorSelectionListener;
+
+        public MapFrameAdapter() {
+            if (mode.equals("conflict")) {
+                conflictSelectionListener = new ListSelectionListener() {
+                    @Override public void valueChanged(ListSelectionEvent e) {
+                        updateEnabledState();
+                    }
+                };
+            } else if (mode.equals("problem")) {
+                validatorSelectionListener = new TreeSelectionListener() {
+                    @Override public void valueChanged(TreeSelectionEvent e) {
+                        updateEnabledState();
+                    }
+                };
+            }
+        }
+
+        @Override public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) {
+            if (conflictSelectionListener != null) {
+                if (newFrame != null) {
+                    newFrame.conflictDialog.addListSelectionListener(conflictSelectionListener);
+                } else if (oldFrame != null) {
+                    oldFrame.conflictDialog.removeListSelectionListener(conflictSelectionListener);
+                }
+            } else if (validatorSelectionListener != null) {
+                if (newFrame != null) {
+                    newFrame.validatorDialog.addTreeSelectionListener(validatorSelectionListener);
+                } else if (oldFrame != null) {
+                    oldFrame.validatorDialog.removeTreeSelectionListener(validatorSelectionListener);
+                }
+            }
+        }
+    }
 }
Index: trunk/src/org/openstreetmap/josm/gui/MainMenu.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/MainMenu.java	(revision 5957)
+++ trunk/src/org/openstreetmap/josm/gui/MainMenu.java	(revision 5958)
@@ -9,4 +9,6 @@
 import java.awt.Toolkit;
 import java.awt.event.KeyEvent;
+import java.util.HashMap;
+import java.util.Map;
 
 import javax.swing.JCheckBoxMenuItem;
@@ -166,4 +168,5 @@
     public final HistoryInfoAction historyinfo = new HistoryInfoAction();
     public final HistoryInfoWebAction historyinfoweb = new HistoryInfoWebAction();
+    public final Map<String, AutoScaleAction> autoScaleActions = new HashMap<String, AutoScaleAction>();
 
     /* Tools menu */
@@ -494,5 +497,6 @@
         viewMenu.addSeparator();
         for (String mode : AutoScaleAction.MODES) {
-            JosmAction autoScaleAction = new AutoScaleAction(mode);
+            AutoScaleAction autoScaleAction = new AutoScaleAction(mode);
+            autoScaleActions.put(mode, autoScaleAction);
             add(viewMenu, autoScaleAction);
         }
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/ChangesetDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/ChangesetDialog.java	(revision 5957)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/ChangesetDialog.java	(revision 5958)
@@ -107,8 +107,4 @@
         lstInSelection.addMouseListener(dblClickHandler);
         lstInActiveDataLayer.addMouseListener(dblClickHandler);
-
-        ChangesetPopupMenuLauncher popupMenuLauncher = new ChangesetPopupMenuLauncher();
-        lstInSelection.addMouseListener(popupMenuLauncher);
-        lstInActiveDataLayer.addMouseListener(popupMenuLauncher);
     }
 
@@ -211,4 +207,8 @@
         popupMenu = new ChangesetDialogPopup(lstInActiveDataLayer, lstInSelection);
 
+        PopupMenuLauncher popupMenuLauncher = new PopupMenuLauncher(popupMenu);
+        lstInSelection.addMouseListener(popupMenuLauncher);
+        lstInActiveDataLayer.addMouseListener(popupMenuLauncher);
+        
         createLayout(pnl, false, Arrays.asList(new SideButton[] {
             new SideButton(selectObjectsAction, false),
@@ -522,18 +522,4 @@
     }
 
-    class ChangesetPopupMenuLauncher extends PopupMenuLauncher {
-        @Override
-        public void launch(MouseEvent evt) {
-            JList lst = getCurrentChangesetList();
-            if (lst.getSelectedIndices().length == 0) {
-                int idx = lst.locationToIndex(evt.getPoint());
-                if (idx >=0) {
-                    lst.getSelectionModel().addSelectionInterval(idx, idx);
-                }
-            }
-            popupMenu.show(lst, evt.getX(), evt.getY());
-        }
-    }
-
     class ChangesetDialogPopup extends ListPopupMenu {
         public ChangesetDialogPopup(JList ... lists) {
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/CommandStackDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/CommandStackDialog.java	(revision 5957)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/CommandStackDialog.java	(revision 5958)
@@ -7,5 +7,4 @@
 import java.awt.Dimension;
 import java.awt.GridBagLayout;
-import java.awt.Point;
 import java.awt.event.ActionEvent;
 import java.awt.event.KeyEvent;
@@ -81,5 +80,5 @@
                 Shortcut.registerShortcut("subwindow:commandstack", tr("Toggle: {0}",
                 tr("Command Stack")), KeyEvent.VK_O, Shortcut.ALT_SHIFT), 100, true);
-        undoTree.addMouseListener(new PopupMenuHandler());
+        undoTree.addMouseListener(new MouseEventHandler());
         undoTree.setRootVisible(false);
         undoTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
@@ -91,5 +90,5 @@
         InputMapUtils.unassignCtrlShiftUpDown(undoTree, JComponent.WHEN_FOCUSED);
         
-        redoTree.addMouseListener(new PopupMenuHandler());
+        redoTree.addMouseListener(new MouseEventHandler());
         redoTree.setRootVisible(false);
         redoTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
@@ -382,5 +381,5 @@
      * undo / redo switch to reduce duplicate code
      */
-    protected enum UndoRedoType {UNDO, REDO};
+    protected enum UndoRedoType {UNDO, REDO}
 
     /**
@@ -444,33 +443,17 @@
     }
 
-    class PopupMenuHandler extends PopupMenuLauncher {
+    class MouseEventHandler extends PopupMenuLauncher {
+
+        public MouseEventHandler() {
+            super(new CommandStackPopup());
+        }
         
         @Override
         public void mouseClicked(MouseEvent evt) {
-            super.mouseClicked(evt);
-            if (evt.getButton() == MouseEvent.BUTTON1 && evt.getClickCount()>1) {
+            if (isDoubleClick(evt)) {
                 selectAndZoomAction.actionPerformed(null);
             }
         }
-        
-        @Override
-        public void launch(MouseEvent evt) {
-            Point p = evt.getPoint();
-            JTree tree = (JTree) evt.getSource();
-            int row = tree.getRowForLocation(p.x, p.y);
-            if (row != -1) {
-                TreePath path = tree.getPathForLocation(p.x, p.y);
-                // right click on unselected element -> select it first
-                if (!tree.isPathSelected(path)) {
-                    tree.setSelectionPath(path);
-                }
-                TreePath[] selPaths = tree.getSelectionPaths();
-
-                CommandStackPopup menu = new CommandStackPopup();
-                menu.show(tree, p.x, p.y-3);
-            }
-        }
-    }
-
+    }
     
     private class CommandStackPopup extends JPopupMenu {
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/ConflictDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/ConflictDialog.java	(revision 5957)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/ConflictDialog.java	(revision 5958)
@@ -12,5 +12,4 @@
 import java.awt.event.ActionEvent;
 import java.awt.event.KeyEvent;
-import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
 import java.util.Arrays;
@@ -25,4 +24,5 @@
 import javax.swing.JList;
 import javax.swing.JOptionPane;
+import javax.swing.JPopupMenu;
 import javax.swing.ListModel;
 import javax.swing.ListSelectionModel;
@@ -46,11 +46,13 @@
 import org.openstreetmap.josm.data.osm.visitor.Visitor;
 import org.openstreetmap.josm.gui.HelpAwareOptionPane;
+import org.openstreetmap.josm.gui.HelpAwareOptionPane.ButtonSpec;
 import org.openstreetmap.josm.gui.MapView;
 import org.openstreetmap.josm.gui.NavigatableComponent;
 import org.openstreetmap.josm.gui.OsmPrimitivRenderer;
+import org.openstreetmap.josm.gui.PopupMenuHandler;
 import org.openstreetmap.josm.gui.SideButton;
-import org.openstreetmap.josm.gui.HelpAwareOptionPane.ButtonSpec;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.gui.util.GuiHelper;
+import org.openstreetmap.josm.gui.widgets.PopupMenuLauncher;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Shortcut;
@@ -81,4 +83,7 @@
     /** the list widget for the list of conflicts */
     private JList lstConflicts;
+    
+    private final JPopupMenu popupMenu = new JPopupMenu();
+    private final PopupMenuHandler popupMenuHandler = new PopupMenuHandler(popupMenu);
 
     private ResolveAction actResolve;
@@ -94,12 +99,6 @@
         lstConflicts.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
         lstConflicts.setCellRenderer(new OsmPrimitivRenderer());
-        lstConflicts.addMouseListener(new MouseAdapter(){
-            @Override public void mouseClicked(MouseEvent e) {
-                if (e.getClickCount() >= 2) {
-                    resolve();
-                }
-            }
-        });
-        lstConflicts.getSelectionModel().addListSelectionListener(new ListSelectionListener(){
+        lstConflicts.addMouseListener(new MouseEventHandler());
+        addListSelectionListener(new ListSelectionListener(){
             public void valueChanged(ListSelectionEvent e) {
                 Main.map.mapView.repaint();
@@ -108,12 +107,14 @@
 
         SideButton btnResolve = new SideButton(actResolve = new ResolveAction());
-        lstConflicts.getSelectionModel().addListSelectionListener(actResolve);
+        addListSelectionListener(actResolve);
 
         SideButton btnSelect = new SideButton(actSelect = new SelectAction());
-        lstConflicts.getSelectionModel().addListSelectionListener(actSelect);
+        addListSelectionListener(actSelect);
 
         createLayout(lstConflicts, true, Arrays.asList(new SideButton[] {
             btnResolve, btnSelect
         }));
+        
+        popupMenuHandler.addAction(Main.main.menu.autoScaleActions.get("conflict"));
     }
 
@@ -141,4 +142,31 @@
         MapView.removeEditLayerChangeListener(this);
         DataSet.removeSelectionListener(this);
+    }
+    
+    /**
+     * Add a list selection listener to the conflicts list.
+     * @param listener the ListSelectionListener
+     * @since 5958
+     */
+    public void addListSelectionListener(ListSelectionListener listener) {
+        lstConflicts.getSelectionModel().addListSelectionListener(listener);
+    }
+    
+    /**
+     * Remove the given list selection listener from the conflicts list.
+     * @param listener the ListSelectionListener
+     * @since 5958
+     */
+    public void removeListSelectionListener(ListSelectionListener listener) {
+        lstConflicts.getSelectionModel().removeListSelectionListener(listener);
+    }
+    
+    /**
+     * Replies the popup menu handler.
+     * @return The popup menu handler
+     * @since 5958
+     */
+    public PopupMenuHandler getPopupMenuHandler() {
+        return popupMenuHandler;
     }
 
@@ -302,4 +330,15 @@
     public String helpTopic() {
         return ht("/Dialog/ConflictList");
+    }
+    
+    class MouseEventHandler extends PopupMenuLauncher {
+        public MouseEventHandler() {
+            super(popupMenu);
+        }
+        @Override public void mouseClicked(MouseEvent e) {
+            if (isDoubleClick(e)) {
+                resolve();
+            }
+        }
     }
 
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/LayerListDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/LayerListDialog.java	(revision 5957)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/LayerListDialog.java	(revision 5958)
@@ -1020,17 +1020,8 @@
 
     class PopupMenuHandler extends PopupMenuLauncher {
-        @Override
-        public void launch(MouseEvent evt) {
-            Point p = evt.getPoint();
-            int index = layerList.rowAtPoint(p);
-            if (index < 0) return;
-            if (!layerList.getCellRect(index, 2, false).contains(evt.getPoint()))
-                return;
-            if (!layerList.isRowSelected(index)) {
-                layerList.setRowSelectionInterval(index, index);
-            }
-            Layer layer = model.getLayer(index);
-            LayerListPopup menu = new LayerListPopup(getModel().getSelectedLayers(), layer);
-            menu.show(layerList, p.x, p.y-3);
+        @Override public void launch(MouseEvent evt) {
+            Layer layer = getModel().getLayer(layerList.getSelectedRow());
+            menu = new LayerListPopup(getModel().getSelectedLayers(), layer);
+            super.launch(evt);
         }
     }
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/MapPaintDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/MapPaintDialog.java	(revision 5957)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/MapPaintDialog.java	(revision 5958)
@@ -694,17 +694,17 @@
             if (cbWireframe.isSelected())
                 return;
-            Point p = evt.getPoint();
-            int index = tblStyles.rowAtPoint(p);
-            if (index < 0) return;
-            if (!tblStyles.getCellRect(index, 1, false).contains(evt.getPoint()))
-                return;
-            if (!tblStyles.isRowSelected(index)) {
-                tblStyles.setRowSelectionInterval(index, index);
-            }
-            MapPaintPopup menu = new MapPaintPopup();
-            menu.show(tblStyles, p.x, p.y);
-        }
-    }
-
+            super.launch(evt);
+        }
+
+        @Override
+        protected void showMenu(MouseEvent evt) {
+            menu = new MapPaintPopup();
+            super.showMenu(evt);
+        }
+    }
+
+    /**
+     * The popup menu displayed when right-clicking a map paint entry
+     */
     public class MapPaintPopup extends JPopupMenu {
         /**
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/RelationListDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/RelationListDialog.java	(revision 5957)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/RelationListDialog.java	(revision 5958)
@@ -6,8 +6,6 @@
 import java.awt.BorderLayout;
 import java.awt.Color;
-import java.awt.Point;
 import java.awt.event.ActionEvent;
 import java.awt.event.KeyEvent;
-import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
 import java.util.ArrayList;
@@ -29,5 +27,4 @@
 import javax.swing.KeyStroke;
 import javax.swing.ListSelectionModel;
-import javax.swing.SwingUtilities;
 import javax.swing.UIManager;
 import javax.swing.event.DocumentEvent;
@@ -70,4 +67,6 @@
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.gui.widgets.DisableShortcutsOnFocusGainedTextField;
+import org.openstreetmap.josm.gui.widgets.JosmTextField;
+import org.openstreetmap.josm.gui.widgets.PopupMenuLauncher;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.InputMapUtils;
@@ -75,5 +74,4 @@
 import org.openstreetmap.josm.tools.Shortcut;
 import org.openstreetmap.josm.tools.Utils;
-import org.openstreetmap.josm.gui.widgets.JosmTextField;
 
 /**
@@ -295,5 +293,10 @@
     }
 
-    class MouseEventHandler extends MouseAdapter {
+    class MouseEventHandler extends PopupMenuLauncher {
+        
+        public MouseEventHandler() {
+            super(popupMenu);
+        }
+        
         protected void setCurrentRelationAsSelection() {
             Main.main.getCurrentDataSet().setSelected((Relation)displaylist.getSelectedValue());
@@ -306,5 +309,5 @@
         @Override public void mouseClicked(MouseEvent e) {
             if (Main.main.getEditLayer() == null) return;
-            if (e.getClickCount() == 2 && SwingUtilities.isLeftMouseButton(e)) {
+            if (isDoubleClick(e)) {
                 if (e.isControlDown()) {
                     editCurrentRelation();
@@ -312,27 +315,4 @@
                     setCurrentRelationAsSelection();
                 }
-            }
-        }
-        private void openPopup(MouseEvent e) {
-            Point p = e.getPoint();
-            int index = displaylist.locationToIndex(p);
-            if (index < 0) return;
-            if (!displaylist.getCellBounds(index, index).contains(e.getPoint()))
-                return;
-            if (! displaylist.isSelectedIndex(index)) {
-                displaylist.setSelectedIndex(index);
-            }
-            popupMenu.show(displaylist, p.x, p.y-3);
-        }
-        @Override public void mousePressed(MouseEvent e) {
-            if (Main.main.getEditLayer() == null) return;
-            if (e.isPopupTrigger()) {
-                openPopup(e);
-            }
-        }
-        @Override public void mouseReleased(MouseEvent e) {
-            if (Main.main.getEditLayer() == null) return;
-            if (e.isPopupTrigger()) {
-                openPopup(e);
             }
         }
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/SelectionListDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/SelectionListDialog.java	(revision 5957)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/SelectionListDialog.java	(revision 5958)
@@ -10,5 +10,4 @@
 import java.awt.event.ActionListener;
 import java.awt.event.KeyEvent;
-import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
 import java.util.ArrayList;
@@ -29,5 +28,4 @@
 import javax.swing.JPopupMenu;
 import javax.swing.ListSelectionModel;
-import javax.swing.SwingUtilities;
 import javax.swing.event.ListDataEvent;
 import javax.swing.event.ListDataListener;
@@ -153,6 +151,5 @@
         });
                 
-        lstPrimitives.addMouseListener(new SelectionPopupMenuLauncher());
-        lstPrimitives.addMouseListener(new DblClickHandler());
+        lstPrimitives.addMouseListener(new MouseEventHandler());
 
         InputMapUtils.addEnterAction(lstPrimitives, actZoomToListSelection);
@@ -182,31 +179,21 @@
 
     /**
-     * Responds to double clicks on the list of selected objects
-     */
-    class DblClickHandler extends MouseAdapter {
+     * Responds to double clicks on the list of selected objects and launches the popup menu
+     */
+    class MouseEventHandler extends PopupMenuLauncher {
+        
+        public MouseEventHandler() {
+            super(popupMenu);
+        }
+        
         @Override
         public void mouseClicked(MouseEvent e) {
-            if (e.getClickCount() < 2 || ! SwingUtilities.isLeftMouseButton(e)) return;
-            int idx = lstPrimitives.locationToIndex(e.getPoint());
-            if (idx < 0) return;
-            OsmDataLayer layer = Main.main.getEditLayer();
-            if(layer == null) return;
-            layer.data.setSelected(Collections.singleton((OsmPrimitive)model.getElementAt(idx)));
-        }
-    }
-
-    /**
-     * The popup menu launcher
-     */
-    class SelectionPopupMenuLauncher extends PopupMenuLauncher {
-
-        @Override
-        public void launch(MouseEvent evt) {
-            if (model.getSelected().isEmpty()) {
-                int idx = lstPrimitives.locationToIndex(evt.getPoint());
+            if (isDoubleClick(e)) {
+                int idx = lstPrimitives.locationToIndex(e.getPoint());
                 if (idx < 0) return;
-                model.setSelected(Collections.singleton((OsmPrimitive)model.getElementAt(idx)));
-            }
-            popupMenu.show(lstPrimitives, evt.getX(), evt.getY());
+                OsmDataLayer layer = Main.main.getEditLayer();
+                if (layer == null) return;
+                layer.data.setSelected(Collections.singleton((OsmPrimitive)model.getElementAt(idx)));
+            }
         }
     }
@@ -758,6 +745,5 @@
 
     /**
-     * The popup menue for the JOSM selection history entries
-     *
+     * The popup menu for the JOSM selection history entries
      */
     protected static class SelectionHistoryPopup extends JPopupMenu {
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/ToggleDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/ToggleDialog.java	(revision 5957)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/ToggleDialog.java	(revision 5958)
@@ -21,5 +21,4 @@
 import java.awt.event.ComponentAdapter;
 import java.awt.event.ComponentEvent;
-import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
 import java.awt.event.WindowAdapter;
@@ -47,4 +46,5 @@
 import javax.swing.JScrollPane;
 import javax.swing.JToggleButton;
+import javax.swing.SwingUtilities;
 
 import org.openstreetmap.josm.Main;
@@ -61,4 +61,5 @@
 import org.openstreetmap.josm.gui.preferences.SubPreferenceSetting;
 import org.openstreetmap.josm.gui.preferences.TabPreferenceSetting;
+import org.openstreetmap.josm.gui.widgets.PopupMenuLauncher;
 import org.openstreetmap.josm.tools.Destroyable;
 import org.openstreetmap.josm.tools.GBC;
@@ -477,64 +478,5 @@
             add(lblTitle_weak, GBC.std().fill(GBC.HORIZONTAL));
 
-            addMouseListener(
-                    new MouseAdapter() {
-                        @Override
-                        public void mouseClicked(MouseEvent e) {
-                            if (isCollapsed) {
-                                expand();
-                                dialogsPanel.reconstruct(Action.COLLAPSED_TO_DEFAULT, ToggleDialog.this);
-                            } else {
-                                collapse();
-                                dialogsPanel.reconstruct(Action.ELEMENT_SHRINKS, null);
-                            }
-                        }
-
-                        private void maybeShowPopup(MouseEvent e) {
-                            if (e.isPopupTrigger()) {
-                                JPopupMenu menu = new JPopupMenu();
-                                JMenu buttonHidingMenu = new JMenu(tr("Side buttons"));
-                                JRadioButtonMenuItem alwaysShown = new JRadioButtonMenuItem(new AbstractAction(tr("Always shown")) {
-                                    @Override
-                                    public void actionPerformed(ActionEvent e) {
-                                        setIsButtonHiding(ButtonHiddingType.ALWAYS_SHOWN);
-                                    }
-                                });
-                                JRadioButtonMenuItem dynamic = new JRadioButtonMenuItem(new AbstractAction(tr("Dynamic")) {
-                                    @Override
-                                    public void actionPerformed(ActionEvent e) {
-                                        setIsButtonHiding(ButtonHiddingType.DYNAMIC);
-                                    }
-                                });
-                                JRadioButtonMenuItem alwaysHidden = new JRadioButtonMenuItem(new AbstractAction(tr("Always hidden")) {
-                                    @Override
-                                    public void actionPerformed(ActionEvent e) {
-                                        setIsButtonHiding(ButtonHiddingType.ALWAYS_HIDDEN);
-                                    }
-                                });
-                                alwaysShown.setSelected(buttonHiding == ButtonHiddingType.ALWAYS_SHOWN);
-                                dynamic.setSelected(buttonHiding == ButtonHiddingType.DYNAMIC);
-                                alwaysHidden.setSelected(buttonHiding == ButtonHiddingType.ALWAYS_HIDDEN);
-                                buttonHidingMenu.add(alwaysShown);
-                                buttonHidingMenu.add(dynamic);
-                                buttonHidingMenu.add(alwaysHidden);
-                                menu.add(buttonHidingMenu);
-                                for (javax.swing.Action action: buttonActions) {
-                                    menu.add(action);
-                                }
-                                menu.show(TitleBar.this, e.getX(), e.getY());
-                            }
-                        }
-
-                        @Override
-                        public void mousePressed(MouseEvent e) {
-                            maybeShowPopup(e);
-                        }
-
-                        @Override
-                        public void mouseReleased(MouseEvent e) {
-                            maybeShowPopup(e);
-                        }
-                    }
-                    );
+            addMouseListener(new MouseEventHandler());
 
             if(Main.pref.getBoolean("dialog.dynamic.buttons", true)) {
@@ -616,4 +558,52 @@
             return lblTitle.getText();
         }
+        
+        public class DialogPopupMenu extends JPopupMenu {
+            public final JMenu buttonHidingMenu = new JMenu(tr("Side buttons"));
+            public final JRadioButtonMenuItem alwaysShown = new JRadioButtonMenuItem(new AbstractAction(tr("Always shown")) {
+                @Override public void actionPerformed(ActionEvent e) {
+                    setIsButtonHiding(ButtonHiddingType.ALWAYS_SHOWN);
+                }
+            });
+            public final JRadioButtonMenuItem dynamic = new JRadioButtonMenuItem(new AbstractAction(tr("Dynamic")) {
+                @Override public void actionPerformed(ActionEvent e) {
+                    setIsButtonHiding(ButtonHiddingType.DYNAMIC);
+                }
+            });
+            public final JRadioButtonMenuItem alwaysHidden = new JRadioButtonMenuItem(new AbstractAction(tr("Always hidden")) {
+                @Override public void actionPerformed(ActionEvent e) {
+                    setIsButtonHiding(ButtonHiddingType.ALWAYS_HIDDEN);
+                }
+            });
+            public DialogPopupMenu() {
+                alwaysShown.setSelected(buttonHiding == ButtonHiddingType.ALWAYS_SHOWN);
+                dynamic.setSelected(buttonHiding == ButtonHiddingType.DYNAMIC);
+                alwaysHidden.setSelected(buttonHiding == ButtonHiddingType.ALWAYS_HIDDEN);
+                buttonHidingMenu.add(alwaysShown);
+                buttonHidingMenu.add(dynamic);
+                buttonHidingMenu.add(alwaysHidden);
+                add(buttonHidingMenu);
+                for (javax.swing.Action action: buttonActions) {
+                    add(action);
+                }
+            }
+        }
+        
+        class MouseEventHandler extends PopupMenuLauncher {
+            public MouseEventHandler() {
+                super(new DialogPopupMenu());
+            }
+            @Override public void mouseClicked(MouseEvent e) {
+                if (SwingUtilities.isLeftMouseButton(e)) {
+                    if (isCollapsed) {
+                        expand();
+                        dialogsPanel.reconstruct(Action.COLLAPSED_TO_DEFAULT, ToggleDialog.this);
+                    } else {
+                        collapse();
+                        dialogsPanel.reconstruct(Action.ELEMENT_SHRINKS, null);
+                    }
+                }
+            }
+        }
     }
 
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/ValidatorDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/ValidatorDialog.java	(revision 5957)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/ValidatorDialog.java	(revision 5958)
@@ -5,7 +5,5 @@
 
 import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
 import java.awt.event.KeyEvent;
-import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
 import java.io.IOException;
@@ -21,5 +19,4 @@
 import javax.swing.AbstractAction;
 import javax.swing.JComponent;
-import javax.swing.JMenuItem;
 import javax.swing.JOptionPane;
 import javax.swing.JPopupMenu;
@@ -45,4 +42,5 @@
 import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
 import org.openstreetmap.josm.gui.PleaseWaitRunnable;
+import org.openstreetmap.josm.gui.PopupMenuHandler;
 import org.openstreetmap.josm.gui.SideButton;
 import org.openstreetmap.josm.gui.dialogs.validator.ValidatorTreePanel;
@@ -51,4 +49,5 @@
 import org.openstreetmap.josm.gui.preferences.ValidatorPreference;
 import org.openstreetmap.josm.gui.progress.ProgressMonitor;
+import org.openstreetmap.josm.gui.widgets.PopupMenuLauncher;
 import org.openstreetmap.josm.io.OsmTransferException;
 import org.openstreetmap.josm.tools.ImageProvider;
@@ -65,6 +64,4 @@
  */
 public class ValidatorDialog extends ToggleDialog implements SelectionChangedListener, LayerChangeListener {
-    /** Serializable ID */
-    private static final long serialVersionUID = 2952292777351992696L;
 
     /** The display tree */
@@ -78,7 +75,7 @@
     private SideButton selectButton;
 
-    private JPopupMenu popupMenu;
-    private TestError popupMenuError = null;
-
+    private final JPopupMenu popupMenu = new JPopupMenu();
+    private final PopupMenuHandler popupMenuHandler = new PopupMenuHandler(popupMenu);
+    
     /** Last selected element */
     private DefaultMutableTreeNode lastSelectedNode = null;
@@ -94,18 +91,9 @@
                         KeyEvent.VK_V, Shortcut.ALT_SHIFT), 150, false, ValidatorPreference.class);
 
-        popupMenu = new JPopupMenu();
-
-        JMenuItem zoomTo = new JMenuItem(tr("Zoom to problem"));
-        zoomTo.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                zoomToProblem();
-            }
-        });
-        popupMenu.add(zoomTo);
+        popupMenuHandler.addAction(Main.main.menu.autoScaleActions.get("problem"));
 
         tree = new ValidatorTreePanel();
-        tree.addMouseListener(new ClickWatch());
-        tree.addTreeSelectionListener(new SelectionWatch());
+        tree.addMouseListener(new MouseEventHandler());
+        addTreeSelectionListener(new SelectionWatch());
         InputMapUtils.unassignCtrlShiftUpDown(tree, JComponent.WHEN_FOCUSED);
 
@@ -317,29 +305,4 @@
     }
 
-    private void showPopupMenu(MouseEvent e) {
-        if (!e.isPopupTrigger())
-            return;
-        popupMenuError = null;
-        TreePath selPath = tree.getPathForLocation(e.getX(), e.getY());
-        if (selPath == null)
-            return;
-        DefaultMutableTreeNode node = (DefaultMutableTreeNode) selPath.getPathComponent(selPath.getPathCount() - 1);
-        if (!(node.getUserObject() instanceof TestError))
-            return;
-        popupMenuError = (TestError) node.getUserObject();
-        popupMenu.show(e.getComponent(), e.getX(), e.getY());
-    }
-
-    private void zoomToProblem() {
-        if (popupMenuError == null)
-            return;
-        ValidatorBoundingXYVisitor bbox = new ValidatorBoundingXYVisitor();
-        bbox.visit(popupMenuError);
-        if (bbox.getBounds() == null)
-            return;
-        bbox.enlargeBoundingBox(Main.pref.getDouble("validator.zoom-enlarge-bbox", 0.0002));
-        Main.map.mapView.recalculateCenterScale(bbox);
-    }
-
     /**
      * Sets the selection of the map to the current selected items.
@@ -447,7 +410,55 @@
 
     /**
-     * Watches for clicks.
-     */
-    public class ClickWatch extends MouseAdapter {
+     * Add a tree selection listener to the validator tree.
+     * @param listener the TreeSelectionListener
+     * @since 5958
+     */
+    public void addTreeSelectionListener(TreeSelectionListener listener) {
+        tree.addTreeSelectionListener(listener);
+    }
+    
+    /**
+     * Remove the given tree selection listener from the validator tree.
+     * @param listener the TreeSelectionListener
+     * @since 5958
+     */
+    public void removeTreeSelectionListener(TreeSelectionListener listener) {
+        tree.removeTreeSelectionListener(listener);
+    }
+    
+    /**
+     * Replies the popup menu handler.
+     * @return The popup menu handler
+     * @since 5958
+     */
+    public PopupMenuHandler getPopupMenuHandler() {
+        return popupMenuHandler;
+    }
+    
+    /**
+     * Replies the currently selected error, or {@code null}.
+     * @return The selected error, if any.
+     * @since 5958
+     */
+    public TestError getSelectedError() {
+        Object comp = tree.getLastSelectedPathComponent();
+        if (comp instanceof DefaultMutableTreeNode) {
+            Object object = ((DefaultMutableTreeNode)comp).getUserObject();
+            if (object instanceof TestError) {
+                return (TestError) object;
+            }
+        }
+        return null;
+    }
+    
+    /**
+     * Watches for double clicks and launches the popup menu.
+     */
+    class MouseEventHandler extends PopupMenuLauncher {
+        
+        public MouseEventHandler() {
+            super(popupMenu);
+        }
+        
         @Override
         public void mouseClicked(MouseEvent e) {
@@ -458,5 +469,5 @@
             selectButton.setEnabled(false);
 
-            boolean isDblClick = e.getClickCount() > 1;
+            boolean isDblClick = isDoubleClick(e);
 
             Collection<OsmPrimitive> sel = isDblClick ? new HashSet<OsmPrimitive>(40) : null;
@@ -467,18 +478,18 @@
             if (isDblClick) {
                 Main.main.getCurrentDataSet().setSelected(sel);
-                if(Main.pref.getBoolean("validator.autozoom", false)) {
+                if (Main.pref.getBoolean("validator.autozoom", false)) {
                     AutoScaleAction.zoomTo(sel);
                 }
             }
         }
-
-        @Override
-        public void mousePressed(MouseEvent e) {
-            showPopupMenu(e);
-        }
-
-        @Override
-        public void mouseReleased(MouseEvent e) {
-            showPopupMenu(e);
+        
+        @Override public void launch(MouseEvent e) {
+            TreePath selPath = tree.getPathForLocation(e.getX(), e.getY());
+            if (selPath == null)
+                return;
+            DefaultMutableTreeNode node = (DefaultMutableTreeNode) selPath.getPathComponent(selPath.getPathCount() - 1);
+            if (!(node.getUserObject() instanceof TestError))
+                return;
+            super.launch(e);
         }
 
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetCacheManager.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetCacheManager.java	(revision 5957)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetCacheManager.java	(revision 5958)
@@ -10,5 +10,4 @@
 import java.awt.event.ActionEvent;
 import java.awt.event.KeyEvent;
-import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
 import java.awt.event.WindowAdapter;
@@ -33,5 +32,4 @@
 import javax.swing.KeyStroke;
 import javax.swing.ListSelectionModel;
-import javax.swing.SwingUtilities;
 import javax.swing.event.ListSelectionEvent;
 import javax.swing.event.ListSelectionListener;
@@ -249,6 +247,5 @@
                 model.getSelectionModel()
         );
-        tblChangesets.addMouseListener(new ChangesetTablePopupMenuLauncher());
-        tblChangesets.addMouseListener(new DblClickHandler());
+        tblChangesets.addMouseListener(new MouseEventHandler());
         tblChangesets.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,0), "showDetails");
         tblChangesets.getActionMap().put("showDetails", new ShowDetailAction());
@@ -559,24 +556,15 @@
     }
 
-    class DblClickHandler extends MouseAdapter {
+    class MouseEventHandler extends PopupMenuLauncher {
+        
+        public MouseEventHandler() {
+            super(new ChangesetTablePopupMenu());
+        }
+        
         @Override
         public void mouseClicked(MouseEvent evt) {
-            if (! SwingUtilities.isLeftMouseButton(evt) || evt.getClickCount()<2)
-                return;
-            new ShowDetailAction().showDetails();
-        }
-    }
-
-    class ChangesetTablePopupMenuLauncher extends PopupMenuLauncher {
-        ChangesetTablePopupMenu menu = new ChangesetTablePopupMenu();
-        @Override
-        public void launch(MouseEvent evt) {
-            if (! model.hasSelectedChangesets()) {
-                int row = tblChangesets.rowAtPoint(evt.getPoint());
-                if (row >= 0) {
-                    model.setSelectedByIdx(row);
-                }
-            }
-            menu.show(tblChangesets, evt.getPoint().x, evt.getPoint().y);
+            if (isDoubleClick(evt)) {
+                new ShowDetailAction().showDetails();
+            }
         }
     }
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetCacheManagerModel.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetCacheManagerModel.java	(revision 5957)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetCacheManagerModel.java	(revision 5958)
@@ -19,4 +19,5 @@
 import org.openstreetmap.josm.data.osm.ChangesetCacheEvent;
 import org.openstreetmap.josm.data.osm.ChangesetCacheListener;
+import org.openstreetmap.josm.gui.util.GuiHelper;
 
 /**
@@ -104,23 +105,21 @@
      */
     public void setSelectedChangesets(Collection<Changeset> selected) {
-        selectionModel.clearSelection();
+        GuiHelper.runInEDTAndWait(new Runnable() {
+            @Override public void run() {
+                selectionModel.clearSelection();
+            }
+        });
         if (selected == null || selected.isEmpty())
             return;
         for (Changeset cs: selected) {
-            int idx = data.indexOf(cs);
+            final int idx = data.indexOf(cs);
             if (idx >= 0) {
-                selectionModel.addSelectionInterval(idx,idx);
+                GuiHelper.runInEDTAndWait(new Runnable() {
+                    @Override public void run() {
+                        selectionModel.addSelectionInterval(idx,idx);
+                    }
+                });
             }
         }
-    }
-
-    /**
-     * Selects the changeset displayed at row <code>row</code>
-     *
-     * @param row the row. Ignored if < 0 or >= {@link #getRowCount()}
-     */
-    public void setSelectedByIdx(int row) {
-        if (row < 0 || row >= getRowCount()) return;
-        selectionModel.setSelectionInterval(row, row);
     }
 
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetContentPanel.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetContentPanel.java	(revision 5957)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetContentPanel.java	(revision 5958)
@@ -10,6 +10,4 @@
 import java.awt.event.ComponentAdapter;
 import java.awt.event.ComponentEvent;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
 import java.beans.PropertyChangeEvent;
 import java.beans.PropertyChangeListener;
@@ -31,5 +29,4 @@
 import javax.swing.JTable;
 import javax.swing.JToolBar;
-import javax.swing.SwingUtilities;
 import javax.swing.event.ListSelectionEvent;
 import javax.swing.event.ListSelectionListener;
@@ -50,4 +47,6 @@
 import org.openstreetmap.josm.gui.history.HistoryLoadTask;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.gui.util.GuiHelper;
+import org.openstreetmap.josm.gui.widgets.PopupMenuLauncher;
 import org.openstreetmap.josm.tools.BugReportExceptionHandler;
 import org.openstreetmap.josm.tools.ImageProvider;
@@ -109,5 +108,5 @@
                 model.getSelectionModel()
         );
-        tblContent.addMouseListener(new ChangesetContentTablePopupMenuLauncher());
+        tblContent.addMouseListener(new PopupMenuLauncher(new ChangesetContentTablePopupMenu()));
         pnl.add(new JScrollPane(tblContent), BorderLayout.CENTER);
         return pnl;
@@ -139,8 +138,15 @@
     }
 
+    /**
+     * Constructs a new {@code ChangesetContentPanel}.
+     */
     public ChangesetContentPanel() {
         build();
     }
 
+    /**
+     * Replies the changeset content model
+     * @return The model
+     */
     public ChangesetContentTableModel getModel() {
         return model;
@@ -204,34 +210,4 @@
     }
 
-    class ChangesetContentTablePopupMenuLauncher extends MouseAdapter {
-        ChangesetContentTablePopupMenu menu = new ChangesetContentTablePopupMenu();
-
-        protected void launch(MouseEvent evt) {
-            if (! evt.isPopupTrigger()) return;
-            if (! model.hasSelectedPrimitives()) {
-                int row = tblContent.rowAtPoint(evt.getPoint());
-                if (row >= 0) {
-                    model.setSelectedByIdx(row);
-                }
-            }
-            menu.show(tblContent, evt.getPoint().x, evt.getPoint().y);
-        }
-
-        @Override
-        public void mouseClicked(MouseEvent evt) {
-            launch(evt);
-        }
-
-        @Override
-        public void mousePressed(MouseEvent evt) {
-            launch(evt);
-        }
-
-        @Override
-        public void mouseReleased(MouseEvent evt) {
-            launch(evt);
-        }
-    }
-
     class ChangesetContentTablePopupMenu extends JPopupMenu {
         public ChangesetContentTablePopupMenu() {
@@ -277,12 +253,16 @@
                     try {
                         for (HistoryOsmPrimitive p : primitives) {
-                            History h = HistoryDataSet.getInstance().getHistory(p.getPrimitiveId());
+                            final History h = HistoryDataSet.getInstance().getHistory(p.getPrimitiveId());
                             if (h == null) {
                                 continue;
                             }
-                            HistoryBrowserDialogManager.getInstance().show(h);
+                            GuiHelper.runInEDT(new Runnable() {
+                                @Override public void run() {
+                                    HistoryBrowserDialogManager.getInstance().show(h);
+                                }
+                            });
                         }
                     } catch (final Exception e) {
-                        SwingUtilities.invokeLater(new Runnable() {
+                        GuiHelper.runInEDT(new Runnable() {
                             public void run() {
                                 BugReportExceptionHandler.handleException(e);
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/properties/PropertiesDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/properties/PropertiesDialog.java	(revision 5957)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/properties/PropertiesDialog.java	(revision 5958)
@@ -395,22 +395,14 @@
         membershipMenu.add(helpAction);
 
-        membershipTable.addMouseListener(new PopupMenuLauncher() {
+        membershipTable.addMouseListener(new PopupMenuLauncher(membershipMenu) {
             @Override
-            public void launch(MouseEvent evt) {
-                Point p = evt.getPoint();
-                int row = membershipTable.rowAtPoint(p);
-                int idx[] = membershipTable.getSelectedRows();
-                // if nothing or one row is selected, select row under mouse instead
-                if (idx.length<2 && row>-1) { 
-                    membershipTable.changeSelection(row, 0, false, false);
-                    idx = new int[]{row};
-                }
+            protected int checkTableSelection(JTable table, Point p) {
+                int row = super.checkTableSelection(table, p);
                 List<Relation> rels = new ArrayList<Relation>();
-                for (int i: idx) {
-                    Relation r = (Relation) (membershipData.getValueAt(i, 0));
-                    rels.add(r);
+                for (int i: table.getSelectedRows()) {
+                    rels.add((Relation) table.getValueAt(i, 0));
                 }
                 membershipMenuHandler.setPrimitives(rels);
-                membershipMenu.show(membershipTable, p.x, p.y-3);
+                return row;
             }
         });
@@ -430,19 +422,5 @@
         propertyMenu.addSeparator();
         propertyMenu.add(helpAction);
-        propertyTable.addMouseListener(new PopupMenuLauncher() {
-            @Override
-            public void launch(MouseEvent evt) {
-                Point p = evt.getPoint();
-                int row = propertyTable.rowAtPoint(p);
-                int selectedCount = propertyTable.getSelectedRowCount();
-                // if nothing or one row is selected, select row under mouse instead
-                if (selectedCount<2 && row>-1) { 
-                    propertyTable.changeSelection(row, 0, false, false);
-                }
-                if (selectedCount>=2 || row>-1) {
-                    propertyMenu.show(propertyTable, p.x, p.y-3);
-                }
-            }
-        });
+        propertyTable.addMouseListener(new PopupMenuLauncher(propertyMenu));
     }
     
Index: trunk/src/org/openstreetmap/josm/gui/download/BoundingBoxSelection.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/download/BoundingBoxSelection.java	(revision 5957)
+++ trunk/src/org/openstreetmap/josm/gui/download/BoundingBoxSelection.java	(revision 5958)
@@ -7,7 +7,4 @@
 import java.awt.Dimension;
 import java.awt.GridBagLayout;
-import java.awt.Toolkit;
-import java.awt.datatransfer.FlavorEvent;
-import java.awt.datatransfer.FlavorListener;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
@@ -17,10 +14,8 @@
 import java.awt.event.MouseEvent;
 
-import javax.swing.AbstractAction;
 import javax.swing.BorderFactory;
 import javax.swing.JButton;
 import javax.swing.JLabel;
 import javax.swing.JPanel;
-import javax.swing.JPopupMenu;
 import javax.swing.UIManager;
 import javax.swing.border.Border;
@@ -35,7 +30,5 @@
 import org.openstreetmap.josm.gui.widgets.JosmTextField;
 import org.openstreetmap.josm.tools.GBC;
-import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.OsmUrlToBounds;
-import org.openstreetmap.josm.tools.Utils;
 
 /**
@@ -121,29 +114,4 @@
         dlg.add(new JLabel(tr("URL from www.openstreetmap.org (you can paste an URL here to download the area)")), GBC.eol().insets(10,5,5,0));
         dlg.add(tfOsmUrl, GBC.eop().insets(10,0,5,0).fill());
-        tfOsmUrl.addMouseListener(
-                new MouseAdapter() {
-                    @Override
-                    public void mousePressed(MouseEvent e) {
-                        checkPopup(e);
-                    }
-
-                    @Override
-                    public void mouseClicked(MouseEvent e) {
-                        checkPopup(e);
-                    }
-
-                    @Override
-                    public void mouseReleased(MouseEvent e) {
-                        checkPopup(e);
-                    }
-
-                    private void checkPopup(MouseEvent e) {
-                        if (e.isPopupTrigger()) {
-                            OsmUrlPopup popup = new OsmUrlPopup();
-                            popup.show(tfOsmUrl, e.getX(), e.getY());
-                        }
-                    }
-                }
-        );
         dlg.add(showUrl, GBC.eop().insets(10,0,5,5));
         showUrl.setEditable(false);
@@ -299,35 +267,4 @@
     }
 
-    class PasteUrlAction extends AbstractAction implements FlavorListener {
-
-        public PasteUrlAction() {
-            putValue(NAME, tr("Paste"));
-            putValue(SMALL_ICON, ImageProvider.get("paste"));
-            putValue(SHORT_DESCRIPTION, tr("Paste URL from clipboard"));
-            Toolkit.getDefaultToolkit().getSystemClipboard().addFlavorListener(this);
-        }
-
-        public void actionPerformed(ActionEvent e) {
-            String content = Utils.getClipboardContent();
-            if (content != null) {
-                tfOsmUrl.setText(content);
-            }
-        }
-
-        protected void updateEnabledState() {
-            setEnabled(Utils.getClipboardContent() != null);
-        }
-
-        public void flavorsChanged(FlavorEvent e) {
-            updateEnabledState();
-        }
-    }
-
-    class OsmUrlPopup extends JPopupMenu {
-        public OsmUrlPopup() {
-            add(new PasteUrlAction());
-        }
-    }
-
     class BoundingBoxBuilder extends FocusAdapter implements ActionListener {
         protected Bounds build() {
Index: trunk/src/org/openstreetmap/josm/gui/history/NodeListViewer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/history/NodeListViewer.java	(revision 5957)
+++ trunk/src/org/openstreetmap/josm/gui/history/NodeListViewer.java	(revision 5958)
@@ -29,4 +29,6 @@
 import org.openstreetmap.josm.data.osm.history.HistoryDataSet;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.gui.util.GuiHelper;
+import org.openstreetmap.josm.gui.widgets.PopupMenuLauncher;
 import org.openstreetmap.josm.tools.ImageProvider;
 
@@ -66,5 +68,5 @@
         table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
         selectionSynchronizer.participateInSynchronizedSelection(table.getSelectionModel());
-        table.addMouseListener(new PopupMenuLauncher(table));
+        table.addMouseListener(new InternalPopupMenuLauncher());
         table.addMouseListener(new DoubleClickAdapter(table));
         return table;
@@ -79,5 +81,5 @@
         table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
         selectionSynchronizer.participateInSynchronizedSelection(table.getSelectionModel());
-        table.addMouseListener(new PopupMenuLauncher(table));
+        table.addMouseListener(new InternalPopupMenuLauncher());
         table.addMouseListener(new DoubleClickAdapter(table));
         return table;
@@ -115,4 +117,6 @@
         selectionSynchronizer = new SelectionSynchronizer();
 
+        popupMenu = new NodeListPopupMenu();
+
         // ---------------------------
         gc.gridx = 0;
@@ -135,6 +139,4 @@
         gc.anchor = GridBagConstraints.NORTHWEST;
         add(embeddInScrollPane(buildCurrentNodeListTable()),gc);
-
-        popupMenu = new NodeListPopupMenu();
     }
 
@@ -172,6 +174,6 @@
 
     static class NodeListPopupMenu extends JPopupMenu {
-        private ZoomToNodeAction zoomToNodeAction;
-        private ShowHistoryAction showHistoryAction;
+        private final ZoomToNodeAction zoomToNodeAction;
+        private final ShowHistoryAction showHistoryAction;
 
         public NodeListPopupMenu() {
@@ -262,8 +264,12 @@
             Runnable r = new Runnable() {
                 public void run() {
-                    History h = HistoryDataSet.getInstance().getHistory(primitiveId);
+                    final History h = HistoryDataSet.getInstance().getHistory(primitiveId);
                     if (h == null)
                         return;
-                    HistoryBrowserDialogManager.getInstance().show(h);
+                    GuiHelper.runInEDT(new Runnable() {
+                        @Override public void run() {
+                            HistoryBrowserDialogManager.getInstance().show(h);
+                        }
+                    });
                 }
             };
@@ -283,31 +289,13 @@
     }
 
-    class PopupMenuLauncher extends MouseAdapter {
-        private JTable table;
-
-        public PopupMenuLauncher(JTable table) {
-            this.table = table;
-        }
-
-        @Override
-        public void mousePressed(MouseEvent e) {
-            showPopup(e);
-        }
-
-        @Override
-        public void mouseReleased(MouseEvent e) {
-            showPopup(e);
-        }
-
-        private void showPopup(MouseEvent e) {
-            if (!e.isPopupTrigger()) return;
-            Point p = e.getPoint();
-            int row = table.rowAtPoint(p);
-
-            PrimitiveId pid = primitiveIdAtRow(table.getModel(), row);
-            if (pid == null)
-                return;
-            popupMenu.prepare(pid);
-            popupMenu.show(e.getComponent(), e.getX(), e.getY());
+    class InternalPopupMenuLauncher extends PopupMenuLauncher {
+        public InternalPopupMenuLauncher() {
+            super(popupMenu);
+        }
+
+        @Override protected int checkTableSelection(JTable table, Point p) {
+            int row = super.checkTableSelection(table, p);
+            popupMenu.prepare(primitiveIdAtRow(table.getModel(), row));
+            return row;
         }
     }
Index: trunk/src/org/openstreetmap/josm/gui/history/VersionTable.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/history/VersionTable.java	(revision 5957)
+++ trunk/src/org/openstreetmap/josm/gui/history/VersionTable.java	(revision 5958)
@@ -6,9 +6,9 @@
 import java.awt.Component;
 import java.awt.Dimension;
+import java.awt.Point;
 import java.awt.Rectangle;
 import java.awt.event.ActionEvent;
 import java.awt.event.ItemEvent;
 import java.awt.event.ItemListener;
-import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
 import java.util.Observable;
@@ -30,4 +30,5 @@
 import org.openstreetmap.josm.actions.AbstractInfoAction;
 import org.openstreetmap.josm.data.osm.history.HistoryOsmPrimitive;
+import org.openstreetmap.josm.gui.widgets.PopupMenuLauncher;
 import org.openstreetmap.josm.tools.ImageProvider;
 
@@ -85,18 +86,12 @@
     }
 
-    protected void showPopupMenu(MouseEvent evt) {
-        HistoryBrowserModel.VersionTableModel model = getVersionTableModel();
-        int row = rowAtPoint(evt.getPoint());
-        if (row > -1 && !model.isLatest(row)) {
-            HistoryOsmPrimitive primitive = model.getPrimitive(row);
-            popupMenu.prepare(primitive);
-            popupMenu.show(evt.getComponent(), evt.getX(), evt.getY());
-        }
-    }
-
-    class MouseListener extends MouseAdapter {
+    class MouseListener extends PopupMenuLauncher {
+        public MouseListener() {
+            super(popupMenu);
+        }
         @Override
         public void mousePressed(MouseEvent e) {
-            if (!showPopup(e) && e.getButton() == MouseEvent.BUTTON1) {
+            super.mousePressed(e);
+            if (!e.isPopupTrigger() && e.getButton() == MouseEvent.BUTTON1) {
                 int row = rowAtPoint(e.getPoint());
                 int col = columnAtPoint(e.getPoint());
@@ -108,13 +103,11 @@
         }
         @Override
-        public void mouseReleased(MouseEvent e) {
-            showPopup(e);
-        }
-        private boolean showPopup(MouseEvent e) {
-            if (e.isPopupTrigger()) {
-                showPopupMenu(e);
-                return true;
+        protected int checkTableSelection(JTable table, Point p) {
+            HistoryBrowserModel.VersionTableModel model = getVersionTableModel();
+            int row = rowAtPoint(p);
+            if (row > -1 && !model.isLatest(row)) {
+                popupMenu.prepare(model.getPrimitive(row));
             }
-            return false;
+            return row;
         }
     }
Index: trunk/src/org/openstreetmap/josm/gui/widgets/BoundingBoxSelectionPanel.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/widgets/BoundingBoxSelectionPanel.java	(revision 5957)
+++ trunk/src/org/openstreetmap/josm/gui/widgets/BoundingBoxSelectionPanel.java	(revision 5958)
@@ -8,15 +8,8 @@
 import java.awt.GridBagLayout;
 import java.awt.Insets;
-import java.awt.Toolkit;
-import java.awt.datatransfer.FlavorEvent;
-import java.awt.datatransfer.FlavorListener;
-import java.awt.event.ActionEvent;
-import java.awt.event.MouseEvent;
-
-import javax.swing.AbstractAction;
+
 import javax.swing.BorderFactory;
 import javax.swing.JLabel;
 import javax.swing.JPanel;
-import javax.swing.JPopupMenu;
 import javax.swing.event.DocumentEvent;
 import javax.swing.event.DocumentListener;
@@ -28,8 +21,5 @@
 import org.openstreetmap.josm.gui.JMultilineLabel;
 import org.openstreetmap.josm.tools.GBC;
-import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.OsmUrlToBounds;
-import org.openstreetmap.josm.tools.Utils;
-import org.openstreetmap.josm.gui.widgets.JosmTextField;
 
 /**
@@ -87,11 +77,4 @@
         gc.insets = new Insets(3,0,0,3);
         add(tfOsmUrl, gc);
-        tfOsmUrl.addMouseListener(new PopupMenuLauncher() {
-            @Override
-            public void launch(MouseEvent e) {
-                OsmUrlPopup popup = new OsmUrlPopup();
-                popup.show(tfOsmUrl, e.getX(), e.getY());
-            }
-        });
     }
 
@@ -224,34 +207,3 @@
         public void removeUpdate(DocumentEvent e) { parseURL(); }
     }
-
-    class PasteUrlAction extends AbstractAction implements FlavorListener {
-
-        public PasteUrlAction() {
-            putValue(NAME, tr("Paste"));
-            putValue(SMALL_ICON, ImageProvider.get("paste"));
-            putValue(SHORT_DESCRIPTION, tr("Paste URL from clipboard"));
-            Toolkit.getDefaultToolkit().getSystemClipboard().addFlavorListener(this);
-        }
-
-        public void actionPerformed(ActionEvent e) {
-            String content = Utils.getClipboardContent();
-            if (content != null) {
-                tfOsmUrl.setText(content);
-            }
-        }
-
-        protected void updateEnabledState() {
-            setEnabled(Utils.getClipboardContent() != null);
-        }
-
-        public void flavorsChanged(FlavorEvent e) {
-            updateEnabledState();
-        }
-    }
-
-    class OsmUrlPopup extends JPopupMenu {
-        public OsmUrlPopup() {
-            add(new PasteUrlAction());
-        }
-    }
 }
Index: trunk/src/org/openstreetmap/josm/gui/widgets/OsmPrimitivesTable.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/widgets/OsmPrimitivesTable.java	(revision 5957)
+++ trunk/src/org/openstreetmap/josm/gui/widgets/OsmPrimitivesTable.java	(revision 5958)
@@ -37,5 +37,5 @@
     public OsmPrimitivesTable(OsmPrimitivesTableModel dm, TableColumnModel cm, ListSelectionModel sm) {
         super(dm, cm, sm);
-        addMouseListener(new PopupListener());
+        addMouseListener(new PopupMenuLauncher(getPopUpMenu()));
         addMouseListener(new DblClickHandler());
     }
@@ -76,22 +76,4 @@
     }
 
-    protected class PopupListener extends MouseAdapter {
-        @Override
-        public void mousePressed(MouseEvent e) {
-            showPopup(e);
-        }
-
-        @Override
-        public void mouseReleased(MouseEvent e) {
-            showPopup(e);
-        }
-
-        private void showPopup(MouseEvent e) {
-            if (e.isPopupTrigger()) {
-                getPopUpMenu().show(e.getComponent(), e.getX(), e.getY());
-            }
-        }
-    }
-    
     protected class DblClickHandler extends MouseAdapter {
 
Index: trunk/src/org/openstreetmap/josm/gui/widgets/PopupMenuLauncher.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/widgets/PopupMenuLauncher.java	(revision 5957)
+++ trunk/src/org/openstreetmap/josm/gui/widgets/PopupMenuLauncher.java	(revision 5958)
@@ -3,4 +3,5 @@
 
 import java.awt.Component;
+import java.awt.Point;
 import java.awt.event.FocusEvent;
 import java.awt.event.FocusListener;
@@ -8,5 +9,10 @@
 import java.awt.event.MouseEvent;
 
+import javax.swing.JList;
 import javax.swing.JPopupMenu;
+import javax.swing.JTable;
+import javax.swing.JTree;
+import javax.swing.SwingUtilities;
+import javax.swing.tree.TreePath;
 
 /**
@@ -15,5 +21,5 @@
  */
 public class PopupMenuLauncher extends MouseAdapter {
-    private final JPopupMenu menu;
+    protected JPopupMenu menu;
     private final boolean checkEnabled;
 
@@ -47,5 +53,5 @@
 
     @Override public void mousePressed(MouseEvent e) { processEvent(e); }
-    @Override public void mouseClicked(MouseEvent e) { processEvent(e); }
+    @Override public void mouseClicked(MouseEvent e) {}
     @Override public void mouseReleased(MouseEvent e) { processEvent(e); }
     
@@ -62,18 +68,69 @@
      */
     public void launch(final MouseEvent evt) {
-        if (menu != null) {
+        if (evt != null) {
             final Component component = evt.getComponent();
-            if (component != null && component.isFocusable() && !component.hasFocus() && component.requestFocusInWindow()) {
-                component.addFocusListener(new FocusListener() {
-                    @Override public void focusLost(FocusEvent e) {}
-                    @Override public void focusGained(FocusEvent e) {
-                        menu.show(component, evt.getX(), evt.getY());
-                        component.removeFocusListener(this);
-                    }
-                });
-            } else {
-                menu.show(component, evt.getX(), evt.getY());
+            if (checkSelection(component, evt.getPoint())) {
+                checkFocusAndShowMenu(component, evt);
             }
         }
+    }
+    
+    protected boolean checkSelection(Component component, Point p) {
+        if (component instanceof JList) {
+            return checkListSelection((JList) component, p) > -1;
+        } else if (component instanceof JTable) {
+            return checkTableSelection((JTable) component, p) > -1;
+        } else if (component instanceof JTree) {
+            return checkTreeSelection((JTree) component, p) != null;
+        }
+        return true;
+    }
+    
+    protected void checkFocusAndShowMenu(final Component component, final MouseEvent evt) {
+        if (component != null && component.isFocusable() && !component.hasFocus() && component.requestFocusInWindow()) {
+            component.addFocusListener(new FocusListener() {
+                @Override public void focusLost(FocusEvent e) {}
+                @Override public void focusGained(FocusEvent e) {
+                    showMenu(evt);
+                    component.removeFocusListener(this);
+                }
+            });
+        } else {
+            showMenu(evt);
+        }
+    }
+    
+    protected void showMenu(MouseEvent evt) {
+        if (menu != null && evt != null) {
+            menu.show(evt.getComponent(), evt.getX(), evt.getY());
+        }
+    }
+    
+    protected int checkListSelection(JList list, Point p) {
+        int idx = list.locationToIndex(p);
+        if (idx >= 0 && idx < list.getModel().getSize() && list.getSelectedIndices().length < 2 && !list.isSelectedIndex(idx)) {
+            list.setSelectedIndex(idx);
+        }
+        return idx;
+    }
+
+    protected int checkTableSelection(JTable table, Point p) {
+        int row = table.rowAtPoint(p);
+        if (row >= 0 && row < table.getRowCount() && table.getSelectedRowCount() < 2 && table.getSelectedRow() != row) {
+            table.getSelectionModel().setSelectionInterval(row, row);
+        }
+        return row;
+    }
+    
+    protected TreePath checkTreeSelection(JTree tree, Point p) {
+        TreePath path = tree.getPathForLocation(p.x, p.y);
+        if (path != null && tree.getSelectionCount() < 2 && !tree.isPathSelected(path)) {
+            tree.setSelectionPath(path);
+        }
+        return path;
+    }
+    
+    protected static boolean isDoubleClick(MouseEvent e) {
+        return e != null && SwingUtilities.isLeftMouseButton(e) && e.getClickCount() == 2;
     }
     
