Index: /trunk/src/org/openstreetmap/josm/gui/preferences/advanced/AbstractListEditor.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/preferences/advanced/AbstractListEditor.java	(revision 9507)
+++ /trunk/src/org/openstreetmap/josm/gui/preferences/advanced/AbstractListEditor.java	(revision 9507)
@@ -0,0 +1,44 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.preferences.advanced;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.Component;
+import java.awt.Dimension;
+import java.util.List;
+
+import javax.swing.JPanel;
+
+import org.openstreetmap.josm.gui.ExtendedDialog;
+import org.openstreetmap.josm.tools.WindowGeometry;
+
+/**
+ * Abstract superclass of {@link ListEditor} and {@link AbstractTableListEditor}.
+ * @param <T> type of elements
+ * @since 9505
+ */
+public abstract class AbstractListEditor<T> extends ExtendedDialog {
+
+    protected final transient PrefEntry entry;
+
+    /**
+     * Constructs a new {@code AbstractListEditor}.
+     * @param parent       The parent element that will be used for position and maximum size
+     * @param title        The text that will be shown in the window titlebar
+     * @param entry        Preference entry
+     */
+    public AbstractListEditor(Component parent, String title, PrefEntry entry) {
+        super(parent, title, new String[] {tr("OK"), tr("Cancel")});
+        this.entry = entry;
+        setButtonIcons(new String[] {"ok.png", "cancel.png"});
+        setRememberWindowGeometry(getClass().getName() + ".geometry", WindowGeometry.centerInWindow(parent, new Dimension(500, 350)));
+    }
+
+    /**
+     * Returns the list of values.
+     * @return The list of values.
+     */
+    public abstract List<T> getData();
+
+    protected abstract JPanel build();
+}
Index: /trunk/src/org/openstreetmap/josm/gui/preferences/advanced/AbstractTableListEditor.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/preferences/advanced/AbstractTableListEditor.java	(revision 9507)
+++ /trunk/src/org/openstreetmap/josm/gui/preferences/advanced/AbstractTableListEditor.java	(revision 9507)
@@ -0,0 +1,160 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.preferences.advanced;
+
+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 javax.swing.AbstractAction;
+import javax.swing.AbstractListModel;
+import javax.swing.DefaultCellEditor;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.JToolBar;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.table.AbstractTableModel;
+import javax.swing.table.TableCellEditor;
+
+import org.openstreetmap.josm.gui.widgets.JosmTextField;
+import org.openstreetmap.josm.tools.GBC;
+import org.openstreetmap.josm.tools.ImageProvider;
+
+/**
+ * Abstract superclass of {@link ListListEditor} and {@link MapListEditor}.
+ * @param <T> type of elements
+ * @since 9505
+ */
+public abstract class AbstractTableListEditor<T> extends AbstractListEditor<T> {
+
+    protected final AbstractEntryListModel entryModel;
+    protected final JList<String> entryList;
+
+    protected final JTable table;
+    protected final AbstractTableModel tableModel;
+
+    protected Integer entryIdx;
+
+    /**
+     * Constructs a new {@code AbstractListEditor}.
+     * @param parent       The parent element that will be used for position and maximum size
+     * @param title        The text that will be shown in the window titlebar
+     * @param entry        Preference entry
+     */
+    public AbstractTableListEditor(Component parent, String title, PrefEntry entry) {
+        super(parent, title, entry);
+        entryModel = newEntryListModel();
+        entryList = new JList<>(entryModel);
+        entryList.getSelectionModel().addListSelectionListener(new EntryListener());
+        tableModel = newTableModel();
+        table = new JTable(tableModel);
+        setContent(build(), false);
+    }
+
+    protected abstract static class AbstractEntryListModel extends AbstractListModel<String> {
+
+        abstract void add();
+
+        abstract void remove(int idx);
+    }
+
+    protected final class NewEntryAction extends AbstractAction {
+        NewEntryAction() {
+            putValue(NAME, tr("New"));
+            putValue(SHORT_DESCRIPTION, tr("add entry"));
+            putValue(SMALL_ICON, ImageProvider.get("dialogs", "add"));
+        }
+
+        @Override
+        public void actionPerformed(ActionEvent evt) {
+            entryModel.add();
+        }
+    }
+
+    protected final class RemoveEntryAction extends AbstractAction implements ListSelectionListener {
+        RemoveEntryAction() {
+            putValue(NAME, tr("Remove"));
+            putValue(SHORT_DESCRIPTION, tr("Remove the selected entry"));
+            putValue(SMALL_ICON, ImageProvider.get("dialogs", "delete"));
+            updateEnabledState();
+        }
+
+        protected void updateEnabledState() {
+            setEnabled(entryList.getSelectedIndices().length == 1);
+        }
+
+        @Override
+        public void valueChanged(ListSelectionEvent e) {
+            updateEnabledState();
+        }
+
+        @Override
+        public void actionPerformed(ActionEvent e) {
+            entryModel.remove(entryList.getSelectedIndices()[0]);
+        }
+    }
+
+    private class EntryListener implements ListSelectionListener {
+        @Override
+        public void valueChanged(ListSelectionEvent e) {
+            TableCellEditor editor = table.getCellEditor();
+            if (editor != null) {
+                ((DefaultCellEditor) editor).stopCellEditing();
+            }
+            if (entryList.getSelectedIndices().length != 1) {
+                entryIdx = null;
+                table.setEnabled(false);
+            } else {
+                entryIdx = entryList.getSelectedIndices()[0];
+                table.setEnabled(true);
+            }
+            tableModel.fireTableStructureChanged();
+            tableModel.fireTableDataChanged();
+        }
+    }
+
+    @Override
+    protected JPanel build() {
+        JPanel p = new JPanel(new GridBagLayout());
+        p.add(new JLabel(tr("Key: {0}", entry.getKey())), GBC.std(0, 0).span(2).weight(1, 0).insets(0, 0, 5, 10));
+
+        JPanel left = new JPanel(new GridBagLayout());
+
+        JScrollPane scroll = new JScrollPane(entryList);
+        left.add(scroll, GBC.eol().fill());
+
+        JToolBar sideButtonTB = new JToolBar(JToolBar.HORIZONTAL);
+        sideButtonTB.setBorderPainted(false);
+        sideButtonTB.setOpaque(false);
+        sideButtonTB.add(new NewEntryAction());
+        RemoveEntryAction removeEntryAction = new RemoveEntryAction();
+        entryList.getSelectionModel().addListSelectionListener(removeEntryAction);
+        sideButtonTB.add(removeEntryAction);
+        left.add(sideButtonTB, GBC.eol());
+
+        left.setPreferredSize(new Dimension(80, 0));
+
+        p.add(left, GBC.std(0, 1).fill().weight(0.3, 1.0));
+
+        table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
+
+        DefaultCellEditor editor = new DefaultCellEditor(new JosmTextField());
+        editor.setClickCountToStart(1);
+        table.setDefaultEditor(table.getColumnClass(0), editor);
+
+        JScrollPane pane = new JScrollPane(table);
+        pane.setPreferredSize(new Dimension(140, 0));
+        p.add(pane, GBC.std(1, 1).insets(5, 0, 0, 0).fill().weight(0.7, 1.0));
+        return p;
+    }
+
+    protected abstract AbstractEntryListModel newEntryListModel();
+
+    protected abstract AbstractTableModel newTableModel();
+}
Index: /trunk/src/org/openstreetmap/josm/gui/preferences/advanced/ListEditor.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/preferences/advanced/ListEditor.java	(revision 9506)
+++ /trunk/src/org/openstreetmap/josm/gui/preferences/advanced/ListEditor.java	(revision 9507)
@@ -4,5 +4,4 @@
 import static org.openstreetmap.josm.tools.I18n.tr;
 
-import java.awt.Dimension;
 import java.awt.GridBagLayout;
 import java.util.ArrayList;
@@ -18,18 +17,16 @@
 
 import org.openstreetmap.josm.data.Preferences.ListSetting;
-import org.openstreetmap.josm.gui.ExtendedDialog;
 import org.openstreetmap.josm.gui.widgets.JosmTextField;
 import org.openstreetmap.josm.tools.GBC;
 import org.openstreetmap.josm.tools.Predicate;
 import org.openstreetmap.josm.tools.Utils;
-import org.openstreetmap.josm.tools.WindowGeometry;
 
 /**
  * Editor for List preference entries.
+ * @since 4634
  */
-public class ListEditor extends ExtendedDialog {
+public class ListEditor extends AbstractListEditor<String> {
 
-    private List<String> data;
-    private final transient PrefEntry entry;
+    private final List<String> data;
 
     /**
@@ -40,6 +37,5 @@
      */
     public ListEditor(final JComponent gui, PrefEntry entry, ListSetting setting) {
-        super(gui, tr("Change list setting"), new String[] {tr("OK"), tr("Cancel")});
-        this.entry = entry;
+        super(gui, tr("Change list setting"), entry);
         List<String> orig = setting.getValue();
         if (orig != null) {
@@ -48,13 +44,8 @@
             data = new ArrayList<>();
         }
-        setButtonIcons(new String[] {"ok.png", "cancel.png"});
-        setRememberWindowGeometry(getClass().getName() + ".geometry", WindowGeometry.centerInWindow(gui, new Dimension(300, 350)));
         setContent(build(), false);
     }
 
-    /**
-     * Returns the list of values.
-     * @return The list of values.
-     */
+    @Override
     public List<String> getData() {
         return new ArrayList<>(Utils.filter(data, new Predicate<String>() {
@@ -66,4 +57,5 @@
     }
 
+    @Override
     protected final JPanel build() {
         JPanel p = new JPanel(new GridBagLayout());
Index: /trunk/src/org/openstreetmap/josm/gui/preferences/advanced/ListListEditor.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/preferences/advanced/ListListEditor.java	(revision 9506)
+++ /trunk/src/org/openstreetmap/josm/gui/preferences/advanced/ListListEditor.java	(revision 9507)
@@ -4,47 +4,21 @@
 import static org.openstreetmap.josm.tools.I18n.tr;
 
-import java.awt.Dimension;
-import java.awt.GridBagLayout;
-import java.awt.event.ActionEvent;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
-import javax.swing.AbstractAction;
-import javax.swing.AbstractListModel;
-import javax.swing.DefaultCellEditor;
 import javax.swing.JComponent;
-import javax.swing.JLabel;
-import javax.swing.JList;
 import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-import javax.swing.JTable;
-import javax.swing.JToolBar;
-import javax.swing.event.ListSelectionEvent;
-import javax.swing.event.ListSelectionListener;
 import javax.swing.table.AbstractTableModel;
-import javax.swing.table.TableCellEditor;
 
 import org.openstreetmap.josm.data.Preferences.ListListSetting;
-import org.openstreetmap.josm.gui.ExtendedDialog;
-import org.openstreetmap.josm.gui.widgets.JosmTextField;
-import org.openstreetmap.josm.tools.GBC;
-import org.openstreetmap.josm.tools.ImageProvider;
-import org.openstreetmap.josm.tools.WindowGeometry;
 
 /**
  * Editor for List of Lists preference entries.
+ * @since 4634
  */
-public class ListListEditor extends ExtendedDialog {
+public class ListListEditor extends AbstractTableListEditor<List<String>> {
 
-    private EntryListModel entryModel;
-    private final List<List<String>> data;
-    private final transient PrefEntry entry;
-
-    private JList<String> entryList;
-    private Integer entryIdx;
-    private JTable table;
-
-    private ListTableModel tableModel;
+    private final transient List<List<String>> data;
 
     /**
@@ -55,6 +29,5 @@
      */
     public ListListEditor(final JComponent gui, PrefEntry entry, ListListSetting setting) {
-        super(gui, tr("Change list of lists setting"), new String[] {tr("OK"), tr("Cancel")});
-        this.entry = entry;
+        super(gui, tr("Change list of lists setting"), entry);
         List<List<String>> orig = setting.getValue();
         data = new ArrayList<>();
@@ -64,58 +37,19 @@
             }
         }
-        setButtonIcons(new String[] {"ok.png", "cancel.png"});
-        setRememberWindowGeometry(getClass().getName() + ".geometry", WindowGeometry.centerInWindow(gui, new Dimension(500, 350)));
-        setContent(build(), false);
     }
 
-    /**
-     * Returns the data.
-     * @return the preference data
-     */
+    @Override
     public List<List<String>> getData() {
         return data;
     }
 
+    @Override
     protected final JPanel build() {
-        JPanel p = new JPanel(new GridBagLayout());
-        p.add(new JLabel(tr("Key: {0}", entry.getKey())), GBC.std(0, 0).span(2).weight(1, 0).insets(0, 0, 5, 10));
-
-        JPanel left = new JPanel(new GridBagLayout());
-
-        entryModel = new EntryListModel();
-        entryList = new JList<>(entryModel);
-        entryList.getSelectionModel().addListSelectionListener(new EntryListener());
-        JScrollPane scroll = new JScrollPane(entryList);
-        left.add(scroll, GBC.eol().fill());
-
-        JToolBar sideButtonTB = new JToolBar(JToolBar.HORIZONTAL);
-        sideButtonTB.setBorderPainted(false);
-        sideButtonTB.setOpaque(false);
-        sideButtonTB.add(new NewEntryAction());
-        RemoveEntryAction removeEntryAction = new RemoveEntryAction();
-        entryList.getSelectionModel().addListSelectionListener(removeEntryAction);
-        sideButtonTB.add(removeEntryAction);
-        left.add(sideButtonTB, GBC.eol());
-
-        left.setPreferredSize(new Dimension(80, 0));
-
-        p.add(left, GBC.std(0, 1).fill().weight(0.3, 1.0));
-
-        tableModel = new ListTableModel();
-        table = new JTable(tableModel);
-        table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
         table.setTableHeader(null);
-
-        DefaultCellEditor editor = new DefaultCellEditor(new JosmTextField());
-        editor.setClickCountToStart(1);
-        table.setDefaultEditor(table.getColumnClass(0), editor);
-
-        JScrollPane pane = new JScrollPane(table);
-        pane.setPreferredSize(new Dimension(140, 0));
-        p.add(pane, GBC.std(1, 1).insets(5, 0, 0, 0).fill().weight(0.7, 1.0));
-        return p;
+        return super.build();
     }
 
-    class EntryListModel extends AbstractListModel<String> {
+    private class EntryListModel extends AbstractEntryListModel {
+
         @Override
         public String getElementAt(int index) {
@@ -128,9 +62,11 @@
         }
 
-        public void add(List<String> l) {
-            data.add(l);
-            fireIntervalAdded(this, data.size() - 1, data.size() - 1);
+        @Override
+        public void add() {
+            data.add(new ArrayList<String>());
+            fireIntervalAdded(this, getSize() - 1, getSize() - 1);
         }
 
+        @Override
         public void remove(int idx) {
             data.remove(idx);
@@ -139,69 +75,17 @@
     }
 
-    class NewEntryAction extends AbstractAction {
-        NewEntryAction() {
-            putValue(NAME, tr("New"));
-            putValue(SHORT_DESCRIPTION, tr("add entry"));
-            putValue(SMALL_ICON, ImageProvider.get("dialogs", "add"));
+    private class ListTableModel extends AbstractTableModel {
+
+        private List<String> data() {
+            return entryIdx == null ? Collections.<String>emptyList() : data.get(entryIdx);
         }
 
-        @Override
-        public void actionPerformed(ActionEvent evt) {
-            entryModel.add(new ArrayList<String>());
-        }
-    }
-
-    class RemoveEntryAction extends AbstractAction implements ListSelectionListener {
-        RemoveEntryAction() {
-            putValue(NAME, tr("Remove"));
-            putValue(SHORT_DESCRIPTION, tr("Remove the selected entry"));
-            putValue(SMALL_ICON, ImageProvider.get("dialogs", "delete"));
-            updateEnabledState();
-        }
-
-        protected final void updateEnabledState() {
-            setEnabled(entryList.getSelectedIndices().length == 1);
-        }
-
-        @Override
-        public void valueChanged(ListSelectionEvent e) {
-            updateEnabledState();
-        }
-
-        @Override
-        public void actionPerformed(ActionEvent e) {
-            int idx = entryList.getSelectedIndices()[0];
-            entryModel.remove(idx);
-        }
-    }
-
-    class EntryListener implements ListSelectionListener {
-        @Override
-        public void valueChanged(ListSelectionEvent e) {
-            TableCellEditor editor = table.getCellEditor();
-            if (editor != null) {
-                ((DefaultCellEditor) editor).stopCellEditing();
-            }
-            if (entryList.getSelectedIndices().length != 1) {
-                entryIdx = null;
-                table.setEnabled(false);
-            } else {
-                entryIdx = entryList.getSelectedIndices()[0];
-                table.setEnabled(true);
-            }
-            tableModel.fireTableStructureChanged();
-        }
-    }
-
-    class ListTableModel extends AbstractTableModel {
-
-        private List<String> data() {
-            if (entryIdx == null) return Collections.emptyList();
-            return data.get(entryIdx);
+        private int size() {
+            return data().size();
         }
 
         @Override
         public int getRowCount() {
-            return entryIdx == null ? 0 : data().size() + 1;
+            return entryIdx == null ? 0 : size() + 1;
         }
 
@@ -213,5 +97,5 @@
         @Override
         public Object getValueAt(int row, int column) {
-            return data().size() == row ? "" : data().get(row);
+            return size() == row ? "" : data().get(row);
         }
 
@@ -219,11 +103,11 @@
         public void setValueAt(Object o, int row, int column) {
             String s = (String) o;
-            if (row == data().size()) {
+            if (row == size()) {
                 data().add(s);
                 fireTableRowsInserted(row+1, row+1);
             } else {
                 data().set(row, s);
+                fireTableCellUpdated(row, column);
             }
-            fireTableCellUpdated(row, column);
         }
 
@@ -233,3 +117,13 @@
         }
     }
+
+    @Override
+    protected AbstractEntryListModel newEntryListModel() {
+        return new EntryListModel();
+    }
+
+    @Override
+    protected AbstractTableModel newTableModel() {
+        return new ListTableModel();
+    }
 }
Index: /trunk/src/org/openstreetmap/josm/gui/preferences/advanced/MapListEditor.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/preferences/advanced/MapListEditor.java	(revision 9506)
+++ /trunk/src/org/openstreetmap/josm/gui/preferences/advanced/MapListEditor.java	(revision 9507)
@@ -4,7 +4,4 @@
 import static org.openstreetmap.josm.tools.I18n.tr;
 
-import java.awt.Dimension;
-import java.awt.GridBagLayout;
-import java.awt.event.ActionEvent;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -15,45 +12,27 @@
 import java.util.Map.Entry;
 
-import javax.swing.AbstractAction;
-import javax.swing.AbstractListModel;
-import javax.swing.DefaultCellEditor;
 import javax.swing.JComponent;
-import javax.swing.JLabel;
-import javax.swing.JList;
 import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-import javax.swing.JTable;
-import javax.swing.JToolBar;
-import javax.swing.event.ListSelectionEvent;
-import javax.swing.event.ListSelectionListener;
 import javax.swing.table.AbstractTableModel;
-import javax.swing.table.TableCellEditor;
 
 import org.openstreetmap.josm.data.Preferences.MapListSetting;
-import org.openstreetmap.josm.gui.ExtendedDialog;
-import org.openstreetmap.josm.gui.widgets.JosmTextField;
-import org.openstreetmap.josm.tools.GBC;
-import org.openstreetmap.josm.tools.ImageProvider;
-import org.openstreetmap.josm.tools.WindowGeometry;
 
 /**
  * Editor for List of Maps preference entries.
+ * @since 4634
  */
-public class MapListEditor extends ExtendedDialog {
+public class MapListEditor extends AbstractTableListEditor<Map<String, String>> {
 
-    private EntryListModel entryModel;
-    private final transient PrefEntry entry;
+    private final transient List<List<String>> dataKeys;
+    private final transient List<List<String>> dataValues;
 
-    private JList<String> entryList;
-    private JTable table;
-    private MapTableModel tableModel;
-
-    private final List<List<String>> dataKeys;
-    private final List<List<String>> dataValues;
-    private Integer entryIdx;
-
+    /**
+     * Constructs a new {@code MapListEditor}.
+     * @param gui The parent component
+     * @param entry preference entry
+     * @param setting list of maps setting
+     */
     public MapListEditor(JComponent gui, PrefEntry entry, MapListSetting setting) {
-        super(gui, tr("Change list of maps setting"), new String[] {tr("OK"), tr("Cancel")});
-        this.entry = entry;
+        super(gui, tr("Change list of maps setting"), entry);
         List<Map<String, String>> orig = setting.getValue();
 
@@ -72,13 +51,7 @@
             }
         }
-        setButtonIcons(new String[] {"ok.png", "cancel.png"});
-        setRememberWindowGeometry(getClass().getName() + ".geometry", WindowGeometry.centerInWindow(gui, new Dimension(500, 350)));
-        setContent(build(), false);
     }
 
-    /**
-     * Returns the data.
-     * @return the preference data
-     */
+    @Override
     public List<Map<String, String>> getData() {
         List<Map<String, String>> data = new ArrayList<>();
@@ -93,45 +66,13 @@
     }
 
+    @Override
     protected final JPanel build() {
-        JPanel p = new JPanel(new GridBagLayout());
-        p.add(new JLabel(tr("Key: {0}", entry.getKey())), GBC.std(0, 0).span(2).weight(1, 0).insets(0, 0, 5, 10));
-
-        JPanel left = new JPanel(new GridBagLayout());
-
-        entryModel = new EntryListModel();
-        entryList = new JList<>(entryModel);
-        entryList.getSelectionModel().addListSelectionListener(new EntryListener());
-        JScrollPane scroll = new JScrollPane(entryList);
-        left.add(scroll, GBC.eol().fill());
-
-        JToolBar sideButtonTB = new JToolBar(JToolBar.HORIZONTAL);
-        sideButtonTB.setBorderPainted(false);
-        sideButtonTB.setOpaque(false);
-        sideButtonTB.add(new NewEntryAction());
-        RemoveEntryAction removeEntryAction = new RemoveEntryAction();
-        entryList.getSelectionModel().addListSelectionListener(removeEntryAction);
-        sideButtonTB.add(removeEntryAction);
-        left.add(sideButtonTB, GBC.eol());
-
-        left.setPreferredSize(new Dimension(80, 0));
-
-        p.add(left, GBC.std(0, 1).fill().weight(0.3, 1.0));
-
-        tableModel = new MapTableModel();
-        table = new JTable(tableModel);
-        table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
         table.getTableHeader().getColumnModel().getColumn(0).setHeaderValue(tr("Key"));
         table.getTableHeader().getColumnModel().getColumn(1).setHeaderValue(tr("Value"));
-        DefaultCellEditor editor = new DefaultCellEditor(new JosmTextField());
-        editor.setClickCountToStart(1);
-        table.setDefaultEditor(table.getColumnClass(0), editor);
-
-        JScrollPane pane = new JScrollPane(table);
-        pane.setPreferredSize(new Dimension(140, 0));
-        p.add(pane, GBC.std(1, 1).insets(5, 0, 0, 0).fill().weight(0.7, 1.0));
-        return p;
+        return super.build();
     }
 
-    class EntryListModel extends AbstractListModel<String> {
+    private class EntryListModel extends AbstractEntryListModel {
+
         @Override
         public String getElementAt(int index) {
@@ -144,4 +85,5 @@
         }
 
+        @Override
         public void add() {
             dataKeys.add(new ArrayList<String>());
@@ -150,4 +92,5 @@
         }
 
+        @Override
         public void remove(int idx) {
             dataKeys.remove(idx);
@@ -157,68 +100,12 @@
     }
 
-    class NewEntryAction extends AbstractAction {
-        NewEntryAction() {
-            putValue(NAME, tr("New"));
-            putValue(SHORT_DESCRIPTION, tr("add entry"));
-            putValue(SMALL_ICON, ImageProvider.get("dialogs", "add"));
-        }
+    private class MapTableModel extends AbstractTableModel {
 
-        @Override
-        public void actionPerformed(ActionEvent evt) {
-            entryModel.add();
-        }
-    }
-
-    class RemoveEntryAction extends AbstractAction implements ListSelectionListener {
-        RemoveEntryAction() {
-            putValue(NAME, tr("Remove"));
-            putValue(SHORT_DESCRIPTION, tr("Remove the selected entry"));
-            putValue(SMALL_ICON, ImageProvider.get("dialogs", "delete"));
-            updateEnabledState();
-        }
-
-        protected final void updateEnabledState() {
-            setEnabled(entryList.getSelectedIndices().length == 1);
-        }
-
-        @Override
-        public void valueChanged(ListSelectionEvent e) {
-            updateEnabledState();
-        }
-
-        @Override
-        public void actionPerformed(ActionEvent e) {
-            int idx = entryList.getSelectedIndices()[0];
-            entryModel.remove(idx);
-        }
-    }
-
-    class EntryListener implements ListSelectionListener {
-        @Override
-        public void valueChanged(ListSelectionEvent e) {
-            TableCellEditor editor = table.getCellEditor();
-            if (editor != null) {
-                ((DefaultCellEditor) editor).stopCellEditing();
-            }
-            if (entryList.getSelectedIndices().length != 1) {
-                entryIdx = null;
-                table.setEnabled(false);
-            } else {
-                entryIdx = entryList.getSelectedIndices()[0];
-                table.setEnabled(true);
-            }
-            tableModel.fireTableDataChanged();
-        }
-    }
-
-    class MapTableModel extends AbstractTableModel {
         private List<List<String>> data() {
-            if (entryIdx == null) return Collections.emptyList();
-            return Arrays.asList(dataKeys.get(entryIdx), dataValues.get(entryIdx));
+            return entryIdx == null ? Collections.<List<String>>emptyList() : Arrays.asList(dataKeys.get(entryIdx), dataValues.get(entryIdx));
         }
 
         private int size() {
-            if (entryIdx == null) return 0;
-            return dataKeys.get(entryIdx).size();
+            return entryIdx == null ? 0 : dataKeys.get(entryIdx).size();
         }
 
@@ -263,3 +150,12 @@
     }
 
+    @Override
+    protected final AbstractEntryListModel newEntryListModel() {
+        return new EntryListModel();
+    }
+
+    @Override
+    protected final AbstractTableModel newTableModel() {
+        return new MapTableModel();
+    }
 }
