Index: /trunk/src/org/openstreetmap/josm/gui/io/ActionFlagsTableCell.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/io/ActionFlagsTableCell.java	(revision 5003)
+++ /trunk/src/org/openstreetmap/josm/gui/io/ActionFlagsTableCell.java	(revision 5003)
@@ -0,0 +1,140 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.io;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.EventObject;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import javax.swing.AbstractAction;
+import javax.swing.ActionMap;
+import javax.swing.JCheckBox;
+import javax.swing.JPanel;
+import javax.swing.JTable;
+import javax.swing.event.CellEditorListener;
+import javax.swing.event.ChangeEvent;
+import javax.swing.table.TableCellEditor;
+import javax.swing.table.TableCellRenderer;
+
+import org.openstreetmap.josm.tools.GBC;
+
+/**
+ * This class creates a table cell that features two checkboxes, Upload and Save. It
+ * handles everything on its own, in other words it renders itself and also functions
+ * as editor so the checkboxes may be set by the user.
+ * 
+ * Intended usage is like this:
+ * ActionFlagsTableCell aftc = new ActionFlagsTableCell();
+ * col = new TableColumn(0);
+ * col.setCellRenderer(aftc);
+ * col.setCellEditor(aftc);
+ */
+class ActionFlagsTableCell extends JPanel implements TableCellRenderer, TableCellEditor {
+    protected JCheckBox[] checkBoxes = new JCheckBox[2];
+    private CopyOnWriteArrayList<CellEditorListener> listeners;
+
+    private ActionListener al = new ActionListener() {
+        public void actionPerformed(ActionEvent e) {
+            fireEditingStopped();
+        }
+    };
+
+    public ActionFlagsTableCell() {
+        super();
+        listeners = new CopyOnWriteArrayList<CellEditorListener>();
+
+        setLayout(new GridBagLayout());
+        checkBoxes[0] = new JCheckBox(tr("Upload"));
+        checkBoxes[1] = new JCheckBox(tr("Save"));
+
+        ActionMap am = getActionMap();
+        for(int i=0; i<checkBoxes.length; i++) {
+            final JCheckBox b = checkBoxes[i];
+            add(b, GBC.eol().fill(GBC.HORIZONTAL));
+            b.setPreferredSize(new Dimension(b.getPreferredSize().width, 19));
+            b.addActionListener(al);
+            am.put(b.getText(), new AbstractAction() {
+                public void actionPerformed(ActionEvent e) {
+                    b.setSelected(!b.isSelected());
+                    fireEditingStopped();
+                }
+            });
+        }
+
+        setToolTipText(tr("<html>Select which actions to perform for this layer, if you click the leftmost button.<br/>Check \"upload\" to upload the changes to the OSM server.<br/>Check \"Save\" to save the layer to the file specified on the left.</html>"));
+    }
+
+    protected void updateCheckboxes(Object v) {
+        boolean[] values;
+        if(v instanceof SaveLayerInfo) {
+            values = new boolean[2];
+            values[0] = ((SaveLayerInfo) v).isDoUploadToServer();
+            values[1] = ((SaveLayerInfo) v).isDoSaveToFile();
+        } else {
+            values = (boolean[]) v;
+        }
+        checkBoxes[0].setSelected(values[0]);
+        checkBoxes[1].setSelected(values[1]);
+    }
+
+    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
+        updateCheckboxes(value);
+        return this;
+    }
+
+    public void addCellEditorListener(CellEditorListener l) {
+        if (l != null) {
+            listeners.addIfAbsent(l);
+        }
+    }
+
+    protected void fireEditingCanceled() {
+        for (CellEditorListener l: listeners) {
+            l.editingCanceled(new ChangeEvent(this));
+        }
+    }
+
+    protected void fireEditingStopped() {
+        for (CellEditorListener l: listeners) {
+            l.editingStopped(new ChangeEvent(this));
+        }
+    }
+
+    public void cancelCellEditing() {
+        fireEditingCanceled();
+    }
+
+    public Object getCellEditorValue() {
+        boolean[] values = new boolean[2];
+        values[0] = checkBoxes[0].isSelected();
+        values[1] = checkBoxes[1].isSelected();
+        return values;
+    }
+
+    public boolean isCellEditable(EventObject anEvent) {
+        return true;
+    }
+
+    public void removeCellEditorListener(CellEditorListener l) {
+        listeners.remove(l);
+    }
+
+    public boolean shouldSelectCell(EventObject anEvent) {
+        return true;
+    }
+
+    public boolean stopCellEditing() {
+        fireEditingStopped();
+        return true;
+    }
+
+    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
+        updateCheckboxes(value);
+        return this;
+    }
+}
Index: /trunk/src/org/openstreetmap/josm/gui/io/LayerNameAndFilePathTableCell.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/io/LayerNameAndFilePathTableCell.java	(revision 5003)
+++ /trunk/src/org/openstreetmap/josm/gui/io/LayerNameAndFilePathTableCell.java	(revision 5003)
@@ -0,0 +1,243 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.io;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.FocusAdapter;
+import java.awt.event.FocusEvent;
+import java.io.File;
+import java.util.EventObject;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import javax.swing.AbstractAction;
+import javax.swing.BorderFactory;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTable;
+import javax.swing.JTextField;
+import javax.swing.event.CellEditorListener;
+import javax.swing.event.ChangeEvent;
+import javax.swing.table.TableCellEditor;
+import javax.swing.table.TableCellRenderer;
+
+import org.openstreetmap.josm.actions.SaveActionBase;
+import org.openstreetmap.josm.tools.GBC;
+
+
+class LayerNameAndFilePathTableCell extends JPanel implements TableCellRenderer, TableCellEditor {
+    private final static Color colorError = new Color(255,197,197);
+    private final static String separator = System.getProperty("file.separator");
+    private final static String ellipsis = "…" + separator;
+
+    private final static JLabel lblLayerName = new JLabel();
+    private final static JLabel lblFilename = new JLabel("");
+    private final static JTextField tfFilename = new JTextField();
+    private final JButton btnFileChooser = new JButton(new LaunchFileChooserAction());
+
+    private final static GBC defaultCellStyle = GBC.eol().fill(GBC.HORIZONTAL).insets(2, 0, 2, 0);
+
+    private CopyOnWriteArrayList<CellEditorListener> listeners;
+    private File value;
+
+
+    /** constructor that sets the default on each element **/
+    public LayerNameAndFilePathTableCell() {
+        setLayout(new GridBagLayout());
+
+        lblLayerName.setPreferredSize(new Dimension(lblLayerName.getPreferredSize().width, 19));
+        lblLayerName.setFont(lblLayerName.getFont().deriveFont(Font.BOLD));
+
+        lblFilename.setPreferredSize(new Dimension(lblFilename.getPreferredSize().width, 19));
+        lblFilename.setOpaque(true);
+
+        tfFilename.setToolTipText(tr("Either edit the path manually in the text field or click the \"...\" button to open a file chooser."));
+        tfFilename.setPreferredSize(new Dimension(tfFilename.getPreferredSize().width, 19));
+        tfFilename.addFocusListener(
+                new FocusAdapter() {
+                    @Override public void focusGained(FocusEvent e) {
+                        tfFilename.selectAll();
+                    }
+                }
+        );
+        // hide border
+        tfFilename.setBorder(BorderFactory.createLineBorder(getBackground()));
+
+        btnFileChooser.setPreferredSize(new Dimension(20, 19));
+        btnFileChooser.setOpaque(true);
+
+        listeners = new CopyOnWriteArrayList<CellEditorListener>();
+    }
+
+    /** renderer used while not editing the file path **/
+    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
+            boolean hasFocus, int row, int column) {
+        removeAll();
+        SaveLayerInfo info = (SaveLayerInfo)value;
+        StringBuilder sb = new StringBuilder();
+        sb.append("<html>");
+        sb.append(addLblLayerName(info));
+        sb.append("<br>");
+        add(btnFileChooser, GBC.std());
+        sb.append(addLblFilename(info));
+
+        sb.append("</html>");
+        setToolTipText(sb.toString());
+        return this;
+    }
+
+    /** renderer used while the file path is being edited **/
+    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected,
+            int row, int column) {
+        removeAll();
+        SaveLayerInfo info = (SaveLayerInfo)value;
+        value = info.getFile();
+        tfFilename.setText(value == null ? "" : value.toString());
+
+        StringBuilder sb = new StringBuilder();
+        sb.append("<html>");
+        sb.append(addLblLayerName(info));
+        sb.append("<br/>");
+
+        add(btnFileChooser, GBC.std());
+        add(tfFilename, GBC.eol().fill(GBC.HORIZONTAL).insets(1, 0, 0, 0));
+        tfFilename.selectAll();
+
+        sb.append(tfFilename.getToolTipText());
+        sb.append("</html>");
+        setToolTipText(sb.toString());
+        return this;
+    }
+
+    private static boolean canWrite(File f) {
+        if (f == null) return false;
+        if (f.isDirectory()) return false;
+        if (f.exists() && f.canWrite()) return true;
+        if (!f.exists() && f.getParentFile() != null && f.getParentFile().canWrite())
+            return true;
+        return false;
+    }
+
+    /** adds layer name label to (this) using the given info. Returns tooltip that
+     * should be added to the panel **/
+    private String addLblLayerName(SaveLayerInfo info) {
+        lblLayerName.setIcon(info.getLayer().getIcon());
+        lblLayerName.setText(info.getName());
+        add(lblLayerName, defaultCellStyle);
+        return tr("The bold text is the name of the layer.");
+    }
+
+    /** adds filename label to (this) using the given info. Returns tooltip that
+     * should be added to the panel */
+    private String addLblFilename(SaveLayerInfo info) {
+        String tooltip = "";
+        boolean error = false;
+        if (info.getFile() == null) {
+            error = info.isDoSaveToFile();
+            lblFilename.setText(tr("Click here to choose save path"));
+            lblFilename.setFont(lblFilename.getFont().deriveFont(Font.ITALIC));
+            tooltip = tr("Layer ''{0}'' is not backed by a file", info.getName());
+        } else {
+            String t = info.getFile().getPath();
+            lblFilename.setText(makePathFit(t));
+            tooltip = info.getFile().getAbsolutePath();
+            if (info.isDoSaveToFile() && !canWrite(info.getFile())) {
+                error = true;
+                tooltip = tr("File ''{0}'' is not writable. Please enter another file name.", info.getFile().getPath());
+            }
+        }
+
+        lblFilename.setBackground(error ? colorError : getBackground());
+        btnFileChooser.setBackground(error ? colorError : getBackground());
+
+        add(lblFilename, defaultCellStyle);
+        return tr("Click cell to change the file path.") + "<br/>" + tooltip;
+    }
+
+    /** makes the given path fit lblFilename, appends ellipsis on the left if it doesn’t fit.
+     * Idea: /home/user/josm → …/user/josm → …/josm; and take the first one that fits */
+    static final private String makePathFit(String t) {
+        boolean hasEllipsis = false;
+        while(t != null && !t.isEmpty()) {
+            int txtwidth = lblFilename.getFontMetrics(lblFilename.getFont()).stringWidth(t);
+            if(txtwidth < lblFilename.getWidth() || t.lastIndexOf(separator) < ellipsis.length()) {
+                break;
+            }
+            // remove ellipsis, if present
+            t = hasEllipsis ? t.substring(ellipsis.length()) : t;
+            // cut next block, and re-add ellipsis
+            t = ellipsis + t.split(separator, 2)[1];
+            hasEllipsis = true;
+        }
+        return t;
+    }
+
+    public void addCellEditorListener(CellEditorListener l) {
+        if (l != null) {
+            listeners.addIfAbsent(l);
+        }
+    }
+
+    protected void fireEditingCanceled() {
+        for (CellEditorListener l: listeners) {
+            l.editingCanceled(new ChangeEvent(this));
+        }
+    }
+
+    protected void fireEditingStopped() {
+        for (CellEditorListener l: listeners) {
+            l.editingStopped(new ChangeEvent(this));
+        }
+    }
+
+    public void cancelCellEditing() {
+        fireEditingCanceled();
+    }
+
+    public Object getCellEditorValue() {
+        return value;
+    }
+
+    public boolean isCellEditable(EventObject anEvent) {
+        return true;
+    }
+
+    public void removeCellEditorListener(CellEditorListener l) {
+        listeners.remove(l);
+    }
+
+    public boolean shouldSelectCell(EventObject anEvent) {
+        return true;
+    }
+
+    public boolean stopCellEditing() {
+        if (tfFilename.getText() == null || tfFilename.getText().trim().equals("")) {
+            value = null;
+        } else {
+            value = new File(tfFilename.getText());
+        }
+        fireEditingStopped();
+        return true;
+    }
+
+    private class LaunchFileChooserAction extends AbstractAction {
+        public LaunchFileChooserAction() {
+            putValue(NAME, "...");
+            putValue(SHORT_DESCRIPTION, tr("Launch a file chooser to select a file"));
+        }
+
+        public void actionPerformed(ActionEvent e) {
+            File f = SaveActionBase.createAndOpenSaveFileChooser(tr("Select filename"), "osm");
+            if (f != null) {
+                tfFilename.setText(f.toString());
+                stopCellEditing();
+            }
+        }
+    }
+}
Index: unk/src/org/openstreetmap/josm/gui/io/SaveFlagCellEditor.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/io/SaveFlagCellEditor.java	(revision 5002)
+++ 	(revision )
@@ -1,95 +1,0 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.gui.io;
-
-import java.awt.Component;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-import java.util.EventObject;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-import javax.swing.JCheckBox;
-import javax.swing.JTable;
-import javax.swing.event.CellEditorListener;
-import javax.swing.event.ChangeEvent;
-import javax.swing.table.TableCellEditor;
-
-/**
- * This is {@see TableCellEditor} for a boolean flag. It is used in two table columns of
- * {@see SaveLayersTable} and renders the values of {@see SaveLayerInfo#isDoSaveToFile()}
- * and {@see SaveLayerInfo#isDoUploadToServer()}
- *
- */
-class SaveFlagCellEditor extends JCheckBox implements TableCellEditor {
-    private CopyOnWriteArrayList<CellEditorListener> listeners;
-    private boolean value;
-
-    public SaveFlagCellEditor() {
-        listeners = new CopyOnWriteArrayList<CellEditorListener>();
-        addMouseListener(
-                new MouseAdapter() {
-                    @Override
-                    public void mouseExited(MouseEvent e) {
-                        stopCellEditing();
-                    }
-                }
-        );
-    }
-
-    public void addCellEditorListener(CellEditorListener l) {
-        if (l != null) {
-            listeners.addIfAbsent(l);
-        }
-    }
-
-    protected void fireEditingCanceled() {
-        for (CellEditorListener l: listeners) {
-            l.editingCanceled(new ChangeEvent(this));
-        }
-    }
-
-    protected void fireEditingStopped() {
-        for (CellEditorListener l: listeners) {
-            l.editingStopped(new ChangeEvent(this));
-        }
-    }
-
-    public void cancelCellEditing() {
-        fireEditingCanceled();
-    }
-
-    public Object getCellEditorValue() {
-        return value;
-    }
-
-    public boolean isCellEditable(EventObject anEvent) {
-        return true;
-    }
-
-    public void removeCellEditorListener(CellEditorListener l) {
-        listeners.remove(l);
-    }
-
-    public boolean shouldSelectCell(EventObject anEvent) {
-        return true;
-    }
-
-    public void setInitialValue(boolean value) {
-        this.value = value;
-        setSelected(value);
-    }
-
-    public boolean stopCellEditing() {
-        this.value = isSelected();
-        fireEditingStopped();
-        return true;
-    }
-
-    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
-        SaveLayerInfo info = (SaveLayerInfo)value;
-        switch(column) {
-        case 4: setInitialValue(info.isDoUploadToServer()); break;
-        case 5: setInitialValue(info.isDoSaveToFile()); break;
-        }
-        return this;
-    }
-}
Index: unk/src/org/openstreetmap/josm/gui/io/SaveLayerInfoCellRenderer.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/io/SaveLayerInfoCellRenderer.java	(revision 5002)
+++ 	(revision )
@@ -1,150 +1,0 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.gui.io;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.Color;
-import java.awt.Component;
-import java.awt.Font;
-import java.io.File;
-
-import javax.swing.JCheckBox;
-import javax.swing.JLabel;
-import javax.swing.JTable;
-import javax.swing.UIManager;
-import javax.swing.table.TableCellRenderer;
-
-import org.openstreetmap.josm.io.OsmApi;
-
-/**
- * This is a {@see TableCellRenderer} for rendering the various fields of a
- * {@see SaveLayerInfo} in the table {@see SaveLayersTable}.
- *
- *
- */
-class SaveLayerInfoCellRenderer implements TableCellRenderer {
-    private JLabel lblRenderer;
-    private JCheckBox cbRenderer;
-
-    public SaveLayerInfoCellRenderer() {
-        lblRenderer = new JLabel();
-        cbRenderer = new JCheckBox();
-    }
-
-    protected Component prepareLayerNameRenderer(SaveLayerInfo info) {
-        lblRenderer.setIcon(info.getLayer().getIcon());
-        lblRenderer.setText(info.getName());
-        lblRenderer.setToolTipText(info.getLayer().getToolTipText());
-        return lblRenderer;
-    }
-
-    protected Component prepareUploadRequiredRenderer(SaveLayerInfo info) {
-        lblRenderer.setIcon(null);
-        lblRenderer.setHorizontalAlignment(JLabel.CENTER);
-        String text = info.getLayer().requiresUploadToServer() ? tr("Yes") : tr("No");
-        lblRenderer.setText(text);
-        if (info.getLayer().requiresUploadToServer()) {
-            lblRenderer.setToolTipText(tr("Layer ''{0}'' has modifications which should be uploaded to the server.", info.getName()));
-        } else {
-            lblRenderer.setToolTipText(tr("Layer ''{0}'' has no modifications to be uploaded.", info.getName()));
-        }
-        return lblRenderer;
-    }
-
-    protected Component prepareSaveToFileRequired(SaveLayerInfo info) {
-        lblRenderer.setIcon(null);
-        lblRenderer.setHorizontalAlignment(JLabel.CENTER);
-        String text = info.getLayer().requiresSaveToFile() ? tr("Yes") : tr("No");
-        lblRenderer.setText(text);
-        if (info.getLayer().requiresSaveToFile()) {
-            lblRenderer.setToolTipText(tr("Layer ''{0}'' has modifications which should be saved to its associated file ''{1}''.", info.getName(), info.getFile().toString()));
-        } else {
-            lblRenderer.setToolTipText(tr("Layer ''{0}'' has no modifications to be saved.", info.getName()));
-        }
-        return lblRenderer;
-    }
-
-    protected boolean canWrite(File f) {
-        if (f == null) return false;
-        if (f.isDirectory()) return false;
-        if (f.exists() && f.canWrite()) return true;
-        if (!f.exists() && f.getParentFile() != null && f.getParentFile().canWrite())
-            return true;
-        return false;
-    }
-
-    protected Component prepareFileNameRenderer(SaveLayerInfo info) {
-        lblRenderer.setIcon(null);
-        if (info.getFile() == null) {
-            if (!info.isDoSaveToFile()) {
-                lblRenderer.setText(tr("No file associated with this layer"));
-            } else {
-                lblRenderer.setBackground(new Color(255,197,197));
-                lblRenderer.setText(tr("Please select a file"));
-            }
-            lblRenderer.setFont(lblRenderer.getFont().deriveFont(Font.ITALIC));
-            lblRenderer.setToolTipText(tr("Layer ''{0}'' is not backed by a file", info.getName()));
-        } else {
-            String text = info.getFile().getName();
-            String parent = info.getFile().getParent();
-            if (parent != null) {
-                if (parent.length() <= 10) {
-                    text = info.getFile().getPath();
-                } else {
-                    text = parent.substring(0, 10) + "..." + File.separator + text;
-                }
-            }
-            lblRenderer.setText(text);
-            lblRenderer.setToolTipText(info.getFile().getAbsolutePath());
-            if (info.isDoSaveToFile() && !canWrite(info.getFile())) {
-                lblRenderer.setBackground(new Color(255,197,197));
-                lblRenderer.setToolTipText(tr("File ''{0}'' is not writable. Please enter another file name.", info.getFile().getPath()));
-            }
-        }
-        return lblRenderer;
-    }
-
-    protected Component prepareUploadRenderer(SaveLayerInfo info){
-        cbRenderer.setSelected(info.isDoUploadToServer());
-        lblRenderer.setToolTipText(tr("Select to upload layer ''{0}'' to the server ''{1}''", info.getName(), OsmApi.getOsmApi().getBaseUrl()));
-        return cbRenderer;
-    }
-
-    protected Component prepareSaveToFileRenderer(SaveLayerInfo info){
-        cbRenderer.setSelected(info.isDoSaveToFile());
-        lblRenderer.setToolTipText(tr("Select to upload layer ''{0}'' to the server ''{1}''", info.getName(), OsmApi.getOsmApi().getBaseUrl()));
-        return cbRenderer;
-    }
-
-    protected void resetRenderers() {
-        lblRenderer.setOpaque(true);
-        lblRenderer.setBackground(UIManager.getColor("Table.background"));
-        lblRenderer.setIcon(null);
-        lblRenderer.setText("");
-        lblRenderer.setFont(UIManager.getFont("Table.font"));
-        lblRenderer.setHorizontalAlignment(JLabel.LEFT);
-
-        cbRenderer.setSelected(false);
-        cbRenderer.setOpaque(true);
-        cbRenderer.setBackground(UIManager.getColor("Table.background"));
-    }
-
-    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
-            boolean hasFocus, int row, int column) {
-
-        resetRenderers();
-        if (value == null)
-            return null;
-
-        SaveLayerInfo info = (SaveLayerInfo)value;
-        switch(column) {
-        case 0: return prepareLayerNameRenderer(info);
-        case 1: return prepareUploadRequiredRenderer(info);
-        case 2: return prepareSaveToFileRequired(info);
-        case 3: return prepareFileNameRenderer(info);
-        case 4: return prepareUploadRenderer(info);
-        case 5: return prepareSaveToFileRenderer(info);
-        }
-        return null;
-    }
-}
Index: /trunk/src/org/openstreetmap/josm/gui/io/SaveLayersDialog.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/io/SaveLayersDialog.java	(revision 5002)
+++ /trunk/src/org/openstreetmap/josm/gui/io/SaveLayersDialog.java	(revision 5003)
@@ -9,9 +9,12 @@
 import java.awt.Dimension;
 import java.awt.FlowLayout;
+import java.awt.Graphics2D;
 import java.awt.GridBagConstraints;
 import java.awt.GridBagLayout;
+import java.awt.Image;
 import java.awt.event.ActionEvent;
 import java.awt.event.WindowAdapter;
 import java.awt.event.WindowEvent;
+import java.awt.image.BufferedImage;
 import java.beans.PropertyChangeEvent;
 import java.beans.PropertyChangeListener;
@@ -24,4 +27,5 @@
 import javax.swing.AbstractAction;
 import javax.swing.DefaultListCellRenderer;
+import javax.swing.ImageIcon;
 import javax.swing.JComponent;
 import javax.swing.JDialog;
@@ -33,4 +37,6 @@
 import javax.swing.KeyStroke;
 import javax.swing.WindowConstants;
+import javax.swing.event.TableModelEvent;
+import javax.swing.event.TableModelListener;
 
 import org.openstreetmap.josm.Main;
@@ -45,5 +51,5 @@
 import org.openstreetmap.josm.tools.WindowGeometry;
 
-public class SaveLayersDialog extends JDialog {
+public class SaveLayersDialog extends JDialog implements TableModelListener {
     static public enum UserAction {
         /**
@@ -76,14 +82,17 @@
 
         model = new SaveLayersModel();
-        SaveLayersTable table;
-        JScrollPane pane = new JScrollPane(table = new SaveLayersTable(model));
+        SaveLayersTable table = new SaveLayersTable(model);
+        JScrollPane pane = new JScrollPane(table);
         model.addPropertyChangeListener(table);
+        table.getModel().addTableModelListener(this);
+
         getContentPane().add(pane, BorderLayout.CENTER);
         getContentPane().add(buildButtonRow(), BorderLayout.SOUTH);
-        table.getTableHeader().setPreferredSize(new Dimension(table.getTableHeader().getWidth(), 40));
 
         addWindowListener(new WindowClosingAdapter());
         setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
     }
+
+    private SideButton saveAndProceedActionButton = null;
 
     /**
@@ -98,5 +107,5 @@
         saveAndProceedAction = new SaveAndProceedAction();
         model.addPropertyChangeListener(saveAndProceedAction);
-        pnl.add(new SideButton(saveAndProceedAction));
+        pnl.add(saveAndProceedActionButton = new SideButton(saveAndProceedAction));
 
         discardAndProceedAction = new DiscardAndProceedAction();
@@ -327,5 +336,5 @@
 
         public void initForDiscardAndExit() {
-            putValue(NAME, tr("Discard and Exit"));
+            putValue(NAME, tr("Exit now!"));
             putValue(SHORT_DESCRIPTION, tr("Exit JOSM without saving. Unsaved changes are lost."));
             putValue(SMALL_ICON, ImageProvider.get("exit"));
@@ -333,5 +342,5 @@
 
         public void initForDiscardAndDelete() {
-            putValue(NAME, tr("Discard and Delete"));
+            putValue(NAME, tr("Delete now!"));
             putValue(SHORT_DESCRIPTION, tr("Delete layers without saving. Unsaved changes are lost."));
             putValue(SMALL_ICON, ImageProvider.get("dialogs", "delete"));
@@ -353,19 +362,45 @@
     }
 
-    class SaveAndProceedAction extends AbstractAction implements PropertyChangeListener {
+    final class SaveAndProceedAction extends AbstractAction implements PropertyChangeListener {
+        private static final int is = 24; // icon size
+        private static final String BASE_ICON = "BASE_ICON";
+        private final Image save = ImageProvider.get("save").getImage();
+        private final Image upld = ImageProvider.get("upload").getImage();
+        private final Image saveDis = new BufferedImage(is, is, BufferedImage.TYPE_4BYTE_ABGR);
+        private final Image upldDis = new BufferedImage(is, is, BufferedImage.TYPE_4BYTE_ABGR);
+
         public SaveAndProceedAction() {
+            // get disabled versions of icons
+            new JLabel(ImageProvider.get("save")).getDisabledIcon().paintIcon(new JPanel(), saveDis.getGraphics(), 0, 0);
+            new JLabel(ImageProvider.get("upload")).getDisabledIcon().paintIcon(new JPanel(), upldDis.getGraphics(), 0, 0);
             initForSaveAndExit();
         }
 
         public void initForSaveAndExit() {
-            putValue(NAME, tr("Save/Upload and Exit"));
+            putValue(NAME, tr("Perform actions before exiting"));
             putValue(SHORT_DESCRIPTION, tr("Exit JOSM with saving. Unsaved changes are uploaded and/or saved."));
-            putValue(SMALL_ICON, ImageProvider.get("exit"));
+            putValue(BASE_ICON, ImageProvider.get("exit"));
+            redrawIcon();
         }
 
         public void initForSaveAndDelete() {
-            putValue(NAME, tr("Save/Upload and Delete"));
+            putValue(NAME, tr("Perform actions before deleting"));
             putValue(SHORT_DESCRIPTION, tr("Save/Upload layers before deleting. Unsaved changes are not lost."));
-            putValue(SMALL_ICON, ImageProvider.get("dialogs", "delete"));
+            putValue(BASE_ICON, ImageProvider.get("dialogs", "delete"));
+            redrawIcon();
+        }
+
+        public void redrawIcon() {
+            try { // Can fail if model is not yet setup properly
+                Image base = ((ImageIcon) getValue(BASE_ICON)).getImage();
+                BufferedImage newIco = new BufferedImage(is*3, is, BufferedImage.TYPE_4BYTE_ABGR);
+                Graphics2D g = newIco.createGraphics();
+                g.drawImage(model.getLayersToUpload().isEmpty() ? upldDis : upld, is*0, 0, is, is, null);
+                g.drawImage(model.getLayersToSave().isEmpty()   ? saveDis : save, is*1, 0, is, is, null);
+                g.drawImage(base,                                                 is*2, 0, is, is, null);
+                putValue(SMALL_ICON, new ImageIcon(newIco));
+            } catch(Exception e) {
+                putValue(SMALL_ICON, getValue(BASE_ICON));
+            }
         }
 
@@ -546,3 +581,12 @@
         }
     }
+
+    @Override
+    public void tableChanged(TableModelEvent arg0) {
+        boolean dis = model.getLayersToSave().isEmpty() && model.getLayersToUpload().isEmpty();
+        if(saveAndProceedActionButton != null) {
+            saveAndProceedActionButton.setEnabled(!dis);
+        }
+        saveAndProceedAction.redrawIcon();
+    }
 }
Index: /trunk/src/org/openstreetmap/josm/gui/io/SaveLayersModel.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/io/SaveLayersModel.java	(revision 5002)
+++ /trunk/src/org/openstreetmap/josm/gui/io/SaveLayersModel.java	(revision 5003)
@@ -24,4 +24,8 @@
     private Mode mode;
     private PropertyChangeSupport support;
+
+    // keep in sync with how the columns are ordered in SaveLayersTableColumnModel#build
+    private static final int columnFilename = 0;
+    private static final int columnActions = 2;
 
     public SaveLayersModel() {
@@ -83,5 +87,5 @@
     @Override
     public boolean isCellEditable(int row, int column) {
-        return column == 3 || column == 4 || column == 5;
+        return column == columnFilename || column == columnActions;
     }
 
@@ -89,10 +93,13 @@
     public void setValueAt(Object value, int row, int column) {
         switch(column) {
-            case 3 /* file name */:
-                this.layerInfo.get(row).setFile((File)value);
-                this.layerInfo.get(row).setDoSaveToFile(true);
-                break;
-            case 4 /* upload */: this.layerInfo.get(row).setDoUploadToServer((Boolean)value);break;
-            case 5 /* save */: this.layerInfo.get(row).setDoSaveToFile((Boolean)value);break;
+        case columnFilename:
+            this.layerInfo.get(row).setFile((File)value);
+            this.layerInfo.get(row).setDoSaveToFile(true);
+            break;
+        case columnActions:
+            boolean[] values = (boolean[]) value;
+            this.layerInfo.get(row).setDoUploadToServer(values[0]);
+            this.layerInfo.get(row).setDoSaveToFile(values[1]);
+            break;
         }
         fireTableDataChanged();
@@ -104,5 +111,5 @@
 
     public List<SaveLayerInfo> getLayersWithoutFilesAndSaveRequest() {
-        List<SaveLayerInfo> ret =new ArrayList<SaveLayerInfo>();
+        List<SaveLayerInfo> ret = new ArrayList<SaveLayerInfo>();
         for (SaveLayerInfo info: layerInfo) {
             if (info.isDoSaveToFile() && info.getFile() == null) {
@@ -215,4 +222,3 @@
         return ret;
     }
-
 }
Index: /trunk/src/org/openstreetmap/josm/gui/io/SaveLayersTable.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/io/SaveLayersTable.java	(revision 5002)
+++ /trunk/src/org/openstreetmap/josm/gui/io/SaveLayersTable.java	(revision 5003)
@@ -2,4 +2,5 @@
 package org.openstreetmap.josm.gui.io;
 
+import java.awt.Dimension;
 import java.beans.PropertyChangeEvent;
 import java.beans.PropertyChangeListener;
@@ -13,4 +14,7 @@
         super(model, new SaveLayersTableColumnModel());
         putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
+        super.setRowHeight(39);
+        super.getTableHeader().setPreferredSize(new Dimension(super.getTableHeader().getWidth(), 24));
+        super.getTableHeader().setReorderingAllowed(false);
     }
 
Index: /trunk/src/org/openstreetmap/josm/gui/io/SaveLayersTableColumnModel.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/io/SaveLayersTableColumnModel.java	(revision 5002)
+++ /trunk/src/org/openstreetmap/josm/gui/io/SaveLayersTableColumnModel.java	(revision 5003)
@@ -4,65 +4,89 @@
 import static org.openstreetmap.josm.tools.I18n.tr;
 
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.GridBagLayout;
+
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTable;
 import javax.swing.table.DefaultTableColumnModel;
-import javax.swing.table.TableCellEditor;
 import javax.swing.table.TableCellRenderer;
 import javax.swing.table.TableColumn;
 
+import org.openstreetmap.josm.tools.GBC;
+
 class SaveLayersTableColumnModel extends DefaultTableColumnModel {
+    /** small renderer class that handles the "should be uploaded/saved" texts. */
+    private static class RecommendedActionsTableCell extends JPanel implements TableCellRenderer {
+        private final static JPanel pnlEmpty = new JPanel();
+        private final static JLabel needsUpload = new JLabel(tr("should be uploaded"));
+        private final static JLabel needsSave = new JLabel(tr("should be saved"));
+        private final static GBC defaultCellStyle = GBC.eol().fill(GBC.HORIZONTAL).insets(2, 0, 2, 0);
+
+        public RecommendedActionsTableCell() {
+            setLayout(new GridBagLayout());
+            pnlEmpty.setPreferredSize(new Dimension(1, 19));
+            needsUpload.setPreferredSize(new Dimension(needsUpload.getPreferredSize().width, 19));
+            needsSave.setPreferredSize(new Dimension(needsSave.getPreferredSize().width, 19));
+        }
+
+        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
+                boolean hasFocus, int row, int column) {
+            SaveLayerInfo info = (SaveLayerInfo)value;
+            StringBuilder sb = new StringBuilder();
+            sb.append("<html>");
+            if (info.getLayer().requiresUploadToServer()) {
+                add(needsUpload, defaultCellStyle);
+                sb.append(tr("Layer ''{0}'' has modifications which should be uploaded to the server.", info.getName()));
+
+            } else {
+                add(pnlEmpty, defaultCellStyle);
+                sb.append(tr("Layer ''{0}'' has no modifications to be uploaded.", info.getName()));
+            }
+            sb.append("<br/>");
+
+            if (info.getLayer().requiresSaveToFile()) {
+                add(needsSave, defaultCellStyle);
+                sb.append(tr("Layer ''{0}'' has modifications which should be saved to its associated file ''{1}''.", info.getName(), info.getFile().toString()));
+            } else {
+                add(pnlEmpty, defaultCellStyle);
+                sb.append(tr("Layer ''{0}'' has no modifications to be saved.", info.getName()));
+            }
+            sb.append("</html>");
+            setToolTipText(sb.toString());
+            return this;
+        }
+    }
+
     protected void build() {
         TableColumn col = null;
-        TableCellRenderer renderer = new SaveLayerInfoCellRenderer();
-        TableCellEditor fileNameEditor = new FilenameCellEditor();
-        TableCellEditor saveFlagEditor = new SaveFlagCellEditor();
 
-        // column 0 - Layer
-        col = new TableColumn(0);
-        col.setHeaderValue(tr("Layer"));
+        // column 0 - layer name, save path editor
+        LayerNameAndFilePathTableCell lnafptc = new LayerNameAndFilePathTableCell();
+        col = new TableColumn(0); // keep in sync with SaveLayersModel#columnFilename
+        col.setHeaderValue(tr("Layer Name and File Path"));
         col.setResizable(true);
-        col.setCellRenderer(renderer);
-        col.setPreferredWidth(100);
+        col.setCellRenderer(lnafptc);
+        col.setCellEditor(lnafptc);
+        col.setPreferredWidth(324);
         addColumn(col);
 
-        // column 1 - Upload required
+        // column 1 - actions required
         col = new TableColumn(1);
-        col.setHeaderValue(tr("Should upload?"));
+        col.setHeaderValue(tr("Recommended Actions"));
         col.setResizable(true);
-        col.setCellRenderer(renderer);
-        col.setPreferredWidth(50);
+        col.setCellRenderer(new RecommendedActionsTableCell());
+        col.setPreferredWidth(150);
         addColumn(col);
 
-        // column 2 - Save to file required
-        col = new TableColumn(2);
-        col.setHeaderValue(tr("Should save?"));
+        // column 2- actions to take
+        ActionFlagsTableCell aftc = new ActionFlagsTableCell();
+        col = new TableColumn(2); // keep in sync with SaveLayersModel#columnActions
+        col.setHeaderValue(tr("Actions To Take"));
         col.setResizable(true);
-        col.setCellRenderer(renderer);
-        col.setPreferredWidth(50);
-        addColumn(col);
-
-        // column 3 - filename
-        col = new TableColumn(3);
-        col.setHeaderValue(tr("Filename"));
-        col.setResizable(true);
-        col.setCellRenderer(renderer);
-        col.setCellEditor(fileNameEditor);
-        col.setPreferredWidth(200);
-        addColumn(col);
-
-        // column 4 - Upload
-        col = new TableColumn(4);
-        col.setHeaderValue(tr("Upload"));
-        col.setResizable(true);
-        col.setCellRenderer(renderer);
-        col.setCellEditor(saveFlagEditor);
-        col.setPreferredWidth(30);
-        addColumn(col);
-
-        // column 5 - Save
-        col = new TableColumn(5);
-        col.setHeaderValue(tr("Save"));
-        col.setResizable(true);
-        col.setCellRenderer(renderer);
-        col.setCellEditor(saveFlagEditor);
-        col.setPreferredWidth(30);
+        col.setCellRenderer(aftc);
+        col.setCellEditor(aftc);
+        col.setPreferredWidth(100);
 
         addColumn(col);
