Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/GenericRelationEditor.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/GenericRelationEditor.java	(revision 14026)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/GenericRelationEditor.java	(revision 14027)
@@ -24,4 +24,5 @@
 import java.awt.event.WindowEvent;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
@@ -49,5 +50,4 @@
 
 import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.actions.ExpertToggleAction;
 import org.openstreetmap.josm.actions.JosmAction;
 import org.openstreetmap.josm.command.ChangeCommand;
@@ -76,4 +76,6 @@
 import org.openstreetmap.josm.gui.dialogs.relation.actions.DuplicateRelationAction;
 import org.openstreetmap.josm.gui.dialogs.relation.actions.EditAction;
+import org.openstreetmap.josm.gui.dialogs.relation.actions.IRelationEditorActionAccess;
+import org.openstreetmap.josm.gui.dialogs.relation.actions.IRelationEditorActionGroup;
 import org.openstreetmap.josm.gui.dialogs.relation.actions.MoveDownAction;
 import org.openstreetmap.josm.gui.dialogs.relation.actions.MoveUpAction;
@@ -93,4 +95,5 @@
 import org.openstreetmap.josm.gui.help.HelpUtil;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.gui.tagging.TagEditorModel;
 import org.openstreetmap.josm.gui.tagging.TagEditorPanel;
 import org.openstreetmap.josm.gui.tagging.ac.AutoCompletingTextField;
@@ -221,10 +224,10 @@
         selectionTable.setRowHeight(ce.getEditor().getPreferredSize().height);
 
-        leftButtonToolbar = new LeftButtonToolbar(memberTable, memberTableModel, this);
+        leftButtonToolbar = new LeftButtonToolbar(new RelationEditorActionAccess());
         tfRole = buildRoleTextField(this);
 
         JSplitPane pane = buildSplitPane(
                 buildTagEditorPanel(tagEditorPanel),
-                buildMemberEditorPanel(memberTable, memberTableModel, selectionTable, selectionTableModel, this, leftButtonToolbar, tfRole),
+                buildMemberEditorPanel(leftButtonToolbar, new RelationEditorActionAccess()),
                 this);
         pane.setPreferredSize(new Dimension(100, 100));
@@ -248,14 +251,16 @@
             }
         });
-
-        refreshAction = new RefreshAction(memberTable, memberTableModel, tagEditorPanel.getModel(), getLayer(), this);
-        applyAction = new ApplyAction(memberTable, memberTableModel, tagEditorPanel.getModel(), getLayer(), this);
-        selectAction = new SelectAction(getLayer(), this);
-        duplicateAction = new DuplicateRelationAction(memberTableModel, tagEditorPanel.getModel(), getLayer());
-        deleteAction = new DeleteCurrentRelationAction(getLayer(), this);
+        
+        IRelationEditorActionAccess actionAccess = new RelationEditorActionAccess();
+
+        refreshAction = new RefreshAction(actionAccess);
+        applyAction = new ApplyAction(actionAccess);
+        selectAction = new SelectAction(actionAccess);
+        duplicateAction = new DuplicateRelationAction(actionAccess);
+        deleteAction = new DeleteCurrentRelationAction(actionAccess);
         addPropertyChangeListener(deleteAction);
 
-        okAction = new OKAction(memberTable, memberTableModel, tagEditorPanel.getModel(), getLayer(), this, tfRole);
-        cancelAction = new CancelAction(memberTable, memberTableModel, tagEditorPanel.getModel(), getLayer(), this, tfRole);
+        okAction = new OKAction(actionAccess);
+        cancelAction = new CancelAction(actionAccess);
 
         getContentPane().add(buildToolBar(refreshAction, applyAction, selectAction, duplicateAction, deleteAction), BorderLayout.NORTH);
@@ -288,6 +293,8 @@
         if (key != null) {
             // handle uncommon situation, that user has no keystroke assigned to paste
-            registerCopyPasteAction(new PasteMembersAction(memberTable, getLayer(), this) {
-                @Override
+            registerCopyPasteAction(new PasteMembersAction(actionAccess) {
+				private static final long serialVersionUID = 1L;
+
+				@Override
                 public void actionPerformed(ActionEvent e) {
                     super.actionPerformed(e);
@@ -299,5 +306,5 @@
         if (key != null) {
             // handle uncommon situation, that user has no keystroke assigned to copy
-            registerCopyPasteAction(new CopyMembersAction(memberTableModel, getLayer(), this),
+            registerCopyPasteAction(new CopyMembersAction(actionAccess),
                     "COPY_MEMBERS", key, getRootPane(), memberTable, selectionTable);
         }
@@ -447,19 +454,13 @@
     /**
      * builds the panel for the relation member editor
-     * @param memberTable member table
-     * @param memberTableModel member table model
-     * @param selectionTable selection table
-     * @param selectionTableModel selection table model
-     * @param re relation editor
      * @param leftButtonToolbar left button toolbar
-     * @param tfRole role text field
+     * @param editorAccess The relation editor
      *
      * @return the panel for the relation member editor
      */
-    protected static JPanel buildMemberEditorPanel(final MemberTable memberTable, MemberTableModel memberTableModel,
-            SelectionTable selectionTable, SelectionTableModel selectionTableModel, IRelationEditor re,
-            LeftButtonToolbar leftButtonToolbar, final AutoCompletingTextField tfRole) {
+    protected static JPanel buildMemberEditorPanel(
+            LeftButtonToolbar leftButtonToolbar, IRelationEditorActionAccess editorAccess) {
         final JPanel pnl = new JPanel(new GridBagLayout());
-        final JScrollPane scrollPane = new JScrollPane(memberTable);
+        final JScrollPane scrollPane = new JScrollPane(editorAccess.getMemberTable());
 
         GridBagConstraints gc = new GridBagConstraints();
@@ -495,13 +496,13 @@
         JPanel p3 = new JPanel(new FlowLayout(FlowLayout.LEFT));
         p3.add(new JLabel(tr("Apply Role:")));
-        p3.add(tfRole);
-        SetRoleAction setRoleAction = new SetRoleAction(memberTable, memberTableModel, tfRole);
-        memberTableModel.getSelectionModel().addListSelectionListener(setRoleAction);
-        tfRole.getDocument().addDocumentListener(setRoleAction);
-        tfRole.addActionListener(setRoleAction);
-        memberTableModel.getSelectionModel().addListSelectionListener(
-                e -> tfRole.setEnabled(memberTable.getSelectedRowCount() > 0)
+        p3.add(editorAccess.getTextFieldRole());
+        SetRoleAction setRoleAction = new SetRoleAction(editorAccess);
+        editorAccess.getMemberTableModel().getSelectionModel().addListSelectionListener(setRoleAction);
+        editorAccess.getTextFieldRole().getDocument().addDocumentListener(setRoleAction);
+        editorAccess.getTextFieldRole().addActionListener(setRoleAction);
+        editorAccess.getMemberTableModel().getSelectionModel().addListSelectionListener(
+                e -> editorAccess.getTextFieldRole().setEnabled(editorAccess.getMemberTable().getSelectedRowCount() > 0)
         );
-        tfRole.setEnabled(memberTable.getSelectedRowCount() > 0);
+        editorAccess.getTextFieldRole().setEnabled(editorAccess.getMemberTable().getSelectedRowCount() > 0);
         JButton btnApply = new JButton(setRoleAction);
         btnApply.setPreferredSize(new Dimension(20, 20));
@@ -537,5 +538,5 @@
         gc.weightx = 0.0;
         gc.weighty = 1.0;
-        pnl2.add(new ScrollViewport(buildSelectionControlButtonToolbar(memberTable, memberTableModel, selectionTableModel, re),
+        pnl2.add(new ScrollViewport(buildSelectionControlButtonToolbar(editorAccess),
                 ScrollViewport.VERTICAL_DIRECTION), gc);
 
@@ -545,5 +546,5 @@
         gc.weighty = 1.0;
         gc.fill = GridBagConstraints.BOTH;
-        pnl2.add(buildSelectionTablePanel(selectionTable), gc);
+        pnl2.add(buildSelectionTablePanel(editorAccess.getSelectionTable()), gc);
 
         final JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
@@ -551,6 +552,6 @@
         splitPane.setRightComponent(pnl2);
         splitPane.setOneTouchExpandable(false);
-        if (re instanceof Window) {
-            ((Window) re).addWindowListener(new WindowAdapter() {
+        if (editorAccess.getEditor() instanceof Window) {
+            ((Window) editorAccess.getEditor()).addWindowListener(new WindowAdapter() {
                 @Override
                 public void windowOpened(WindowEvent e) {
@@ -608,77 +609,50 @@
      */
     static class LeftButtonToolbar extends JToolBar {
-
-        /**
-         * Button for performing the {@link org.openstreetmap.josm.gui.dialogs.relation.actions.SortBelowAction}.
-         */
-        final JButton sortBelowButton;
-
-        /**
+		private static final long serialVersionUID = 1L;
+
+		/**
          * Constructs a new {@code LeftButtonToolbar}.
-         * @param memberTable member table
-         * @param memberTableModel member table model
          * @param re relation editor
          */
-        LeftButtonToolbar(MemberTable memberTable, MemberTableModel memberTableModel, IRelationEditor re) {
+        LeftButtonToolbar(IRelationEditorActionAccess editorAccess) {
             setOrientation(JToolBar.VERTICAL);
             setFloatable(false);
 
-            // -- move up action
-            MoveUpAction moveUpAction = new MoveUpAction(memberTable, memberTableModel, "moveUp");
-            memberTableModel.getSelectionModel().addListSelectionListener(moveUpAction);
-            add(moveUpAction);
-
-            // -- move down action
-            MoveDownAction moveDownAction = new MoveDownAction(memberTable, memberTableModel, "moveDown");
-            memberTableModel.getSelectionModel().addListSelectionListener(moveDownAction);
-            add(moveDownAction);
-
-            addSeparator();
-
-            // -- edit action
-            EditAction editAction = new EditAction(memberTable, memberTableModel, re.getLayer());
-            memberTableModel.getSelectionModel().addListSelectionListener(editAction);
-            add(editAction);
-
-            // -- delete action
-            RemoveAction removeSelectedAction = new RemoveAction(memberTable, memberTableModel, "removeSelected");
-            memberTable.getSelectionModel().addListSelectionListener(removeSelectedAction);
-            add(removeSelectedAction);
-
-            addSeparator();
-            // -- sort action
-            SortAction sortAction = new SortAction(memberTable, memberTableModel);
-            memberTableModel.addTableModelListener(sortAction);
-            add(sortAction);
-            final SortBelowAction sortBelowAction = new SortBelowAction(memberTable, memberTableModel);
-            memberTableModel.addTableModelListener(sortBelowAction);
-            memberTableModel.getSelectionModel().addListSelectionListener(sortBelowAction);
-            sortBelowButton = add(sortBelowAction);
-
-            // -- reverse action
-            ReverseAction reverseAction = new ReverseAction(memberTable, memberTableModel);
-            memberTableModel.addTableModelListener(reverseAction);
-            add(reverseAction);
-
-            addSeparator();
-
-            // -- download action
-            DownloadIncompleteMembersAction downloadIncompleteMembersAction = new DownloadIncompleteMembersAction(
-                    memberTable, memberTableModel, "downloadIncomplete", re.getLayer(), re);
-            memberTable.getModel().addTableModelListener(downloadIncompleteMembersAction);
-            add(downloadIncompleteMembersAction);
-
-            // -- download selected action
-            DownloadSelectedIncompleteMembersAction downloadSelectedIncompleteMembersAction = new DownloadSelectedIncompleteMembersAction(
-                    memberTable, memberTableModel, null, re.getLayer(), re);
-            memberTable.getModel().addTableModelListener(downloadSelectedIncompleteMembersAction);
-            memberTable.getSelectionModel().addListSelectionListener(downloadSelectedIncompleteMembersAction);
-            add(downloadSelectedIncompleteMembersAction);
-
-            InputMap inputMap = memberTable.getInputMap(MemberTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
-            inputMap.put((KeyStroke) removeSelectedAction.getValue(AbstractAction.ACCELERATOR_KEY), "removeSelected");
-            inputMap.put((KeyStroke) moveUpAction.getValue(AbstractAction.ACCELERATOR_KEY), "moveUp");
-            inputMap.put((KeyStroke) moveDownAction.getValue(AbstractAction.ACCELERATOR_KEY), "moveDown");
-            inputMap.put((KeyStroke) downloadIncompleteMembersAction.getValue(AbstractAction.ACCELERATOR_KEY), "downloadIncomplete");
+            List<IRelationEditorActionGroup> groups = new ArrayList<>();
+            // Move
+            groups.add(buildNativeGroup(10,
+            		new MoveUpAction(editorAccess, "moveUp"),
+            		new MoveDownAction(editorAccess, "moveDown")
+            		));
+            // Edit
+            groups.add(buildNativeGroup(20,
+            		new EditAction(editorAccess),
+            		new RemoveAction(editorAccess, "removeSelected")
+            		));
+            // Sort
+            groups.add(buildNativeGroup(30,
+            		new SortAction(editorAccess),
+            		new SortBelowAction(editorAccess)
+            		));
+            // Reverse
+            groups.add(buildNativeGroup(40,
+            		new ReverseAction(editorAccess)
+            		));
+            // Download
+            groups.add(buildNativeGroup(50,
+            		new DownloadIncompleteMembersAction(editorAccess, "downloadIncomplete"),
+            		new DownloadSelectedIncompleteMembersAction(editorAccess)
+            		));
+            groups.addAll(RelationEditorHooks.getMemberActions());
+            
+            IRelationEditorActionGroup.fillToolbar(this, groups, editorAccess);
+            
+
+            InputMap inputMap = editorAccess.getMemberTable().getInputMap(MemberTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
+            inputMap.put((KeyStroke) new RemoveAction(editorAccess, "removeSelected").getValue(AbstractAction.ACCELERATOR_KEY), "removeSelected");
+            inputMap.put((KeyStroke) new MoveUpAction(editorAccess, "moveUp").getValue(AbstractAction.ACCELERATOR_KEY), "moveUp");
+            inputMap.put((KeyStroke) new MoveDownAction(editorAccess, "moveDown").getValue(AbstractAction.ACCELERATOR_KEY), "moveDown");
+            inputMap.put((KeyStroke) new DownloadIncompleteMembersAction(
+            		editorAccess, "downloadIncomplete").getValue(AbstractAction.ACCELERATOR_KEY), "downloadIncomplete");
         }
     }
@@ -693,58 +667,40 @@
      * @return control buttons panel for selection/members
      */
-    protected static JToolBar buildSelectionControlButtonToolbar(MemberTable memberTable,
-            MemberTableModel memberTableModel, SelectionTableModel selectionTableModel, IRelationEditor re) {
+    protected static JToolBar buildSelectionControlButtonToolbar(IRelationEditorActionAccess editorAccess) {
         JToolBar tb = new JToolBar(JToolBar.VERTICAL);
         tb.setFloatable(false);
 
-        // -- add at start action
-        AddSelectedAtStartAction addSelectionAction = new AddSelectedAtStartAction(
-                memberTableModel, selectionTableModel, re);
-        selectionTableModel.addTableModelListener(addSelectionAction);
-        tb.add(addSelectionAction);
-
-        // -- add before selected action
-        AddSelectedBeforeSelection addSelectedBeforeSelectionAction = new AddSelectedBeforeSelection(
-                memberTableModel, selectionTableModel, re);
-        selectionTableModel.addTableModelListener(addSelectedBeforeSelectionAction);
-        memberTableModel.getSelectionModel().addListSelectionListener(addSelectedBeforeSelectionAction);
-        tb.add(addSelectedBeforeSelectionAction);
-
-        // -- add after selected action
-        AddSelectedAfterSelection addSelectedAfterSelectionAction = new AddSelectedAfterSelection(
-                memberTableModel, selectionTableModel, re);
-        selectionTableModel.addTableModelListener(addSelectedAfterSelectionAction);
-        memberTableModel.getSelectionModel().addListSelectionListener(addSelectedAfterSelectionAction);
-        tb.add(addSelectedAfterSelectionAction);
-
-        // -- add at end action
-        AddSelectedAtEndAction addSelectedAtEndAction = new AddSelectedAtEndAction(
-                memberTableModel, selectionTableModel, re);
-        selectionTableModel.addTableModelListener(addSelectedAtEndAction);
-        tb.add(addSelectedAtEndAction);
-
-        tb.addSeparator();
-
-        // -- select members action
-        SelectedMembersForSelectionAction selectMembersForSelectionAction = new SelectedMembersForSelectionAction(
-                memberTableModel, selectionTableModel, re.getLayer());
-        selectionTableModel.addTableModelListener(selectMembersForSelectionAction);
-        memberTableModel.addTableModelListener(selectMembersForSelectionAction);
-        tb.add(selectMembersForSelectionAction);
-
-        // -- select action
-        SelectPrimitivesForSelectedMembersAction selectAction = new SelectPrimitivesForSelectedMembersAction(
-                memberTable, memberTableModel, re.getLayer());
-        memberTable.getSelectionModel().addListSelectionListener(selectAction);
-        tb.add(selectAction);
-
-        tb.addSeparator();
-
-        // -- remove selected action
-        RemoveSelectedAction removeSelectedAction = new RemoveSelectedAction(memberTableModel, selectionTableModel, re.getLayer());
-        selectionTableModel.addTableModelListener(removeSelectedAction);
-        tb.add(removeSelectedAction);
-
+		List<IRelationEditorActionGroup> groups = new ArrayList<>();
+		groups.add(buildNativeGroup(10,
+				new AddSelectedAtStartAction(editorAccess),
+				new AddSelectedBeforeSelection(editorAccess),
+				new AddSelectedAfterSelection(editorAccess),
+				new AddSelectedAtEndAction(editorAccess)
+				));
+		groups.add(buildNativeGroup(20,
+				new SelectedMembersForSelectionAction(editorAccess),
+				new SelectPrimitivesForSelectedMembersAction(editorAccess)
+				));
+		groups.add(buildNativeGroup(30,
+				new RemoveSelectedAction(editorAccess)
+				));
+		groups.addAll(RelationEditorHooks.getSelectActions());
+        
+        IRelationEditorActionGroup.fillToolbar(tb, groups, editorAccess);
         return tb;
+    }
+    
+    private static IRelationEditorActionGroup buildNativeGroup(int order, AbstractRelationEditorAction... actions) {
+    	return new IRelationEditorActionGroup() {
+    		@Override
+    		public int order() {
+    			return order;
+    		}
+    		
+			@Override
+			public List<AbstractRelationEditorAction> getActions(IRelationEditorActionAccess editorAccess) {
+				return Arrays.asList(actions);
+			}
+		};
     }
 
@@ -765,5 +721,4 @@
         Clipboard clipboard = ClipboardUtils.getClipboard();
         if (visible) {
-            leftButtonToolbar.sortBelowButton.setVisible(ExpertToggleAction.isExpert());
             RelationDialogManager.getRelationDialogManager().positionOnScreen(this);
             if (windowMenuItem == null) {
@@ -806,5 +761,7 @@
                 tr("Focus Relation Editor with relation ''{0}'' in layer ''{1}''", name, layerName),
                 null, false, false) {
-            @Override
+			private static final long serialVersionUID = 1L;
+
+			@Override
             public void actionPerformed(ActionEvent e) {
                 ((RelationEditor) getValue("relationEditor")).setVisible(true);
@@ -988,7 +945,46 @@
         public void mouseClicked(MouseEvent e) {
             if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 2) {
-                new EditAction(memberTable, memberTableModel, getLayer()).actionPerformed(null);
-            }
-        }
+                new EditAction(new RelationEditorActionAccess()).actionPerformed(null);
+            }
+        }
+    }
+    
+    private class RelationEditorActionAccess implements IRelationEditorActionAccess {
+
+		@Override
+		public MemberTable getMemberTable() {
+			return memberTable;
+		}
+
+		@Override
+		public MemberTableModel getMemberTableModel() {
+			return memberTableModel;
+		}
+
+		@Override
+		public SelectionTable getSelectionTable() {
+			return selectionTable;
+		}
+
+		@Override
+		public SelectionTableModel getSelectionTableModel() {
+			return selectionTableModel;
+		}
+
+		@Override
+		public IRelationEditor getEditor() {
+			return GenericRelationEditor.this;
+		}
+
+		@Override
+		public TagEditorModel getTagModel() {
+			return tagEditorPanel.getModel();
+		}
+
+		@Override
+		public AutoCompletingTextField getTextFieldRole() {
+			return tfRole;
+		}
+    	
     }
 }
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/RelationEditor.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/RelationEditor.java	(revision 14026)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/RelationEditor.java	(revision 14027)
@@ -6,8 +6,5 @@
 import java.beans.PropertyChangeListener;
 import java.beans.PropertyChangeSupport;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
 import java.util.Collection;
-import java.util.List;
 
 import org.openstreetmap.josm.Main;
@@ -17,5 +14,4 @@
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
-import org.openstreetmap.josm.tools.Logging;
 
 /**
@@ -24,6 +20,7 @@
  */
 public abstract class RelationEditor extends ExtendedDialog implements IRelationEditor {
+	private static final long serialVersionUID = 1L;
 
-    /** the property name for the current relation.
+	/** the property name for the current relation.
      * @see #setRelation(Relation)
      * @see #getRelation()
@@ -35,7 +32,4 @@
      */
     public static final String RELATION_SNAPSHOT_PROP = RelationEditor.class.getName() + ".relationSnapshot";
-
-    /** the list of registered relation editor classes */
-    private static List<Class<RelationEditor>> editors = new ArrayList<>();
 
     /** The relation that this editor is working on. */
@@ -71,26 +65,8 @@
 
     /**
-     * Registers a relation editor class. Depending on the type of relation to be edited
-     * {@link #getEditor(OsmDataLayer, Relation, Collection)} will create an instance of
-     * this class.
-     *
-     * @param clazz the class
-     */
-    public void registerRelationEditor(Class<RelationEditor> clazz) {
-        if (clazz != null && !editors.contains(clazz)) {
-            editors.add(clazz);
-        }
-    }
-
-    /**
      * This is a factory method that creates an appropriate RelationEditor instance suitable for editing the relation
      * that was passed in as an argument.
      *
-     * This method is guaranteed to return a working RelationEditor. If no specific editor has been registered for the
-     * type of relation, then a generic editor will be returned.
-     *
-     * Editors can be registered by adding their class to the static list "editors" in the RelationEditor class.
-     * When it comes to editing a relation, all registered editors are queried via their static "canEdit" method whether
-     * they feel responsible for that kind of relation, and if they return true then an instance of that class will be used.
+     * This method is guaranteed to return a working RelationEditor.
      *
      * @param layer the data layer the relation is a member of
@@ -100,15 +76,4 @@
      */
     public static RelationEditor getEditor(OsmDataLayer layer, Relation r, Collection<RelationMember> selectedMembers) {
-        for (Class<RelationEditor> e : editors) {
-            try {
-                Method m = e.getMethod("canEdit", Relation.class);
-                Boolean canEdit = (Boolean) m.invoke(null, r);
-                if (canEdit) {
-                    return e.getConstructor(Relation.class, Collection.class).newInstance(layer, r, selectedMembers);
-                }
-            } catch (ReflectiveOperationException ex) {
-                Logging.warn(ex);
-            }
-        }
         if (RelationDialogManager.getRelationDialogManager().isOpenInEditor(layer, r))
             return RelationDialogManager.getRelationDialogManager().getEditorForRelation(layer, r);
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/RelationEditorHooks.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/RelationEditorHooks.java	(revision 14027)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/RelationEditorHooks.java	(revision 14027)
@@ -0,0 +1,48 @@
+package org.openstreetmap.josm.gui.dialogs.relation;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.openstreetmap.josm.gui.dialogs.relation.actions.IRelationEditorActionGroup;
+
+/**
+ * This class allows to hook into the relation editor. It can be used to overwrite specific behavior.
+ * 
+ * @author Michael Zangl
+ * @since 14027
+ */
+public class RelationEditorHooks {
+	
+	private static final CopyOnWriteArrayList<IRelationEditorActionGroup> memberActions = new CopyOnWriteArrayList<>();
+	private static final CopyOnWriteArrayList<IRelationEditorActionGroup> selectionActions = new CopyOnWriteArrayList<>();
+
+	private RelationEditorHooks() {
+		// only static methods.
+	}
+	
+	/**
+	 * Adds actions to the members action toolbar
+	 * @param group The group to add
+	 */
+	public static void addActionsToMembers(IRelationEditorActionGroup group) {
+		memberActions.add(group);
+	}
+	
+	/**
+	 * Adds actions to the selection action toolbar
+	 * @param group The group to add
+	 */
+	public static void addActionsToSelectio(IRelationEditorActionGroup group) {
+		selectionActions.add(group);
+	}
+	
+	/* package */ static List<IRelationEditorActionGroup> getMemberActions() {
+		return Collections.unmodifiableList(memberActions);
+	}
+	
+	/* package */ static List<IRelationEditorActionGroup> getSelectActions() {
+		return Collections.unmodifiableList(selectionActions);
+	}
+	
+}
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AbstractRelationEditorAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AbstractRelationEditorAction.java	(revision 14026)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AbstractRelationEditorAction.java	(revision 14027)
@@ -1,4 +1,8 @@
 // License: GPL. For details, see LICENSE file.
 package org.openstreetmap.josm.gui.dialogs.relation.actions;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.Objects;
 
 import javax.swing.AbstractAction;
@@ -14,50 +18,115 @@
 import org.openstreetmap.josm.gui.dialogs.relation.MemberTable;
 import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
+import org.openstreetmap.josm.gui.dialogs.relation.SelectionTable;
+import org.openstreetmap.josm.gui.dialogs.relation.SelectionTableModel;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.gui.tagging.TagEditorModel;
 import org.openstreetmap.josm.io.OnlineResource;
 
 /**
  * Abstract superclass of relation editor actions.
+ * 
  * @since 9496
  */
-public abstract class AbstractRelationEditorAction extends AbstractAction implements TableModelListener, ListSelectionListener {
-    protected final MemberTable memberTable;
-    protected final MemberTableModel memberTableModel;
-    protected final transient OsmDataLayer layer;
-    protected final transient IRelationEditor editor;
+public abstract class AbstractRelationEditorAction extends AbstractAction
+		implements TableModelListener, ListSelectionListener, PropertyChangeListener {
+	private static final long serialVersionUID = 1L;
+	protected final transient IRelationEditorActionAccess editorAccess;
 
-    protected AbstractRelationEditorAction(MemberTable memberTable, MemberTableModel memberTableModel, String actionMapKey) {
-        this(memberTable, memberTableModel, actionMapKey, null, null);
-    }
+	/**
+	 * Create a new relation editor action
+	 * 
+	 * @param editorAccess
+	 *            The editor this action is for
+	 * @param actionMapKey
+	 *            The key for the member table action map.
+	 * @param updateOn
+	 *            The events that may cause the enabled state of this button to
+	 *            change.
+	 */
+	protected AbstractRelationEditorAction(IRelationEditorActionAccess editorAccess,
+			IRelationEditorUpdateOn... updateOn) {
+		Objects.requireNonNull(editorAccess, "editorAccess");
+		Objects.requireNonNull(updateOn, "updateOn");
+		this.editorAccess = editorAccess;
+		for (IRelationEditorUpdateOn u : updateOn) {
+			u.register(editorAccess, this);
+		}
+	}
 
-    protected AbstractRelationEditorAction(MemberTable memberTable, MemberTableModel memberTableModel, String actionMapKey,
-            OsmDataLayer layer, IRelationEditor editor) {
-        this.memberTable = memberTable;
-        this.memberTableModel = memberTableModel;
-        this.layer = layer;
-        this.editor = editor;
-        if (actionMapKey != null) {
-            this.memberTable.getActionMap().put(actionMapKey, this);
-        }
-    }
+	/**
+	 * Create a new relation editor action
+	 * 
+	 * @param editorAccess
+	 *            The editor this action is for
+	 * @param actionMapKey
+	 *            The key for the member table action map.
+	 * @param updateOn
+	 *            The events that may cause the enabled state of this button to
+	 *            change.
+	 */
+	protected AbstractRelationEditorAction(IRelationEditorActionAccess editorAccess, String actionMapKey,
+			IRelationEditorUpdateOn... updateOn) {
+		this(editorAccess, updateOn);
+		Objects.requireNonNull(actionMapKey, "actionMapKey");
+
+		this.editorAccess.addMemberTableAction(actionMapKey, this);
+	}
+
+	@Override
+	public void tableChanged(TableModelEvent e) {
+		updateEnabledState();
+	}
+
+	@Override
+	public void valueChanged(ListSelectionEvent e) {
+		updateEnabledState();
+	}
 
     @Override
-    public void tableChanged(TableModelEvent e) {
+    public void propertyChange(PropertyChangeEvent evt) {
         updateEnabledState();
     }
 
-    @Override
-    public void valueChanged(ListSelectionEvent e) {
-        updateEnabledState();
-    }
+	protected abstract void updateEnabledState();
 
-    protected abstract void updateEnabledState();
+	protected final boolean canDownload() {
+		if (editorAccess.getEditor().getRelation() == null)
+			return false;
+		DataSet ds = editorAccess.getEditor().getRelation().getDataSet();
+		return !Main.isOffline(OnlineResource.OSM_API) && ds != null && !ds.isLocked()
+				&& !DownloadPolicy.BLOCKED.equals(ds.getDownloadPolicy());
+	}
 
-    protected final boolean canDownload() {
-        if (editor.getRelation() == null)
-            return false;
-        DataSet ds = editor.getRelation().getDataSet();
-        return !Main.isOffline(OnlineResource.OSM_API)
-            && ds != null && !ds.isLocked() && !DownloadPolicy.BLOCKED.equals(ds.getDownloadPolicy());
-    }
+	protected MemberTable getMemberTable() {
+		return editorAccess.getMemberTable();
+	}
+
+	protected MemberTableModel getMemberTableModel() {
+		return editorAccess.getMemberTableModel();
+	}
+
+	protected SelectionTable getSelectionTable() {
+		return editorAccess.getSelectionTable();
+	}
+
+	protected SelectionTableModel getSelectionTableModel() {
+		return editorAccess.getSelectionTableModel();
+	}
+
+	protected IRelationEditor getEditor() {
+		return editorAccess.getEditor();
+	}
+
+	protected TagEditorModel getTagModel() {
+		return editorAccess.getTagModel();
+	}
+
+	protected OsmDataLayer getLayer() {
+		return editorAccess.getEditor().getLayer();
+	}
+
+	public boolean isExpertOnly() {
+		return false;
+	}
 }
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AddFromSelectionAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AddFromSelectionAction.java	(revision 14026)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AddFromSelectionAction.java	(revision 14027)
@@ -11,10 +11,4 @@
 import org.openstreetmap.josm.gui.dialogs.relation.GenericRelationEditor;
 import org.openstreetmap.josm.gui.dialogs.relation.GenericRelationEditor.AddAbortException;
-import org.openstreetmap.josm.gui.dialogs.relation.IRelationEditor;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTable;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
-import org.openstreetmap.josm.gui.dialogs.relation.SelectionTable;
-import org.openstreetmap.josm.gui.dialogs.relation.SelectionTableModel;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 
 /**
@@ -23,17 +17,13 @@
  */
 abstract class AddFromSelectionAction extends AbstractRelationEditorAction {
+	private static final long serialVersionUID = 1L;
 
-    protected final SelectionTable selectionTable;
-    protected final SelectionTableModel selectionTableModel;
-
-    protected AddFromSelectionAction(MemberTable memberTable, MemberTableModel memberTableModel, SelectionTable selectionTable,
-            SelectionTableModel selectionTableModel, String actionMapKey, OsmDataLayer layer, IRelationEditor editor) {
-        super(memberTable, memberTableModel, actionMapKey, layer, editor);
-        this.selectionTable = selectionTable;
-        this.selectionTableModel = selectionTableModel;
+    protected AddFromSelectionAction(IRelationEditorActionAccess editorAccess,
+			IRelationEditorUpdateOn... updateOn) {
+        super(editorAccess, updateOn);
     }
 
     protected boolean isPotentialDuplicate(OsmPrimitive primitive) {
-        return memberTableModel.hasMembersReferringTo(Collections.singleton(primitive));
+        return editorAccess.getMemberTableModel().hasMembersReferringTo(Collections.singleton(primitive));
     }
 
@@ -44,5 +34,5 @@
         ConditionalOptionPaneUtil.startBulkOperation("add_primitive_to_relation");
         for (OsmPrimitive primitive : primitives) {
-            if (primitive instanceof Relation && editor.getRelation() != null && editor.getRelation().equals(primitive)) {
+            if (primitive instanceof Relation && editorAccess.getEditor().getRelation() != null && editorAccess.getEditor().getRelation().equals(primitive)) {
                 GenericRelationEditor.warnOfCircularReferences(primitive);
                 continue;
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AddSelectedAfterSelection.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AddSelectedAfterSelection.java	(revision 14026)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AddSelectedAfterSelection.java	(revision 14027)
@@ -7,7 +7,4 @@
 
 import org.openstreetmap.josm.gui.dialogs.relation.GenericRelationEditor.AddAbortException;
-import org.openstreetmap.josm.gui.dialogs.relation.IRelationEditor;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
-import org.openstreetmap.josm.gui.dialogs.relation.SelectionTableModel;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Logging;
@@ -18,4 +15,5 @@
  */
 public class AddSelectedAfterSelection extends AddFromSelectionAction {
+	private static final long serialVersionUID = 1L;
 
     /**
@@ -25,6 +23,6 @@
      * @param editor relation editor
      */
-    public AddSelectedAfterSelection(MemberTableModel memberTableModel, SelectionTableModel selectionTableModel, IRelationEditor editor) {
-        super(null, memberTableModel, null, selectionTableModel, null, null, editor);
+    public AddSelectedAfterSelection(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess, IRelationEditorUpdateOn.MEMBER_TABLE_SELECTION, IRelationEditorUpdateOn.SELECTION_TABLE_CHANGE);
         putValue(SHORT_DESCRIPTION, tr("Add all objects selected in the current dataset after the last selected member"));
         new ImageProvider("dialogs/conflict", "copyaftercurrentright").getResource().attachImageIcon(this, true);
@@ -34,5 +32,6 @@
     @Override
     protected void updateEnabledState() {
-        setEnabled(selectionTableModel.getRowCount() > 0 && memberTableModel.getSelectionModel().getMinSelectionIndex() >= 0);
+		setEnabled(getSelectionTableModel().getRowCount() > 0
+				&& getMemberTableModel().getSelectionModel().getMinSelectionIndex() >= 0);
     }
 
@@ -40,6 +39,6 @@
     public void actionPerformed(ActionEvent e) {
         try {
-            memberTableModel.addMembersAfterIdx(filterConfirmedPrimitives(selectionTableModel.getSelection()),
-                    memberTableModel.getSelectionModel().getMaxSelectionIndex());
+        	getMemberTableModel().addMembersAfterIdx(filterConfirmedPrimitives(getSelectionTableModel().getSelection()),
+        			getMemberTableModel().getSelectionModel().getMaxSelectionIndex());
         } catch (AddAbortException ex) {
             Logging.trace(ex);
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AddSelectedAtEndAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AddSelectedAtEndAction.java	(revision 14026)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AddSelectedAtEndAction.java	(revision 14027)
@@ -7,7 +7,4 @@
 
 import org.openstreetmap.josm.gui.dialogs.relation.GenericRelationEditor.AddAbortException;
-import org.openstreetmap.josm.gui.dialogs.relation.IRelationEditor;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
-import org.openstreetmap.josm.gui.dialogs.relation.SelectionTableModel;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Logging;
@@ -18,4 +15,5 @@
  */
 public class AddSelectedAtEndAction extends AddFromSelectionAction {
+	private static final long serialVersionUID = 1L;
 
     /**
@@ -25,6 +23,6 @@
      * @param editor relation editor
      */
-    public AddSelectedAtEndAction(MemberTableModel memberTableModel, SelectionTableModel selectionTableModel, IRelationEditor editor) {
-        super(null, memberTableModel, null, selectionTableModel, null, null, editor);
+    public AddSelectedAtEndAction(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess, IRelationEditorUpdateOn.SELECTION_TABLE_CHANGE);
         putValue(SHORT_DESCRIPTION, tr("Add all objects selected in the current dataset after the last member"));
         new ImageProvider("dialogs/conflict", "copyendright").getResource().attachImageIcon(this, true);
@@ -34,5 +32,5 @@
     @Override
     protected void updateEnabledState() {
-        setEnabled(selectionTableModel.getRowCount() > 0);
+        setEnabled(getSelectionTableModel().getRowCount() > 0);
     }
 
@@ -40,5 +38,5 @@
     public void actionPerformed(ActionEvent e) {
         try {
-            memberTableModel.addMembersAtEnd(filterConfirmedPrimitives(selectionTableModel.getSelection()));
+        	getMemberTableModel().addMembersAtEnd(filterConfirmedPrimitives(getSelectionTableModel().getSelection()));
         } catch (AddAbortException ex) {
             Logging.trace(ex);
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AddSelectedAtStartAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AddSelectedAtStartAction.java	(revision 14026)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AddSelectedAtStartAction.java	(revision 14027)
@@ -7,7 +7,4 @@
 
 import org.openstreetmap.josm.gui.dialogs.relation.GenericRelationEditor.AddAbortException;
-import org.openstreetmap.josm.gui.dialogs.relation.IRelationEditor;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
-import org.openstreetmap.josm.gui.dialogs.relation.SelectionTableModel;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Logging;
@@ -18,4 +15,5 @@
  */
 public class AddSelectedAtStartAction extends AddFromSelectionAction {
+	private static final long serialVersionUID = 1L;
 
     /**
@@ -25,6 +23,6 @@
      * @param editor relation editor
      */
-    public AddSelectedAtStartAction(MemberTableModel memberTableModel, SelectionTableModel selectionTableModel, IRelationEditor editor) {
-        super(null, memberTableModel, null, selectionTableModel, null, null, editor);
+    public AddSelectedAtStartAction(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess, IRelationEditorUpdateOn.SELECTION_TABLE_CHANGE);
         putValue(SHORT_DESCRIPTION, tr("Add all objects selected in the current dataset before the first member"));
         new ImageProvider("dialogs/conflict", "copystartright").getResource().attachImageIcon(this, true);
@@ -34,5 +32,5 @@
     @Override
     protected void updateEnabledState() {
-        setEnabled(selectionTableModel.getRowCount() > 0);
+        setEnabled(getSelectionTableModel().getRowCount() > 0);
     }
 
@@ -40,5 +38,5 @@
     public void actionPerformed(ActionEvent e) {
         try {
-            memberTableModel.addMembersAtBeginning(filterConfirmedPrimitives(selectionTableModel.getSelection()));
+        	getMemberTableModel().addMembersAtBeginning(filterConfirmedPrimitives(getSelectionTableModel().getSelection()));
         } catch (AddAbortException ex) {
             Logging.trace(ex);
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AddSelectedBeforeSelection.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AddSelectedBeforeSelection.java	(revision 14026)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AddSelectedBeforeSelection.java	(revision 14027)
@@ -7,7 +7,4 @@
 
 import org.openstreetmap.josm.gui.dialogs.relation.GenericRelationEditor.AddAbortException;
-import org.openstreetmap.josm.gui.dialogs.relation.IRelationEditor;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
-import org.openstreetmap.josm.gui.dialogs.relation.SelectionTableModel;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Logging;
@@ -18,4 +15,5 @@
  */
 public class AddSelectedBeforeSelection extends AddFromSelectionAction {
+	private static final long serialVersionUID = 1L;
 
     /**
@@ -25,6 +23,6 @@
      * @param editor relation editor
      */
-    public AddSelectedBeforeSelection(MemberTableModel memberTableModel, SelectionTableModel selectionTableModel, IRelationEditor editor) {
-        super(null, memberTableModel, null, selectionTableModel, null, null, editor);
+    public AddSelectedBeforeSelection(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess, IRelationEditorUpdateOn.MEMBER_TABLE_SELECTION, IRelationEditorUpdateOn.SELECTION_TABLE_CHANGE);
         putValue(SHORT_DESCRIPTION, tr("Add all objects selected in the current dataset before the first selected member"));
         new ImageProvider("dialogs/conflict", "copybeforecurrentright").getResource().attachImageIcon(this, true);
@@ -34,5 +32,6 @@
     @Override
     protected void updateEnabledState() {
-        setEnabled(selectionTableModel.getRowCount() > 0 && memberTableModel.getSelectionModel().getMinSelectionIndex() >= 0);
+		setEnabled(getSelectionTableModel().getRowCount() > 0
+				&& editorAccess.getMemberTableModel().getSelectionModel().getMinSelectionIndex() >= 0);
     }
 
@@ -40,6 +39,6 @@
     public void actionPerformed(ActionEvent e) {
         try {
-            memberTableModel.addMembersBeforeIdx(filterConfirmedPrimitives(selectionTableModel.getSelection()),
-                    memberTableModel.getSelectionModel().getMinSelectionIndex());
+        	editorAccess.getMemberTableModel().addMembersBeforeIdx(filterConfirmedPrimitives(getSelectionTableModel().getSelection()),
+        			editorAccess.getMemberTableModel().getSelectionModel().getMinSelectionIndex());
         } catch (AddAbortException ex) {
             Logging.trace(ex);
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/ApplyAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/ApplyAction.java	(revision 14026)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/ApplyAction.java	(revision 14027)
@@ -5,14 +5,5 @@
 
 import java.awt.event.ActionEvent;
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
 
-import javax.swing.event.TableModelEvent;
-
-import org.openstreetmap.josm.gui.dialogs.relation.IRelationEditor;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTable;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
-import org.openstreetmap.josm.gui.tagging.TagEditorModel;
 import org.openstreetmap.josm.tools.ImageProvider;
 
@@ -21,5 +12,6 @@
  * @since 9496
  */
-public class ApplyAction extends SavingAction implements PropertyChangeListener {
+public class ApplyAction extends SavingAction {
+	private static final long serialVersionUID = 1L;
 
     /**
@@ -31,13 +23,10 @@
      * @param tagModel tag editor model
      */
-    public ApplyAction(MemberTable memberTable, MemberTableModel memberTableModel, TagEditorModel tagModel, OsmDataLayer layer,
-            IRelationEditor editor) {
-        super(memberTable, memberTableModel, tagModel, layer, editor, null);
+    public ApplyAction(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess, IRelationEditorUpdateOn.MEMBER_TABLE_CHANGE, IRelationEditorUpdateOn.TAG_CHANGE);
         putValue(SHORT_DESCRIPTION, tr("Apply the current updates"));
         new ImageProvider("save").getResource().attachImageIcon(this, true);
         putValue(NAME, tr("Apply"));
-        updateEnabledState();
-        memberTableModel.addTableModelListener(this);
-        tagModel.addPropertyChangeListener(this);
+        updateEnabledState();        
     }
 
@@ -45,5 +34,5 @@
     public void actionPerformed(ActionEvent e) {
         if (applyChanges()) {
-            editor.reloadDataFromRelation();
+        	editorAccess.getEditor().reloadDataFromRelation();
         }
     }
@@ -53,13 +42,3 @@
         setEnabled(isEditorDirty());
     }
-
-    @Override
-    public void propertyChange(PropertyChangeEvent evt) {
-        updateEnabledState();
-    }
-
-    @Override
-    public void tableChanged(TableModelEvent e) {
-        updateEnabledState();
-    }
 }
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/CancelAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/CancelAction.java	(revision 14026)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/CancelAction.java	(revision 14027)
@@ -13,10 +13,4 @@
 import org.openstreetmap.josm.gui.HelpAwareOptionPane;
 import org.openstreetmap.josm.gui.HelpAwareOptionPane.ButtonSpec;
-import org.openstreetmap.josm.gui.dialogs.relation.IRelationEditor;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTable;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
-import org.openstreetmap.josm.gui.tagging.TagEditorModel;
-import org.openstreetmap.josm.gui.tagging.ac.AutoCompletingTextField;
 import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.tools.ImageProvider;
@@ -28,4 +22,5 @@
  */
 public class CancelAction extends SavingAction {
+	private static final long serialVersionUID = 1L;
 
     /**
@@ -38,13 +33,12 @@
      * @param tfRole role text field
      */
-    public CancelAction(MemberTable memberTable, MemberTableModel memberTableModel, TagEditorModel tagModel, OsmDataLayer layer,
-            IRelationEditor editor, AutoCompletingTextField tfRole) {
-        super(memberTable, memberTableModel, tagModel, layer, editor, tfRole);
+    public CancelAction(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess);
         putValue(SHORT_DESCRIPTION, tr("Cancel the updates and close the dialog"));
         new ImageProvider("cancel").getResource().attachImageIcon(this);
         putValue(NAME, tr("Cancel"));
 
-        if (editor instanceof RootPaneContainer) {
-            InputMapUtils.addEscapeAction(((RootPaneContainer) editor).getRootPane(), this);
+        if (getEditor() instanceof RootPaneContainer) {
+            InputMapUtils.addEscapeAction(((RootPaneContainer) getEditor()).getRootPane(), this);
         }
         setEnabled(true);
@@ -53,8 +47,8 @@
     @Override
     public void actionPerformed(ActionEvent e) {
-        memberTable.stopHighlighting();
-        Relation snapshot = editor.getRelationSnapshot();
-        if ((!memberTableModel.hasSameMembersAs(snapshot) || tagModel.isDirty())
-         && !(snapshot == null && tagModel.getTags().isEmpty())) {
+        getMemberTable().stopHighlighting();
+        Relation snapshot = getEditor().getRelationSnapshot();
+        if ((!getMemberTableModel().hasSameMembersAs(snapshot) || getTagModel().isDirty())
+         && !(snapshot == null && getTagModel().getTags().isEmpty())) {
             //give the user a chance to save the changes
             int ret = confirmClosingByCancel();
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/CopyMembersAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/CopyMembersAction.java	(revision 14026)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/CopyMembersAction.java	(revision 14027)
@@ -8,7 +8,4 @@
 import org.openstreetmap.josm.gui.datatransfer.ClipboardUtils;
 import org.openstreetmap.josm.gui.datatransfer.RelationMemberTransferable;
-import org.openstreetmap.josm.gui.dialogs.relation.IRelationEditor;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 
 /**
@@ -17,4 +14,5 @@
  */
 public class CopyMembersAction extends AddFromSelectionAction {
+	private static final long serialVersionUID = 1L;
 
     /**
@@ -24,11 +22,11 @@
      * @param editor relation editor
      */
-    public CopyMembersAction(MemberTableModel memberTableModel, OsmDataLayer layer, IRelationEditor editor) {
-        super(null, memberTableModel, null, null, null, layer, editor);
+    public CopyMembersAction(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess);
     }
 
     @Override
     public void actionPerformed(ActionEvent e) {
-        final Collection<RelationMember> members = memberTableModel.getSelectedMembers();
+        final Collection<RelationMember> members = getMemberTableModel().getSelectedMembers();
 
         if (!members.isEmpty()) {
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/DeleteCurrentRelationAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/DeleteCurrentRelationAction.java	(revision 14026)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/DeleteCurrentRelationAction.java	(revision 14027)
@@ -11,6 +11,4 @@
 import org.openstreetmap.josm.data.osm.Relation;
 import org.openstreetmap.josm.gui.dialogs.relation.GenericRelationEditor;
-import org.openstreetmap.josm.gui.dialogs.relation.IRelationEditor;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.tools.ImageProvider;
 
@@ -20,4 +18,5 @@
  */
 public class DeleteCurrentRelationAction extends AbstractRelationEditorAction implements PropertyChangeListener {
+	private static final long serialVersionUID = 1L;
 
     /**
@@ -26,6 +25,6 @@
      * @param editor relation editor
      */
-    public DeleteCurrentRelationAction(OsmDataLayer layer, IRelationEditor editor) {
-        super(null, null, null, layer, editor);
+    public DeleteCurrentRelationAction(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess);
         putValue(SHORT_DESCRIPTION, tr("Delete the currently edited relation"));
         new ImageProvider("dialogs", "delete").getResource().attachImageIcon(this, true);
@@ -36,13 +35,13 @@
     @Override
     public void actionPerformed(ActionEvent e) {
-        Relation toDelete = editor.getRelation();
+        Relation toDelete = getEditor().getRelation();
         if (toDelete == null)
             return;
-        DeleteAction.deleteRelation(layer, toDelete);
+        DeleteAction.deleteRelation(getLayer(), toDelete);
     }
 
     @Override
     protected void updateEnabledState() {
-        setEnabled(editor.getRelationSnapshot() != null);
+        setEnabled(getEditor().getRelationSnapshot() != null);
     }
 
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/DownloadIncompleteMembersAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/DownloadIncompleteMembersAction.java	(revision 14026)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/DownloadIncompleteMembersAction.java	(revision 14027)
@@ -11,8 +11,4 @@
 import org.openstreetmap.josm.gui.MainApplication;
 import org.openstreetmap.josm.gui.dialogs.relation.DownloadRelationMemberTask;
-import org.openstreetmap.josm.gui.dialogs.relation.IRelationEditor;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTable;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Shortcut;
@@ -23,4 +19,5 @@
  */
 public class DownloadIncompleteMembersAction extends AbstractRelationEditorAction {
+	private static final long serialVersionUID = 1L;
 
     /**
@@ -32,7 +29,6 @@
      * @param editor relation editor
      */
-    public DownloadIncompleteMembersAction(MemberTable memberTable, MemberTableModel memberTableModel, String actionMapKey,
-            OsmDataLayer layer, IRelationEditor editor) {
-        super(memberTable, memberTableModel, actionMapKey, layer, editor);
+    public DownloadIncompleteMembersAction(IRelationEditorActionAccess editorAccess, String actionMapKey) {
+        super(editorAccess, actionMapKey, IRelationEditorUpdateOn.MEMBER_TABLE_CHANGE);
         Shortcut sc = Shortcut.registerShortcut("relationeditor:downloadincomplete", tr("Relation Editor: Download Members"),
             KeyEvent.VK_HOME, Shortcut.ALT);
@@ -49,8 +45,8 @@
             return;
         MainApplication.worker.submit(new DownloadRelationMemberTask(
-                editor.getRelation(),
-                memberTableModel.getIncompleteMemberPrimitives(),
-                layer,
-                (Dialog) editor)
+        		getEditor().getRelation(),
+                getMemberTableModel().getIncompleteMemberPrimitives(),
+                getLayer(),
+                (Dialog) getEditor())
         );
     }
@@ -58,5 +54,5 @@
     @Override
     protected void updateEnabledState() {
-        setEnabled(memberTableModel.hasIncompleteMembers() && canDownload());
+        setEnabled(getMemberTableModel().hasIncompleteMembers() && canDownload());
     }
 }
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/DownloadSelectedIncompleteMembersAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/DownloadSelectedIncompleteMembersAction.java	(revision 14026)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/DownloadSelectedIncompleteMembersAction.java	(revision 14027)
@@ -9,8 +9,4 @@
 import org.openstreetmap.josm.gui.MainApplication;
 import org.openstreetmap.josm.gui.dialogs.relation.DownloadRelationMemberTask;
-import org.openstreetmap.josm.gui.dialogs.relation.IRelationEditor;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTable;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.tools.ImageProvider;
 
@@ -20,4 +16,5 @@
  */
 public class DownloadSelectedIncompleteMembersAction extends AbstractRelationEditorAction {
+	private static final long serialVersionUID = 1L;
 
     /**
@@ -29,7 +26,6 @@
      * @param editor relation editor
      */
-    public DownloadSelectedIncompleteMembersAction(MemberTable memberTable, MemberTableModel memberTableModel, String actionMapKey,
-            OsmDataLayer layer, IRelationEditor editor) {
-        super(memberTable, memberTableModel, actionMapKey, layer, editor);
+    public DownloadSelectedIncompleteMembersAction(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess, IRelationEditorUpdateOn.MEMBER_TABLE_CHANGE, IRelationEditorUpdateOn.MEMBER_TABLE_SELECTION);
         putValue(SHORT_DESCRIPTION, tr("Download selected incomplete members"));
         new ImageProvider("dialogs/relation", "downloadincompleteselected").getResource().attachImageIcon(this, true);
@@ -43,8 +39,8 @@
             return;
         MainApplication.worker.submit(new DownloadRelationMemberTask(
-                editor.getRelation(),
-                memberTableModel.getSelectedIncompleteMemberPrimitives(),
-                layer,
-                (Dialog) editor)
+        		getEditor().getRelation(),
+                getMemberTableModel().getSelectedIncompleteMemberPrimitives(),
+                getLayer(),
+                (Dialog) getEditor())
         );
     }
@@ -52,5 +48,5 @@
     @Override
     protected void updateEnabledState() {
-        setEnabled(memberTableModel.hasIncompleteSelectedMembers() && canDownload());
+        setEnabled(getMemberTableModel().hasIncompleteSelectedMembers() && canDownload());
     }
 }
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/DuplicateRelationAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/DuplicateRelationAction.java	(revision 14026)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/DuplicateRelationAction.java	(revision 14027)
@@ -8,8 +8,5 @@
 
 import org.openstreetmap.josm.data.osm.Relation;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
 import org.openstreetmap.josm.gui.dialogs.relation.RelationEditor;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
-import org.openstreetmap.josm.gui.tagging.TagEditorModel;
 import org.openstreetmap.josm.tools.ImageProvider;
 
@@ -19,6 +16,5 @@
  */
 public class DuplicateRelationAction extends AbstractRelationEditorAction {
-
-    private final transient TagEditorModel tagEditorModel;
+	private static final long serialVersionUID = 1L;
 
     /**
@@ -28,7 +24,6 @@
      * @param layer OSM data layer
      */
-    public DuplicateRelationAction(MemberTableModel memberTableModel, TagEditorModel tagEditorModel, OsmDataLayer layer) {
-        super(null, memberTableModel, null, layer, null);
-        this.tagEditorModel = tagEditorModel;
+    public DuplicateRelationAction(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess);
         putValue(SHORT_DESCRIPTION, tr("Create a copy of this relation and open it in another editor window"));
         // FIXME provide an icon
@@ -41,8 +36,8 @@
     public void actionPerformed(ActionEvent e) {
         Relation copy = new Relation();
-        tagEditorModel.applyToPrimitive(copy);
-        memberTableModel.applyToRelation(copy);
+        getTagModel().applyToPrimitive(copy);
+        editorAccess.getMemberTableModel().applyToRelation(copy);
         if (!GraphicsEnvironment.isHeadless()) {
-            RelationEditor.getEditor(layer, copy, memberTableModel.getSelectedMembers()).setVisible(true);
+            RelationEditor.getEditor(getLayer(), copy, editorAccess.getMemberTableModel().getSelectedMembers()).setVisible(true);
         }
     }
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/EditAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/EditAction.java	(revision 14026)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/EditAction.java	(revision 14027)
@@ -11,8 +11,5 @@
 import org.openstreetmap.josm.data.osm.Relation;
 import org.openstreetmap.josm.data.osm.RelationMember;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTable;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
 import org.openstreetmap.josm.gui.dialogs.relation.RelationEditor;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.tools.ImageProvider;
 
@@ -22,4 +19,5 @@
  */
 public class EditAction extends AbstractRelationEditorAction {
+	private static final long serialVersionUID = 1L;
 
     /**
@@ -29,6 +27,6 @@
      * @param layer layer
      */
-    public EditAction(MemberTable memberTable, MemberTableModel memberTableModel, OsmDataLayer layer) {
-        super(memberTable, memberTableModel, null, layer, null);
+    public EditAction(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess, IRelationEditorUpdateOn.MEMBER_TABLE_SELECTION);
         putValue(SHORT_DESCRIPTION, tr("Edit the relation the currently selected relation member refers to"));
         new ImageProvider("dialogs", "edit").getResource().attachImageIcon(this, true);
@@ -38,11 +36,12 @@
     @Override
     protected void updateEnabledState() {
-        setEnabled(memberTable.getSelectedRowCount() == 1
-                && memberTableModel.isEditableRelation(memberTable.getSelectedRow()));
+        setEnabled(editorAccess.getMemberTable().getSelectedRowCount() == 1
+				&& editorAccess.getMemberTableModel()
+						.isEditableRelation(editorAccess.getMemberTable().getSelectedRow()));
     }
 
     protected Collection<RelationMember> getMembersForCurrentSelection(Relation r) {
         Collection<RelationMember> members = new HashSet<>();
-        Collection<OsmPrimitive> selection = layer.data.getSelected();
+        Collection<OsmPrimitive> selection = getLayer().data.getSelected();
         for (RelationMember member: r.getMembers()) {
             if (selection.contains(member.getMember())) {
@@ -57,8 +56,8 @@
         if (!isEnabled())
             return;
-        int idx = memberTable.getSelectedRow();
+        int idx = editorAccess.getMemberTable().getSelectedRow();
         if (idx < 0)
             return;
-        OsmPrimitive primitive = memberTableModel.getReferredPrimitive(idx);
+        OsmPrimitive primitive = editorAccess.getMemberTableModel().getReferredPrimitive(idx);
         if (!(primitive instanceof Relation))
             return;
@@ -67,5 +66,5 @@
             return;
 
-        RelationEditor.getEditor(layer, r, getMembersForCurrentSelection(r)).setVisible(true);
+        RelationEditor.getEditor(getLayer(), r, getMembersForCurrentSelection(r)).setVisible(true);
     }
 }
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/IRelationEditorActionAccess.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/IRelationEditorActionAccess.java	(revision 14027)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/IRelationEditorActionAccess.java	(revision 14027)
@@ -0,0 +1,63 @@
+package org.openstreetmap.josm.gui.dialogs.relation.actions;
+
+import javax.swing.Action;
+
+import org.openstreetmap.josm.gui.dialogs.relation.IRelationEditor;
+import org.openstreetmap.josm.gui.dialogs.relation.MemberTable;
+import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
+import org.openstreetmap.josm.gui.dialogs.relation.SelectionTable;
+import org.openstreetmap.josm.gui.dialogs.relation.SelectionTableModel;
+import org.openstreetmap.josm.gui.tagging.TagEditorModel;
+import org.openstreetmap.josm.gui.tagging.ac.AutoCompletingTextField;
+
+/**
+ * This interface provides access to the relation editor for actions.
+ * <p>
+ * 
+ * @author Michael Zangl
+ * @since 14027
+ */
+public interface IRelationEditorActionAccess {
+
+	/**
+	 * Adds a keyboard action to the member table.
+	 * @param actionMapKey The key to use
+	 * @param action The action to map for that key.
+	 */
+	default void addMemberTableAction(String actionMapKey, Action action) {
+		getMemberTable().getActionMap().put(actionMapKey, action);
+	}
+
+	/**
+	 * Get the member table that is used by the dialog.
+	 * @return The member table
+	 */
+	MemberTable getMemberTable();
+	
+	/**
+	 * Get the model the member table is using.
+	 * @return That model
+	 */
+	MemberTableModel getMemberTableModel();
+	
+	/**
+	 * Get the table that displays the current user selection
+	 * @return That table
+	 */
+	SelectionTable getSelectionTable();
+	
+	/**
+	 * Get the model that the selection table is based on.
+	 * @return The model
+	 */
+    SelectionTableModel getSelectionTableModel();
+    
+    IRelationEditor getEditor();
+    TagEditorModel getTagModel();
+    
+    /**
+     * Get the text field that is used to edit the role.
+     * @return The role text field.
+     */
+    AutoCompletingTextField getTextFieldRole();
+}
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/IRelationEditorActionGroup.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/IRelationEditorActionGroup.java	(revision 14027)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/IRelationEditorActionGroup.java	(revision 14027)
@@ -0,0 +1,52 @@
+package org.openstreetmap.josm.gui.dialogs.relation.actions;
+
+import java.util.Comparator;
+import java.util.List;
+
+import javax.swing.JButton;
+import javax.swing.JToolBar;
+
+import org.openstreetmap.josm.actions.ExpertToggleAction;
+
+/**
+ * An action group for the relation editor, to be used in one of the tool bars.
+ * 
+ * @author Michael Zangl
+ * @since 14027
+ */
+public interface IRelationEditorActionGroup {
+
+	/**
+	 * Get the position at which the action group should be added.
+	 * 
+	 * @return The order index, default is to add at the end.
+	 */
+	default int order() {
+		return 100;
+	}
+
+	/**
+	 * Get the actions in this action group.
+	 * 
+	 * @param editorAccess
+	 *            Methods to access the relation editor.
+	 * @return The actions
+	 */
+	List<AbstractRelationEditorAction> getActions(IRelationEditorActionAccess editorAccess);
+
+	static void fillToolbar(JToolBar toolbar, List<IRelationEditorActionGroup> groups,
+			IRelationEditorActionAccess editorAccess) {
+		groups.stream().sorted(Comparator.comparingInt(IRelationEditorActionGroup::order)).forEach(group -> {
+			if (toolbar.getComponentCount() > 0) {
+				toolbar.addSeparator();
+			}
+
+			for (AbstractRelationEditorAction action : group.getActions(editorAccess)) {
+				JButton button = toolbar.add(action);
+				if (action.isExpertOnly()) {
+					ExpertToggleAction.addVisibilitySwitcher(button);
+				}
+			}
+		});
+	}
+}
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/IRelationEditorUpdateOn.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/IRelationEditorUpdateOn.java	(revision 14027)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/IRelationEditorUpdateOn.java	(revision 14027)
@@ -0,0 +1,30 @@
+package org.openstreetmap.josm.gui.dialogs.relation.actions;
+
+/**
+ * This interface can be used to register the event listeners for a
+ * {@link AbstractRelationEditorAction}.
+ * <p>
+ * It holds common constants that are often used.
+ * 
+ * @author Michael Zangl
+ * @since 14027
+ */
+@FunctionalInterface
+public interface IRelationEditorUpdateOn {
+	/**
+	 * Update when the member table contents change
+	 */
+	IRelationEditorUpdateOn MEMBER_TABLE_CHANGE = (editor, action) -> editor.getMemberTableModel()
+			.addTableModelListener(action);
+	/**
+	 * Update upon a member table selection change
+	 */
+	IRelationEditorUpdateOn MEMBER_TABLE_SELECTION = (editor, action) -> editor.getMemberTable().getSelectionModel()
+			.addListSelectionListener(action);
+
+	IRelationEditorUpdateOn TAG_CHANGE = (editor, action) -> editor.getTagModel().addPropertyChangeListener(action);
+	IRelationEditorUpdateOn SELECTION_TABLE_CHANGE = (editor, action) -> editor.getSelectionTableModel()
+			.addTableModelListener(action);
+
+	void register(IRelationEditorActionAccess editor, AbstractRelationEditorAction action);
+}
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/MoveDownAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/MoveDownAction.java	(revision 14026)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/MoveDownAction.java	(revision 14027)
@@ -8,6 +8,4 @@
 
 import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTable;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Shortcut;
@@ -18,4 +16,5 @@
  */
 public class MoveDownAction extends AbstractRelationEditorAction {
+	private static final long serialVersionUID = 1L;
 
     /**
@@ -25,6 +24,6 @@
      * @param actionMapKey action map key
      */
-    public MoveDownAction(MemberTable memberTable, MemberTableModel memberTableModel, String actionMapKey) {
-        super(memberTable, memberTableModel, actionMapKey);
+    public MoveDownAction(IRelationEditorActionAccess editorAccess, String actionMapKey) {
+        super(editorAccess, actionMapKey, IRelationEditorUpdateOn.MEMBER_TABLE_SELECTION);
         new ImageProvider("dialogs", "movedown").getResource().attachImageIcon(this, true);
         Shortcut sc = Shortcut.registerShortcut("relationeditor:movedown", tr("Relation Editor: Move Down"), KeyEvent.VK_DOWN, Shortcut.ALT);
@@ -36,10 +35,10 @@
     @Override
     public void actionPerformed(ActionEvent e) {
-        memberTableModel.moveDown(memberTable.getSelectedRows());
+    	editorAccess.getMemberTableModel().moveDown(editorAccess.getMemberTable().getSelectedRows());
     }
 
     @Override
     protected void updateEnabledState() {
-        setEnabled(memberTableModel.canMoveDown(memberTable.getSelectedRows()));
+        setEnabled(editorAccess.getMemberTableModel().canMoveDown(editorAccess.getMemberTable().getSelectedRows()));
     }
 }
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/MoveUpAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/MoveUpAction.java	(revision 14026)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/MoveUpAction.java	(revision 14027)
@@ -8,6 +8,4 @@
 
 import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTable;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Shortcut;
@@ -18,4 +16,5 @@
  */
 public class MoveUpAction extends AbstractRelationEditorAction {
+	private static final long serialVersionUID = 1L;
 
     /**
@@ -25,6 +24,6 @@
      * @param actionMapKey key in table action map
      */
-    public MoveUpAction(MemberTable memberTable, MemberTableModel memberTableModel, String actionMapKey) {
-        super(memberTable, memberTableModel, actionMapKey);
+    public MoveUpAction(IRelationEditorActionAccess editorAccess, String actionMapKey) {
+        super(editorAccess, actionMapKey, IRelationEditorUpdateOn.MEMBER_TABLE_SELECTION);
         new ImageProvider("dialogs", "moveup").getResource().attachImageIcon(this, true);
         Shortcut sc = Shortcut.registerShortcut("relationeditor:moveup", tr("Relation Editor: Move Up"), KeyEvent.VK_UP, Shortcut.ALT);
@@ -36,10 +35,10 @@
     @Override
     public void actionPerformed(ActionEvent e) {
-        memberTableModel.moveUp(memberTable.getSelectedRows());
+    	editorAccess.getMemberTableModel().moveUp(editorAccess.getMemberTable().getSelectedRows());
     }
 
     @Override
     protected void updateEnabledState() {
-        setEnabled(memberTableModel.canMoveUp(memberTable.getSelectedRows()));
+        setEnabled(editorAccess.getMemberTableModel().canMoveUp(editorAccess.getMemberTable().getSelectedRows()));
     }
 }
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/OKAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/OKAction.java	(revision 14026)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/OKAction.java	(revision 14027)
@@ -6,10 +6,4 @@
 import java.awt.event.ActionEvent;
 
-import org.openstreetmap.josm.gui.dialogs.relation.IRelationEditor;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTable;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
-import org.openstreetmap.josm.gui.tagging.TagEditorModel;
-import org.openstreetmap.josm.gui.tagging.ac.AutoCompletingTextField;
 import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.tools.ImageProvider;
@@ -19,4 +13,5 @@
  */
 public class OKAction extends SavingAction {
+	private static final long serialVersionUID = 1L;
 
     /**
@@ -29,7 +24,6 @@
      * @param tfRole role text field
      */
-    public OKAction(MemberTable memberTable, MemberTableModel memberTableModel, TagEditorModel tagModel, OsmDataLayer layer,
-            IRelationEditor editor, AutoCompletingTextField tfRole) {
-        super(memberTable, memberTableModel, tagModel, layer, editor, tfRole);
+    public OKAction(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess);
         putValue(SHORT_DESCRIPTION, tr("Apply the updates and close the dialog"));
         new ImageProvider("ok").getResource().attachImageIcon(this);
@@ -41,5 +35,5 @@
     public void actionPerformed(ActionEvent e) {
         Config.getPref().put("relation.editor.generic.lastrole", tfRole.getText());
-        memberTable.stopHighlighting();
+        editorAccess.getMemberTable().stopHighlighting();
         if (!applyChanges())
             return;
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/PasteMembersAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/PasteMembersAction.java	(revision 14026)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/PasteMembersAction.java	(revision 14027)
@@ -10,8 +10,5 @@
 
 import org.openstreetmap.josm.gui.datatransfer.ClipboardUtils;
-import org.openstreetmap.josm.gui.dialogs.relation.IRelationEditor;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTable;
 import org.openstreetmap.josm.gui.dialogs.relation.MemberTransferHandler;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.tools.Logging;
 
@@ -21,4 +18,5 @@
  */
 public class PasteMembersAction extends AddFromSelectionAction implements FlavorListener {
+	private static final long serialVersionUID = 1L;
 
     /**
@@ -28,6 +26,6 @@
      * @param editor relation editor
      */
-    public PasteMembersAction(MemberTable memberTable, OsmDataLayer layer, IRelationEditor editor) {
-        super(memberTable, null, null, null, null, layer, editor);
+    public PasteMembersAction(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess);
         updateEnabledState();
     }
@@ -43,5 +41,5 @@
 
     private TransferSupport getSupport() {
-        return new TransferSupport(memberTable, Optional.ofNullable(ClipboardUtils.getClipboardContent())
+        return new TransferSupport(editorAccess.getMemberTable(), Optional.ofNullable(ClipboardUtils.getClipboardContent())
                 .orElseThrow(() -> new IllegalStateException("Failed to retrieve clipboard content")));
     }
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/RefreshAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/RefreshAction.java	(revision 14026)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/RefreshAction.java	(revision 14027)
@@ -16,9 +16,4 @@
 import org.openstreetmap.josm.gui.HelpAwareOptionPane.ButtonSpec;
 import org.openstreetmap.josm.gui.MainApplication;
-import org.openstreetmap.josm.gui.dialogs.relation.IRelationEditor;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTable;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
-import org.openstreetmap.josm.gui.tagging.TagEditorModel;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Shortcut;
@@ -29,4 +24,5 @@
  */
 public class RefreshAction extends SavingAction implements CommandQueueListener {
+	private static final long serialVersionUID = 1L;
 
     /**
@@ -38,7 +34,6 @@
      * @param tagModel tag editor model
      */
-    public RefreshAction(MemberTable memberTable, MemberTableModel memberTableModel, TagEditorModel tagModel, OsmDataLayer layer,
-            IRelationEditor editor) {
-        super(memberTable, memberTableModel, tagModel, layer, editor, null);
+    public RefreshAction(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess);
         // CHECKSTYLE.OFF: LineLength
         Shortcut sc = Shortcut.registerShortcut("relationeditor:refresh", tr("Relation Editor: Refresh"), KeyEvent.CHAR_UNDEFINED, Shortcut.NONE);
@@ -47,7 +42,7 @@
         new ImageProvider("dialogs/refresh").getResource().attachImageIcon(this, true);
         putValue(NAME, tr("Refresh"));
-        if (editor instanceof JComponent) {
-            ((JComponent) editor).getRootPane().getActionMap().put("refresh", this);
-            ((JComponent) editor).getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(sc.getKeyStroke(), "refresh");
+        if (editorAccess.getEditor() instanceof JComponent) {
+            ((JComponent) editorAccess.getEditor()).getRootPane().getActionMap().put("refresh", this);
+            ((JComponent) editorAccess.getEditor()).getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(sc.getKeyStroke(), "refresh");
         }
         MainApplication.undoRedo.addCommandQueueListener(this);
@@ -57,5 +52,5 @@
     @Override
     public void actionPerformed(ActionEvent e) {
-        Relation relation = editor.getRelation();
+        Relation relation = editorAccess.getEditor().getRelation();
         if (relation == null)
             return;
@@ -68,11 +63,11 @@
         if (isEditorDirty() && confirmDiscardDirtyData() != 0)
             return;
-        editor.reloadDataFromRelation();
+        editorAccess.getEditor().reloadDataFromRelation();
     }
 
     @Override
     public void updateEnabledState() {
-        Relation relation = editor.getRelation();
-        Relation snapshot = editor.getRelationSnapshot();
+        Relation relation = editorAccess.getEditor().getRelation();
+        Relation snapshot = editorAccess.getEditor().getRelationSnapshot();
         setEnabled(snapshot != null && (
             !relation.hasEqualTechnicalAttributes(snapshot) ||
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/RemoveAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/RemoveAction.java	(revision 14026)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/RemoveAction.java	(revision 14027)
@@ -8,6 +8,4 @@
 
 import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTable;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Shortcut;
@@ -18,4 +16,5 @@
  */
 public class RemoveAction extends AbstractRelationEditorAction {
+	private static final long serialVersionUID = 1L;
 
     /**
@@ -25,6 +24,6 @@
      * @param actionMapKey action map key
      */
-    public RemoveAction(MemberTable memberTable, MemberTableModel memberTableModel, String actionMapKey) {
-        super(memberTable, memberTableModel, actionMapKey);
+    public RemoveAction(IRelationEditorActionAccess editorAccess, String actionMapKey) {
+        super(editorAccess, actionMapKey, IRelationEditorUpdateOn.MEMBER_TABLE_SELECTION);
         new ImageProvider("dialogs", "delete").getResource().attachImageIcon(this, true);
         putValue(NAME, tr("Remove"));
@@ -37,10 +36,10 @@
     @Override
     public void actionPerformed(ActionEvent e) {
-        memberTableModel.remove(memberTable.getSelectedRows());
+        editorAccess.getMemberTableModel().remove(editorAccess.getMemberTable().getSelectedRows());
     }
 
     @Override
     protected void updateEnabledState() {
-        setEnabled(memberTableModel.canRemove(memberTable.getSelectedRows()));
+        setEnabled(editorAccess.getMemberTableModel().canRemove(editorAccess.getMemberTable().getSelectedRows()));
     }
 }
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/RemoveSelectedAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/RemoveSelectedAction.java	(revision 14026)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/RemoveSelectedAction.java	(revision 14027)
@@ -7,7 +7,4 @@
 
 import org.openstreetmap.josm.data.osm.DataSet;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
-import org.openstreetmap.josm.gui.dialogs.relation.SelectionTableModel;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.tools.ImageProvider;
 
@@ -17,4 +14,5 @@
  */
 public class RemoveSelectedAction extends AddFromSelectionAction {
+	private static final long serialVersionUID = 1L;
 
     /**
@@ -24,6 +22,6 @@
      * @param layer OSM data layer
      */
-    public RemoveSelectedAction(MemberTableModel memberTableModel, SelectionTableModel selectionTableModel, OsmDataLayer layer) {
-        super(null, memberTableModel, null, selectionTableModel, null, layer, null);
+    public RemoveSelectedAction(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess, IRelationEditorUpdateOn.SELECTION_TABLE_CHANGE);
         putValue(SHORT_DESCRIPTION, tr("Remove all members referring to one of the selected objects"));
         new ImageProvider("dialogs/relation", "deletemembers").getResource().attachImageIcon(this, true);
@@ -33,5 +31,5 @@
     @Override
     protected void updateEnabledState() {
-        DataSet ds = layer.data;
+        DataSet ds = getLayer().data;
         if (ds == null || ds.selectionEmpty()) {
             setEnabled(false);
@@ -39,10 +37,10 @@
         }
         // only enable the action if we have members referring to the selected primitives
-        setEnabled(memberTableModel.hasMembersReferringTo(ds.getSelected()));
+        setEnabled(editorAccess.getMemberTableModel().hasMembersReferringTo(ds.getSelected()));
     }
 
     @Override
     public void actionPerformed(ActionEvent e) {
-        memberTableModel.removeMembersReferringTo(selectionTableModel.getSelection());
+    	editorAccess.getMemberTableModel().removeMembersReferringTo(getSelectionTableModel().getSelection());
     }
 }
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/ReverseAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/ReverseAction.java	(revision 14026)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/ReverseAction.java	(revision 14027)
@@ -6,6 +6,4 @@
 import java.awt.event.ActionEvent;
 
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTable;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
 import org.openstreetmap.josm.tools.ImageProvider;
 
@@ -15,12 +13,13 @@
  */
 public class ReverseAction extends AbstractRelationEditorAction {
+	private static final long serialVersionUID = 1L;
 
     /**
      * Constructs a new {@code ReverseAction}.
-     * @param memberTable member table
-     * @param memberTableModel member table model
+     * @param editorAccess
      */
-    public ReverseAction(MemberTable memberTable, MemberTableModel memberTableModel) {
-        super(memberTable, memberTableModel, null);
+    public ReverseAction(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess, IRelationEditorUpdateOn.MEMBER_TABLE_CHANGE);
+
         putValue(SHORT_DESCRIPTION, tr("Reverse the order of the relation members"));
         new ImageProvider("dialogs/relation", "reverse").getResource().attachImageIcon(this, true);
@@ -31,10 +30,10 @@
     @Override
     public void actionPerformed(ActionEvent e) {
-        memberTableModel.reverse();
+        editorAccess.getMemberTableModel().reverse();
     }
 
     @Override
     protected void updateEnabledState() {
-        setEnabled(memberTableModel.getRowCount() > 0);
+        setEnabled(editorAccess.getMemberTableModel().getRowCount() > 0);
     }
 }
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SavingAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SavingAction.java	(revision 14026)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SavingAction.java	(revision 14027)
@@ -22,10 +22,6 @@
 import org.openstreetmap.josm.gui.HelpAwareOptionPane.ButtonSpec;
 import org.openstreetmap.josm.gui.MainApplication;
-import org.openstreetmap.josm.gui.dialogs.relation.IRelationEditor;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTable;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
 import org.openstreetmap.josm.gui.dialogs.relation.RelationDialogManager;
 import org.openstreetmap.josm.gui.dialogs.relation.RelationEditor;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.gui.tagging.TagEditorModel;
 import org.openstreetmap.josm.gui.tagging.ac.AutoCompletingTextField;
@@ -38,13 +34,11 @@
  */
 abstract class SavingAction extends AbstractRelationEditorAction {
+	private static final long serialVersionUID = 1L;
 
-    protected final TagEditorModel tagModel;
     protected final AutoCompletingTextField tfRole;
 
-    protected SavingAction(MemberTable memberTable, MemberTableModel memberTableModel, TagEditorModel tagModel, OsmDataLayer layer,
-            IRelationEditor editor, AutoCompletingTextField tfRole) {
-        super(memberTable, memberTableModel, null, layer, editor);
-        this.tagModel = tagModel;
-        this.tfRole = tfRole;
+    protected SavingAction(IRelationEditorActionAccess editorAccess, IRelationEditorUpdateOn... updateOn) {
+        super(editorAccess, updateOn);
+        this.tfRole = editorAccess.getTextFieldRole();
     }
 
@@ -56,5 +50,5 @@
         final Relation newRelation = new Relation();
         tagEditorModel.applyToPrimitive(newRelation);
-        memberTableModel.applyToRelation(newRelation);
+        getMemberTableModel().applyToRelation(newRelation);
         List<RelationMember> newMembers = new ArrayList<>();
         for (RelationMember rm: newRelation.getMembers()) {
@@ -73,12 +67,12 @@
         if (newRelation.getMembersCount() == 0 && !newRelation.hasKeys())
             return;
-        MainApplication.undoRedo.add(new AddCommand(layer.getDataSet(), newRelation));
+        MainApplication.undoRedo.add(new AddCommand(getLayer().getDataSet(), newRelation));
 
         // make sure everybody is notified about the changes
         //
-        editor.setRelation(newRelation);
-        if (editor instanceof RelationEditor) {
+        getEditor().setRelation(newRelation);
+        if (getEditor() instanceof RelationEditor) {
             RelationDialogManager.getRelationDialogManager().updateContext(
-                    layer, editor.getRelation(), (RelationEditor) editor);
+                    getLayer(), getEditor().getRelation(), (RelationEditor) getEditor());
         }
         // Relation list gets update in EDT so selecting my be postponed to following EDT run
@@ -91,9 +85,9 @@
      */
     protected void applyExistingConflictingRelation(TagEditorModel tagEditorModel) {
-        Relation editedRelation = new Relation(editor.getRelation());
+        Relation editedRelation = new Relation(editorAccess.getEditor().getRelation());
         tagEditorModel.applyToPrimitive(editedRelation);
-        memberTableModel.applyToRelation(editedRelation);
-        Conflict<Relation> conflict = new Conflict<>(editor.getRelation(), editedRelation);
-        MainApplication.undoRedo.add(new ConflictAddCommand(layer.getDataSet(), conflict));
+        editorAccess.getMemberTableModel().applyToRelation(editedRelation);
+        Conflict<Relation> conflict = new Conflict<>(editorAccess.getEditor().getRelation(), editedRelation);
+        MainApplication.undoRedo.add(new ConflictAddCommand(getLayer().getDataSet(), conflict));
     }
 
@@ -103,8 +97,8 @@
      */
     protected void applyExistingNonConflictingRelation(TagEditorModel tagEditorModel) {
-        Relation originRelation = editor.getRelation();
+        Relation originRelation = editorAccess.getEditor().getRelation();
         Relation editedRelation = new Relation(originRelation);
         tagEditorModel.applyToPrimitive(editedRelation);
-        memberTableModel.applyToRelation(editedRelation);
+        getMemberTableModel().applyToRelation(editedRelation);
         if (!editedRelation.hasEqualSemanticAttributes(originRelation, false)) {
             MainApplication.undoRedo.add(new ChangeCommand(originRelation, editedRelation));
@@ -153,6 +147,6 @@
                         + "''{1}''.<br>"
                         + "Please resolve this conflict first, then try again.</html>",
-                        Utils.escapeReservedCharactersHTML(layer.getName()),
-                        Utils.escapeReservedCharactersHTML(editor.getRelation().getDisplayName(DefaultNameFormatter.getInstance()))
+                        Utils.escapeReservedCharactersHTML(getLayer().getName()),
+                        Utils.escapeReservedCharactersHTML(getEditor().getRelation().getDisplayName(DefaultNameFormatter.getInstance()))
                 ),
                 tr("Double conflict"),
@@ -167,34 +161,34 @@
 
     protected boolean applyChanges() {
-        if (editor.getRelation() == null) {
-            applyNewRelation(tagModel);
+        if (editorAccess.getEditor().getRelation() == null) {
+            applyNewRelation(getTagModel());
         } else if (isEditorDirty()) {
-            if (editor.isDirtyRelation()) {
+            if (editorAccess.getEditor().isDirtyRelation()) {
                 if (confirmClosingBecauseOfDirtyState()) {
-                    if (layer.getConflicts().hasConflictForMy(editor.getRelation())) {
+                    if (getLayer().getConflicts().hasConflictForMy(editorAccess.getEditor().getRelation())) {
                         warnDoubleConflict();
                         return false;
                     }
-                    applyExistingConflictingRelation(tagModel);
+                    applyExistingConflictingRelation(getTagModel());
                     hideEditor();
                 } else
                     return false;
             } else {
-                applyExistingNonConflictingRelation(tagModel);
+                applyExistingNonConflictingRelation(getTagModel());
             }
         }
-        editor.setRelation(editor.getRelation());
+        editorAccess.getEditor().setRelation(editorAccess.getEditor().getRelation());
         return true;
     }
 
     protected void hideEditor() {
-        if (editor instanceof Component) {
-            ((Component) editor).setVisible(false);
+        if (editorAccess.getEditor() instanceof Component) {
+            ((Component) editorAccess.getEditor()).setVisible(false);
         }
     }
 
     protected boolean isEditorDirty() {
-        Relation snapshot = editor.getRelationSnapshot();
-        return (snapshot != null && !memberTableModel.hasSameMembersAs(snapshot)) || tagModel.isDirty();
+        Relation snapshot = editorAccess.getEditor().getRelationSnapshot();
+        return (snapshot != null && !getMemberTableModel().hasSameMembersAs(snapshot)) || getTagModel().isDirty();
     }
 }
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SelectAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SelectAction.java	(revision 14026)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SelectAction.java	(revision 14027)
@@ -7,6 +7,4 @@
 
 import org.openstreetmap.josm.data.osm.Relation;
-import org.openstreetmap.josm.gui.dialogs.relation.IRelationEditor;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.tools.ImageProvider;
 
@@ -16,4 +14,5 @@
  */
 public class SelectAction extends AbstractRelationEditorAction {
+	private static final long serialVersionUID = 1L;
 
     /**
@@ -22,6 +21,6 @@
      * @param editor relation editor
      */
-    public SelectAction(OsmDataLayer layer, IRelationEditor editor) {
-        super(null, null, null, layer, editor);
+    public SelectAction(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess);
         putValue(NAME, tr("Select"));
         putValue(SHORT_DESCRIPTION, tr("Select the currently edited relation"));
@@ -32,13 +31,13 @@
     @Override
     public void actionPerformed(ActionEvent e) {
-        Relation toSelect = editor.getRelation();
+        Relation toSelect = editorAccess.getEditor().getRelation();
         if (toSelect == null)
             return;
-        layer.data.setSelected(toSelect);
+        getLayer().data.setSelected(toSelect);
     }
 
     @Override
     protected void updateEnabledState() {
-        setEnabled(editor.getRelationSnapshot() != null);
+        setEnabled(editorAccess.getEditor().getRelationSnapshot() != null);
     }
 }
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SelectPrimitivesForSelectedMembersAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SelectPrimitivesForSelectedMembersAction.java	(revision 14026)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SelectPrimitivesForSelectedMembersAction.java	(revision 14027)
@@ -6,7 +6,4 @@
 import java.awt.event.ActionEvent;
 
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTable;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.tools.ImageProvider;
 
@@ -17,4 +14,5 @@
  */
 public class SelectPrimitivesForSelectedMembersAction extends AbstractRelationEditorAction {
+	private static final long serialVersionUID = 1L;
 
     /**
@@ -24,6 +22,6 @@
      * @param layer layer
      */
-    public SelectPrimitivesForSelectedMembersAction(MemberTable memberTable, MemberTableModel memberTableModel, OsmDataLayer layer) {
-        super(memberTable, memberTableModel, null, layer, null);
+    public SelectPrimitivesForSelectedMembersAction(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess, IRelationEditorUpdateOn.MEMBER_TABLE_SELECTION);
         putValue(SHORT_DESCRIPTION, tr("Select objects for selected relation members"));
         new ImageProvider("dialogs/relation", "selectprimitives").getResource().attachImageIcon(this, true);
@@ -33,10 +31,10 @@
     @Override
     protected void updateEnabledState() {
-        setEnabled(memberTable.getSelectedRowCount() > 0);
+        setEnabled(editorAccess.getMemberTable().getSelectedRowCount() > 0);
     }
 
     @Override
     public void actionPerformed(ActionEvent e) {
-        layer.data.setSelected(memberTableModel.getSelectedChildPrimitives());
+        getLayer().data.setSelected(editorAccess.getMemberTableModel().getSelectedChildPrimitives());
     }
 }
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SelectedMembersForSelectionAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SelectedMembersForSelectionAction.java	(revision 14026)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SelectedMembersForSelectionAction.java	(revision 14027)
@@ -6,7 +6,4 @@
 import java.awt.event.ActionEvent;
 
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
-import org.openstreetmap.josm.gui.dialogs.relation.SelectionTableModel;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.tools.ImageProvider;
 
@@ -16,4 +13,5 @@
  */
 public class SelectedMembersForSelectionAction extends AddFromSelectionAction {
+	private static final long serialVersionUID = 1L;
 
     /**
@@ -23,6 +21,6 @@
      * @param layer OSM data layer
      */
-    public SelectedMembersForSelectionAction(MemberTableModel memberTableModel, SelectionTableModel selectionTableModel, OsmDataLayer layer) {
-        super(null, memberTableModel, null, selectionTableModel, null, layer, null);
+    public SelectedMembersForSelectionAction(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess, IRelationEditorUpdateOn.SELECTION_TABLE_CHANGE, IRelationEditorUpdateOn.MEMBER_TABLE_CHANGE);
         putValue(SHORT_DESCRIPTION, tr("Select relation members which refer to objects in the current selection"));
         new ImageProvider("dialogs/relation", "selectmembers").getResource().attachImageIcon(this, true);
@@ -32,10 +30,10 @@
     @Override
     protected void updateEnabledState() {
-        boolean enabled = selectionTableModel.getRowCount() > 0
-        && !memberTableModel.getChildPrimitives(layer.data.getSelected()).isEmpty();
+        boolean enabled = getSelectionTableModel().getRowCount() > 0
+        && !editorAccess.getMemberTableModel().getChildPrimitives(getLayer().data.getSelected()).isEmpty();
 
         if (enabled) {
             putValue(SHORT_DESCRIPTION, tr("Select relation members which refer to {0} objects in the current selection",
-                    memberTableModel.getChildPrimitives(layer.data.getSelected()).size()));
+            		editorAccess.getMemberTableModel().getChildPrimitives(getLayer().data.getSelected()).size()));
         } else {
             putValue(SHORT_DESCRIPTION, tr("Select relation members which refer to objects in the current selection"));
@@ -46,5 +44,5 @@
     @Override
     public void actionPerformed(ActionEvent e) {
-        memberTableModel.selectMembersReferringTo(layer.data.getSelected());
+    	editorAccess.getMemberTableModel().selectMembersReferringTo(getLayer().data.getSelected());
     }
 }
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SetRoleAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SetRoleAction.java	(revision 14026)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SetRoleAction.java	(revision 14027)
@@ -13,6 +13,4 @@
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.gui.ConditionalOptionPaneUtil;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTable;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
 import org.openstreetmap.josm.gui.tagging.ac.AutoCompletingTextField;
 import org.openstreetmap.josm.tools.ImageProvider;
@@ -23,4 +21,5 @@
  */
 public class SetRoleAction extends AbstractRelationEditorAction implements DocumentListener {
+	private static final long serialVersionUID = 1L;
 
     private final transient AutoCompletingTextField tfRole;
@@ -32,7 +31,7 @@
      * @param tfRole role text field
      */
-    public SetRoleAction(MemberTable memberTable, MemberTableModel memberTableModel, AutoCompletingTextField tfRole) {
-        super(memberTable, memberTableModel, null);
-        this.tfRole = tfRole;
+    public SetRoleAction(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess);
+        this.tfRole = editorAccess.getTextFieldRole();
         putValue(SHORT_DESCRIPTION, tr("Sets a role for the selected members"));
         new ImageProvider("apply").getResource().attachImageIcon(this);
@@ -43,5 +42,5 @@
     @Override
     protected void updateEnabledState() {
-        setEnabled(memberTable.getSelectedRowCount() > 0);
+        setEnabled(editorAccess.getMemberTable().getSelectedRowCount() > 0);
     }
 
@@ -83,8 +82,8 @@
     @Override
     public void actionPerformed(ActionEvent e) {
-        if (isEmptyRole() && !confirmSettingEmptyRole(memberTable.getSelectedRowCount())) {
+        if (isEmptyRole() && !confirmSettingEmptyRole(editorAccess.getMemberTable().getSelectedRowCount())) {
             return;
         }
-        memberTableModel.updateRole(memberTable.getSelectedRows(), tfRole.getText());
+        editorAccess.getMemberTableModel().updateRole(editorAccess.getMemberTable().getSelectedRows(), tfRole.getText());
     }
 
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SortAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SortAction.java	(revision 14026)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SortAction.java	(revision 14027)
@@ -8,6 +8,4 @@
 
 import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTable;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Shortcut;
@@ -18,4 +16,5 @@
  */
 public class SortAction extends AbstractRelationEditorAction {
+	private static final long serialVersionUID = 1L;
 
     /**
@@ -24,6 +23,6 @@
      * @param memberTableModel member table model
      */
-    public SortAction(MemberTable memberTable, MemberTableModel memberTableModel) {
-        super(memberTable, memberTableModel, null);
+    public SortAction(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess, IRelationEditorUpdateOn.MEMBER_TABLE_CHANGE);
         new ImageProvider("dialogs", "sort").getResource().attachImageIcon(this, true);
         putValue(NAME, tr("Sort"));
@@ -36,10 +35,10 @@
     @Override
     public void actionPerformed(ActionEvent e) {
-        memberTableModel.sort();
+    	editorAccess.getMemberTableModel().sort();
     }
 
     @Override
     protected void updateEnabledState() {
-        setEnabled(memberTableModel.getRowCount() > 0);
+        setEnabled(editorAccess.getMemberTableModel().getRowCount() > 0);
     }
 }
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SortBelowAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SortBelowAction.java	(revision 14026)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SortBelowAction.java	(revision 14027)
@@ -6,6 +6,4 @@
 import java.awt.event.ActionEvent;
 
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTable;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
 import org.openstreetmap.josm.tools.ImageProvider;
 
@@ -15,4 +13,5 @@
  */
 public class SortBelowAction extends AbstractRelationEditorAction {
+	private static final long serialVersionUID = 1L;
 
     /**
@@ -21,6 +20,6 @@
      * @param memberTableModel member table model
      */
-    public SortBelowAction(MemberTable memberTable, MemberTableModel memberTableModel) {
-        super(memberTable, memberTableModel, null);
+    public SortBelowAction(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess, IRelationEditorUpdateOn.MEMBER_TABLE_CHANGE, IRelationEditorUpdateOn.MEMBER_TABLE_SELECTION);
         new ImageProvider("dialogs", "sort_below").getResource().attachImageIcon(this, true);
         putValue(NAME, tr("Sort below"));
@@ -31,10 +30,15 @@
     @Override
     public void actionPerformed(ActionEvent e) {
-        memberTableModel.sortBelow();
+    	editorAccess.getMemberTableModel().sortBelow();
     }
 
     @Override
     protected void updateEnabledState() {
-        setEnabled(memberTableModel.getRowCount() > 0 && !memberTableModel.getSelectionModel().isSelectionEmpty());
+        setEnabled(editorAccess.getMemberTableModel().getRowCount() > 0 && !editorAccess.getMemberTableModel().getSelectionModel().isSelectionEmpty());
+    }
+    
+    @Override
+    public boolean isExpertOnly() {
+    	return true;
     }
 }
