Index: /trunk/src/org/openstreetmap/josm/actions/ActionParameter.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/ActionParameter.java	(revision 3175)
+++ /trunk/src/org/openstreetmap/josm/actions/ActionParameter.java	(revision 3175)
@@ -0,0 +1,72 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.actions;
+
+import org.openstreetmap.josm.actions.search.SearchAction.SearchSetting;
+
+public abstract class ActionParameter<T> {
+
+    private final String name;
+
+    public ActionParameter(String name) {
+        this.name = name;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public abstract Class<T> getType();
+
+    public abstract String writeToString(T value);
+
+    public abstract T readFromString(String s);
+
+    public static class StringActionParameter extends ActionParameter<String> {
+
+        public StringActionParameter(String name) {
+            super(name);
+        }
+
+        @Override
+        public Class<String> getType() {
+            return String.class;
+        }
+
+        @Override
+        public String readFromString(String s) {
+            return s;
+        }
+
+        @Override
+        public String writeToString(String value) {
+            return value;
+        }
+
+    }
+
+    public static class SearchSettingsActionParameter extends ActionParameter<SearchSetting> {
+
+        public SearchSettingsActionParameter(String name) {
+            super(name);
+        }
+
+        @Override
+        public Class<SearchSetting> getType() {
+            return SearchSetting.class;
+        }
+
+        @Override
+        public SearchSetting readFromString(String s) {
+            SearchSetting result = SearchSetting.readFromString(s);
+            return result;
+        }
+
+        @Override
+        public String writeToString(SearchSetting value) {
+            if (value == null)
+                return "";
+            return value.writeToString();
+        }
+
+    }
+}
Index: /trunk/src/org/openstreetmap/josm/actions/ParameterizedAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/ParameterizedAction.java	(revision 3175)
+++ /trunk/src/org/openstreetmap/josm/actions/ParameterizedAction.java	(revision 3175)
@@ -0,0 +1,15 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.actions;
+
+import java.awt.event.ActionEvent;
+import java.util.List;
+import java.util.Map;
+
+import javax.swing.Action;
+
+public interface ParameterizedAction extends Action {
+
+    List<ActionParameter<?>> getActionParameters();
+    void actionPerformed(ActionEvent e, Map<String, Object> parameters);
+
+}
Index: /trunk/src/org/openstreetmap/josm/actions/ParameterizedActionDecorator.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/ParameterizedActionDecorator.java	(revision 3175)
+++ /trunk/src/org/openstreetmap/josm/actions/ParameterizedActionDecorator.java	(revision 3175)
@@ -0,0 +1,47 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.actions;
+
+import java.awt.event.ActionEvent;
+import java.beans.PropertyChangeListener;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.swing.Action;
+
+public class ParameterizedActionDecorator implements Action {
+
+    private final ParameterizedAction action;
+    private final Map<String, Object> parameters;
+
+    public ParameterizedActionDecorator(ParameterizedAction action, Map<String, Object> parameters) {
+        this.action = action;
+        this.parameters = new HashMap<String, Object>(parameters);
+    }
+
+    public void addPropertyChangeListener(PropertyChangeListener listener) {
+        action.addPropertyChangeListener(listener);
+    }
+    public Object getValue(String key) {
+        return action.getValue(key);
+    }
+    public boolean isEnabled() {
+        return action.isEnabled();
+    }
+    public void putValue(String key, Object value) {
+        action.putValue(key, value);
+    }
+    public void removePropertyChangeListener(PropertyChangeListener listener) {
+        action.removePropertyChangeListener(listener);
+    }
+    public void setEnabled(boolean b) {
+        action.setEnabled(b);
+    }
+    public void actionPerformed(ActionEvent e) {
+        action.actionPerformed(e, parameters);
+    }
+
+    public Map<String, Object> getParameters() {
+        return parameters;
+    }
+
+}
Index: /trunk/src/org/openstreetmap/josm/actions/search/SearchAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/search/SearchAction.java	(revision 3174)
+++ /trunk/src/org/openstreetmap/josm/actions/search/SearchAction.java	(revision 3175)
@@ -16,4 +16,5 @@
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
 
 import javax.swing.ButtonGroup;
@@ -25,5 +26,8 @@
 
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.ActionParameter;
 import org.openstreetmap.josm.actions.JosmAction;
+import org.openstreetmap.josm.actions.ParameterizedAction;
+import org.openstreetmap.josm.actions.ActionParameter.SearchSettingsActionParameter;
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.Filter;
@@ -34,10 +38,30 @@
 import org.openstreetmap.josm.tools.Shortcut;
 
-public class SearchAction extends JosmAction{
+public class SearchAction extends JosmAction implements ParameterizedAction {
 
     public static final int DEFAULT_SEARCH_HISTORY_SIZE = 10;
 
+    private static final String SEARCH_EXPRESSION = "searchExpression";
+
     public static enum SearchMode {
-        replace, add, remove, in_selection
+        replace('R'), add('A'), remove('D'), in_selection('S');
+
+        private final char code;
+
+        SearchMode(char code) {
+            this.code = code;
+        }
+
+        public char getCode() {
+            return code;
+        }
+
+        public static SearchMode fromCode(char code) {
+            for (SearchMode mode: values()) {
+                if (mode.getCode() == code)
+                    return mode;
+            }
+            return null;
+        }
     }
 
@@ -56,4 +80,12 @@
             return;
         search();
+    }
+
+    public void actionPerformed(ActionEvent e, Map<String, Object> parameters) {
+        if (parameters.get(SEARCH_EXPRESSION) == null) {
+            actionPerformed(e);
+        } else {
+            searchWithoutHistory((SearchSetting) parameters.get(SEARCH_EXPRESSION));
+        }
     }
 
@@ -349,4 +381,58 @@
             return text.hashCode();
         }
+
+        public static SearchSetting readFromString(String s) {
+            if (s.length() == 0)
+                return null;
+
+            SearchSetting result = new SearchSetting();
+
+            int index = 1;
+
+            result.mode = SearchMode.fromCode(s.charAt(0));
+            if (result.mode == null) {
+                result.mode = SearchMode.replace;
+                index = 0;
+            }
+
+            while (index < s.length()) {
+                if (s.charAt(index) == 'C') {
+                    result.caseSensitive = true;
+                } else if (s.charAt(index) == 'R') {
+                    result.regexSearch = true;
+                } else if (s.charAt(index) == ' ') {
+                    break;
+                } else {
+                    System.out.println("Uknown char in SearchSettings: " + s);
+                    break;
+                }
+                index++;
+            }
+
+            if (index < s.length() && s.charAt(index) == ' ') {
+                index++;
+            }
+
+            result.text = s.substring(index);
+
+            return result;
+        }
+
+        public String writeToString() {
+            if (text == null || text.length() == 0)
+                return "";
+
+            StringBuilder result = new StringBuilder();
+            result.append(mode.getCode());
+            if (caseSensitive) {
+                result.append('C');
+            }
+            if (regexSearch) {
+                result.append('R');
+            }
+            result.append(' ');
+            result.append(text);
+            return result.toString();
+        }
     }
 
@@ -359,3 +445,7 @@
         setEnabled(getEditLayer() != null);
     }
+
+    public List<ActionParameter<?>> getActionParameters() {
+        return Collections.<ActionParameter<?>>singletonList(new SearchSettingsActionParameter(SEARCH_EXPRESSION));
+    }
 }
Index: /trunk/src/org/openstreetmap/josm/gui/preferences/ToolbarPreferences.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/preferences/ToolbarPreferences.java	(revision 3174)
+++ /trunk/src/org/openstreetmap/josm/gui/preferences/ToolbarPreferences.java	(revision 3175)
@@ -18,4 +18,5 @@
 import java.awt.event.InputEvent;
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -25,5 +26,4 @@
 import java.util.Map;
 
-import javax.swing.AbstractAction;
 import javax.swing.Action;
 import javax.swing.DefaultListCellRenderer;
@@ -38,4 +38,5 @@
 import javax.swing.JPopupMenu;
 import javax.swing.JScrollPane;
+import javax.swing.JTable;
 import javax.swing.JToolBar;
 import javax.swing.JTree;
@@ -45,4 +46,5 @@
 import javax.swing.event.ListSelectionEvent;
 import javax.swing.event.ListSelectionListener;
+import javax.swing.table.AbstractTableModel;
 import javax.swing.tree.DefaultMutableTreeNode;
 import javax.swing.tree.DefaultTreeCellRenderer;
@@ -51,4 +53,7 @@
 
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.ActionParameter;
+import org.openstreetmap.josm.actions.ParameterizedAction;
+import org.openstreetmap.josm.actions.ParameterizedActionDecorator;
 import org.openstreetmap.josm.gui.tagging.TaggingPreset;
 import org.openstreetmap.josm.tools.GBC;
@@ -56,4 +61,193 @@
 
 public class ToolbarPreferences implements PreferenceSettingFactory {
+
+    public static class ActionDefinition {
+
+        public static ActionDefinition SEPARATOR = new ActionDefinition(null);
+
+        private final Action action;
+        private final Map<String, Object> parameters = new HashMap<String, Object>();
+
+        public ActionDefinition(Action action) {
+            this.action = action;
+        }
+
+        public Map<String, Object> getParameters() {
+            return parameters;
+        }
+
+        public Action getParametrizedAction() {
+            if (getAction() instanceof ParameterizedAction)
+                return new ParameterizedActionDecorator((ParameterizedAction) getAction(), parameters);
+            else
+                return getAction();
+        }
+
+        public Action getAction() {
+            return action;
+        }
+
+    }
+
+    public static class ActionParser {
+        private final Map<String, Action> actions;
+        private final StringBuilder result = new StringBuilder();
+        private int index;
+        private char[] s;
+
+        public ActionParser(Map<String, Action> actions) {
+            this.actions = actions;
+        }
+
+        private String readTillChar(char ch1, char ch2) {
+            result.setLength(0);
+            while (index < s.length && s[index] != ch1 && s[index] != ch2) {
+                if (s[index] == '\\') {
+                    index++;
+                    if (index >= s.length) {
+                        break;
+                    }
+                }
+                result.append(s[index]);
+                index++;
+            }
+            return result.toString();
+        }
+
+        private void skip(char ch) {
+            if (index < s.length && s[index] == ch) {
+                index++;
+            }
+        }
+
+        public ActionDefinition loadAction(String actionName) {
+            index = 0;
+            this.s = actionName.toCharArray();
+
+            String name = readTillChar('(', '(');
+            Action action = actions.get(name);
+
+            if (action == null)
+                return null;
+
+            ActionDefinition result = new ActionDefinition(action);
+
+            if (action instanceof ParameterizedAction) {
+                skip('(');
+
+                ParameterizedAction parametrizedAction = (ParameterizedAction)action;
+                Map<String, ActionParameter<?>> actionParams = new HashMap<String, ActionParameter<?>>();
+                for (ActionParameter<?> param: parametrizedAction.getActionParameters()) {
+                    actionParams.put(param.getName(), param);
+                }
+
+                do {
+                    String paramName = readTillChar('=', '=');
+                    skip('=');
+                    String paramValue = readTillChar(',',')');
+                    if (paramName.length() > 0) {
+                        ActionParameter<?> actionParam = actionParams.get(paramName);
+                        if (actionParam != null) {
+                            result.getParameters().put(paramName, actionParam.readFromString(paramValue));
+                        }
+                    }
+                    skip(',');
+                } while (index < s.length && s[index] != ')');
+            }
+
+            return result;
+        }
+
+        private void escape(String s) {
+            for (int i=0; i<s.length(); i++) {
+                char ch = s.charAt(i);
+                if (ch == '\\' || ch == '(' || ch == ',' || ch == ')' || ch == '=') {
+                    result.append('\\');
+                    result.append(ch);
+                } else {
+                    result.append(ch);
+                }
+            }
+        }
+
+        @SuppressWarnings("unchecked")
+        public String saveAction(ActionDefinition action) {
+            result.setLength(0);
+
+            escape((String) action.getAction().getValue("toolbar"));
+            if (action.getAction() instanceof ParameterizedAction) {
+                result.append('(');
+                List<ActionParameter<?>> params = ((ParameterizedAction)action.getAction()).getActionParameters();
+                for (int i=0; i<params.size(); i++) {
+                    ActionParameter<Object> param = (ActionParameter<Object>)params.get(i);
+                    escape(param.getName());
+                    result.append('=');
+                    Object value = action.getParameters().get(param.getName());
+                    if (value != null) {
+                        escape(param.writeToString(value));
+                    }
+                    if (i < params.size() - 1) {
+                        result.append(',');
+                    } else {
+                        result.append(')');
+                    }
+                }
+            }
+
+            return result.toString();
+        }
+    }
+
+    private static class ActionParametersTableModel extends AbstractTableModel {
+
+        private ActionDefinition currentAction = ActionDefinition.SEPARATOR;
+
+        public int getColumnCount() {
+            return 2;
+        }
+
+        public int getRowCount() {
+            if (currentAction == ActionDefinition.SEPARATOR || !(currentAction.getAction() instanceof ParameterizedAction))
+                return 0;
+            ParameterizedAction pa = (ParameterizedAction)currentAction.getAction();
+            return pa.getActionParameters().size();
+        }
+
+        @SuppressWarnings("unchecked")
+        private ActionParameter<Object> getParam(int index) {
+            ParameterizedAction pa = (ParameterizedAction)currentAction.getAction();
+            return (ActionParameter<Object>) pa.getActionParameters().get(index);
+        }
+
+        public Object getValueAt(int rowIndex, int columnIndex) {
+            ActionParameter<Object> param = getParam(rowIndex);
+            switch (columnIndex) {
+            case 0:
+                return param.getName();
+            case 1:
+                return param.writeToString(currentAction.getParameters().get(param.getName()));
+            default:
+                return null;
+            }
+        }
+
+        @Override
+        public boolean isCellEditable(int row, int column) {
+            return column == 1;
+        }
+
+        @Override
+        public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
+            ActionParameter<Object> param = getParam(rowIndex);
+            currentAction.getParameters().put(param.getName(), param.readFromString((String)aValue));
+        }
+
+
+        public void setCurrentAction(ActionDefinition currentAction) {
+            this.currentAction = currentAction;
+            fireTableDataChanged();
+        }
+
+    }
 
     /**
@@ -72,5 +266,5 @@
     }
 
-    public static class Settings implements PreferenceSetting {
+    public class Settings implements PreferenceSetting {
 
         private final class Move implements ActionListener {
@@ -85,8 +279,9 @@
                     for (TreePath selectedAction : actionsTree.getSelectionPaths()) {
                         DefaultMutableTreeNode node = (DefaultMutableTreeNode) selectedAction.getLastPathComponent();
-                        if (node.getUserObject() == null)
-                            selected.add(leadItem++, null);
-                        else if (node.getUserObject() == null || node.getUserObject() instanceof Action)
-                            selected.add(leadItem++, ((Action)node.getUserObject()).getValue("toolbar"));
+                        if (node.getUserObject() == null) {
+                            selected.add(leadItem++, ActionDefinition.SEPARATOR);
+                        } else if (node.getUserObject() instanceof Action) {
+                            selected.add(leadItem++, new ActionDefinition((Action)node.getUserObject()));
+                        }
                     }
                 } else if (e.getActionCommand().equals(">") && selectedList.getSelectedIndex() != -1) {
@@ -114,15 +309,11 @@
         }
 
-        private static class ActionTransferable implements Transferable {
+        private class ActionTransferable implements Transferable {
 
             private DataFlavor[] flavors = new DataFlavor[] { ACTION_FLAVOR };
 
-            private Object[] actions;
-
-            public ActionTransferable(Action action) {
-                this.actions = new Action[] { action };
-            }
-
-            public ActionTransferable(Object[] actions) {
+            private final List<ActionDefinition> actions;
+
+            public ActionTransferable(List<ActionDefinition> actions) {
                 this.actions = actions;
             }
@@ -148,4 +339,8 @@
         private final DefaultTreeModel actionsTreeModel;
         private final JTree actionsTree;
+
+        private final ActionParametersTableModel actionParametersModel = new ActionParametersTableModel();
+        private final JTable actionParametersTable = new JTable(actionParametersModel);
+        private JPanel actionParametersPanel;
 
         private JButton upButton;
@@ -161,10 +356,11 @@
         private JButton createButton(String name) {
             JButton b = new JButton();
-            if (name.equals("up"))
+            if (name.equals("up")) {
                 b.setIcon(ImageProvider.get("dialogs", "up"));
-            else if (name.equals("down"))
+            } else if (name.equals("down")) {
                 b.setIcon(ImageProvider.get("dialogs", "down"));
-            else
+            } else {
                 b.setText(name);
+            }
             b.addActionListener(moveAction);
             b.setActionCommand(name);
@@ -197,8 +393,8 @@
                     String s;
                     Icon i;
-                    if (value != null) {
-                        Action action = Main.toolbar.getAction((String)value);
-                        s = (String) action.getValue(Action.NAME);
-                        i = (Icon) action.getValue(Action.SMALL_ICON);
+                    if (value != ActionDefinition.SEPARATOR) {
+                        ActionDefinition action = (ActionDefinition)value;
+                        s = (String) action.getAction().getValue(Action.NAME);
+                        i = (Icon) action.getAction().getValue(Action.SMALL_ICON);
                     } else {
                         i = ImageProvider.get("preferences/separator");
@@ -214,6 +410,10 @@
                 public void valueChanged(ListSelectionEvent e) {
                     boolean sel = selectedList.getSelectedIndex() != -1;
-                    if (sel)
+                    if (sel) {
                         actionsTree.clearSelection();
+                        ActionDefinition action = (ActionDefinition) selected.get(selectedList.getSelectedIndex());
+                        actionParametersModel.setCurrentAction(action);
+                        actionParametersPanel.setVisible(actionParametersModel.getRowCount() > 0);
+                    }
                     upButton.setEnabled(sel);
                     downButton.setEnabled(sel);
@@ -225,5 +425,9 @@
                 @Override
                 protected Transferable createTransferable(JComponent c) {
-                    return new ActionTransferable(((JList)c).getSelectedValues());
+                    List<ActionDefinition> actions = new ArrayList<ActionDefinition>();
+                    for (Object o: ((JList)c).getSelectedValues()) {
+                        actions.add((ActionDefinition)o);
+                    }
+                    return new ActionTransferable(actions);
                 }
 
@@ -236,7 +440,6 @@
                 public boolean canImport(JComponent comp, DataFlavor[] transferFlavors) {
                     for (DataFlavor f : transferFlavors) {
-                        if (ACTION_FLAVOR.equals(f)) {
+                        if (ACTION_FLAVOR.equals(f))
                             return true;
-                        }
                     }
                     return false;
@@ -253,13 +456,15 @@
                     try {
                         int dropIndex = selectedList.locationToIndex(selectedList.getMousePosition(true));
-                        Object[] draggedData = (Object[]) t.getTransferData(ACTION_FLAVOR);
+                        List<?> draggedData = (List<?>) t.getTransferData(ACTION_FLAVOR);
 
                         Object leadItem = dropIndex >= 0 ? selected.elementAt(dropIndex) : null;
-                        int dataLength = draggedData.length;
-
-                        if (leadItem != null)
-                            for (int i = 0; i < dataLength; i++)
-                                if (leadItem.equals(draggedData[i]))
+                        int dataLength = draggedData.size();
+
+                        if (leadItem != null) {
+                            for (Object o: draggedData) {
+                                if (leadItem.equals(o))
                                     return false;
+                            }
+                        }
 
                         int dragLeadIndex = -1;
@@ -267,7 +472,8 @@
 
                         if (localDrop) {
-                            dragLeadIndex = selected.indexOf(draggedData[0]);
-                            for (int i = 0; i < dataLength; i++)
-                                selected.removeElement(draggedData[i]);
+                            dragLeadIndex = selected.indexOf(draggedData.get(0));
+                            for (Object o: draggedData) {
+                                selected.removeElement(o);
+                            }
                         }
                         int[] indices = new int[dataLength];
@@ -277,10 +483,10 @@
                             int insertionAdjustment = dragLeadIndex <= adjustedLeadIndex ? 1 : 0;
                             for (int i = 0; i < dataLength; i++) {
-                                selected.insertElementAt(draggedData[i], adjustedLeadIndex + insertionAdjustment + i);
+                                selected.insertElementAt(draggedData.get(i), adjustedLeadIndex + insertionAdjustment + i);
                                 indices[i] = adjustedLeadIndex + insertionAdjustment + i;
                             }
                         } else {
                             for (int i = 0; i < dataLength; i++) {
-                                selected.add(dropIndex, draggedData[i]);
+                                selected.add(dropIndex, draggedData.get(i));
                                 indices[i] = dropIndex + i;
                             }
@@ -300,6 +506,6 @@
                     if (movingComponent.equals("list")) {
                         try {
-                            Object[] draggedData = (Object[]) data.getTransferData(ACTION_FLAVOR);
-                            boolean localDrop = selected.contains(draggedData[0]);
+                            List<?> draggedData = (List<?>) data.getTransferData(ACTION_FLAVOR);
+                            boolean localDrop = selected.contains(draggedData.get(0));
                             if (localDrop) {
                                 int[] indices = selectedList.getSelectedIndices();
@@ -332,16 +538,16 @@
                 protected Transferable createTransferable(JComponent c) {
                     TreePath[] paths = actionsTree.getSelectionPaths();
-                    List<String> dragActions = new LinkedList<String>();
+                    List<ActionDefinition> dragActions = new ArrayList<ActionDefinition>();
                     for (TreePath path : paths) {
                         DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent();
                         Object obj = node.getUserObject();
                         if (obj == null) {
-                            dragActions.add(null);
+                            dragActions.add(ActionDefinition.SEPARATOR);
                         }
                         else if (obj instanceof Action) {
-                            dragActions.add((String) ((Action) obj).getValue("toolbar"));
+                            dragActions.add(new ActionDefinition((Action) obj));
                         }
                     }
-                    return new ActionTransferable(dragActions.toArray());
+                    return new ActionTransferable(dragActions);
                 }
             });
@@ -392,14 +598,19 @@
             p.add(right);
 
+            actionParametersPanel = new JPanel(new GridBagLayout());
+            actionParametersPanel.add(new JLabel(tr("Action parameters")), GBC.eol().insets(0, 10, 0, 20));
+            actionParametersTable.getColumnModel().getColumn(0).setHeaderValue(tr("Parameter name"));
+            actionParametersTable.getColumnModel().getColumn(1).setHeaderValue(tr("Parameter value"));
+            actionParametersPanel.add(actionParametersTable.getTableHeader(), GBC.eol().fill(GBC.HORIZONTAL));
+            actionParametersPanel.add(actionParametersTable, GBC.eol().fill(GBC.BOTH).insets(0, 0, 0, 10));
+            actionParametersPanel.setVisible(false);
+
             JPanel panel = gui.createPreferenceTab("toolbar", tr("Toolbar customization"),
                     tr("Customize the elements on the toolbar."), false);
             panel.add(p, GBC.eol().fill(GBC.BOTH));
-
+            panel.add(actionParametersPanel, GBC.eol().fill(GBC.HORIZONTAL));
             selected.removeAllElements();
-            for (String s : getToolString()) {
-                if (s.equals("|"))
-                    selected.addElement(null);
-                else if (Main.toolbar.getAction(s) != null)
-                    selected.addElement(s);
+            for (ActionDefinition actionDefinition: getDefinedActions()) {
+                selected.addElement(actionDefinition);
             }
         }
@@ -407,9 +618,11 @@
         public boolean ok() {
             Collection<String> t = new LinkedList<String>();
+            ActionParser parser = new ActionParser(null);
             for (int i = 0; i < selected.size(); ++i) {
-                if (selected.get(i) == null)
+                if (selected.get(i) == ActionDefinition.SEPARATOR) {
                     t.add("|");
-                else
-                    t.add((String)((Main.toolbar.getAction((String)selected.get(i))).getValue("toolbar")));
+                } else {
+                    t.add(parser.saveAction((ActionDefinition)(selected.get(i))));
+                }
             }
             Main.pref.putCollection("toolbar", t);
@@ -451,6 +664,7 @@
     {
         Action e = actions.get(s);
-        if(e == null)
+        if(e == null) {
             e = regactions.get(s);
+        }
         return e;
     }
@@ -461,6 +675,7 @@
         for(Map.Entry<String, Action> a : regactions.entrySet())
         {
-            if(actions.get(a.getKey()) == null)
+            if(actions.get(a.getKey()) == null) {
                 rootActionsNode.add(new DefaultMutableTreeNode(a.getValue()));
+            }
         }
         rootActionsNode.add(new DefaultMutableTreeNode(null));
@@ -471,4 +686,27 @@
     private static Collection<String> getToolString() {
         return Main.pref.getCollection("toolbar", Arrays.asList(deftoolbar));
+    }
+
+    private Collection<ActionDefinition> getDefinedActions() {
+        loadActions();
+
+        Map<String, Action> allActions = new HashMap<String, Action>(regactions);
+        allActions.putAll(actions);
+        ActionParser actionParser = new ActionParser(allActions);
+
+        Collection<ActionDefinition> result = new ArrayList<ActionDefinition>();
+
+        for (String s : getToolString()) {
+            if (s.equals("|")) {
+                result.add(ActionDefinition.SEPARATOR);
+            } else {
+                ActionDefinition a = actionParser.loadAction(s);
+                if(a != null) {
+                    result.add(a);
+                }
+            }
+        }
+
+        return result;
     }
 
@@ -488,17 +726,15 @@
      */
     public void refreshToolbarControl() {
-        loadActions();
         control.removeAll();
-        for (String s : getToolString()) {
-            if (s.equals("|"))
+
+        for (ActionDefinition action : getDefinedActions()) {
+            if (action == ActionDefinition.SEPARATOR) {
                 control.addSeparator();
-            else {
-                Action a = getAction(s);
-                if(a != null)
-                {
-                    JButton b = control.add(a);
-                    Object tt = a.getValue(TaggingPreset.OPTIONAL_TOOLTIP_TEXT);
-                    if (tt != null)
-                        b.setToolTipText((String)tt);
+            } else {
+                Action a = action.getParametrizedAction();
+                JButton b = control.add(a);
+                Object tt = a.getValue(TaggingPreset.OPTIONAL_TOOLTIP_TEXT);
+                if (tt != null) {
+                    b.setToolTipText((String)tt);
                 }
             }
@@ -508,5 +744,5 @@
 
     private static DataFlavor ACTION_FLAVOR = new DataFlavor(
-            AbstractAction.class, "ActionItem");
+            ActionDefinition.class, "ActionItem");
 
 }
Index: /trunk/test/unit/org/openstreetmap/josm/gui/preferences/ToolbarPreferencesTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/gui/preferences/ToolbarPreferencesTest.java	(revision 3175)
+++ /trunk/test/unit/org/openstreetmap/josm/gui/preferences/ToolbarPreferencesTest.java	(revision 3175)
@@ -0,0 +1,74 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.preferences;
+
+import java.awt.event.ActionEvent;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.openstreetmap.josm.actions.ActionParameter;
+import org.openstreetmap.josm.actions.ParameterizedAction;
+import org.openstreetmap.josm.actions.ActionParameter.StringActionParameter;
+import org.openstreetmap.josm.gui.preferences.ToolbarPreferences.ActionDefinition;
+import org.openstreetmap.josm.gui.preferences.ToolbarPreferences.ActionParser;
+
+public class ToolbarPreferencesTest {
+
+    private static class TestAction extends AbstractAction implements ParameterizedAction {
+
+        public TestAction() {
+            putValue("toolbar", "action");
+        }
+
+        public void actionPerformed(ActionEvent e, Map<String, Object> parameters) {
+        }
+
+        public List<ActionParameter<?>> getActionParameters() {
+            List<ActionParameter<?>> result = new ArrayList<ActionParameter<?>>();
+            result.add(new StringActionParameter("param1"));
+            result.add(new StringActionParameter("param2"));
+            return result;
+        }
+
+        public void actionPerformed(ActionEvent e) {
+
+        }
+
+    }
+
+    private void checkAction(ActionDefinition a, Object... params) {
+        Map<String, Object> expected = new HashMap<String, Object>();
+        for (int i=0; i<params.length; i+=2) {
+            expected.put((String)params[i], params[i+1]);
+        }
+        Assert.assertEquals(expected, a.getParameters());
+    }
+
+    @Test
+    public void test1() {
+        Map<String, Action> actions = new HashMap<String, Action>();
+        actions.put("action", new TestAction());
+        ActionParser parser = new ActionParser(actions);
+        checkAction(parser.loadAction("action(param1=value1)"), "param1", "value1");
+        checkAction(parser.loadAction("action(param1=value1,param2=2)"), "param1", "value1", "param2", "2");
+        checkAction(parser.loadAction("action(param1=value1,param2=2\\(\\=\\,\\\\)"), "param1", "value1", "param2", "2(=,\\");
+        checkAction(parser.loadAction("action(param1=value1,"), "param1", "value1");
+        checkAction(parser.loadAction("action(param1=value1"), "param1", "value1");
+        checkAction(parser.loadAction("action(param1="), "param1", "");
+        checkAction(parser.loadAction("action(param1"), "param1", "");
+        checkAction(parser.loadAction("action("));
+        checkAction(parser.loadAction("action"));
+        checkAction(parser.loadAction("action(uknownParam=aa)"));
+
+        Assert.assertEquals("action(param1=value1,param2=value2)", parser.saveAction(parser.loadAction("action(param1=value1,param2=value2)")));
+        Assert.assertEquals("action(param1=value1,param2=)", parser.saveAction(parser.loadAction("action(param1=value1)")));
+        Assert.assertEquals("action(param1=value1,param2=2\\(\\=\\,\\\\)", parser.saveAction(parser.loadAction("action(param1=value1,param2=2\\(\\=\\,\\\\)")));
+    }
+
+}
