Index: src/org/openstreetmap/josm/gui/MapView.java
===================================================================
--- src/org/openstreetmap/josm/gui/MapView.java	(revision 3695)
+++ src/org/openstreetmap/josm/gui/MapView.java	(working copy)
@@ -3,6 +3,7 @@ package org.openstreetmap.josm.gui;
 
 import static org.openstreetmap.josm.tools.I18n.tr;
 
+import java.awt.AlphaComposite;
 import java.awt.Color;
 import java.awt.Graphics;
 import java.awt.Graphics2D;
@@ -183,6 +184,7 @@ public class MapView extends NavigatableComponent implements PropertyChangeListe
     private BufferedImage offscreenBuffer;
     // Layers that wasn't changed since last paint
     private final List<Layer> nonChangedLayers = new ArrayList<Layer>();
+    private Layer changedLayer;
     private int lastViewID;
     private boolean paintPreferencesChanged = true;
     private Rectangle lastClipBounds = new Rectangle();
@@ -439,6 +441,14 @@ public class MapView extends NavigatableComponent implements PropertyChangeListe
         return ret;
     }
 
+    private void paintLayer(Layer layer, Graphics2D g, Bounds box) {
+        if (layer.getOpacity() < 1) {
+            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,(float)layer.getOpacity()));
+        }
+        layer.paint(g, this, box);
+        g.setPaintMode();
+    }
+
     /**
      * Draw the component.
      */
@@ -453,7 +463,7 @@ public class MapView extends NavigatableComponent implements PropertyChangeListe
 
         int nonChangedLayersCount = 0;
         for (Layer l: visibleLayers) {
-            if (l.isChanged()) {
+            if (l.isChanged() || l == changedLayer) {
                 break;
             } else {
                 nonChangedLayersCount++;
@@ -489,7 +499,7 @@ public class MapView extends NavigatableComponent implements PropertyChangeListe
             g2.fillRect(0, 0, getWidth(), getHeight());
 
             for (int i=0; i<nonChangedLayersCount; i++) {
-                visibleLayers.get(i).paint(g2, this, box);
+                paintLayer(visibleLayers.get(i),g2, box);
             }
         } else {
             // Maybe there were more unchanged layers then last time - draw them to buffer
@@ -497,12 +507,13 @@ public class MapView extends NavigatableComponent implements PropertyChangeListe
                 Graphics2D g2 = nonChangedLayersBuffer.createGraphics();
                 g2.setClip(g.getClip());
                 for (int i=nonChangedLayers.size(); i<nonChangedLayersCount; i++) {
-                    visibleLayers.get(i).paint(g2, this, box);
+                    paintLayer(visibleLayers.get(i),g2, box);
                 }
             }
         }
 
         nonChangedLayers.clear();
+        changedLayer = null;
         for (int i=0; i<nonChangedLayersCount; i++) {
             nonChangedLayers.add(visibleLayers.get(i));
         }
@@ -513,7 +524,7 @@ public class MapView extends NavigatableComponent implements PropertyChangeListe
         tempG.drawImage(nonChangedLayersBuffer, 0, 0, null);
 
         for (int i=nonChangedLayersCount; i<visibleLayers.size(); i++) {
-            visibleLayers.get(i).paint(tempG, this, box);
+            paintLayer(visibleLayers.get(i),tempG, box);
         }
 
         for (MapViewPaintable mvp : temporaryLayers) {
@@ -782,6 +793,12 @@ public class MapView extends NavigatableComponent implements PropertyChangeListe
     public void propertyChange(PropertyChangeEvent evt) {
         if (evt.getPropertyName().equals(Layer.VISIBLE_PROP)) {
             repaint();
+        } else if (evt.getPropertyName().equals(Layer.OPACITY_PROP)) {
+            Layer l = (Layer)evt.getSource();
+            if (l.isVisible()) {
+                changedLayer = l;
+                repaint();
+            }
         } else if (evt.getPropertyName().equals(OsmDataLayer.REQUIRES_SAVE_TO_DISK_PROP)
                 || evt.getPropertyName().equals(OsmDataLayer.REQUIRES_UPLOAD_TO_SERVER_PROP)) {
             OsmDataLayer layer = (OsmDataLayer)evt.getSource();
Index: src/org/openstreetmap/josm/gui/dialogs/LayerListDialog.java
===================================================================
--- src/org/openstreetmap/josm/gui/dialogs/LayerListDialog.java	(revision 3695)
+++ src/org/openstreetmap/josm/gui/dialogs/LayerListDialog.java	(working copy)
@@ -30,13 +30,17 @@ import javax.swing.JComponent;
 import javax.swing.JLabel;
 import javax.swing.JMenuItem;
 import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
 import javax.swing.JScrollPane;
+import javax.swing.JSlider;
 import javax.swing.JTable;
 import javax.swing.JTextField;
 import javax.swing.JViewport;
 import javax.swing.KeyStroke;
 import javax.swing.ListSelectionModel;
 import javax.swing.UIManager;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
 import javax.swing.event.ListSelectionEvent;
 import javax.swing.event.ListSelectionListener;
 import javax.swing.event.TableModelEvent;
@@ -107,6 +111,8 @@ public class LayerListDialog extends ToggleDialog {
     /** the list of layers (technically its a JTable, but appears like a list) */
     private LayerList layerList;
 
+    private SideButton opacityButton;
+
     ActivateLayerAction activateLayerAction;
 
     protected JPanel createButtonPanel() {
@@ -152,6 +158,12 @@ public class LayerListDialog extends ToggleDialog {
         adaptTo(deleteLayerAction, selectionModel);
         buttonPanel.add(new SideButton(deleteLayerAction, false));
 
+        //-- layer opacity action
+        LayerOpacityAction layerOpacityAction = new LayerOpacityAction();
+        adaptTo(layerOpacityAction, selectionModel);
+        opacityButton = new SideButton(layerOpacityAction);
+        buttonPanel.add(opacityButton);
+
         return buttonPanel;
     }
 
@@ -184,7 +196,7 @@ public class LayerListDialog extends ToggleDialog {
         layerList.getColumnModel().getColumn(0).setPreferredWidth(12);
         layerList.getColumnModel().getColumn(0).setResizable(false);
         layerList.getColumnModel().getColumn(1).setCellRenderer(new LayerVisibleCellRenderer());
-        layerList.getColumnModel().getColumn(1).setCellEditor(new DefaultCellEditor(new LayerVisibleCheckBox()));
+        layerList.getColumnModel().getColumn(1).setCellEditor(new LayerVisibleCellEditor(new LayerVisibleCheckBox()));
         layerList.getColumnModel().getColumn(1).setMaxWidth(16);
         layerList.getColumnModel().getColumn(1).setPreferredWidth(16);
         layerList.getColumnModel().getColumn(1).setResizable(false);
@@ -199,7 +211,7 @@ public class LayerListDialog extends ToggleDialog {
                 KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, InputEvent.SHIFT_MASK),
                 KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP, 0),
                 KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN, 0),
-                })
+        })
         {
             layerList.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(ks, new Object());
         }
@@ -278,13 +290,13 @@ public class LayerListDialog extends ToggleDialog {
      */
     protected void adaptTo(final IEnabledStateUpdating listener, LayerListModel listModel) {
         listModel.addTableModelListener(
-            new TableModelListener() {
+                new TableModelListener() {
 
-                @Override
-                public void tableChanged(TableModelEvent e) {
-                    listener.updateEnabledState();
+                    @Override
+                    public void tableChanged(TableModelEvent e) {
+                        listener.updateEnabledState();
+                    }
                 }
-            }
         );
     }
 
@@ -445,6 +457,106 @@ public class LayerListDialog extends ToggleDialog {
         }
     }
 
+    public final class LayerOpacityAction extends AbstractAction implements IEnabledStateUpdating, LayerAction {
+        private Layer layer;
+        private JPopupMenu popup;
+        private JSlider slider = new JSlider(JSlider.VERTICAL);
+
+        /**
+         * Creates a {@see LayerOpacityAction} which allows to chenge the
+         * opacity of one or more layers.
+         *
+         * @param layer  the layer. Must not be null.
+         * @exception IllegalArgumentException thrown, if layer is null
+         */
+        public LayerOpacityAction(Layer layer) throws IllegalArgumentException {
+            this();
+            putValue(NAME, tr("Opacity"));
+            CheckParameterUtil.ensureParameterNotNull(layer, "layer");
+            this.layer = layer;
+            updateEnabledState();
+        }
+
+        /**
+         * Creates a {@see ShowHideLayerAction} which will toggle the visibility of
+         * the currently selected layers
+         *
+         */
+        public LayerOpacityAction() {
+            putValue(SHORT_DESCRIPTION, tr("Adjust opacity of the layer."));
+            putValue(SMALL_ICON, ImageProvider.get("dialogs/layerlist", "transparency"));
+            updateEnabledState();
+
+            popup = new JPopupMenu();
+            slider.addChangeListener(new ChangeListener() {
+                @Override
+                public void stateChanged(ChangeEvent e) {
+                    setOpacity((double)slider.getValue()/100);
+                }
+            });
+            popup.add(slider);
+        }
+
+        private void setOpacity(double value) {
+            if (!isEnabled()) return;
+            if (layer != null) {
+                layer.setOpacity(value);
+            } else {
+                for(Layer layer: model.getSelectedLayers()) {
+                    layer.setOpacity(value);
+                }
+            }
+        }
+
+        private double getOpacity() {
+            if (layer != null)
+                return layer.getOpacity();
+            else {
+                double opacity = 0;
+                List<Layer> layers = model.getSelectedLayers();
+                for(Layer layer: layers) {
+                    opacity += layer.getOpacity();
+                }
+                return opacity / layers.size();
+            }
+        }
+
+        @Override
+        public void actionPerformed(ActionEvent e) {
+            slider.setValue((int)Math.round(getOpacity()*100));
+            popup.show(opacityButton, 0, opacityButton.getHeight());
+        }
+
+        @Override
+        public void updateEnabledState() {
+            if (layer == null) {
+                setEnabled(! getModel().getSelectedLayers().isEmpty());
+            } else {
+                setEnabled(true);
+            }
+        }
+
+        @Override
+        public Component createMenuComponent() {
+            return new JMenuItem(this);
+        }
+
+        @Override
+        public boolean supportLayers(List<Layer> layers) {
+            return true;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            return obj instanceof LayerOpacityAction;
+        }
+
+        @Override
+        public int hashCode() {
+            return getClass().hashCode();
+        }
+    }
+
     /**
      * The action to activate the currently selected layer
      */
@@ -634,15 +746,34 @@ public class LayerListDialog extends ToggleDialog {
     }
 
     private static class LayerVisibleCheckBox extends JCheckBox {
+        private final ImageIcon icon_eye;
+        private final ImageIcon icon_eye_translucent;
+        private boolean isTranslucent;
         public LayerVisibleCheckBox() {
             setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
-            ImageIcon eye = ImageProvider.get("dialogs/layerlist", "eye");
-            ImageIcon eye_off = ImageProvider.get("dialogs/layerlist", "eye-off");
-            setIcon(eye_off);
-            setSelectedIcon(eye);
-            setRolloverIcon(eye_off);
-            setRolloverSelectedIcon(eye);
+            icon_eye = ImageProvider.get("dialogs/layerlist", "eye");
+            icon_eye_translucent = ImageProvider.get("dialogs/layerlist", "eye-translucent");
+            setIcon(ImageProvider.get("dialogs/layerlist", "eye-off"));
             setPressedIcon(ImageProvider.get("dialogs/layerlist", "eye-pressed"));
+            setSelectedIcon(icon_eye);
+            isTranslucent = false;
+        }
+
+        public void setTranslucent(boolean isTranslucent) {
+            if (this.isTranslucent == isTranslucent) return;
+            if (isTranslucent) {
+                setSelectedIcon(icon_eye_translucent);
+            } else {
+                setSelectedIcon(icon_eye);
+            }
+            this.isTranslucent = isTranslucent;
+        }
+
+        public void updateStatus(Layer layer) {
+            boolean visible = layer.isVisible();
+            setSelected(visible);
+            setTranslucent(layer.getOpacity()<1.0);
+            setToolTipText(visible ? tr("layer is currently visible (click to hide layer)") : tr("layer is currently hidden (click to show layer)"));
         }
     }
 
@@ -662,21 +793,33 @@ public class LayerListDialog extends ToggleDialog {
     }
 
     private static class LayerVisibleCellRenderer implements TableCellRenderer {
-        JCheckBox cb;
+        LayerVisibleCheckBox cb;
         public LayerVisibleCellRenderer() {
-            cb = new LayerVisibleCheckBox();
+            this.cb = new LayerVisibleCheckBox();
         }
 
         @Override
         public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
-            boolean visible = (Boolean) value;
-            cb.setSelected(visible);
-            cb.setToolTipText(visible ? tr("layer is currently visible (click to hide layer)") : tr("layer is currently hidden (click to show layer)"));
+            cb.updateStatus((Layer)value);
             return cb;
         }
     }
 
-   private static class LayerNameCellRenderer extends DefaultTableCellRenderer {
+    private static class LayerVisibleCellEditor extends DefaultCellEditor {
+        LayerVisibleCheckBox cb;
+        public LayerVisibleCellEditor(LayerVisibleCheckBox cb) {
+            super(cb);
+            this.cb = cb;
+        }
+
+        @Override
+        public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
+            cb.updateStatus((Layer)value);
+            return cb;
+        }
+    }
+
+    private static class LayerNameCellRenderer extends DefaultTableCellRenderer {
 
         protected boolean isActiveLayer(Layer layer) {
             if (Main.map == null) return false;
@@ -1141,7 +1284,7 @@ public class LayerListDialog extends ToggleDialog {
         public Object getValueAt(int row, int col) {
             switch (col) {
             case 0: return getLayers().get(row) == getActiveLayer();
-            case 1: return getLayers().get(row).isVisible();
+            case 1: return getLayers().get(row);
             case 2: return getLayers().get(row);
             default: throw new RuntimeException();
             }
@@ -1168,7 +1311,7 @@ public class LayerListDialog extends ToggleDialog {
             case 2:
                 l.setName((String) value);
                 break;
-                default: throw new RuntimeException();
+            default: throw new RuntimeException();
             }
             fireTableCellUpdated(row, col);
         }
Index: src/org/openstreetmap/josm/gui/layer/Layer.java
===================================================================
--- src/org/openstreetmap/josm/gui/layer/Layer.java	(revision 3695)
+++ src/org/openstreetmap/josm/gui/layer/Layer.java	(working copy)
@@ -69,6 +69,7 @@ abstract public class Layer implements Destroyable, MapViewPaintable {
     }
 
     static public final String VISIBLE_PROP = Layer.class.getName() + ".visible";
+    static public final String OPACITY_PROP = Layer.class.getName() + ".opacity";
     static public final String NAME_PROP = Layer.class.getName() + ".name";
 
 
@@ -82,6 +83,12 @@ abstract public class Layer implements Destroyable, MapViewPaintable {
     private boolean visible = true;
 
     /**
+     * The opacity of the layer.
+     *
+     */
+    private double opacity = 1;
+
+    /**
      * The layer should be handled as a background layer in automatic handling
      *
      */
@@ -110,6 +117,7 @@ abstract public class Layer implements Destroyable, MapViewPaintable {
      * Paint the dataset using the engine set.
      * @param mv The object that can translate GeoPoints to screen coordinates.
      */
+    @Override
     abstract public void paint(Graphics2D g, MapView mv, Bounds box);
     /**
      * Return a representative small image for this layer. The image must not
@@ -159,6 +167,7 @@ abstract public class Layer implements Destroyable, MapViewPaintable {
      * to the layerlist dialog, because there may be no such dialog yet (loaded
      * via command line parameter).
      */
+    @Override
     public void destroy() {}
 
     public File getAssociatedFile() { return associatedFile; }
@@ -215,10 +224,12 @@ abstract public class Layer implements Destroyable, MapViewPaintable {
      * @param visible true, if the layer is visible; false, otherwise.
      */
     public void setVisible(boolean visible) {
-        boolean oldValue = this.visible;
+        boolean oldValue = isVisible();
         this.visible  = visible;
-        if (oldValue != this.visible) {
-            fireVisibleChanged(oldValue, this.visible);
+        if (visible && opacity == 0) {
+            setOpacity(1);
+        } else if (oldValue != isVisible()) {
+            fireVisibleChanged(oldValue, isVisible());
         }
     }
 
@@ -227,7 +238,25 @@ abstract public class Layer implements Destroyable, MapViewPaintable {
      * @return  true if this layer is visible. False, otherwise.
      */
     public boolean isVisible() {
-        return visible;
+        return visible && opacity != 0;
+    }
+
+    public double getOpacity() {
+        return opacity;
+    }
+
+    public void setOpacity(double opacity) {
+        if (!(opacity >= 0 && opacity <= 1))
+            throw new IllegalArgumentException("Opacity value must be between 0 and 1");
+        double oldOpacity = getOpacity();
+        boolean oldVisible = isVisible();
+        this.opacity = opacity;
+        if (oldOpacity != getOpacity()) {
+            fireOpacityChanged(oldOpacity, getOpacity());
+        }
+        if (oldVisible != isVisible()) {
+            fireVisibleChanged(oldVisible, isVisible());
+        }
     }
 
     /**
@@ -266,6 +295,16 @@ abstract public class Layer implements Destroyable, MapViewPaintable {
     }
 
     /**
+     * fires a property change for the property {@see #OPACITY_PROP}
+     *
+     * @param oldValue the old value
+     * @param newValue the new value
+     */
+    protected void fireOpacityChanged(double oldValue, double newValue) {
+        propertyChangeSupport.firePropertyChange(OPACITY_PROP, oldValue, newValue);
+    }
+
+    /**
      *
      *
      * @return True if layer was changed since last paint
