Index: src/org/openstreetmap/josm/gui/tagging/presets/TaggingPreset.java
===================================================================
--- src/org/openstreetmap/josm/gui/tagging/presets/TaggingPreset.java	(revision 18643)
+++ src/org/openstreetmap/josm/gui/tagging/presets/TaggingPreset.java	(working copy)
@@ -138,6 +138,11 @@
     public boolean preset_name_label;
 
     /**
+     * If menu items should be sorted
+     */
+    public String items_sort = "yes";
+
+    /**
      * The types as preparsed collection.
      */
     public transient Set<TaggingPresetType> types;
@@ -255,6 +260,15 @@
     }
 
     /**
+     * Called from the XML parser to set the sort option.
+     * @param sort The sort value for the menu items.
+     * @since 18619
+     */
+    public void setItems_sort(final String sort) {
+        this.items_sort = sort;
+    }
+
+    /**
      * Called from the XML parser to set the icon.
      * The loading task is performed in the background in order to speedup startup.
      * @param iconName icon name
Index: src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetMenu.java
===================================================================
--- src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetMenu.java	(revision 18643)
+++ src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetMenu.java	(working copy)
@@ -120,14 +120,23 @@
      * Sorts the menu items using the translated item text
      */
     public void sortMenu() {
-        TaggingPresetMenu.sortMenu(this.menu);
+        TaggingPresetMenu.sortMenu(this.menu, TaggingPresets.SORT_MENU.get());
     }
 
     /**
      * Sorts the menu items using the translated item text
      * @param menu menu to sort
+     * @param itemssort if menu should be sorted.
      */
-    public static void sortMenu(JMenu menu) {
+    public static void sortMenu(JMenu menu, boolean itemssort) {
+        Action a = menu.getAction();
+
+        boolean sort = itemssort;
+
+        if (a instanceof TaggingPreset) {
+            sort = (sort && ((TaggingPreset) a).items_sort.equals("yes")) || ((TaggingPreset) a).items_sort.equals("always");
+        }
+
         Component[] items = menu.getMenuComponents();
         PresetTextComparator comp = new PresetTextComparator();
         List<JMenuItem> sortarray = new ArrayList<>();
@@ -135,19 +144,21 @@
         for (int i = 0; i < items.length; i++) {
             Object item = items[i];
             if (item instanceof JMenu) {
-                sortMenu((JMenu) item);
+                sortMenu((JMenu) item, itemssort);
             }
-            if (item instanceof JMenuItem) {
-                sortarray.add((JMenuItem) item);
-                if (i == items.length-1) {
+            if (sort) {
+                if (item instanceof JMenuItem) {
+                    sortarray.add((JMenuItem) item);
+                    if (i == items.length-1) {
+                        handleMenuItem(menu, comp, sortarray, lastSeparator);
+                        sortarray = new ArrayList<>();
+                        lastSeparator = 0;
+                    }
+                } else if (item instanceof JSeparator) {
                     handleMenuItem(menu, comp, sortarray, lastSeparator);
                     sortarray = new ArrayList<>();
-                    lastSeparator = 0;
+                    lastSeparator = i;
                 }
-            } else if (item instanceof JSeparator) {
-                handleMenuItem(menu, comp, sortarray, lastSeparator);
-                sortarray = new ArrayList<>();
-                lastSeparator = i;
             }
         }
     }
Index: src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetReader.java
===================================================================
--- src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetReader.java	(revision 18643)
+++ src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetReader.java	(working copy)
@@ -39,6 +39,7 @@
 import org.openstreetmap.josm.gui.tagging.presets.items.PresetListEntry;
 import org.openstreetmap.josm.gui.tagging.presets.items.Roles;
 import org.openstreetmap.josm.gui.tagging.presets.items.Roles.Role;
+import org.openstreetmap.josm.gui.tagging.presets.items.SelectGroup;
 import org.openstreetmap.josm.gui.tagging.presets.items.Space;
 import org.openstreetmap.josm.gui.tagging.presets.items.Text;
 import org.openstreetmap.josm.io.CachedFile;
@@ -145,6 +146,7 @@
         parser.mapOnStart("roles", Roles.class);
         parser.map("role", Role.class);
         parser.mapBoth("checkgroup", CheckGroup.class);
+        parser.mapBoth("selectgroup", SelectGroup.class);
         parser.map("check", Check.class);
         parser.map("combo", Combo.class);
         parser.map("multiselect", MultiSelect.class);
@@ -182,6 +184,9 @@
 
         /** to detect end of {@code <checkgroup>} */
         CheckGroup lastcheckgroup = null;
+        /** to detect end of {@code <selectgroup>} */
+        SelectGroup lastselectgroup = null;
+        int selectgroupcount = PresetListEntry.SELECT_GROUP_NONE;
         /** to detect end of {@code <group>} */
         TaggingPresetMenu lastmenu = null;
         /** to detect end of reused {@code <group>} */
@@ -302,7 +307,18 @@
                             all.getLast().data.add((TaggingPresetItem) o);
                         }
                     } else if (o instanceof PresetListEntry) {
-                        listEntries.add((PresetListEntry) o);
+                        PresetListEntry entry = (PresetListEntry) o;
+
+                        if(lastselectgroup != null) {
+                            if(!lastselectgroup.exclusive) {
+                                entry.select_group = selectgroupcount;
+                            }
+                            else {
+                                entry.select_group = -selectgroupcount;
+                            }
+                        }
+
+                        listEntries.add(entry);
                     } else if (o instanceof CheckGroup) {
                         CheckGroup cg = (CheckGroup) o;
                         if (cg == lastcheckgroup) {
@@ -316,6 +332,14 @@
                         } else {
                             lastcheckgroup = cg;
                         }
+                    } else if (o instanceof SelectGroup) {
+                        SelectGroup sg = (SelectGroup) o;
+                        if (sg == lastselectgroup) {
+                            lastselectgroup = null;
+                        } else {
+                            lastselectgroup = sg;
+                            selectgroupcount++;
+                        }
                     } else {
                         if (!checks.isEmpty()) {
                             all.getLast().data.addAll(checks);
@@ -329,6 +353,7 @@
                         }
                         listEntries.clear();
                         lastrole = null;
+                        selectgroupcount = PresetListEntry.SELECT_GROUP_NONE;
                     }
                 } else
                     throw new SAXException(tr("Preset sub element without parent"));
Index: src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresets.java
===================================================================
--- src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresets.java	(revision 18643)
+++ src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresets.java	(working copy)
@@ -123,9 +123,9 @@
                 }
             }
         }
-        if (SORT_MENU.get()) {
-            TaggingPresetMenu.sortMenu(presetsMenu);
-        }
+
+        TaggingPresetMenu.sortMenu(presetsMenu, SORT_MENU.get());
+
         listeners.forEach(TaggingPresetListener::taggingPresetsModified);
     }
 
Index: src/org/openstreetmap/josm/gui/tagging/presets/items/Combo.java
===================================================================
--- src/org/openstreetmap/josm/gui/tagging/presets/items/Combo.java	(revision 18643)
+++ src/org/openstreetmap/josm/gui/tagging/presets/items/Combo.java	(working copy)
@@ -168,9 +168,12 @@
         combobox.setToolTipText(getKeyTooltipText());
         combobox.applyComponentOrientation(OrientationAction.getValueOrientation(key));
 
-        return true;
+
+        return isNeeded(usage);
     }
 
+
+
     /**
      * Finds the PresetListEntry that matches value.
      * <p>
Index: src/org/openstreetmap/josm/gui/tagging/presets/items/ComboMultiSelect.java
===================================================================
--- src/org/openstreetmap/josm/gui/tagging/presets/items/ComboMultiSelect.java	(revision 18643)
+++ src/org/openstreetmap/josm/gui/tagging/presets/items/ComboMultiSelect.java	(working copy)
@@ -35,7 +35,7 @@
  * Abstract superclass for combo box and multi-select list types.
  */
 public abstract class ComboMultiSelect extends KeyedItem {
-
+    protected static final String VALUE_SORT_USER = "user";
     /**
      * A list of entries.
      * The list has to be separated by commas (for the {@link Combo} box) or by the specified delimiter (for the {@link MultiSelect}).
@@ -53,7 +53,10 @@
     /** Disabled internationalisation for value to avoid mistakes, see #11696 */
     public boolean values_no_i18n; // NOSONAR
     /** Whether to sort the values, defaults to true. */
-    public boolean values_sort = true; // NOSONAR
+    public String values_sort = String.valueOf(true); // NOSONAR
+    /** Whether to show this combo in dialog only when it's needed.
+     * It's needed when key doesn't exist or if current value is not in values */
+    public boolean if_needed_only = false; // NOSONAR
     /**
      * A list of entries that is displayed to the user.
      * Must be the same number and order of entries as {@link #values} and editable must be false or not specified.
@@ -138,6 +141,7 @@
                 // editor-ersatz of a readonly combobox. fixes #6157
                 l.setText(value.getListDisplay(width));
             }
+
             if (value.getCount() > 0) {
                 l.setFont(l.getFont().deriveFont(Font.ITALIC + Font.BOLD));
             }
@@ -310,7 +314,7 @@
             addListEntry(e);
         }
 
-        if (values_sort && TaggingPresets.SORT_MENU.get()) {
+        if (values_sort.equals(String.valueOf(true)) && TaggingPresets.SORT_MENU.get()) {
             Collections.sort(presetListEntries, (a, b) -> AlphanumComparator.getInstance().compare(a.getDisplayValue(), b.getDisplayValue()));
         }
     }
@@ -430,4 +434,20 @@
     public MatchType getDefaultMatch() {
         return MatchType.NONE;
     }
+
+    protected boolean isNeeded(Usage usage) {
+        boolean result = !if_needed_only || usage.unused();
+
+        if (!result) {
+            for (String v : usage.map.keySet()) {
+                for (PresetListEntry p : presetListEntries) {
+                    if (p.value.equals(v)) {
+                        return false;
+                    }
+                }
+            }
+        }
+
+        return result;
+    }
 }
Index: src/org/openstreetmap/josm/gui/tagging/presets/items/Key.java
===================================================================
--- src/org/openstreetmap/josm/gui/tagging/presets/items/Key.java	(revision 18643)
+++ src/org/openstreetmap/josm/gui/tagging/presets/items/Key.java	(working copy)
@@ -7,6 +7,7 @@
 
 import javax.swing.JPanel;
 
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.Tag;
 import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetItemGuiSupport;
 
@@ -14,12 +15,55 @@
  * Invisible type allowing to hardcode an OSM key/value from the preset definition.
  */
 public class Key extends KeyedItem {
+    private static final String VALUE_APPEND_ALWAYS = "always";
 
     /** The hardcoded value for key */
     public String value; // NOSONAR
 
+    /** The hardcoded value for key appending existing value **/
+    public String append_value;  // NOSONAR
+
+    /** The hardcoded delimiter to use for appending values **/
+    public String delimiter = ";"; // NOSONAR
+
+    /** The hardcoded type of appending */
+    public String append = null; // NOSONAR
+
+    /** The hardcoded prefix to use for setting value to empty key */
+    public String prefix = null; // NOSONAR
+
+    private String useValue;
+
     @Override
     public boolean addToPanel(JPanel p, TaggingPresetItemGuiSupport support) {
+        if (prefix != null) {
+            useValue = prefix + value;
+        }
+        else {
+            useValue = value;
+        }
+
+        // If append_value is present append also if append was not set
+        if (append_value != null || append != null) {
+            String toUse = append_value != null ? append_value : value;
+
+            Collection<OsmPrimitive> col = support.getSelected();
+
+            for (OsmPrimitive pr : col) {
+                String currentValue = pr.get(key);
+
+                if (currentValue != null) {
+                    useValue = currentValue;
+
+                    if ((append != null && append.equals(VALUE_APPEND_ALWAYS)) || !useValue.contains(toUse)) {
+                        useValue += delimiter + toUse;
+                    }
+
+                    break;
+                }
+            }
+        }
+
         return false;
     }
 
@@ -33,7 +77,7 @@
      * @return the tag
      */
     public Tag asTag() {
-        return new Tag(key, value);
+        return new Tag(key, useValue != null ? useValue : value);
     }
 
     @Override
@@ -43,13 +87,13 @@
 
     @Override
     public Collection<String> getValues() {
-        return Collections.singleton(value);
+        return Collections.singleton(useValue != null ? useValue : value);
     }
 
     @Override
     public String toString() {
-        return "Key [key=" + key + ", value=" + value + ", text=" + text
-                + ", text_context=" + text_context + ", match=" + match
-                + ']';
+        return "Key [key=" + key + ", value=" + value + ", value_append=" + append_value
+                + ", text=" + text + ", text_context=" + text_context + ", match=" + match
+                + ", delimiter=" + delimiter + ']';
     }
 }
Index: src/org/openstreetmap/josm/gui/tagging/presets/items/MultiSelect.java
===================================================================
--- src/org/openstreetmap/josm/gui/tagging/presets/items/MultiSelect.java	(revision 18643)
+++ src/org/openstreetmap/josm/gui/tagging/presets/items/MultiSelect.java	(working copy)
@@ -1,40 +1,139 @@
 // License: GPL. For details, see LICENSE file.
 package org.openstreetmap.josm.gui.tagging.presets.items;
 
+import static org.openstreetmap.josm.tools.I18n.tr;
+
 import java.awt.Dimension;
+import java.awt.GridBagLayout;
 import java.awt.Insets;
 import java.awt.Rectangle;
-import java.util.stream.Collectors;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
 
 import javax.swing.DefaultListModel;
+import javax.swing.DefaultListSelectionModel;
+import javax.swing.JButton;
 import javax.swing.JLabel;
 import javax.swing.JList;
 import javax.swing.JPanel;
 import javax.swing.JScrollPane;
+import javax.swing.ListModel;
+import javax.swing.ListSelectionModel;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
 
 import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetItemGuiSupport;
+import org.openstreetmap.josm.gui.util.ReorderableTableModel;
 import org.openstreetmap.josm.gui.widgets.OrientationAction;
 import org.openstreetmap.josm.tools.GBC;
+import org.openstreetmap.josm.tools.ImageProvider;
+import org.openstreetmap.josm.tools.ImageProvider.ImageSizes;
 
 /**
  * Multi-select list type.
  */
 public class MultiSelect extends ComboMultiSelect {
-
     /**
      * Number of rows to display (positive integer, optional).
      */
     public short rows; // NOSONAR
 
     /** The model for the JList */
-    protected final DefaultListModel<PresetListEntry> model = new DefaultListModel<>();
+    protected final PresetListModel model = new PresetListModel();
     /** The swing component */
     protected final JList<PresetListEntry> list = new JList<>(model);
 
+    /**
+     * Text that will be put in front of the resulting value.
+     */
+    public String prefix; // NOSONAR
+
+    /**
+     * If the entries in the list should be selected with clicking only.
+     */
+    public boolean quick_select = false;
+
+    /**
+     * Use selection model that selects/deselects values with single click.
+     * @since 18619
+     */
+    public MultiSelect() {
+        list.setSelectionModel(new SingleClickSelectionModel(list));
+    }
+
     private void addEntry(PresetListEntry entry) {
+        addEntry(entry, -1);
+    }
+
+    private void addEntry(PresetListEntry entry, int presetCount) {
+        if (prefix != null && entry.value.startsWith(prefix)) {
+            entry.value = entry.value.substring(prefix.length());
+        }
+
         if (!seenValues.containsKey(entry.value)) {
-            model.addElement(entry);
-            seenValues.put(entry.value, entry);
+            boolean add = true;
+
+            for (int i = 0; i < model.size(); i++) {
+                PresetListEntry test = model.get(i);
+
+                if (test.delimiter != null && entry.value.matches(".*\\\\{0}" + test.delimiter+".*")) {
+                    add = false;
+
+                    String[] parts = entry.value.split(test.delimiter,-1);
+
+                    for (int j = 0; j < parts.length; j++) {
+                        if (prefix != null && parts[j].startsWith(prefix)) {
+                            parts[j] = parts[j].substring(prefix.length());
+                        }
+                        addEntry(new PresetListEntry(parts[j], this, j == 0 ? String.valueOf(delimiter) : test.delimiter), presetCount);
+                    }
+
+                    break;
+                }
+            }
+
+            if (add) {
+                if (presetCount == -1) {
+                    model.addElement(entry);
+                }
+                else {
+                    model.insertElementAt(entry, model.getSize() - presetCount);
+                }
+                seenValues.put(entry.value, entry);
+            }
+        }
+    }
+
+    private void select(PresetListEntry entry) {
+        for (int i = 0; i < model.getSize(); i++) {
+            PresetListEntry test = model.get(i);
+
+            if (Objects.equals(test.value, entry.value)) {
+                int[] indices = model.getSelectedIndices();
+
+                if (indices != null && indices.length > 0 && indices[indices.length - 1] > i) {
+                    PresetListEntry removed = model.remove(i);
+                    model.add(indices[indices.length-1], removed);
+                    list.addSelectionInterval(indices[indices.length-1], indices[indices.length-1]);
+                }
+                else {
+                    list.addSelectionInterval(i, i);
+                }
+
+                if(usage != null && usage.map != null && !usage.map.containsKey(test.value)) {
+                    usage.map.put(test.value, 1);
+                }
+
+                break;
+            }
+            else if (test.delimiter != null && entry.value.matches(".*\\\\{0}" + test.delimiter+".*")) {
+                for (String part : entry.value.split(test.delimiter, -1)) {
+                    select(new PresetListEntry(part, this, test.delimiter));
+                }
+            }
         }
     }
 
@@ -53,22 +152,30 @@
         // Add values from the preset.
         presetListEntries.forEach(this::addEntry);
 
+        int count = model.getSize();
+
         // Add all values used in the selected primitives. This also adds custom values and makes
         // sure we won't lose them.
         usage = usage.splitValues(String.valueOf(delimiter));
         for (String value: usage.map.keySet()) {
-            addEntry(new PresetListEntry(value, this));
+            addEntry(new PresetListEntry(value, this), count);
         }
 
         // Select the values in the initial value.
         if (!initialValue.isEmpty() && !DIFFERENT.equals(initialValue)) {
+            if(prefix != null && initialValue.startsWith(prefix)) {
+                initialValue = initialValue.substring(prefix.length());
+            }
+
             for (String value : initialValue.split(String.valueOf(delimiter), -1)) {
                 PresetListEntry e = new PresetListEntry(value, this);
                 addEntry(e);
-                int i = model.indexOf(e);
-                list.addSelectionInterval(i, i);
+                select(e);
             }
         }
+        else if (default_ != null) {
+            select(new PresetListEntry(default_, this));
+        }
 
         ComboMultiSelectListCellRenderer renderer = new ComboMultiSelectListCellRenderer(list, list.getCellRenderer(), 200, key);
         list.setCellRenderer(renderer);
@@ -89,10 +196,44 @@
                 insets = sp.getInsets();
                 r.width += insets.left + insets.right;
                 r.height += insets.top + insets.bottom;
-                sp.setPreferredSize(new Dimension(r.width, r.height));
+                sp.setPreferredSize(new Dimension(Math.max(r.width, sp.getPreferredSize().width), r.height));
             }
         }
-        p.add(sp, GBC.eol().fill(GBC.HORIZONTAL)); // NOSONAR
+
+        if(values_sort.equals(VALUE_SORT_USER)) {
+            final JButton up = new JButton(ImageProvider.get("dialogs", "up", ImageSizes.LARGEICON));
+            up.setToolTipText(tr("Move the currently selected members up"));
+            up.addActionListener(e -> {
+                model.moveUp();
+            });
+            final JButton down = new JButton(ImageProvider.get("dialogs", "down", ImageSizes.LARGEICON));
+            down.setToolTipText(tr("Move the currently selected members down"));
+            down.addActionListener(e -> {
+                model.moveDown();
+            });
+            up.setEnabled(model.canMoveUp());
+            down.setEnabled(model.canMoveDown());
+
+            list.addListSelectionListener(new ListSelectionListener() {
+                @Override
+                public void valueChanged(ListSelectionEvent e) {
+                    up.setEnabled(model.canMoveUp());
+                    down.setEnabled(model.canMoveDown());
+                }
+            });
+
+            JPanel content = new JPanel(new GridBagLayout());
+            content.add(sp, GBC.std(0,0).span(1, 4).fill());
+            content.add(GBC.glue(0, 1), GBC.std(1, 0).fill(GBC.VERTICAL));
+            content.add(up, GBC.std(1, 1));
+            content.add(down, GBC.std(1, 2));
+            content.add(GBC.glue(0, 1), GBC.std(1, 3).fill(GBC.VERTICAL));
+
+            p.add(content, GBC.eol().fill(GBC.HORIZONTAL)); // NOSONAR
+        }
+        else {
+            p.add(sp, GBC.eol().fill(GBC.HORIZONTAL)); // NOSONAR
+        }
 
         list.addListSelectionListener(l -> support.fireItemValueModified(this, key, getSelectedItem().value));
         list.setToolTipText(getKeyTooltipText());
@@ -103,7 +244,104 @@
 
     @Override
     protected PresetListEntry getSelectedItem() {
-        return new PresetListEntry(list.getSelectedValuesList()
-            .stream().map(e -> e.value).distinct().sorted().collect(Collectors.joining(String.valueOf(delimiter))), this);
+         StringBuilder result = new StringBuilder();
+         List<PresetListEntry> temp = list.getSelectedValuesList();
+
+         if (!temp.isEmpty()) {
+             if (values_sort.equals(String.valueOf(true))) {
+                 Collections.sort(temp);
+             }
+
+             if (prefix != null) {
+                 result.append(prefix);
+             }
+
+             result.append(temp.get(0).value);
+
+             for (int i = 1; i < temp.size(); i++) {
+                 if (result.indexOf(temp.get(i).value) == -1) {
+                     result.append(temp.get(i).delimiter != null ? temp.get(i).delimiter : delimiter).append(temp.get(i).value);
+                 }
+             }
+         }
+
+         return new PresetListEntry(result.toString(), this);
+    }
+
+    private final class SingleClickSelectionModel extends DefaultListSelectionModel {
+        private boolean mousePressed;
+        private ListModel<PresetListEntry> model;
+
+        private SingleClickSelectionModel(JList<PresetListEntry> list) {
+            this.model = list.getModel();
+            list.addMouseListener(new MouseAdapter() {
+                @Override
+                public void mousePressed(MouseEvent e) {
+                    mousePressed = true;
+                }
+                @Override
+                public void mouseReleased(MouseEvent e) {
+                    mousePressed = false;
+                }
+            });
+        }
+
+        @Override
+        public void addSelectionInterval(int index0, int index1) {
+            removeSelectionForGroupAtIndex(index0);
+            super.addSelectionInterval(index0, index1);
+        }
+
+        private void removeSelectionForGroupAtIndex(int index) {
+            if(!isSelectedIndex(index)) {
+                int selectGroup = model.getElementAt(index).select_group;
+
+                for(int i = 0; i < model.getSize(); i++) {
+                    if(isSelectedIndex(i) && (selectGroup < 0 || (model.getElementAt(i).select_group != PresetListEntry.SELECT_GROUP_NONE && model.getElementAt(i).select_group == selectGroup) || model.getElementAt(i).select_group < 0)) {
+                        super.removeSelectionInterval(i, i);
+                    }
+                }
+            }
+        }
+
+        @Override
+        public void setSelectionInterval(int index0, int index1) {
+            if (quick_select && getSelectionMode() == MULTIPLE_INTERVAL_SELECTION) {
+                if (!mousePressed) {
+                    if (isSelectedIndex(index0)) {
+                        super.removeSelectionInterval(index0, index1);
+                    }
+                    else {
+                        removeSelectionForGroupAtIndex(index0);
+                        super.addSelectionInterval(index0, index1);
+                    }
+                }
+            }
+            else {
+                super.setSelectionInterval(index0, index1);
+            }
+        }
+    }
+
+    private final class PresetListModel extends DefaultListModel<PresetListEntry> implements ReorderableTableModel<PresetListEntry> {
+        @Override
+        public PresetListEntry getValue(int index) {
+            return get(index);
+        }
+
+        @Override
+        public PresetListEntry setValue(int index, PresetListEntry value) {
+            return set(index, value);
+        }
+
+        @Override
+        public ListSelectionModel getSelectionModel() {
+            return list.getSelectionModel();
+        }
+
+        @Override
+        public int getRowCount() {
+            return size();
+        }
     }
 }
Index: src/org/openstreetmap/josm/gui/tagging/presets/items/PresetListEntry.java
===================================================================
--- src/org/openstreetmap/josm/gui/tagging/presets/items/PresetListEntry.java	(revision 18643)
+++ src/org/openstreetmap/josm/gui/tagging/presets/items/PresetListEntry.java	(working copy)
@@ -21,6 +21,8 @@
  * {@link MultiSelect}.
  */
 public class PresetListEntry implements Comparable<PresetListEntry> {
+    /** Value for entries without a select group*/
+    public static final int SELECT_GROUP_NONE = 0;
     /** Used to display an entry matching several different values. */
     protected static final PresetListEntry ENTRY_DIFFERENT = new PresetListEntry(KeyedItem.DIFFERENT, null);
     /** Used to display an empty entry used to clear values. */
@@ -46,11 +48,16 @@
     public String locale_display_value; // NOSONAR
     /** The localized version of {@link #short_description}. */
     public String locale_short_description; // NOSONAR
+    /** The delimiter for separating this entry from the previous */
+    public String delimiter; // NOSONAR
+    /** The select group for multi select */
+    public int select_group = SELECT_GROUP_NONE;
 
     private String cachedDisplayValue;
     private String cachedShortDescription;
     private ImageIcon cachedIcon;
 
+
     /**
      * Constructs a new {@code PresetListEntry}, uninitialized.
      *
@@ -67,8 +74,22 @@
      * @param cms the ComboMultiSelect
      */
     public PresetListEntry(String value, ComboMultiSelect cms) {
+        this(value, cms, null);
+    }
+
+    /**
+     * Constructs a new {@code PresetListEntry}, initialized with a value and
+     * {@link ComboMultiSelect} context and the delimiter for this entry.
+     *
+     * @param value value
+     * @param cms the ComboMultiSelect
+     * @param delimiter The character to use to separate this entry from the previous
+     * @since 18619
+     */
+    public PresetListEntry(String value, ComboMultiSelect cms, String delimiter) {
         this.value = value;
         this.cms = cms;
+        this.delimiter = delimiter;
     }
 
     /**
Index: src/org/openstreetmap/josm/gui/tagging/presets/items/SelectGroup.java
===================================================================
--- src/org/openstreetmap/josm/gui/tagging/presets/items/SelectGroup.java	(nonexistent)
+++ src/org/openstreetmap/josm/gui/tagging/presets/items/SelectGroup.java	(working copy)
@@ -0,0 +1,32 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.tagging.presets.items;
+
+import java.util.List;
+
+import javax.swing.JPanel;
+
+import org.openstreetmap.josm.data.osm.Tag;
+import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetItem;
+import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetItemGuiSupport;
+
+/**
+ * A group of {@link PresetListEntry}s.
+ * @since 18637
+ */
+public class SelectGroup extends TaggingPresetItem {
+    /** If items in this SelectGroup can only be selected when no item in the complete list is selected */
+    public boolean exclusive = false;
+
+    @Override
+    protected boolean addToPanel(JPanel p, TaggingPresetItemGuiSupport support) {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    protected void addCommands(List<Tag> changedTags) {
+        // TODO Auto-generated method stub
+
+    }
+
+}

Property changes on: src/org/openstreetmap/josm/gui/tagging/presets/items/SelectGroup.java
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
