Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/GenericRelationEditor.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/GenericRelationEditor.java	(revision 1829)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/GenericRelationEditor.java	(revision 1830)
@@ -586,9 +586,231 @@
     }
 
-    /**
-     * This function saves the user's changes. Must be invoked manually.
-     */
-    protected void applyChanges() {
-        if (getRelation() == null) {
+    @Override
+    protected Dimension findMaxDialogSize() {
+        // FIXME: Make it remember dialog size
+        return new Dimension(700, 500);
+    }
+
+    /**
+     * Asynchronously download the members of the currently edited relation
+     * 
+     */
+    private void downloadRelationMembers() {
+        if (!memberTableModel.hasIncompleteMembers())
+            return;
+        Main.worker.submit(new DownloadTask(this));
+    }
+
+    @Override
+    public void dispose() {
+        selectionTableModel.unregister();
+        super.dispose();
+    }
+
+    @Override
+    public void setVisible(boolean b) {
+        super.setVisible(b);
+        if (!b) {
+            dispose();
+        }
+    }
+
+    class AddSelectedAtStartAction extends AbstractAction implements TableModelListener {
+        public AddSelectedAtStartAction() {
+            putValue(SHORT_DESCRIPTION,
+                    tr("Add all primitives selected in the current dataset before the first member"));
+            putValue(SMALL_ICON, ImageProvider.get("dialogs/conflict", "copystartright"));
+            // putValue(NAME, tr("Add Selected"));
+            refreshEnabled();
+        }
+
+        protected void refreshEnabled() {
+            setEnabled(selectionTableModel.getRowCount() > 0);
+        }
+
+        public void actionPerformed(ActionEvent e) {
+            memberTableModel.addMembersAtBeginning(selectionTableModel.getSelection());
+        }
+
+        public void tableChanged(TableModelEvent e) {
+            refreshEnabled();
+        }
+    }
+
+    class AddSelectedAtEndAction extends AbstractAction implements TableModelListener {
+        public AddSelectedAtEndAction() {
+            putValue(SHORT_DESCRIPTION, tr("Add all primitives selected in the current dataset after the last member"));
+            putValue(SMALL_ICON, ImageProvider.get("dialogs/conflict", "copyendright"));
+            // putValue(NAME, tr("Add Selected"));
+            refreshEnabled();
+        }
+
+        protected void refreshEnabled() {
+            setEnabled(selectionTableModel.getRowCount() > 0);
+        }
+
+        public void actionPerformed(ActionEvent e) {
+            memberTableModel.addMembersAtEnd(selectionTableModel.getSelection());
+        }
+
+        public void tableChanged(TableModelEvent e) {
+            refreshEnabled();
+        }
+    }
+
+    class AddSelectedBeforeSelection extends AbstractAction implements TableModelListener, ListSelectionListener {
+        public AddSelectedBeforeSelection() {
+            putValue(SHORT_DESCRIPTION,
+                    tr("Add all primitives selected in the current dataset before the first selected member"));
+            putValue(SMALL_ICON, ImageProvider.get("dialogs/conflict", "copybeforecurrentright"));
+            // putValue(NAME, tr("Add Selected"));
+            refreshEnabled();
+        }
+
+        protected void refreshEnabled() {
+            setEnabled(selectionTableModel.getRowCount() > 0
+                    && memberTableModel.getSelectionModel().getMinSelectionIndex() >= 0);
+        }
+
+        public void actionPerformed(ActionEvent e) {
+            memberTableModel.addMembersBeforeIdx(selectionTableModel.getSelection(), memberTableModel
+                    .getSelectionModel().getMinSelectionIndex());
+        }
+
+        public void tableChanged(TableModelEvent e) {
+            refreshEnabled();
+        }
+
+        public void valueChanged(ListSelectionEvent e) {
+            refreshEnabled();
+        }
+    }
+
+    class AddSelectedAfterSelection extends AbstractAction implements TableModelListener, ListSelectionListener {
+        public AddSelectedAfterSelection() {
+            putValue(SHORT_DESCRIPTION,
+                    tr("Add all primitives selected in the current dataset after the last selected member"));
+            putValue(SMALL_ICON, ImageProvider.get("dialogs/conflict", "copyaftercurrentright"));
+            // putValue(NAME, tr("Add Selected"));
+            refreshEnabled();
+        }
+
+        protected void refreshEnabled() {
+            setEnabled(selectionTableModel.getRowCount() > 0
+                    && memberTableModel.getSelectionModel().getMinSelectionIndex() >= 0);
+        }
+
+        public void actionPerformed(ActionEvent e) {
+            memberTableModel.addMembersAfterIdx(selectionTableModel.getSelection(), memberTableModel
+                    .getSelectionModel().getMaxSelectionIndex());
+        }
+
+        public void tableChanged(TableModelEvent e) {
+            refreshEnabled();
+        }
+
+        public void valueChanged(ListSelectionEvent e) {
+            refreshEnabled();
+        }
+    }
+
+    class RemoveSelectedAction extends AbstractAction implements TableModelListener {
+        public RemoveSelectedAction() {
+            putValue(SHORT_DESCRIPTION, tr("Remove all currently selected objects from relation"));
+            putValue(SMALL_ICON, ImageProvider.get("dialogs", "removeselected"));
+            // putValue(NAME, tr("Remove Selected"));
+            Shortcut.registerShortcut("relationeditor:removeselected", tr("Relation Editor: Remove Selected"),
+                    KeyEvent.VK_S, Shortcut.GROUP_MNEMONIC);
+
+            DataSet ds = getLayer().data;
+            setEnabled(ds != null && !ds.getSelected().isEmpty());
+        }
+
+        public void actionPerformed(ActionEvent e) {
+            memberTableModel.removeMembersReferringTo(selectionTableModel.getSelection());
+        }
+
+        public void tableChanged(TableModelEvent e) {
+            setEnabled(selectionTableModel.getRowCount() > 0);
+        }
+    }
+
+    class SortAction extends AbstractAction {
+        public SortAction() {
+            putValue(SHORT_DESCRIPTION, tr("Sort the relation members"));
+            putValue(SMALL_ICON, ImageProvider.get("dialogs", "sort"));
+            // putValue(NAME, tr("Sort"));
+            Shortcut.registerShortcut("relationeditor:sort", tr("Relation Editor: Sort"), KeyEvent.VK_T,
+                    Shortcut.GROUP_MNEMONIC);
+            //setEnabled(false);
+        }
+
+        public void actionPerformed(ActionEvent e) {
+            memberTableModel.sort();
+        }
+    }
+
+    class MoveUpAction extends AbstractAction implements ListSelectionListener {
+        public MoveUpAction() {
+            putValue(SHORT_DESCRIPTION, tr("Move the currently selected members up"));
+            putValue(SMALL_ICON, ImageProvider.get("dialogs", "moveup"));
+            // putValue(NAME, tr("Move Up"));
+            Shortcut.registerShortcut("relationeditor:moveup", tr("Relation Editor: Move Up"), KeyEvent.VK_N,
+                    Shortcut.GROUP_MNEMONIC);
+            setEnabled(false);
+        }
+
+        public void actionPerformed(ActionEvent e) {
+            memberTableModel.moveUp(memberTable.getSelectedRows());
+        }
+
+        public void valueChanged(ListSelectionEvent e) {
+            setEnabled(memberTableModel.canMoveUp(memberTable.getSelectedRows()));
+        }
+    }
+
+    class MoveDownAction extends AbstractAction implements ListSelectionListener {
+        public MoveDownAction() {
+            putValue(SHORT_DESCRIPTION, tr("Move the currently selected members down"));
+            putValue(SMALL_ICON, ImageProvider.get("dialogs", "movedown"));
+            // putValue(NAME, tr("Move Down"));
+            Shortcut.registerShortcut("relationeditor:moveup", tr("Relation Editor: Move Down"), KeyEvent.VK_J,
+                    Shortcut.GROUP_MNEMONIC);
+            setEnabled(false);
+        }
+
+        public void actionPerformed(ActionEvent e) {
+            memberTableModel.moveDown(memberTable.getSelectedRows());
+        }
+
+        public void valueChanged(ListSelectionEvent e) {
+            setEnabled(memberTableModel.canMoveDown(memberTable.getSelectedRows()));
+        }
+    }
+
+    class RemoveAction extends AbstractAction implements ListSelectionListener {
+        public RemoveAction() {
+            putValue(SHORT_DESCRIPTION, tr("Remove the member in the current table row from this relation"));
+            putValue(SMALL_ICON, ImageProvider.get("dialogs", "remove"));
+            // putValue(NAME, tr("Remove"));
+            Shortcut.registerShortcut("relationeditor:remove", tr("Relation Editor: Remove"), KeyEvent.VK_J,
+                    Shortcut.GROUP_MNEMONIC);
+            setEnabled(false);
+        }
+
+        public void actionPerformed(ActionEvent e) {
+            memberTableModel.remove(memberTable.getSelectedRows());
+        }
+
+        public void valueChanged(ListSelectionEvent e) {
+            setEnabled(memberTableModel.canRemove(memberTable.getSelectedRows()));
+        }
+    }
+
+    class OKAction extends AbstractAction {
+        /**
+         * apply updates to a new relation
+         */
+        protected void applyNewRelation() {
             // If the user wanted to create a new relation, but hasn't added any members or
             // tags, don't add an empty relation
@@ -600,5 +822,10 @@
             Main.main.undoRedo.add(new AddCommand(newRelation));
             DataSet.fireSelectionChanged(getLayer().data.getSelected());
-        } else if (!memberTableModel.hasSameMembersAs(getRelation()) || tagEditorModel.isDirty()) {
+        }
+
+        /**
+         * apply updates to an existing relation
+         */
+        protected void applyExistingRelation() {
             Relation editedRelation = new Relation(getRelation());
             tagEditorModel.applyToPrimitive(editedRelation);
@@ -607,8 +834,10 @@
                 Conflict<Relation> conflict = new Conflict<Relation>(getRelation(), editedRelation);
                 getLayer().getConflicts().add(conflict);
-                JOptionPane op = new JOptionPane(tr("<html>The relation has changed outside of the editor.<br>"
-                        + "Your edit can't be applied directly, a conflict has been created instead.</html>"),
-                        JOptionPane.WARNING_MESSAGE);
-                JDialog dialog = op.createDialog(this, tr("Conflict created"));
+                JOptionPane op = new JOptionPane(
+                        tr("<html>The relation has changed outside of the editor.<br>"
+                                + "Your edits can't be applied directly, a conflict has been created instead.</html>"),
+                                JOptionPane.WARNING_MESSAGE
+                );
+                JDialog dialog = op.createDialog(GenericRelationEditor.this, tr("Conflict created"));
                 dialog.setAlwaysOnTop(true);
                 dialog.setModal(true);
@@ -616,236 +845,23 @@
                 dialog.setVisible(true);
             } else {
-                Relation clone = new Relation(getRelation());
-                tagEditorModel.applyToPrimitive(clone);
-                memberTableModel.applyToRelation(clone);
-                Main.main.undoRedo.add(new ChangeCommand(getRelation(), clone));
+                tagEditorModel.applyToPrimitive(editedRelation);
+                memberTableModel.applyToRelation(editedRelation);
+                Main.main.undoRedo.add(new ChangeCommand(getRelation(), editedRelation));
                 DataSet.fireSelectionChanged(getLayer().data.getSelected());
             }
         }
-    }
-
-    @Override
-    protected Dimension findMaxDialogSize() {
-        // FIXME: Make it remember dialog size
-        return new Dimension(700, 500);
-    }
-
-    /**
-     * Asynchronously download the members of the currently edited relation
-     * 
-     */
-    private void downloadRelationMembers() {
-        if (!memberTableModel.hasIncompleteMembers())
-            return;
-        Main.worker.submit(new DownloadTask(this));
-    }
-
-    @Override
-    public void dispose() {
-        selectionTableModel.unregister();
-        super.dispose();
-    }
-
-    @Override
-    public void setVisible(boolean b) {
-        super.setVisible(b);
-        if (!b) {
-            dispose();
-        }
-    }
-
-    class AddSelectedAtStartAction extends AbstractAction implements TableModelListener {
-        public AddSelectedAtStartAction() {
-            putValue(SHORT_DESCRIPTION,
-                    tr("Add all primitives selected in the current dataset before the first member"));
-            putValue(SMALL_ICON, ImageProvider.get("dialogs/conflict", "copystartright"));
-            // putValue(NAME, tr("Add Selected"));
-            refreshEnabled();
-        }
-
-        protected void refreshEnabled() {
-            setEnabled(selectionTableModel.getRowCount() > 0);
-        }
-
-        public void actionPerformed(ActionEvent e) {
-            memberTableModel.addMembersAtBeginning(selectionTableModel.getSelection());
-        }
-
-        public void tableChanged(TableModelEvent e) {
-            refreshEnabled();
-        }
-    }
-
-    class AddSelectedAtEndAction extends AbstractAction implements TableModelListener {
-        public AddSelectedAtEndAction() {
-            putValue(SHORT_DESCRIPTION, tr("Add all primitives selected in the current dataset after the last member"));
-            putValue(SMALL_ICON, ImageProvider.get("dialogs/conflict", "copyendright"));
-            // putValue(NAME, tr("Add Selected"));
-            refreshEnabled();
-        }
-
-        protected void refreshEnabled() {
-            setEnabled(selectionTableModel.getRowCount() > 0);
-        }
-
-        public void actionPerformed(ActionEvent e) {
-            memberTableModel.addMembersAtEnd(selectionTableModel.getSelection());
-        }
-
-        public void tableChanged(TableModelEvent e) {
-            refreshEnabled();
-        }
-    }
-
-    class AddSelectedBeforeSelection extends AbstractAction implements TableModelListener, ListSelectionListener {
-        public AddSelectedBeforeSelection() {
-            putValue(SHORT_DESCRIPTION,
-                    tr("Add all primitives selected in the current dataset before the first selected member"));
-            putValue(SMALL_ICON, ImageProvider.get("dialogs/conflict", "copybeforecurrentright"));
-            // putValue(NAME, tr("Add Selected"));
-            refreshEnabled();
-        }
-
-        protected void refreshEnabled() {
-            setEnabled(selectionTableModel.getRowCount() > 0
-                    && memberTableModel.getSelectionModel().getMinSelectionIndex() >= 0);
-        }
-
-        public void actionPerformed(ActionEvent e) {
-            memberTableModel.addMembersBeforeIdx(selectionTableModel.getSelection(), memberTableModel
-                    .getSelectionModel().getMinSelectionIndex());
-        }
-
-        public void tableChanged(TableModelEvent e) {
-            refreshEnabled();
-        }
-
-        public void valueChanged(ListSelectionEvent e) {
-            refreshEnabled();
-        }
-    }
-
-    class AddSelectedAfterSelection extends AbstractAction implements TableModelListener, ListSelectionListener {
-        public AddSelectedAfterSelection() {
-            putValue(SHORT_DESCRIPTION,
-                    tr("Add all primitives selected in the current dataset after the last selected member"));
-            putValue(SMALL_ICON, ImageProvider.get("dialogs/conflict", "copyaftercurrentright"));
-            // putValue(NAME, tr("Add Selected"));
-            refreshEnabled();
-        }
-
-        protected void refreshEnabled() {
-            setEnabled(selectionTableModel.getRowCount() > 0
-                    && memberTableModel.getSelectionModel().getMinSelectionIndex() >= 0);
-        }
-
-        public void actionPerformed(ActionEvent e) {
-            memberTableModel.addMembersAfterIdx(selectionTableModel.getSelection(), memberTableModel
-                    .getSelectionModel().getMaxSelectionIndex());
-        }
-
-        public void tableChanged(TableModelEvent e) {
-            refreshEnabled();
-        }
-
-        public void valueChanged(ListSelectionEvent e) {
-            refreshEnabled();
-        }
-    }
-
-    class RemoveSelectedAction extends AbstractAction implements TableModelListener {
-        public RemoveSelectedAction() {
-            putValue(SHORT_DESCRIPTION, tr("Remove all currently selected objects from relation"));
-            putValue(SMALL_ICON, ImageProvider.get("dialogs", "removeselected"));
-            // putValue(NAME, tr("Remove Selected"));
-            Shortcut.registerShortcut("relationeditor:removeselected", tr("Relation Editor: Remove Selected"),
-                    KeyEvent.VK_S, Shortcut.GROUP_MNEMONIC);
-
-            DataSet ds = getLayer().data;
-            setEnabled(ds != null && !ds.getSelected().isEmpty());
-        }
-
-        public void actionPerformed(ActionEvent e) {
-            memberTableModel.removeMembersReferringTo(selectionTableModel.getSelection());
-        }
-
-        public void tableChanged(TableModelEvent e) {
-            setEnabled(selectionTableModel.getRowCount() > 0);
-        }
-    }
-
-    class SortAction extends AbstractAction {
-        public SortAction() {
-            putValue(SHORT_DESCRIPTION, tr("Sort the relation members"));
-            putValue(SMALL_ICON, ImageProvider.get("dialogs", "sort"));
-            // putValue(NAME, tr("Sort"));
-            Shortcut.registerShortcut("relationeditor:sort", tr("Relation Editor: Sort"), KeyEvent.VK_T,
-                    Shortcut.GROUP_MNEMONIC);
-            //setEnabled(false);
-        }
-
-        public void actionPerformed(ActionEvent e) {
-            memberTableModel.sort();
-        }
-    }
-
-    class MoveUpAction extends AbstractAction implements ListSelectionListener {
-        public MoveUpAction() {
-            putValue(SHORT_DESCRIPTION, tr("Move the currently selected members up"));
-            putValue(SMALL_ICON, ImageProvider.get("dialogs", "moveup"));
-            // putValue(NAME, tr("Move Up"));
-            Shortcut.registerShortcut("relationeditor:moveup", tr("Relation Editor: Move Up"), KeyEvent.VK_N,
-                    Shortcut.GROUP_MNEMONIC);
-            setEnabled(false);
-        }
-
-        public void actionPerformed(ActionEvent e) {
-            memberTableModel.moveUp(memberTable.getSelectedRows());
-        }
-
-        public void valueChanged(ListSelectionEvent e) {
-            setEnabled(memberTableModel.canMoveUp(memberTable.getSelectedRows()));
-        }
-    }
-
-    class MoveDownAction extends AbstractAction implements ListSelectionListener {
-        public MoveDownAction() {
-            putValue(SHORT_DESCRIPTION, tr("Move the currently selected members down"));
-            putValue(SMALL_ICON, ImageProvider.get("dialogs", "movedown"));
-            // putValue(NAME, tr("Move Down"));
-            Shortcut.registerShortcut("relationeditor:moveup", tr("Relation Editor: Move Down"), KeyEvent.VK_J,
-                    Shortcut.GROUP_MNEMONIC);
-            setEnabled(false);
-        }
-
-        public void actionPerformed(ActionEvent e) {
-            memberTableModel.moveDown(memberTable.getSelectedRows());
-        }
-
-        public void valueChanged(ListSelectionEvent e) {
-            setEnabled(memberTableModel.canMoveDown(memberTable.getSelectedRows()));
-        }
-    }
-
-    class RemoveAction extends AbstractAction implements ListSelectionListener {
-        public RemoveAction() {
-            putValue(SHORT_DESCRIPTION, tr("Remove the member in the current table row from this relation"));
-            putValue(SMALL_ICON, ImageProvider.get("dialogs", "remove"));
-            // putValue(NAME, tr("Remove"));
-            Shortcut.registerShortcut("relationeditor:remove", tr("Relation Editor: Remove"), KeyEvent.VK_J,
-                    Shortcut.GROUP_MNEMONIC);
-            setEnabled(false);
-        }
-
-        public void actionPerformed(ActionEvent e) {
-            memberTableModel.remove(memberTable.getSelectedRows());
-        }
-
-        public void valueChanged(ListSelectionEvent e) {
-            setEnabled(memberTableModel.canRemove(memberTable.getSelectedRows()));
-        }
-    }
-
-    class OKAction extends AbstractAction {
+
+        /**
+         * Applies updates
+         */
+        protected void applyChanges() {
+            if (getRelation() == null) {
+                applyNewRelation();
+            } else if (!memberTableModel.hasSameMembersAs(getRelationSnapshot())
+                    || tagEditorModel.isDirty()) {
+                applyExistingRelation();
+            }
+        }
+
         public OKAction() {
             putValue(SHORT_DESCRIPTION, tr("Apply the updates and close the dialog"));
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/MemberTableModel.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/MemberTableModel.java	(revision 1829)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/MemberTableModel.java	(revision 1830)
@@ -64,5 +64,7 @@
         members.clear();
         if (relation != null && relation.members != null) {
-            members.addAll(relation.members);
+            // make sure we work with clones of the relation members
+            // in the model.
+            members.addAll(new Relation(relation).members);
         }
         fireTableDataChanged();
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/RelationEditor.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/RelationEditor.java	(revision 1829)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/RelationEditor.java	(revision 1830)
@@ -108,12 +108,29 @@
     }
 
+    /**
+     * Replies the currently edited relation
+     * 
+     * @return the currently edited relation
+     */
     protected Relation getRelation() {
         return relation;
     }
 
+    /**
+     * Replies the {@see OsmDataLayer} in whose context this relation editor is
+     * open
+     * 
+     * @return the {@see OsmDataLayer} in whose context this relation editor is
+     * open
+     */
     protected OsmDataLayer getLayer() {
         return layer;
     }
 
+    /**
+     * Replies the state of the edited relation when the editor has been launched
+     * 
+     * @return the state of the edited relation when the editor has been launched
+     */
     protected Relation getRelationSnapshot() {
         return relationSnapshot;
