Index: applications/editors/josm/plugins/smed/plugs/harbour/src/harbour/widgets/TextFieldEx.java
===================================================================
--- applications/editors/josm/plugins/smed/plugs/harbour/src/harbour/widgets/TextFieldEx.java	(revision 24428)
+++ applications/editors/josm/plugins/smed/plugs/harbour/src/harbour/widgets/TextFieldEx.java	(revision 24428)
@@ -0,0 +1,226 @@
+package harbour.widgets;
+
+import java.awt.GridBagLayout;
+
+import javax.swing.ButtonGroup;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import java.awt.Rectangle;
+import javax.swing.JLabel;
+import java.awt.Font;
+import javax.swing.JRadioButton;
+
+public class TextFieldEx extends JPanel {
+
+	private static final long serialVersionUID = 1L;
+	
+	private ButtonGroup buttons = new ButtonGroup();
+	private JTextField sizeTextField = null;
+	private JLabel sizeLabel = null;
+	private JRadioButton sizeRadioButton = null;
+	private JTextField chTextField = null;
+	private JLabel chLabel = null;
+	private JRadioButton chRadioButton = null;
+	private JTextField tieTextField = null;
+	private JLabel tieLabel = null;
+	private JRadioButton tieRadioButton = null;
+	private JTextField cargoTextField = null;
+	private JLabel cargoLabel = null;
+	private JRadioButton cargoRadioButton = null;
+
+	private JTextField oilTextField = null;
+
+	private JLabel oilLabel = null;
+
+	private JRadioButton oilRadioButton = null;
+
+	/**
+	 * This is the default constructor
+	 */
+	public TextFieldEx() {
+		super();
+		initialize();
+	}
+
+	/**
+	 * This method initializes this
+	 * 
+	 * @return void
+	 */
+	private void initialize() {
+		oilLabel = new JLabel();
+		oilLabel.setBounds(new Rectangle(75, 94, 80, 15));
+		oilLabel.setFont(new Font("Dialog", Font.PLAIN, 12));
+		oilLabel.setText("Oelterminal");
+		cargoLabel = new JLabel();
+		cargoLabel.setBounds(new Rectangle(75, 71, 90, 15));
+		cargoLabel.setFont(new Font("Dialog", Font.PLAIN, 12));
+		cargoLabel.setText("Frachtanleger");
+		tieLabel = new JLabel();
+		tieLabel.setBounds(new Rectangle(75, 48, 75, 15));
+		tieLabel.setFont(new Font("Dialog", Font.PLAIN, 12));
+		tieLabel.setText("Ankerplatz");
+		chLabel = new JLabel();
+		chLabel.setBounds(new Rectangle(75, 25, 60, 15));
+		chLabel.setFont(new Font("Dialog", Font.PLAIN, 12));
+		chLabel.setText("Channel");
+		sizeLabel = new JLabel();
+		sizeLabel.setBounds(new Rectangle(75, 2, 95, 15));
+		sizeLabel.setFont(new Font("Dialog", Font.PLAIN, 12));
+		sizeLabel.setText("Schiffsgroesse");
+		this.setSize(190, 112);
+		this.setLayout(null);
+		this.add(getSizeTextField(), null);
+		this.add(sizeLabel, null);
+		this.add(getSizeRadioButton(), null);
+		this.add(getChTextField(), null);
+		this.add(chLabel, null);
+		this.add(getChRadioButton(), null);
+		this.add(getTieTextField(), null);
+		this.add(tieLabel, null);
+		this.add(getTieRadioButton(), null);
+		this.add(getCargoTextField(), null);
+		this.add(cargoLabel, null);
+		this.add(getCargoRadioButton(), null);
+		this.add(getOilTextField(), null);
+		this.add(oilLabel, null);
+		this.add(getOilRadioButton(), null);
+		
+		buttons.add(sizeRadioButton);
+		buttons.add(chRadioButton);
+		buttons.add(tieRadioButton);
+		buttons.add(cargoRadioButton);
+		buttons.add(oilRadioButton);
+	}
+
+	/**
+	 * This method initializes sizeTextField	
+	 * 	
+	 * @return javax.swing.JTextField	
+	 */
+	private JTextField getSizeTextField() {
+		if (sizeTextField == null) {
+			sizeTextField = new JTextField();
+			sizeTextField.setBounds(new Rectangle(0, 0, 75, 20));
+		}
+		return sizeTextField;
+	}
+
+	/**
+	 * This method initializes sizeRadioButton	
+	 * 	
+	 * @return javax.swing.JRadioButton	
+	 */
+	private JRadioButton getSizeRadioButton() {
+		if (sizeRadioButton == null) {
+			sizeRadioButton = new JRadioButton();
+			sizeRadioButton.setBounds(new Rectangle(170, 0, 20, 20));
+		}
+		return sizeRadioButton;
+	}
+
+	/**
+	 * This method initializes chTextField	
+	 * 	
+	 * @return javax.swing.JTextField	
+	 */
+	private JTextField getChTextField() {
+		if (chTextField == null) {
+			chTextField = new JTextField();
+			chTextField.setBounds(new Rectangle(0, 23, 75, 20));
+		}
+		return chTextField;
+	}
+
+	/**
+	 * This method initializes chRadioButton	
+	 * 	
+	 * @return javax.swing.JRadioButton	
+	 */
+	private JRadioButton getChRadioButton() {
+		if (chRadioButton == null) {
+			chRadioButton = new JRadioButton();
+			chRadioButton.setBounds(new Rectangle(170, 23, 20, 20));
+		}
+		return chRadioButton;
+	}
+
+	/**
+	 * This method initializes tieTextField	
+	 * 	
+	 * @return javax.swing.JTextField	
+	 */
+	private JTextField getTieTextField() {
+		if (tieTextField == null) {
+			tieTextField = new JTextField();
+			tieTextField.setBounds(new Rectangle(0, 46, 75, 20));
+		}
+		return tieTextField;
+	}
+
+	/**
+	 * This method initializes tieRadioButton	
+	 * 	
+	 * @return javax.swing.JRadioButton	
+	 */
+	private JRadioButton getTieRadioButton() {
+		if (tieRadioButton == null) {
+			tieRadioButton = new JRadioButton();
+			tieRadioButton.setBounds(new Rectangle(170, 46, 20, 20));
+		}
+		return tieRadioButton;
+	}
+
+	/**
+	 * This method initializes cargoTextField	
+	 * 	
+	 * @return javax.swing.JTextField	
+	 */
+	private JTextField getCargoTextField() {
+		if (cargoTextField == null) {
+			cargoTextField = new JTextField();
+			cargoTextField.setBounds(new Rectangle(0, 69, 75, 20));
+		}
+		return cargoTextField;
+	}
+
+	/**
+	 * This method initializes cargoRadioButton	
+	 * 	
+	 * @return javax.swing.JRadioButton	
+	 */
+	private JRadioButton getCargoRadioButton() {
+		if (cargoRadioButton == null) {
+			cargoRadioButton = new JRadioButton();
+			cargoRadioButton.setBounds(new Rectangle(170, 69, 20, 20));
+		}
+		return cargoRadioButton;
+	}
+
+	/**
+	 * This method initializes oilTextField	
+	 * 	
+	 * @return javax.swing.JTextField	
+	 */
+	private JTextField getOilTextField() {
+		if (oilTextField == null) {
+			oilTextField = new JTextField();
+			oilTextField.setBounds(new Rectangle(0, 92, 75, 20));
+		}
+		return oilTextField;
+	}
+
+	/**
+	 * This method initializes oilRadioButton	
+	 * 	
+	 * @return javax.swing.JRadioButton	
+	 */
+	private JRadioButton getOilRadioButton() {
+		if (oilRadioButton == null) {
+			oilRadioButton = new JRadioButton();
+			oilRadioButton.setBounds(new Rectangle(170, 92, 20, 20));
+		}
+		return oilRadioButton;
+	}
+
+}
Index: applications/editors/josm/plugins/smed/plugs/harbour/src/harbour/widgets/TristateCheckBox.java
===================================================================
--- applications/editors/josm/plugins/smed/plugs/harbour/src/harbour/widgets/TristateCheckBox.java	(revision 24428)
+++ applications/editors/josm/plugins/smed/plugs/harbour/src/harbour/widgets/TristateCheckBox.java	(revision 24428)
@@ -0,0 +1,273 @@
+package harbour.widgets;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+
+import javax.swing.AbstractAction;
+import javax.swing.ActionMap;
+import javax.swing.ButtonGroup;
+import javax.swing.ButtonModel;
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
+import javax.swing.JCheckBox;
+import javax.swing.SwingUtilities;
+import javax.swing.event.ChangeListener;
+import javax.swing.plaf.ActionMapUIResource;
+
+public class TristateCheckBox extends JCheckBox {
+
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 1L;
+	
+	public static class State {private State() {} }
+	public static final State NOT_SELECTED = new State();
+	public static final State SELECTED = new State();
+	public static final State DONT_CARE = new State();
+	
+	private TristateDecorator model;
+	
+	Icon d = new ImageIcon(getClass().getResource("/images/qm.png"));
+	Icon s = new ImageIcon(getClass().getResource("/images/cm.png"));
+	Icon n = new ImageIcon(getClass().getResource("/images/xm.png"));
+	
+	@SuppressWarnings("serial")
+	public TristateCheckBox(String text, Icon icon, State initial) {
+		super(text,icon);
+		
+		// add a listener for when the mouse is pressed
+		super.addMouseListener(new MouseAdapter() {
+			public void mousePressed(MouseEvent e) {
+				grabFocus();
+				model.nextState();
+				if(model.getState() == NOT_SELECTED) setIcon(n);
+				if(model.getState() == DONT_CARE) setIcon(d);
+				if(model.getState() == SELECTED) setIcon(s);
+			}
+		} );
+		
+		// reset the keyboard action map
+		ActionMap map = new ActionMapUIResource();
+		map.put("pressed", new AbstractAction() {
+
+			@Override
+			public void actionPerformed(ActionEvent e) {
+				grabFocus();
+				model.nextState();
+			}
+			
+		});
+		
+		map.put("released", null);
+		SwingUtilities.replaceUIActionMap(this, map);
+		
+		// set the model to the adapted model
+		model = new TristateDecorator(getModel());
+		setModel(model);
+		setState(DONT_CARE);
+		setIcon(d);
+	}
+	
+	public TristateCheckBox(String text, State initial) {
+		this(text, null, initial);
+	}
+	
+	public TristateCheckBox(String text) {
+		this(text, DONT_CARE);
+	}
+	
+	public TristateCheckBox(){
+		this(null);
+	}
+
+	/** No one may add mouse listeners, not even Swing! */
+	public void addMouseListener(MouseListener l) { }
+	
+	/**
+	 * Set the new state to either SELECTED, NOT_SELECTED or
+	 * DONT_CARE. If state == null, it is treated as DONT_CARE
+	 */
+	public void setState(State state) { model.setState(state); }
+	
+	/**
+	 * Return the current state, which is determined by the
+	 * selection status of the model
+	 */
+	public State getState() { return model.getState(); }
+	
+	public void setState(boolean b) {
+		if(b)	setState(SELECTED);
+		else	setState(NOT_SELECTED);
+	}
+	
+	/**
+	 * Exactly which Design Pattern is this? Is it an Adapter,
+	 * a Proxy or a Decorator? In this case, my vote lies with the
+	 * Decorator, because we are extending functionality and
+	 * "decorating" the original model with a more powerful model
+	 */
+	private class TristateDecorator implements ButtonModel {
+		
+		private final ButtonModel other;
+		
+		private TristateDecorator(ButtonModel other) {
+			this.other = other;
+		}
+		
+		private void setState(State state) {
+			if(state == NOT_SELECTED) {
+				other.setArmed(false);
+				setPressed(false);
+				setSelected(false);
+			} else if(state == SELECTED) {
+				other.setArmed(false);
+				setPressed(false);
+				setSelected(true);
+			} else { // either "null" or DONT_CARE
+				other.setArmed(true);
+				setPressed(true);
+				setSelected(true);
+			}
+		}
+		
+		/**
+		 * The current state is embedded in the selection / armed
+		 * state of the model.
+		 * 
+		 * We return the SELECTED state when the checkbox is selected
+		 * but not armed, DONT_CARE state when the checkbox is
+		 * selected and armed (grey) and NOT_SELECTED when the
+		 * checkbox is deselected
+		 */
+		private State getState() {
+			if(isSelected() && !isArmed()) 		return SELECTED;
+			else if (isSelected() && isArmed()) return DONT_CARE;
+			else 								return NOT_SELECTED;
+			}
+
+		/** we rotate between NOT_SELECTED, SELECTED, and DONT_CARE */
+		private void nextState() {
+			State current = getState();
+			
+			if(current == NOT_SELECTED) 	setState(DONT_CARE);
+			else if(current == SELECTED) 	setState(NOT_SELECTED);
+			else if(current == DONT_CARE) 	setState(SELECTED);
+		}
+		
+		@Override
+		public Object[] getSelectedObjects() {
+			return other.getSelectedObjects();
+		}
+
+		@Override
+		public void addActionListener(ActionListener l) {
+			other.addActionListener(l);
+		}
+
+		@Override
+		public void addChangeListener(ChangeListener l) {
+			other.addChangeListener(l);
+		}
+
+		@Override
+		public void addItemListener(ItemListener l) {
+			other.addItemListener(l);
+		}
+
+		@Override
+		public String getActionCommand() {
+			return other.getActionCommand();
+		}
+
+		@Override
+		public int getMnemonic() {
+			return other.getMnemonic();
+		}
+
+		@Override
+		public boolean isArmed() {
+			return other.isArmed();
+		}
+
+		@Override
+		public boolean isEnabled() {
+			return other.isEnabled();
+		}
+
+		@Override
+		public boolean isPressed() {
+			return other.isPressed();
+		}
+
+		@Override
+		public boolean isRollover() {
+			return other.isRollover();
+		}
+
+		@Override
+		public boolean isSelected() {
+			return other.isSelected();
+		}
+
+		@Override
+		public void removeActionListener(ActionListener l) {
+			other.removeActionListener(l);
+		}
+
+		@Override
+		public void removeChangeListener(ChangeListener l) {
+			other.removeChangeListener(l);
+		}
+
+		@Override
+		public void removeItemListener(ItemListener l) {
+			other.removeItemListener(l);
+		}
+
+		@Override
+		public void setActionCommand(String s) {
+			other.setActionCommand(s);
+		}
+
+		/** Filter: No one may change the armed status except us */
+		@Override
+		public void setArmed(boolean b) {
+		}
+
+		@Override
+		public void setEnabled(boolean b) {
+			setFocusable(b);
+			other.setEnabled(b);
+		}
+
+		@Override
+		public void setGroup(ButtonGroup group) {
+			other.setGroup(group);
+		}
+
+		@Override
+		public void setMnemonic(int key) {
+			other.setMnemonic(key);
+		}
+
+		@Override
+		public void setPressed(boolean b) {
+			other.setPressed(b);
+		}
+
+		@Override
+		public void setRollover(boolean b) {
+			other.setRollover(b);
+		}
+
+		@Override
+		public void setSelected(boolean b) {
+			other.setSelected(b);
+		}
+	}
+}
