Index: applications/editors/josm/plugins/smed/src/smed/jide/swing/CheckBoxList.java
===================================================================
--- applications/editors/josm/plugins/smed/src/smed/jide/swing/CheckBoxList.java	(revision 23311)
+++ applications/editors/josm/plugins/smed/src/smed/jide/swing/CheckBoxList.java	(revision 23311)
@@ -0,0 +1,817 @@
+// License: GPL. For details, see LICENSE file.
+// Copyright (c) 2010 by Werner Koenig
+// this is a modified version of CheckBoxList.java,
+// which is part of the jide-oss, see https://jide-oss.dev.java.net
+
+/*
+ * @(#)CheckBoxList.java 4/21/2005
+ *
+ * Copyright 2002 - 2005 JIDE Software Inc. All rights reserved.
+ */
+package smed.jide.swing;
+
+import javax.swing.*;
+import javax.swing.event.ListDataEvent;
+import javax.swing.event.ListDataListener;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.text.Position;
+import java.awt.*;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.*;
+import java.util.List;
+
+/**
+ * <code>CheckBoxList</code> is a special JList which uses JCheckBox as the list element. In addition to regular JList
+ * feature, it also allows you select any number of elements in the list by selecting the check boxes.
+ * <p/>
+ * To select an element, user can mouse click on the check box, or highlight the rows and press SPACE key to toggle the
+ * selections.
+ * <p/>
+ * We used cell renderer feature in JList to add the check box in each row. However you can still set your own cell
+ * renderer just like before using {@link #setCellRenderer(javax.swing.ListCellRenderer)}. CheckBoxList will use your
+ * cell renderer and automatically put a check box before it.
+ * <p/>
+ * The selection state is kept in a ListSelectionModel called CheckBoxListSelectionModel, which you can get using {@link
+ * CheckBoxList#getCheckBoxListSelectionModel()}. If you need to add a check to a check box or to find out if a check
+ * box is checked, you need to ask the getCheckBoxListSelectionModel() by using addListSelectionListener.
+ * <p/>
+ * Please note, we changed CheckBoxList implementation in 1.9.2 release. The old CheckBoxList class is renamed to {@link
+ * CheckBoxListWithSelectable}. If you want to use the old implementation, you can use CheckBoxListWithSelectable
+ * instead. The main difference between the two implementation is at how the selection state is kept. In new
+ * implementation, the selection state is kept at a separate ListSelectionModel which you can get using {@link
+ * CheckBoxList#getCheckBoxListSelectionModel()}. If you need to add a check to a check box or to find out if a check
+ * box is checked, you need to ask the getCheckBoxListSelectionModel() by using addListSelectionListener. The old
+ * implementation kept the selection state at Selectable object in the ListModel. The new implementation also has the
+ * same design as that of {@link CheckBoxTree}.
+ */
+public class CheckBoxList extends JList {
+    /**
+	 * 
+	 */
+	private static final long serialVersionUID = 1L;
+
+	protected CheckBoxListCellRenderer _listCellRenderer;
+
+    public static final String PROPERTY_CHECKBOX_ENABLED = "checkBoxEnabled";
+    public static final String PROPERTY_CLICK_IN_CHECKBOX_ONLY = "clickInCheckBoxOnly";
+
+    private boolean _checkBoxEnabled = true;
+    private boolean _clickInCheckBoxOnly = true;
+
+    private CheckBoxListSelectionModel _checkBoxListSelectionModel;
+    protected Handler _handler;
+
+    /**
+     * Constructs a <code>CheckBoxList</code> with an empty model.
+     */
+    public CheckBoxList() {
+        init();
+    }
+
+    /**
+     * Constructs a <code>CheckBoxList</code> that displays the elements in the specified <code>Vector</code>.
+     *
+     * @param listData the <code>Vector</code> to be loaded into the data model
+     */
+    public CheckBoxList(final Vector<?> listData) {
+        super(listData);
+        init();
+    }
+
+    /**
+     * Constructs a <code>CheckBoxList</code> that displays the elements in the specified <code>Object[]</code>.
+     *
+     * @param listData the array of Objects to be loaded into the data model
+     */
+    public CheckBoxList(final Object[] listData) {
+        super(listData);
+        init();
+    }
+
+    /**
+     * Constructs a <code>CheckBoxList</code> that displays the elements in the specified, non-<code>null</code> model.
+     * All <code>CheckBoxList</code> constructors delegate to this one.
+     * <p/>
+     *
+     * @param dataModel the data model for this list
+     * @throws IllegalArgumentException if <code>dataModel</code> is <code>null</code>
+     */
+    public CheckBoxList(ListModel dataModel) {
+        super(dataModel);
+        init();
+    }
+
+    @Override
+    public void setModel(ListModel model) {
+        super.setModel(model);
+        if (getCheckBoxListSelectionModel() != null) {
+            getCheckBoxListSelectionModel().clearSelection();
+        }
+    }
+
+    /**
+     * Initialize the CheckBoxList.
+     */
+    protected void init() {
+        _checkBoxListSelectionModel = createCheckBoxListSelectionModel(getModel());
+        setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
+        _listCellRenderer = createCellRenderer();
+        _handler = createHandler();
+        _checkBoxListSelectionModel.addListSelectionListener(_handler);
+        JideSwingUtilities.insertMouseListener(this, _handler, 0);
+        addKeyListener(_handler);
+        addPropertyChangeListener("model", _handler);
+        ListModel model = getModel();
+        if (model != null) {
+            model.addListDataListener(_handler);
+        }
+    }
+
+    @Override
+    public int getLastVisibleIndex() {
+        int visibleIndex = super.getLastVisibleIndex();
+        if (visibleIndex < 0) {
+            return getModel().getSize() - 1;
+        }
+        return visibleIndex;
+    }
+
+    protected CheckBoxListSelectionModel createCheckBoxListSelectionModel(ListModel model) {
+        return new CheckBoxListSelectionModel(model);
+    }
+
+    /**
+     * Creates the cell renderer.
+     *
+     * @return the cell renderer.
+     */
+    protected CheckBoxListCellRenderer createCellRenderer() {
+        return new CheckBoxListCellRenderer();
+    }
+
+    /**
+     * Creates the mouse listener and key listener used by CheckBoxList.
+     *
+     * @return the Handler.
+     */
+    protected Handler createHandler() {
+        return new Handler(this);
+    }
+
+    @Override
+    public ListCellRenderer getCellRenderer() {
+        if (_listCellRenderer != null) {
+            _listCellRenderer.setActualListRenderer(super.getCellRenderer());
+            return _listCellRenderer;
+        }
+        else {
+            return super.getCellRenderer();
+        }
+    }
+
+    public ListCellRenderer getActualCellRenderer() {
+        return super.getCellRenderer();
+    }
+
+    protected static class Handler implements MouseListener, KeyListener, ListSelectionListener, PropertyChangeListener, ListDataListener {
+        protected CheckBoxList _list;
+        int hotspot = new JCheckBox().getPreferredSize().width;
+
+
+        public Handler(CheckBoxList list) {
+            _list = list;
+        }
+
+        public void propertyChange(PropertyChangeEvent evt) {
+            if (evt.getOldValue() instanceof ListModel) {
+                ((ListModel) evt.getOldValue()).removeListDataListener(this);
+            }
+            if (evt.getNewValue() instanceof ListModel) {
+                _list.getCheckBoxListSelectionModel().setModel((ListModel) evt.getNewValue());
+                ((ListModel) evt.getNewValue()).addListDataListener(this);
+            }
+        }
+
+        protected boolean clicksInCheckBox(MouseEvent e) {
+            int index = _list.locationToIndex(e.getPoint());
+            Rectangle bounds = _list.getCellBounds(index, index);
+
+            if (bounds != null) {
+                if (_list.getComponentOrientation().isLeftToRight()) {
+                    return e.getX() < bounds.x + hotspot;
+                }
+                else {
+                    return e.getX() > bounds.x + bounds.width - hotspot;
+                }
+            }
+            else {
+                return false;
+            }
+        }
+
+        public void mouseClicked(MouseEvent e) {
+        }
+
+        public void mousePressed(MouseEvent e) {
+            if (e.isConsumed()) {
+                return;
+            }
+
+            if (!_list.isCheckBoxEnabled()) {
+                return;
+            }
+
+            if (!_list.isClickInCheckBoxOnly() || clicksInCheckBox(e)) {
+                int index = _list.locationToIndex(e.getPoint());
+                toggleSelection(index);
+                e.consume();
+            }
+        }
+
+        public void mouseReleased(MouseEvent e) {
+            if (e.isConsumed()) {
+                return;
+            }
+
+            if (!_list.isCheckBoxEnabled()) {
+                return;
+            }
+
+            if (!_list.isClickInCheckBoxOnly() || clicksInCheckBox(e)) {
+                e.consume();
+            }
+        }
+
+        public void mouseEntered(MouseEvent e) {
+        }
+
+        public void mouseExited(MouseEvent e) {
+        }
+
+        public void keyPressed(KeyEvent e) {
+            if (e.isConsumed()) {
+                return;
+            }
+
+            if (!_list.isCheckBoxEnabled()) {
+                return;
+            }
+
+            if (e.getModifiers() == 0 && e.getKeyChar() == KeyEvent.VK_SPACE)
+                toggleSelections();
+        }
+
+        public void keyTyped(KeyEvent e) {
+        }
+
+        public void keyReleased(KeyEvent e) {
+        }
+
+        protected void toggleSelections() {
+            int[] indices = _list.getSelectedIndices();
+            CheckBoxListSelectionModel selectionModel = _list.getCheckBoxListSelectionModel();
+            selectionModel.removeListSelectionListener(this);
+            selectionModel.setValueIsAdjusting(true);
+            try {
+                if (indices.length > 0) {
+                    boolean selected = selectionModel.isSelectedIndex(indices[0]);
+                    for (int index : indices) {
+                        if (!_list.isCheckBoxEnabled(index)) {
+                            continue;
+                        }
+                        if (selected && selectionModel.isSelectedIndex(index)) {
+                            selectionModel.removeSelectionInterval(index, index);
+                        }
+                        else if (!selected && !selectionModel.isSelectedIndex(index)) {
+                            selectionModel.addSelectionInterval(index, index);
+                        }
+                    }
+                }
+            }
+            finally {
+                selectionModel.setValueIsAdjusting(false);
+                selectionModel.addListSelectionListener(this);
+                _list.repaint();
+            }
+        }
+
+
+        public void valueChanged(ListSelectionEvent e) {
+            _list.repaint();
+        }
+
+        protected void toggleSelection(int index) {
+            if (!_list.isEnabled() || !_list.isCheckBoxEnabled(index)) {
+                return;
+            }
+
+            CheckBoxListSelectionModel selectionModel = _list.getCheckBoxListSelectionModel();
+            boolean selected = selectionModel.isSelectedIndex(index);
+            selectionModel.removeListSelectionListener(this);
+            try {
+                if (selected)
+                    selectionModel.removeSelectionInterval(index, index);
+                else
+                    selectionModel.addSelectionInterval(index, index);
+            }
+            finally {
+                selectionModel.addListSelectionListener(this);
+                _list.repaint();
+            }
+        }
+
+        protected void toggleSelection() {
+            int index = _list.getSelectedIndex();
+            toggleSelection(index);
+        }
+
+        public void intervalAdded(ListDataEvent e) {
+            int minIndex = Math.min(e.getIndex0(), e.getIndex1());
+            int maxIndex = Math.max(e.getIndex0(), e.getIndex1());
+
+            /* Sync the SelectionModel with the DataModel.
+             */
+
+            ListSelectionModel listSelectionModel = _list.getCheckBoxListSelectionModel();
+            if (listSelectionModel != null) {
+                listSelectionModel.insertIndexInterval(minIndex, maxIndex - minIndex + 1, true);
+            }
+        }
+
+
+        public void intervalRemoved(ListDataEvent e) {
+            /* Sync the SelectionModel with the DataModel.
+             */
+            ListSelectionModel listSelectionModel = _list.getCheckBoxListSelectionModel();
+            if (listSelectionModel != null) {
+                listSelectionModel.removeIndexInterval(e.getIndex0(), e.getIndex1());
+            }
+        }
+
+
+        public void contentsChanged(ListDataEvent e) {
+        }
+    }
+
+    @Override
+    public int getNextMatch(String prefix, int startIndex, Position.Bias bias) {
+        return -1;
+    }
+
+    /**
+     * Checks if check box is enabled. There is no setter for it. The only way is to override this method to return true
+     * or false.
+     *
+     * @param index the row index.
+     * @return true or false. If false, the check box on the particular row index will be disabled.
+     */
+    public boolean isCheckBoxEnabled(int index) {
+        return true;
+    }
+
+    /**
+     * Checks if check box is visible. There is no setter for it. The only way is to override this method to return true
+     * or false.
+     *
+     * @param index whether the check box on the row index is visible.
+     * @return true or false. If false, there is not check box on the particular row index. By default, we always return
+     *         true. You override this method to return true of false depending on your need.
+     */
+    @SuppressWarnings({"UnusedDeclaration"})
+    public boolean isCheckBoxVisible(int index) {
+        return true;
+    }
+
+    /**
+     * Gets the value of property checkBoxEnabled. If true, user can click on check boxes on each tree node to select
+     * and deselect. If false, user can't click but you as developer can programmatically call API to select/deselect
+     * it.
+     *
+     * @return the value of property checkBoxEnabled.
+     */
+    public boolean isCheckBoxEnabled() {
+        return _checkBoxEnabled;
+    }
+
+    /**
+     * Sets the value of property checkBoxEnabled.
+     *
+     * @param checkBoxEnabled true to allow to check the check box. False to disable it which means user can see whether
+     *                        a row is checked or not but they cannot change it.
+     */
+    public void setCheckBoxEnabled(boolean checkBoxEnabled) {
+        if (checkBoxEnabled != _checkBoxEnabled) {
+            boolean old = _checkBoxEnabled;
+            _checkBoxEnabled = checkBoxEnabled;
+            firePropertyChange(PROPERTY_CHECKBOX_ENABLED, old, _checkBoxEnabled);
+            repaint();
+        }
+    }
+
+    /**
+     * Gets the value of property clickInCheckBoxOnly. If true, user can click on check boxes on each tree node to
+     * select and deselect. If false, user can't click but you as developer can programmatically call API to
+     * select/deselect it.
+     *
+     * @return the value of property clickInCheckBoxOnly.
+     */
+    public boolean isClickInCheckBoxOnly() {
+        return _clickInCheckBoxOnly;
+    }
+
+    /**
+     * Sets the value of property clickInCheckBoxOnly.
+     *
+     * @param clickInCheckBoxOnly true to allow to check the check box. False to disable it which means user can see
+     *                            whether a row is checked or not but they cannot change it.
+     */
+    public void setClickInCheckBoxOnly(boolean clickInCheckBoxOnly) {
+        if (clickInCheckBoxOnly != _clickInCheckBoxOnly) {
+            boolean old = _clickInCheckBoxOnly;
+            _clickInCheckBoxOnly = clickInCheckBoxOnly;
+            firePropertyChange(PROPERTY_CLICK_IN_CHECKBOX_ONLY, old, _clickInCheckBoxOnly);
+        }
+    }
+
+    /**
+     * Gets the ListSelectionModel that keeps the check boxes' state information for CheckBoxList.
+     *
+     * @return the ListSelectionModel that keeps the check boxes' state information for CheckBoxList.
+     */
+    public CheckBoxListSelectionModel getCheckBoxListSelectionModel() {
+        return _checkBoxListSelectionModel;
+    }
+
+    public void setCheckBoxListSelectionModel(CheckBoxListSelectionModel checkBoxListSelectionModel) {
+        _checkBoxListSelectionModel = checkBoxListSelectionModel;
+        _checkBoxListSelectionModel.setModel(getModel());
+    }
+
+    /**
+     * Returns an array of all of the selected indices in increasing order.
+     *
+     * @return all of the selected indices, in increasing order
+     *
+     * @see #removeSelectionInterval
+     * @see #addListSelectionListener
+     */
+    public int[] getCheckBoxListSelectedIndices() {
+        ListSelectionModel listSelectionModel = getCheckBoxListSelectionModel();
+        int iMin = listSelectionModel.getMinSelectionIndex();
+        int iMax = listSelectionModel.getMaxSelectionIndex();
+
+        if ((iMin < 0) || (iMax < 0)) {
+            return new int[0];
+        }
+
+        int[] temp = new int[1 + (iMax - iMin)];
+        int n = 0;
+        for (int i = iMin; i <= iMax; i++) {
+            if (listSelectionModel.isSelectedIndex(i)) {
+                temp[n] = i;
+                n++;
+            }
+        }
+        int[] indices = new int[n];
+        System.arraycopy(temp, 0, indices, 0, n);
+        return indices;
+    }
+
+
+    /**
+     * Selects a single cell and clear all other selections.
+     *
+     * @param index the index of the one cell to select
+     * @see ListSelectionModel#setSelectionInterval
+     * @see #isSelectedIndex
+     * @see #addListSelectionListener
+     */
+    public void setCheckBoxListSelectedIndex(int index) {
+        if (index >= 0 && index < getModel().getSize()) {
+            getCheckBoxListSelectionModel().setSelectionInterval(index, index);
+        }
+    }
+
+    /**
+     * Selects a single cell and keeps all previous selections.
+     *
+     * @param index the index of the one cell to select
+     * @see ListSelectionModel#setSelectionInterval
+     * @see #isSelectedIndex
+     * @see #addListSelectionListener
+     */
+    public void addCheckBoxListSelectedIndex(int index) {
+        if (index >= 0 && index < getModel().getSize()) {
+            getCheckBoxListSelectionModel().addSelectionInterval(index, index);
+        }
+    }
+
+    /**
+     * Deselects a single cell.
+     *
+     * @param index the index of the one cell to select
+     * @see ListSelectionModel#setSelectionInterval
+     * @see #isSelectedIndex
+     * @see #addListSelectionListener
+     */
+    public void removeCheckBoxListSelectedIndex(int index) {
+        if (index >= 0 && index < getModel().getSize()) {
+            getCheckBoxListSelectionModel().removeSelectionInterval(index, index);
+        }
+    }
+
+    /**
+     * Selects a set of cells.
+     *
+     * @param indices an array of the indices of the cells to select
+     * @see ListSelectionModel#addSelectionInterval
+     * @see #isSelectedIndex
+     * @see #addListSelectionListener
+     */
+    public void setCheckBoxListSelectedIndices(int[] indices) {
+        ListSelectionModel listSelectionModel = getCheckBoxListSelectionModel();
+        try {
+            listSelectionModel.setValueIsAdjusting(true);
+            listSelectionModel.clearSelection();
+            int size = getModel().getSize();
+            for (int indice : indices) {
+                if (indice >= 0 && indice < size) {
+                    listSelectionModel.addSelectionInterval(indice, indice);
+                }
+            }
+        }
+        finally {
+            listSelectionModel.setValueIsAdjusting(false);
+        }
+    }
+
+    /**
+     * Sets the selected elements.
+     *
+     * @param elements sets the select elements. All the rows that have the value in the array will be checked.
+     */
+    public void setSelectedObjects(Object[] elements) {
+        Map<Object, String> selected = new HashMap<Object, String>();
+        for (Object element : elements) {
+            selected.put(element, "");
+        }
+        setSelectedObjects(selected);
+    }
+
+    /**
+     * Sets the selected elements.
+     *
+     * @param elements sets the select elements. All the rows that have the value in the Vector will be checked.
+     */
+    public void setSelectedObjects(Vector<?> elements) {
+        Map<Object, String> selected = new HashMap<Object, String>();
+        for (Object element : elements) {
+            selected.put(element, "");
+        }
+        setSelectedObjects(selected);
+    }
+
+    private void setSelectedObjects(Map<Object, String> selected) {
+        List<Integer> indices = new ArrayList<Integer>();
+        for (int i = 0; i < getModel().getSize(); i++) {
+            Object elementAt = getModel().getElementAt(i);
+            if (selected.get(elementAt) != null) {
+                indices.add(i);
+            }
+        }
+        int[] selectedIndices = new int[indices.size()];
+        for (int i = 0; i < indices.size(); i++) {
+            Integer row = indices.get(i);
+            selectedIndices[i] = row;
+        }
+        setCheckBoxListSelectedIndices(selectedIndices);
+    }
+
+    /**
+     * Returns an array of the values for the selected cells. The returned values are sorted in increasing index order.
+     *
+     * @return the selected values or an empty list if nothing is selected
+     *
+     * @see #isSelectedIndex
+     * @see #getModel
+     * @see #addListSelectionListener
+     */
+    public Object[] getCheckBoxListSelectedValues() {
+        ListSelectionModel listSelectionModel = getCheckBoxListSelectionModel();
+        ListModel model = getModel();
+
+        int iMin = listSelectionModel.getMinSelectionIndex();
+        int iMax = listSelectionModel.getMaxSelectionIndex();
+
+        if ((iMin < 0) || (iMax < 0)) {
+            return new Object[0];
+        }
+
+        Object[] temp = new Object[1 + (iMax - iMin)];
+        int n = 0;
+        for (int i = iMin; i <= iMax; i++) {
+            if (listSelectionModel.isSelectedIndex(i)) {
+                temp[n] = model.getElementAt(i);
+                n++;
+            }
+        }
+        Object[] indices = new Object[n];
+        System.arraycopy(temp, 0, indices, 0, n);
+        return indices;
+    }
+
+
+    /**
+     * Returns the first selected index; returns -1 if there is no selected item.
+     *
+     * @return the value of <code>getMinSelectionIndex</code>
+     *
+     * @see #getMinSelectionIndex
+     * @see #addListSelectionListener
+     */
+    public int getCheckBoxListSelectedIndex() {
+        return getCheckBoxListSelectionModel().getMinSelectionIndex();
+    }
+
+
+    /**
+     * Returns the first selected value, or <code>null</code> if the selection is empty.
+     *
+     * @return the first selected value
+     *
+     * @see #getMinSelectionIndex
+     * @see #getModel
+     * @see #addListSelectionListener
+     */
+    public Object getCheckBoxListSelectedValue() {
+        int i = getCheckBoxListSelectionModel().getMinSelectionIndex();
+        return (i == -1) ? null : getModel().getElementAt(i);
+    }
+
+    /**
+     * Selects the specified object from the list and clear all other selections.
+     *
+     * @param anObject     the object to select
+     * @param shouldScroll true if the list should scroll to display the selected object, if one exists; otherwise
+     *                     false
+     */
+    public void setCheckBoxListSelectedValue(Object anObject, boolean shouldScroll) {
+        if (anObject == null)
+            setSelectedIndex(-1);
+        else {
+            int i, c;
+            ListModel model = getModel();
+            for (i = 0, c = model.getSize(); i < c; i++)
+                if (anObject.equals(model.getElementAt(i))) {
+                    setCheckBoxListSelectedIndex(i);
+                    if (shouldScroll)
+                        ensureIndexIsVisible(i);
+                    repaint();  /** FIX-ME setSelectedIndex does not redraw all the time with the basic l&f**/
+                    return;
+                }
+            setCheckBoxListSelectedIndex(-1);
+        }
+        repaint(); /** FIX-ME setSelectedIndex does not redraw all the time with the basic l&f**/
+    }
+
+    /**
+     * Selects the specified object from the list and keep all previous selections.
+     *
+     * @param anObject     the object to be selected
+     * @param shouldScroll true if the list should scroll to display the selected object, if one exists; otherwise
+     *                     false
+     */
+    public void addCheckBoxListSelectedValue(Object anObject, boolean shouldScroll) {
+        ListModel model = getModel();
+        int i, c;
+        if (anObject != null) {
+            for (i = 0, c = model.getSize(); i < c; i++)
+                if (anObject.equals(model.getElementAt(i))) {
+                    addCheckBoxListSelectedIndex(i);
+                    if (shouldScroll)
+                        ensureIndexIsVisible(i);
+                    repaint();  /** FIX-ME setSelectedIndex does not redraw all the time with the basic l&f**/
+                    return;
+                }
+        }
+        else {
+            for (i = 0, c = model.getSize(); i < c; i++) {
+                if (model.getElementAt(i) == null) {
+                    addCheckBoxListSelectedIndex(i);
+                    if (shouldScroll)
+                        ensureIndexIsVisible(i);
+                    repaint();  /** FIX-ME setSelectedIndex does not redraw all the time with the basic l&f**/
+                    return;
+                }
+            }
+        }
+    }
+
+    /**
+     * Selects the specified objects from the list and keep all previous selections.
+     *
+     * @param objects the objects to be selected
+     */
+    public void addCheckBoxListSelectedValues(Object[] objects) {
+        if (objects != null) {
+            Map<Object, String> map = new HashMap<Object, String>();
+            for (Object o : objects) {
+                map.put(o, "");
+            }
+            int i, c;
+            ListModel model = getModel();
+            boolean changed = false;
+            for (i = 0, c = model.getSize(); i < c; i++)
+                if (map.get(model.getElementAt(i)) != null) {
+                    addCheckBoxListSelectedIndex(i);
+                    changed = true;
+                }
+            if (changed) {
+                repaint();
+            }
+            map.clear();
+        }
+    }
+
+    /**
+     * Deselects the specified objects from the list and keep all previous selections.
+     *
+     * @param objects the objects to be selected
+     */
+    public void removeCheckBoxListSelectedValues(Object[] objects) {
+        if (objects != null) {
+            Map<Object, String> map = new HashMap<Object, String>();
+            for (Object o : objects) {
+                map.put(o, "");
+            }
+            int i, c;
+            ListModel model = getModel();
+            boolean changed = false;
+            for (i = 0, c = model.getSize(); i < c; i++)
+                if (map.get(model.getElementAt(i)) != null) {
+                    removeCheckBoxListSelectedIndex(i);
+                    changed = true;
+                }
+            if (changed) {
+                repaint();
+            }
+            map.clear();
+        }
+    }
+
+    /**
+     * Deselects the specified object from the list.
+     *
+     * @param anObject     the object to select
+     * @param shouldScroll true if the list should scroll to display the selected object, if one exists; otherwise
+     *                     false
+     */
+    public void removeCheckBoxListSelectedValue(Object anObject, boolean shouldScroll) {
+        if (anObject != null) {
+            int i, c;
+            ListModel model = getModel();
+            for (i = 0, c = model.getSize(); i < c; i++)
+                if (anObject.equals(model.getElementAt(i))) {
+                    removeCheckBoxListSelectedIndex(i);
+                    if (shouldScroll)
+                        ensureIndexIsVisible(i);
+                    repaint();  /** FIX-ME setSelectedIndex does not redraw all the time with the basic l&f**/
+                    return;
+                }
+        }
+    }
+
+    public void clearCheckBoxListSelection() {
+        getCheckBoxListSelectionModel().clearSelection();
+    }
+
+    /**
+     * Selects all objects in this list.
+     */
+    public void selectAll() {
+        if (getModel().getSize() > 0) {
+            getCheckBoxListSelectionModel().setSelectionInterval(0, getModel().getSize() - 1);
+        }
+    }
+
+    /**
+     * Deselects all objects in this list.
+     */
+    public void selectNone() {
+        if (getModel().getSize() > 0) {
+            getCheckBoxListSelectionModel().removeIndexInterval(0, getModel().getSize() - 1);
+        }
+    }
+
+    @Override
+    public Dimension getPreferredScrollableViewportSize() {
+        return JideSwingUtilities.adjustPreferredScrollableViewportSize(this, super.getPreferredScrollableViewportSize());
+
+    }
+}
Index: applications/editors/josm/plugins/smed/src/smed/jide/swing/CheckBoxListCellRenderer.java
===================================================================
--- applications/editors/josm/plugins/smed/src/smed/jide/swing/CheckBoxListCellRenderer.java	(revision 23311)
+++ applications/editors/josm/plugins/smed/src/smed/jide/swing/CheckBoxListCellRenderer.java	(revision 23311)
@@ -0,0 +1,221 @@
+// License: GPL. For details, see LICENSE file.
+// Copyright (c) 2010 by Werner Koenig
+// this is a modified version of CheckBoxList.java,
+// which is part of the jide-oss, see https://jide-oss.dev.java.net
+
+/*
+ * @(#)CheckBoxtListCellRenderer.java 5/11/2005
+ *
+ * Copyright 2002 - 2005 JIDE Software Inc. All rights reserved.
+ */
+
+package smed.jide.swing;
+
+import javax.swing.*;
+import javax.swing.border.Border;
+import java.awt.*;
+import java.awt.event.MouseEvent;
+import java.io.Serializable;
+
+
+/**
+ * Renders an item in a list using JCheckBox.
+ */
+public class CheckBoxListCellRenderer extends JPanel implements ListCellRenderer, Serializable {
+    private static final long serialVersionUID = 2003073492549917883L;
+
+    /**
+     * The checkbox that is used to paint the check box in cell renderer
+     */
+    protected JCheckBox _checkBox = new NullCheckBox();
+    protected JLabel _label = new NullLabel();
+
+    /**
+     * The label which appears after the check box.
+     */
+    protected ListCellRenderer _actualListRenderer;
+
+    public CheckBoxListCellRenderer(ListCellRenderer renderer) {
+        setOpaque(true);
+        setLayout(new BorderLayout(0, 0));
+        add(_checkBox, BorderLayout.BEFORE_LINE_BEGINS);
+        _actualListRenderer = renderer;
+    }
+
+    /**
+     * Constructs a default renderer object for an item in a list.
+     */
+    public CheckBoxListCellRenderer() {
+        this(null);
+    }
+
+    public ListCellRenderer getActualListRenderer() {
+        return _actualListRenderer;
+    }
+
+    public void setActualListRenderer(ListCellRenderer actualListRenderer) {
+        _actualListRenderer = actualListRenderer;
+    }
+
+    @Override
+    public String getToolTipText(MouseEvent event) {
+        if (_actualListRenderer instanceof JComponent) {
+            Point p = event.getPoint();
+            p.translate(-_checkBox.getWidth(), 0);
+            MouseEvent newEvent = new MouseEvent(((JComponent) _actualListRenderer), event.getID(),
+                    event.getWhen(),
+                    event.getModifiers(),
+                    p.x, p.y, event.getClickCount(),
+                    event.isPopupTrigger());
+
+            String tip = ((JComponent) _actualListRenderer).getToolTipText(
+                    newEvent);
+
+            if (tip != null) {
+                return tip;
+            }
+        }
+        return super.getToolTipText(event);
+    }
+
+    public Component getListCellRendererComponent(JList list,
+                                                  Object value,
+                                                  int index,
+                                                  boolean isSelected,
+                                                  boolean cellHasFocus) {
+
+        _checkBox.setPreferredSize(new Dimension(_checkBox.getPreferredSize().width, 0));
+        applyComponentOrientation(list.getComponentOrientation());
+
+        Object actualValue;
+        if (list instanceof CheckBoxList) {
+            CheckBoxListSelectionModel selectionModel = ((CheckBoxList) list).getCheckBoxListSelectionModel();
+            if (selectionModel != null) {
+                boolean enabled = list.isEnabled()
+                        && ((CheckBoxList) list).isCheckBoxEnabled()
+                        && ((CheckBoxList) list).isCheckBoxEnabled(index);
+                if (!enabled && !isSelected) {
+                    if (getBackground() != null) {
+                        setForeground(getBackground().darker());
+                    }
+                }
+                _checkBox.setEnabled(enabled);
+                _checkBox.setSelected(selectionModel.isSelectedIndex(index));
+            }
+            actualValue = value;
+        }
+        /* working only with version 1.9.2 and higher
+         * CheckBoxListWithSelectable isn't needed longer
+        else if (list instanceof CheckBoxListWithSelectable) {
+            if (value instanceof Selectable) {
+                _checkBox.setSelected(((Selectable) value).isSelected());
+                boolean enabled = list.isEnabled() && ((Selectable) value).isEnabled() && ((CheckBoxListWithSelectable) list).isCheckBoxEnabled();
+                if (!enabled && !isSelected) {
+                    setForeground(getBackground().darker());
+                }
+                _checkBox.setEnabled(enabled);
+            }
+            else {
+                boolean enabled = list.isEnabled();
+                if (!enabled && !isSelected) {
+                    setForeground(getBackground().darker());
+                }
+                _checkBox.setEnabled(enabled);
+            }
+
+            if (value instanceof DefaultSelectable) {
+                actualValue = ((DefaultSelectable) value).getObject();
+            }
+            else {
+                actualValue = value;
+            }
+        }
+        */
+        else {
+            throw new IllegalArgumentException("CheckBoxListCellRenderer should only be used for CheckBoxList.");
+        }
+
+        if (_actualListRenderer != null) {
+            JComponent listCellRendererComponent = (JComponent) _actualListRenderer.getListCellRendererComponent(list, actualValue, index, isSelected, cellHasFocus);
+            /* working only with version 1.9.2 and higher
+             * * CheckBoxListWithSelectable isn't needed longer
+            if (list instanceof CheckBoxListWithSelectable) {
+                if (!((CheckBoxListWithSelectable) list).isCheckBoxVisible(index)) {
+                    return listCellRendererComponent;
+                }
+            }
+            */
+            if (list instanceof CheckBoxList) {
+                if (!((CheckBoxList) list).isCheckBoxVisible(index)) {
+                    return listCellRendererComponent;
+                }
+            }
+            Border border = listCellRendererComponent.getBorder();
+            setBorder(border);
+            listCellRendererComponent.setBorder(BorderFactory.createEmptyBorder());
+            if (getComponentCount() == 2) {
+                remove(1);
+            }
+            add(listCellRendererComponent);
+            setBackground(listCellRendererComponent.getBackground());
+            setForeground(listCellRendererComponent.getForeground());
+        }
+        else {
+            if (isSelected) {
+                setBackground(list.getSelectionBackground());
+                setForeground(list.getSelectionForeground());
+            }
+            else {
+                setBackground(list.getBackground());
+                setForeground(list.getForeground());
+            }
+            if (getComponentCount() == 2) {
+                remove(1);
+            }
+            add(_label);
+            customizeDefaultCellRenderer(actualValue);
+            setFont(list.getFont());
+        }
+
+        return this;
+    }
+
+    /**
+     * Customizes the cell renderer. By default, it will use toString to covert the object and use it as the text for
+     * the checkbox. You can subclass it to set an icon, change alignment etc. Since "this" is a JCheckBox, you can call
+     * all methods available on JCheckBox in the overridden method.
+     *
+     * @param value the value on the cell renderer.
+     */
+    protected void customizeDefaultCellRenderer(Object value) {
+        if (value instanceof Icon) {
+            _label.setIcon((Icon) value);
+            _label.setText("");
+        }
+        else {
+            _label.setIcon(null);
+            _label.setText((value == null) ? "" : value.toString());
+        }
+    }
+
+
+    /**
+     * A subclass of DefaultListCellRenderer that implements UIResource. DefaultListCellRenderer doesn't implement
+     * UIResource directly so that applications can safely override the cellRenderer property with
+     * DefaultListCellRenderer subclasses.
+     * <p/>
+     * <strong>Warning:</strong> Serialized objects of this class will not be compatible with future Swing releases. The
+     * current serialization support is appropriate for short term storage or RMI between applications running the same
+     * version of Swing.  As of 1.4, support for long term storage of all JavaBeans<sup><font size="-2">TM</font></sup>
+     * has been added to the <code>java.beans</code> package. Please see {@link java.beans.XMLEncoder}.
+     */
+    public static class UIResource extends CheckBoxListCellRenderer
+            implements javax.swing.plaf.UIResource {
+
+		/**
+		 * 
+		 */
+		private static final long serialVersionUID = 1L;
+    }
+
+}
Index: applications/editors/josm/plugins/smed/src/smed/jide/swing/CheckBoxListSelectionModel.java
===================================================================
--- applications/editors/josm/plugins/smed/src/smed/jide/swing/CheckBoxListSelectionModel.java	(revision 23311)
+++ applications/editors/josm/plugins/smed/src/smed/jide/swing/CheckBoxListSelectionModel.java	(revision 23311)
@@ -0,0 +1,75 @@
+// License: GPL. For details, see LICENSE file.
+// Copyright (c) 2010 by Werner Koenig
+// this is a modified version of CheckBoxListSelectionModel.java,
+// which is part of the jide-oss, see https://jide-oss.dev.java.net
+
+
+package smed.jide.swing;
+
+import javax.swing.*;
+
+public class CheckBoxListSelectionModel extends DefaultListSelectionModel {
+    /**
+	 * 
+	 */
+	private static final long serialVersionUID = 1L;
+	private ListModel _model;
+
+    public CheckBoxListSelectionModel() {
+        setSelectionMode(MULTIPLE_INTERVAL_SELECTION);
+    }
+
+    public CheckBoxListSelectionModel(ListModel model) {
+        _model = model;
+        setSelectionMode(MULTIPLE_INTERVAL_SELECTION);
+    }
+
+    public ListModel getModel() {
+        return _model;
+    }
+
+    public void setModel(ListModel model) {
+        int oldLength = 0;
+        int newLength = 0;
+        if (_model != null) {
+            oldLength = _model.getSize();
+        }
+        _model = model;
+        if (_model != null) {
+            newLength = _model.getSize();
+        }
+        if (oldLength > newLength) {
+            removeIndexInterval(newLength, oldLength);
+        }
+    }
+
+    /**
+     * Overrides so that inserting a row will not be selected automatically if the row after it is selected.
+     *
+     * @param index  the index where the rows will be inserted.
+     * @param length the number of the rows that will be inserted.
+     * @param before it's before or after the index.
+     */
+    @Override
+    public void insertIndexInterval(int index, int length, boolean before) {
+        if (before) {
+            boolean old = isSelectedIndex(index);
+            super.setValueIsAdjusting(true);
+            try {
+                if (old) {
+                    removeSelectionInterval(index, index);
+                }
+                super.insertIndexInterval(index, length, before);
+                if (old) {
+                    addSelectionInterval(index + length, index + length);
+                }
+            }
+            finally {
+                super.setValueIsAdjusting(false);
+            }
+        }
+        else {
+            super.insertIndexInterval(index, length, before);
+        }
+    }
+}
Index: applications/editors/josm/plugins/smed/src/smed/jide/swing/JideSwingUtilities.java
===================================================================
--- applications/editors/josm/plugins/smed/src/smed/jide/swing/JideSwingUtilities.java	(revision 23311)
+++ applications/editors/josm/plugins/smed/src/smed/jide/swing/JideSwingUtilities.java	(revision 23311)
@@ -0,0 +1,224 @@
+package smed.jide.swing;
+
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Rectangle;
+import java.awt.event.MouseListener;
+import java.security.AccessControlException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.swing.JList;
+import javax.swing.ListCellRenderer;
+
+public class JideSwingUtilities {
+
+    /**
+     * Inserts the mouse listener at the particular index in the listeners' chain.
+     *
+     * @param component
+     * @param l
+     * @param index
+     */
+    public static void insertMouseListener(Component component, MouseListener l, int index) {
+        MouseListener[] listeners = component.getMouseListeners();
+        for (MouseListener listener : listeners) {
+            component.removeMouseListener(listener);
+        }
+        for (int i = 0; i < listeners.length; i++) {
+            MouseListener listener = listeners[i];
+            if (index == i) {
+                component.addMouseListener(l);
+            }
+            component.addMouseListener(listener);
+        }
+        // index is too large, add to the end.
+        if (index < 0 || index > listeners.length - 1) {
+            component.addMouseListener(l);
+        }
+    }
+    /**
+     * This method can be used to fix two JDK bugs. One is to fix the row height is wrong when the first element in the
+     * model is null or empty string. The second bug is only on JDK1.4.2 where the vertical scroll bar is shown even all
+     * rows are visible. To use it, you just need to override JList#getPreferredScrollableViewportSize and call this
+     * method.
+     * <pre><code>
+     * public Dimension getPreferredScrollableViewportSize() {
+     *    return JideSwingUtilities.adjustPreferredScrollableViewportSize(this, super.getPreferredScrollableViewportSize());
+     * }
+     * <p/>
+     * </code></pre>
+     *
+     * @param list                the JList
+     * @param defaultViewportSize the default viewport size from JList#getPreferredScrollableViewportSize().
+     * @return the adjusted size.
+     */
+    public static Dimension adjustPreferredScrollableViewportSize(JList list, Dimension defaultViewportSize) {
+        // workaround the bug that the list is tiny when the first element is empty
+        Rectangle cellBonds = list.getCellBounds(0, 0);
+        if (cellBonds != null && cellBonds.height < 3) {
+            ListCellRenderer renderer = list.getCellRenderer();
+            if (renderer != null) {
+                Component c = renderer.getListCellRendererComponent(list, "DUMMY STRING", 0, false, false);
+                if (c != null) {
+                    Dimension preferredSize = c.getPreferredSize();
+                    if (preferredSize != null) {
+                        int height = preferredSize.height;
+                        if (height < 3) {
+                            try {
+                                height = list.getCellBounds(1, 1).height;
+                            }
+                            catch (Exception e) {
+                                height = 16;
+                            }
+                        }
+                        list.setFixedCellHeight(height);
+                    }
+                }
+            }
+        }
+        if (/*SystemInfo.*/isJdk15Above()) {
+            return defaultViewportSize;
+        }
+        else {
+            // in JDK1.4.2, the vertical scroll bar is shown because of the wrong size is calculated.
+            defaultViewportSize.height++;
+            return defaultViewportSize;
+        }
+    }
+    
+    private static JavaVersion _currentVersion;
+    
+    /**
+     * Gets the system property.
+     *
+     * @param key          the property key
+     * @param defaultValue the default value for the property.
+     * @return the system property.
+     */
+    public static String getProperty(String key, String defaultValue) {
+        try {
+            return System.getProperty(key, defaultValue);
+        }
+        catch (AccessControlException e) {
+            return defaultValue;
+        }
+    }
+    
+    /**
+     * Returns the version of java we're using.
+     *
+     * @return the java version.
+     */
+    public static String getJavaVersion() {
+        return /* SecurityUtils.*/ getProperty("java.version", "1.4.2");
+    }
+    
+    private static void checkJdkVersion() {
+        if (_currentVersion == null) {
+            _currentVersion = new JavaVersion(getJavaVersion());
+        }
+    }
+
+    
+    /**
+     * Returns whether or no the JDK version is 1.5 and above.
+     *
+     * @return <tt>true</tt> if the application is running on JDK 1.5 and above, <tt>false</tt> otherwise.
+     */
+    public static boolean isJdk15Above() {
+        checkJdkVersion();
+        return _currentVersion.compareVersion(1.5, 0, 0) >= 0;
+    }
+
+
+public static class JavaVersion {
+    /**
+     * For example: 1.6.0_12: Group 1 = major version (1.6) Group 3 = minor version (0) Group 5 = build number (12)
+     */
+    private static Pattern SUN_JAVA_VERSION = Pattern.compile("(\\d+\\.\\d+)(\\.(\\d+))?(_([^-]+))?(.*)");
+    private static Pattern SUN_JAVA_VERSION_SIMPLE = Pattern.compile("(\\d+\\.\\d+)(\\.(\\d+))?(.*)");
+
+    private double _majorVersion;
+    private int _minorVersion;
+    private int _buildNumber;
+    private String _patch;
+
+    public JavaVersion(String version) {
+        _majorVersion = 1.4;
+        _minorVersion = 0;
+        _buildNumber = 0;
+        try {
+            Matcher matcher = SUN_JAVA_VERSION.matcher(version);
+            if (matcher.matches()) {
+                int groups = matcher.groupCount();
+                _majorVersion = Double.parseDouble(matcher.group(1));
+                if (groups >= 3 && matcher.group(3) != null) {
+                    _minorVersion = Integer.parseInt(matcher.group(3));
+                }
+                if (groups >= 5 && matcher.group(5) != null) {
+                    try {
+                        _buildNumber = Integer.parseInt(matcher.group(5));
+                    }
+                    catch (NumberFormatException e) {
+                        _patch = matcher.group(5);
+                    }
+                }
+                if (groups >= 6 && matcher.group(6) != null) {
+                    String s = matcher.group(6);
+                    if (s != null && s.trim().length() > 0) _patch = s;
+                }
+            }
+        }
+        catch (NumberFormatException e) {
+            try {
+                Matcher matcher = SUN_JAVA_VERSION_SIMPLE.matcher(version);
+                if (matcher.matches()) {
+                    int groups = matcher.groupCount();
+                    _majorVersion = Double.parseDouble(matcher.group(1));
+                    if (groups >= 3 && matcher.group(3) != null) {
+                        _minorVersion = Integer.parseInt(matcher.group(3));
+                    }
+                }
+            }
+            catch (NumberFormatException e1) {
+                System.err.println("Please check the installation of your JDK. The version number " + version + " is not right.");
+            }
+        }
+    }
+
+    public JavaVersion(double major, int minor, int build) {
+        _majorVersion = major;
+        _minorVersion = minor;
+        _buildNumber = build;
+    }
+
+    public int compareVersion(double major, int minor, int build) {
+        double majorResult = _majorVersion - major;
+        if (majorResult != 0) {
+            return majorResult < 0 ? -1 : 1;
+        }
+        int result = _minorVersion - minor;
+        if (result != 0) {
+            return result;
+        }
+        return _buildNumber - build;
+    }
+
+    public double getMajorVersion() {
+        return _majorVersion;
+    }
+
+    public int getMinorVersion() {
+        return _minorVersion;
+    }
+
+    public int getBuildNumber() {
+        return _buildNumber;
+    }
+
+    public String getPatch() {
+        return _patch;
+    }
+	}
+}
Index: applications/editors/josm/plugins/smed/src/smed/jide/swing/NullCheckBox.java
===================================================================
--- applications/editors/josm/plugins/smed/src/smed/jide/swing/NullCheckBox.java	(revision 23311)
+++ applications/editors/josm/plugins/smed/src/smed/jide/swing/NullCheckBox.java	(revision 23311)
@@ -0,0 +1,149 @@
+// License: GPL. For details, see LICENSE file.
+// Copyright (c) 2010 by Werner Koenig
+// this is a modified version of NullCheckBox.java,
+// which is part of the jide-oss, see https://jide-oss.dev.java.net
+
+/*
+ * @(#)NullCheckBox.java 7/25/2005
+ *
+ * Copyright 2002 - 2005 JIDE Software Inc. All rights reserved.
+ */
+package smed.jide.swing;
+
+import javax.swing.*;
+import javax.swing.plaf.FontUIResource;
+import javax.swing.plaf.ColorUIResource;
+import java.awt.*;
+
+/**
+ * This is part of the null-components. A null component doesn't have foreground, background or font value set. In the
+ * other words, the foreground, background and font value of null-component are null. But this doesn't mean
+ * getBackground(), getForeground() or getFont() will return null. According to {@link
+ * java.awt.Component#getBackground()}, {@link java.awt.Component#getForeground()} and {@link
+ * java.awt.Component#getFont()}, if the value is null, it will get the value from its parent. In the other words, if
+ * you add a null-component to JPanel, you can use JPanel to control the background, foreground and font of this
+ * null-component. The feature is very helpful if you want to make sure all components in a JPanel has the same
+ * background, foreground or font.
+ * <p/>
+ * Even in null-components, you can still change the foreground, background or font value if you do want. However, you'll
+ * have to use a font which is not an instance of FontUIResource or a color which is not an instance of ColorUIResource.
+ * <p/>
+ * We creates a few null-components. It doesn't cover all components. You can always create your own. All you need to do
+ * is this
+ * <pre><code>
+ * public class NullXxxComponent extends XxxComponent {
+ *     // invoke clearAttribute() in all the constructors
+ * <p/>
+ * public void setFont(Font font) {
+ *     if (font instanceof FontUIResource) {
+ *         return;
+ *     }
+ *     super.setFont(font);
+ * }
+ * <p/>
+ * public void setBackground(Color bg) {
+ *     if (bg instanceof ColorUIResource) {
+ *         return;
+ *     }
+ *     super.setBackground(bg);
+ * }
+ * <p/>
+ * public void setForeground(Color fg) {
+ *     if (fg instanceof ColorUIResource) {
+ *         return;
+ *     }
+ *     super.setForeground(fg);
+ * }
+ * <p/>
+ *     private void clearAttribute() {
+ *         setFont(null);
+ *         setBackground(null);
+ *         // do not do this for JButton since JButton always paints button
+ *         // content background. So it'd better to leave the foreground alone
+ *         setForeground(null);
+ *     }
+ * }
+ * </code></pre>
+ *
+ * @see com.jidesoft.swing.NullButton
+ * @see com.jidesoft.swing.NullPanel
+ * @see com.jidesoft.swing.NullJideButton
+ * @see com.jidesoft.swing.NullLabel
+ * @see com.jidesoft.swing.NullRadioButton
+ * @see com.jidesoft.swing.NullTristateCheckBox
+ */
+public class NullCheckBox extends JCheckBox {
+    /**
+	 * 
+	 */
+	private static final long serialVersionUID = 1L;
+
+	public NullCheckBox() {
+        clearAttribute();
+    }
+
+    public NullCheckBox(Icon icon) {
+        super(icon);
+        clearAttribute();
+    }
+
+    public NullCheckBox(Icon icon, boolean selected) {
+        super(icon, selected);
+        clearAttribute();
+    }
+
+    public NullCheckBox(String text) {
+        super(text);
+        clearAttribute();
+    }
+
+    public NullCheckBox(Action a) {
+        super(a);
+        clearAttribute();
+    }
+
+    public NullCheckBox(String text, boolean selected) {
+        super(text, selected);
+        clearAttribute();
+    }
+
+    public NullCheckBox(String text, Icon icon) {
+        super(text, icon);
+        clearAttribute();
+    }
+
+    public NullCheckBox(String text, Icon icon, boolean selected) {
+        super(text, icon, selected);
+        clearAttribute();
+    }
+
+    private void clearAttribute() {
+        super.setFont(null);
+        super.setBackground(null);
+        super.setForeground(null);
+    }
+
+    @Override
+    public void setFont(Font font) {
+        if (font instanceof FontUIResource) {
+            return;
+        }
+        super.setFont(font);
+    }
+
+    @Override
+    public void setBackground(Color bg) {
+        if (bg instanceof ColorUIResource) {
+            return;
+        }
+        super.setBackground(bg);
+    }
+
+    @Override
+    public void setForeground(Color fg) {
+        if (fg instanceof ColorUIResource) {
+            return;
+        }
+        super.setForeground(fg);
+    }
+}
Index: applications/editors/josm/plugins/smed/src/smed/jide/swing/NullLabel.java
===================================================================
--- applications/editors/josm/plugins/smed/src/smed/jide/swing/NullLabel.java	(revision 23311)
+++ applications/editors/josm/plugins/smed/src/smed/jide/swing/NullLabel.java	(revision 23311)
@@ -0,0 +1,139 @@
+// License: GPL. For details, see LICENSE file.
+// Copyright (c) 2010 by Werner Koenig
+// this is a modified version of CheckBoxList.java,
+// which is part of the jide-oss, see https://jide-oss.dev.java.net
+
+/*
+ * @(#)HollowLabel.java 7/12/2005
+ *
+ * Copyright 2002 - 2005 JIDE Software Inc. All rights reserved.
+ */
+package smed.jide.swing;
+
+import javax.swing.*;
+import javax.swing.plaf.FontUIResource;
+import javax.swing.plaf.ColorUIResource;
+import java.awt.*;
+
+/**
+ * This is part of the null-components. A null component doesn't have foreground, background or font value set. In the
+ * other words, the foreground, background and font value of null-component are null. But this doesn't mean
+ * getBackground(), getForeground() or getFont() will return null. According to {@link
+ * java.awt.Component#getBackground()}, {@link java.awt.Component#getForeground()} and {@link
+ * java.awt.Component#getFont()}, if the value is null, it will get the value from its parent. In the other words, if
+ * you add a null-component to JPanel, you can use JPanel to control the background, foreground and font of this
+ * null-component. The feature is very helpful if you want to make sure all components in a JPanel has the same
+ * background, foreground or font.
+ * <p/>
+ * Even in null-components, you can still change the foreground, background or font value if you do want. However, you'll
+ * have to use a font which is not an instance of FontUIResource or a color which is not an instance of ColorUIResource.
+ * <p/>
+ * We creates a few null-components. It doesn't cover all components. You can always create your own. All you need to do
+ * is this
+ * <pre><code>
+ * public class NullXxxComponent extends XxxComponent {
+ *     // invoke clearAttribute() in all the constructors
+ * <p/>
+ * public void setFont(Font font) {
+ *     if (font instanceof FontUIResource) {
+ *         return;
+ *     }
+ *     super.setFont(font);
+ * }
+ * <p/>
+ * public void setBackground(Color bg) {
+ *     if (bg instanceof ColorUIResource) {
+ *         return;
+ *     }
+ *     super.setBackground(bg);
+ * }
+ * <p/>
+ * public void setForeground(Color fg) {
+ *     if (fg instanceof ColorUIResource) {
+ *         return;
+ *     }
+ *     super.setForeground(fg);
+ * }
+ * <p/>
+ *     private void clearAttribute() {
+ *         setFont(null);
+ *         setBackground(null);
+ *         // do not do this for JButton since JButton always paints button
+ *         // content background. So it'd better to leave the foreground alone
+ *         setForeground(null);
+ *     }
+ * }
+ * </code></pre>
+ *
+ * @see com.jidesoft.swing.NullButton
+ * @see com.jidesoft.swing.NullCheckBox
+ * @see com.jidesoft.swing.NullJideButton
+ * @see com.jidesoft.swing.NullPanel
+ * @see com.jidesoft.swing.NullRadioButton
+ * @see com.jidesoft.swing.NullTristateCheckBox
+ */
+public class NullLabel extends JLabel {
+    /**
+	 * 
+	 */
+	private static final long serialVersionUID = 1L;
+
+	public NullLabel() {
+        clearAttribute();
+    }
+
+    public NullLabel(String text, Icon icon, int horizontalAlignment) {
+        super(text, icon, horizontalAlignment);
+        clearAttribute();
+    }
+
+    public NullLabel(String text, int horizontalAlignment) {
+        super(text, horizontalAlignment);
+        clearAttribute();
+    }
+
+    public NullLabel(String text) {
+        super(text);
+        clearAttribute();
+    }
+
+    public NullLabel(Icon image, int horizontalAlignment) {
+        super(image, horizontalAlignment);
+        clearAttribute();
+    }
+
+    public NullLabel(Icon image) {
+        super(image);
+        clearAttribute();
+    }
+
+    private void clearAttribute() {
+        super.setFont(null);
+        super.setBackground(null);
+        super.setForeground(null);
+    }
+
+    @Override
+    public void setFont(Font font) {
+        if (font instanceof FontUIResource) {
+            return;
+        }
+        super.setFont(font);
+    }
+
+    @Override
+    public void setBackground(Color bg) {
+        if (bg instanceof ColorUIResource) {
+            return;
+        }
+        super.setBackground(bg);
+    }
+
+    @Override
+    public void setForeground(Color fg) {
+        if (fg instanceof ColorUIResource) {
+            return;
+        }
+        super.setForeground(fg);
+    }
+}
