Index: applications/editors/josm/plugins/terracer/src/terracer/HouseNumberInputDialog.java
===================================================================
--- applications/editors/josm/plugins/terracer/src/terracer/HouseNumberInputDialog.java	(revision 19627)
+++ applications/editors/josm/plugins/terracer/src/terracer/HouseNumberInputDialog.java	(revision 19658)
@@ -12,7 +12,9 @@
 import java.awt.Choice;
 import java.awt.Color;
+import java.awt.Container;
 import java.awt.Dimension;
 import java.awt.FlowLayout;
 import java.awt.Frame;
+import java.awt.GridBagLayout;
 import java.awt.GridLayout;
 import java.util.TreeSet;
@@ -20,6 +22,8 @@
 import javax.swing.BoxLayout;
 import javax.swing.JButton;
+import javax.swing.JCheckBox;
 import javax.swing.JDialog;
 import javax.swing.JLabel;
+import javax.swing.JOptionPane;
 import javax.swing.JPanel;
 import javax.swing.JTextArea;
@@ -28,274 +32,298 @@
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.gui.widgets.AutoCompleteComboBox;
+import org.openstreetmap.josm.tools.GBC;
+
 
 /**
  * The HouseNumberInputDialog is the layout of the house number input logic.
  * Created with the Eclipse Visual Editor.
- * 
+ *
  *  This dialog is concerned with the layout, all logic goes into the
  *  HouseNumberinputHandler class.
- * 
+ *
  * @author casualwalker
  *
  */
 public class HouseNumberInputDialog extends JDialog {
-
-	protected static final String DEFAULT_MESSAGE = "Enter housenumbers or amount of segments";
-	private static final long serialVersionUID = 1L;
-	private JPanel jContentPane = null;
-	private JPanel inputPanel = null;
-	private JPanel buttonPanel = null;
-	private JLabel loLabel = null;
-	JTextField lo = null;
-	private JLabel hiLabel = null;
-	JTextField hi = null;
-	private JLabel streetLabel = null;
-	AutoCompleteComboBox street;
-	// JTextField street = null;
-	private JLabel segmentsLabel = null;
-	JTextField segments = null;
-	JTextArea messageLabel = null;
-	JButton okButton = null;
-	JButton cancelButton = null;
-	private JLabel interpolationLabel = null;
-	Choice interpolation = null;
-
-	/**
-	 * @param owner
-	 */
-	public HouseNumberInputDialog(Frame owner) {
-		super(owner);
-		initialize();
-	}
-
-	/**
-	 * This method initializes this
-	 * 
-	 * @return void
-	 */
-	private void initialize() {
-		this.setSize(300, 200);
-		this.setTitle("Terrace a house");
-		this.setContentPane(getJContentPane());
-	}
-
-	/**
-	 * This method initializes jContentPane
-	 * 
-	 * @return javax.swing.JPanel
-	 */
-	private JPanel getJContentPane() {
-		if (jContentPane == null) {
-			messageLabel = new JTextArea();
-			messageLabel.setText(DEFAULT_MESSAGE);
-			messageLabel.setAutoscrolls(true);
-
-			messageLabel.setLineWrap(true);
-			messageLabel.setRows(2);
-			messageLabel.setBackground(new Color(238, 238, 238));
-			messageLabel.setEditable(false);
-			jContentPane = new JPanel();
-			jContentPane.setLayout(new BoxLayout(getJContentPane(),
-					BoxLayout.Y_AXIS));
-			jContentPane.add(getInputPanel(), null);
-			jContentPane.add(messageLabel, null);
-			jContentPane.add(getButtonPanel(), null);
-
-		}
-		return jContentPane;
-	}
-
-	/**
-	 * This method initializes inputPanel	
-	 * 	
-	 * @return javax.swing.JPanel	
-	 */
-	private JPanel getInputPanel() {
-		if (inputPanel == null) {
-			interpolationLabel = new JLabel();
-			interpolationLabel.setText("Interpolation");
-			segmentsLabel = new JLabel();
-			segmentsLabel.setText("Segments");
-			streetLabel = new JLabel();
-			streetLabel.setText("Street");
-			hiLabel = new JLabel();
-			hiLabel.setText("Highest Number");
-			loLabel = new JLabel();
-			loLabel.setText("Lowest Number");
-			loLabel.setPreferredSize(new Dimension(111, 16));
-			loLabel.setToolTipText("Lowest housenumber of the terraced house");
-			GridLayout gridLayout = new GridLayout();
-			gridLayout.setRows(5);
-			gridLayout.setColumns(2);
-			inputPanel = new JPanel();
-			inputPanel.setLayout(gridLayout);
-			inputPanel.add(loLabel, null);
-
-			inputPanel.add(getLo(), null);
-			inputPanel.add(hiLabel, null);
-			inputPanel.add(getHi(), null);
-			inputPanel.add(interpolationLabel, null);
-			inputPanel.add(getInterpolation(), null);
-			inputPanel.add(segmentsLabel, null);
-			inputPanel.add(getSegments(), null);
-			inputPanel.add(streetLabel, null);
-			inputPanel.add(getStreet(), null);
-		}
-		return inputPanel;
-	}
-
-	/**
-	 * This method initializes buttonPanel	
-	 * 	
-	 * @return javax.swing.JPanel	
-	 */
-	private JPanel getButtonPanel() {
-		if (buttonPanel == null) {
-			buttonPanel = new JPanel();
-			buttonPanel.setLayout(new FlowLayout());
-			buttonPanel.add(getOkButton(), null);
-			buttonPanel.add(getCancelButton(), null);
-		}
-		return buttonPanel;
-	}
-
-	/**
-	 * This method initializes lo	
-	 * 	
-	 * @return javax.swing.JTextField	
-	 */
-	private JTextField getLo() {
-		if (lo == null) {
-			lo = new JTextField();
-			lo.setText("");
-		}
-		return lo;
-	}
-
-	/**
-	 * This method initializes hi	
-	 * 	
-	 * @return javax.swing.JTextField	
-	 */
-	private JTextField getHi() {
-		if (hi == null) {
-			hi = new JTextField();
-			hi.setText("");
-		}
-		return hi;
-	}
-
-	/**
-	 * This method initializes street	
-	 * 	
-	 * @return javax.swing.JTextField	
-	 */
-	private AutoCompleteComboBox getStreet() {
-
-		if (street == null) {
-			final TreeSet<String> names = createAutoCompletionInfo();
-
-			street = new AutoCompleteComboBox();
-			street.setPossibleItems(names);
-			street.setEditable(true);
-			street.setSelectedItem(null);
-
-		}
-		return street;
-	}
-
-	/**
-	 * This method initializes segments	
-	 * 	
-	 * @return javax.swing.JTextField	
-	 */
-	private JTextField getSegments() {
-		if (segments == null) {
-			segments = new JTextField();
-			segments.setText("1");
-		}
-		return segments;
-	}
-
-	/**
-	 * This method initializes okButton	
-	 * 	
-	 * @return javax.swing.JButton	
-	 */
-	private JButton getOkButton() {
-		if (okButton == null) {
-			okButton = new JButton();
-			okButton.setText("OK");
-			okButton.setName("OK");
-		}
-		return okButton;
-	}
-
-	/**
-	 * This method initializes cancelButton	
-	 * 	
-	 * @return javax.swing.JButton	
-	 */
-	private JButton getCancelButton() {
-		if (cancelButton == null) {
-			cancelButton = new JButton();
-			cancelButton.setText("Cancel");
-			cancelButton.setName("CANCEL");
-		}
-		return cancelButton;
-	}
-
-	/**
-	 * This method initializes interpolation	
-	 * 	
-	 * @return java.awt.Choice	
-	 */
-	private Choice getInterpolation() {
-		if (interpolation == null) {
-			interpolation = new Choice();
-			interpolation.add(tr("All"));
-			interpolation.add(tr("Even/Odd"));
-		}
-		return interpolation;
-	}
-
-	/**
-	 * Registers the handler as a listener to all relevant events.
-	 * 
-	 * @param handler the handler
-	 */
-	public void addHandler(HouseNumberInputHandler handler) {
-		this.hi.addActionListener(handler);
-		this.hi.addFocusListener(handler);
-
-		this.lo.addActionListener(handler);
-		this.lo.addFocusListener(handler);
-
-		this.segments.addActionListener(handler);
-		this.segments.addFocusListener(handler);
-
-		this.okButton.addActionListener(handler);
-		this.cancelButton.addActionListener(handler);
-
-		this.interpolation.addItemListener(handler);
-
-	}
-
-	/**
-	 * Generates a list of all visible names of highways in order to do
-	 * autocompletion on the road name.
-	 */
-	TreeSet<String> createAutoCompletionInfo() {
-		final TreeSet<String> names = new TreeSet<String>();
-		for (OsmPrimitive osm : Main.main.getCurrentDataSet()
-				.allNonDeletedPrimitives()) {
-			if (osm.getKeys() != null && osm.keySet().contains("highway")
-					&& osm.keySet().contains("name")) {
-				names.add(osm.get("name"));
-			}
-		}
-		return names;
-	}
-
+    /*
+    final static String MIN_NUMBER = "plugin.terracer.lowest_number";
+    final static String MAX_NUMBER = "plugin.terracer.highest_number";
+    final static String INTERPOLATION = "plugin.terracer.interpolation_mode";
+    */
+    final static String HANDLE_RELATION = "plugins.terracer.handle_relation";
+    final static String DELETE_OUTLINE = "plugins.terracer.delete_outline";
+
+    final private Way street;
+    final private boolean relationExists;
+
+    protected static final String DEFAULT_MESSAGE = tr("Enter housenumbers or amount of segments");
+    private static final long serialVersionUID = 1L;
+    private Container jContentPane;
+    private JPanel inputPanel;
+    private JPanel buttonPanel;
+    private JLabel loLabel;
+    JTextField lo;
+    private JLabel hiLabel;
+    JTextField hi;
+    private JLabel streetLabel;
+    AutoCompleteComboBox streetComboBox;
+    private JLabel segmentsLabel;
+    JTextField segments;
+    JTextArea messageLabel;
+    JButton okButton;
+    JButton cancelButton;
+    private JLabel interpolationLabel;
+    Choice interpolation;
+    JCheckBox handleRelationCheckBox;
+    JCheckBox deleteOutlineCheckBox;
+
+    /**
+     * @param street If street is not null, we assume, the name of the street to be fixed
+     * and just show a label. If street is null, we show a ComboBox/InputField.
+     * @param relationExists If the buildings can be added to an existing relation or not.
+     */
+    public HouseNumberInputDialog(Way street, boolean relationExists) {
+        super(JOptionPane.getFrameForComponent(Main.parent));
+        this.street = street;
+        this.relationExists = relationExists;
+        initialize();
+    }
+
+    /**
+     * This method initializes this
+     *
+     * @return void
+     */
+    private void initialize() {
+        this.setTitle(tr("Terrace a house"));
+        getJContentPane();
+        this.pack();
+        this.setLocationRelativeTo(Main.parent);
+    }
+
+    /**
+     * This method initializes jContentPane
+     *
+     * @return javax.swing.JPanel
+     */
+    private Container getJContentPane() {
+        if (jContentPane == null) {
+            messageLabel = new JTextArea();
+            messageLabel.setText(DEFAULT_MESSAGE);
+            messageLabel.setAutoscrolls(true);
+
+            messageLabel.setLineWrap(true);
+            messageLabel.setRows(2);
+            messageLabel.setBackground(new Color(238, 238, 238));
+            messageLabel.setEditable(false);
+            jContentPane = this.getContentPane();
+            jContentPane.setLayout(new BoxLayout(jContentPane,
+                    BoxLayout.Y_AXIS));
+            jContentPane.add(messageLabel, jContentPane);
+            jContentPane.add(getInputPanel(), jContentPane);
+            jContentPane.add(getButtonPanel(), jContentPane);
+
+        }
+        return jContentPane;
+    }
+
+    /**
+     * This method initializes inputPanel
+     *
+     * @return javax.swing.JPanel
+     */
+    private JPanel getInputPanel() {
+        if (inputPanel == null) {
+            interpolationLabel = new JLabel();
+            interpolationLabel.setText(tr("Interpolation"));
+            segmentsLabel = new JLabel();
+            segmentsLabel.setText(tr("Segments"));
+            streetLabel = new JLabel();
+            streetLabel.setText(tr("Street"));
+            hiLabel = new JLabel();
+            hiLabel.setText(tr("Highest Number"));
+            loLabel = new JLabel();
+            loLabel.setText(tr("Lowest Number"));
+            loLabel.setPreferredSize(new Dimension(111, 16));
+            loLabel.setToolTipText(tr("Lowest housenumber of the terraced house"));
+            final String txt = relationExists ? tr("add to existing associatedStreet relation") : tr("create an associatedStreet relation");
+            handleRelationCheckBox = new JCheckBox(txt, Main.pref.getBoolean(HANDLE_RELATION, true));
+            deleteOutlineCheckBox = new JCheckBox(tr("delete outline way"), Main.pref.getBoolean(DELETE_OUTLINE, true));
+
+            inputPanel = new JPanel();
+            inputPanel.setLayout(new GridBagLayout());
+            inputPanel.add(loLabel, GBC.std().insets(3,3,0,0));
+            inputPanel.add(getLo(), GBC.eol().fill(GBC.HORIZONTAL).insets(5,3,0,0));
+            inputPanel.add(hiLabel, GBC.std().insets(3,3,0,0));
+            inputPanel.add(getHi(), GBC.eol().fill(GBC.HORIZONTAL).insets(5,3,0,0));
+            inputPanel.add(interpolationLabel, GBC.std().insets(3,3,0,0));
+            inputPanel.add(getInterpolation(), GBC.eol().insets(5,3,0,0));
+            inputPanel.add(segmentsLabel, GBC.std().insets(3,3,0,0));
+            inputPanel.add(getSegments(), GBC.eol().fill(GBC.HORIZONTAL).insets(5,3,0,0));
+            if (street == null) {
+                inputPanel.add(streetLabel, GBC.std().insets(3,3,0,0));
+                inputPanel.add(getStreet(), GBC.eol().insets(5,3,0,0));
+            } else {
+                inputPanel.add(new JLabel(tr("Street name: ")+"\""+street.get("name")+"\""), GBC.eol().insets(3,3,0,0));
+            }
+            inputPanel.add(handleRelationCheckBox, GBC.eol().insets(3,3,0,0));
+            inputPanel.add(deleteOutlineCheckBox, GBC.eol().insets(3,3,0,0));
+        }
+        return inputPanel;
+    }
+
+    /**
+     * This method initializes buttonPanel
+     *
+     * @return javax.swing.JPanel
+     */
+    private JPanel getButtonPanel() {
+        if (buttonPanel == null) {
+            buttonPanel = new JPanel();
+            buttonPanel.setLayout(new FlowLayout());
+            buttonPanel.add(getOkButton(), null);
+            buttonPanel.add(getCancelButton(), null);
+        }
+        return buttonPanel;
+    }
+
+    /**
+     * This method initializes lo
+     *
+     * @return javax.swing.JTextField
+     */
+    private JTextField getLo() {
+        if (lo == null) {
+            lo = new JTextField();
+            lo.setText("");
+        }
+        return lo;
+    }
+
+    /**
+     * This method initializes hi
+     *
+     * @return javax.swing.JTextField
+     */
+    private JTextField getHi() {
+        if (hi == null) {
+            hi = new JTextField();
+            hi.setText("");
+        }
+        return hi;
+    }
+
+    /**
+     * This method initializes street
+     *
+     * @return javax.swing.JTextField
+     */
+    private AutoCompleteComboBox getStreet() {
+
+        if (streetComboBox == null) {
+            final TreeSet<String> names = createAutoCompletionInfo();
+
+            streetComboBox = new AutoCompleteComboBox();
+            streetComboBox.setPossibleItems(names);
+            streetComboBox.setEditable(true);
+            streetComboBox.setSelectedItem(null);
+
+        }
+        return streetComboBox;
+    }
+
+    /**
+     * This method initializes segments
+     *
+     * @return javax.swing.JTextField
+     */
+    private JTextField getSegments() {
+        if (segments == null) {
+            segments = new JTextField();
+            segments.setText("1");
+        }
+        return segments;
+    }
+
+    /**
+     * This method initializes okButton
+     *
+     * @return javax.swing.JButton
+     */
+    private JButton getOkButton() {
+        if (okButton == null) {
+            okButton = new JButton();
+            okButton.setText(tr("OK"));
+            okButton.setName("OK");
+        }
+        return okButton;
+    }
+
+    /**
+     * This method initializes cancelButton
+     *
+     * @return javax.swing.JButton
+     */
+    private JButton getCancelButton() {
+        if (cancelButton == null) {
+            cancelButton = new JButton();
+            cancelButton.setText(tr("Cancel"));
+            cancelButton.setName("CANCEL");
+        }
+        return cancelButton;
+    }
+
+    /**
+     * This method initializes interpolation
+     *
+     * @return java.awt.Choice
+     */
+    private Choice getInterpolation() {
+        if (interpolation == null) {
+            interpolation = new Choice();
+            interpolation.add(tr("All"));
+            interpolation.add(tr("Even/Odd"));
+        }
+        return interpolation;
+    }
+
+    /**
+     * Registers the handler as a listener to all relevant events.
+     *
+     * @param handler the handler
+     */
+    public void addHandler(HouseNumberInputHandler handler) {
+        this.hi.addActionListener(handler);
+        this.hi.addFocusListener(handler);
+
+        this.lo.addActionListener(handler);
+        this.lo.addFocusListener(handler);
+
+        this.segments.addActionListener(handler);
+        this.segments.addFocusListener(handler);
+
+        this.okButton.addActionListener(handler);
+        this.cancelButton.addActionListener(handler);
+
+        this.interpolation.addItemListener(handler);
+
+    }
+
+    /**
+     * Generates a list of all visible names of highways in order to do
+     * autocompletion on the road name.
+     */
+    TreeSet<String> createAutoCompletionInfo() {
+        final TreeSet<String> names = new TreeSet<String>();
+        for (OsmPrimitive osm : Main.main.getCurrentDataSet()
+                .allNonDeletedPrimitives()) {
+            if (osm.getKeys() != null && osm.keySet().contains("highway")
+                    && osm.keySet().contains("name")) {
+                names.add(osm.get("name"));
+            }
+        }
+        return names;
+    }
 }
Index: applications/editors/josm/plugins/terracer/src/terracer/HouseNumberInputHandler.java
===================================================================
--- applications/editors/josm/plugins/terracer/src/terracer/HouseNumberInputHandler.java	(revision 19627)
+++ applications/editors/josm/plugins/terracer/src/terracer/HouseNumberInputHandler.java	(revision 19658)
@@ -22,316 +22,357 @@
 import javax.swing.event.ChangeEvent;
 import javax.swing.event.ChangeListener;
- 
+
+import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.osm.Way;
+import org.openstreetmap.josm.data.osm.Relation;
 
 /**
  * The Class HouseNumberInputHandler contains all the logic
  * behind the house number input dialog.
- * 
+ *
  * From a refactoring viewpoint, this class is indeed more interested in the fields
- * of the HouseNumberInputDialog. This is desired design, as the HouseNumberInputDialog 
+ * of the HouseNumberInputDialog. This is desired design, as the HouseNumberInputDialog
  * is already cluttered with auto-generated layout code.
- * 
+ *
  * @author casualwalker
  */
 public class HouseNumberInputHandler implements ChangeListener, ItemListener,
-		ActionListener, FocusListener {
-
-	private TerracerAction terracerAction;
-	private Way way;
-	private HouseNumberInputDialog dialog;
-
-	/**
-	 * Instantiates a new house number input handler.
-	 * 
-	 * @param terracerAction the terracer action
-	 * @param way the way
-	 * @param title the title
-	 */
-	public HouseNumberInputHandler(final TerracerAction terracerAction,
-			final Way way, final String title) {
-		this.terracerAction = terracerAction;
-		this.way = way;
-		dialog = new HouseNumberInputDialog(null);
-		dialog.addHandler(this);
-
-		dialog.setVisible(true);
-		dialog.setTitle(title);
-
-	}
-
-	/**
-	 * Validate the current input fields.
-	 * When the validation fails, a red message is 
-	 * displayed and the OK button is disabled.
-	 * 
-	 * Should be triggered each time the input changes.
-	 */
-	private void validateInput() {
-		boolean isOk = true;
-		StringBuffer message = new StringBuffer();
-
-		isOk = isOk && checkNumberOrder(message);
-		isOk = isOk && checkSegmentsFromHousenumber(message);
-		isOk = isOk && checkSegments(message);
-		isOk = isOk
-				&& checkNumberStringField(dialog.lo, tr("Lowest number"),
-						message);
-		isOk = isOk
-				&& checkNumberStringField(dialog.hi, tr("Highest number"),
-						message);
-		isOk = isOk
-				&& checkNumberStringField(dialog.segments, tr("Segments"),
-						message);
-
-		if (isOk) {
-			dialog.okButton.setEnabled(true);
-			dialog.messageLabel.setForeground(Color.black);
-			dialog.messageLabel
-					.setText(tr(HouseNumberInputDialog.DEFAULT_MESSAGE));
-
-		} else {
-			dialog.okButton.setEnabled(false);
-			dialog.messageLabel.setForeground(Color.red);
-			dialog.messageLabel.setText(message.toString());
-		}
-	}
-
-	/**
-	 * Checks, if the lowest house number is indeed lower than the 
-	 * highest house number.
-	 * This check applies only, if the house number fields are used at all. 
-	 * 
-	 * @param message the message
-	 * 
-	 * @return true, if successful
-	 */
-	private boolean checkNumberOrder(final StringBuffer message) {
-		if (numberFrom() != null && numberTo() != null) {
-			if (numberFrom().intValue() > numberTo().intValue()) {
-				appendMessageNewLine(message);
-				message
-						.append(tr("Lowest housenumber cannot be higher than highest housenumber"));
-				return false;
-			}
-		}
-		return true;
-	}
-
-	/**
-	 * Obtain the number segments from the house number fields and check, 
-	 * if they are valid.
-	 * 
-	 * Also disables the segments field, if the house numbers contain
-	 * valid information.
-	 * 
-	 * @param message the message
-	 * 
-	 * @return true, if successful
-	 */
-	private boolean checkSegmentsFromHousenumber(final StringBuffer message) {
-		dialog.segments.setEditable(true);
-
-		if (numberFrom() != null && numberTo() != null) {
-
-			int segments = numberTo().intValue() - numberFrom().intValue();
-
-			if (segments % stepSize() != 0) {
-				appendMessageNewLine(message);
-				message
-						.append(tr("Housenumbers do not match odd/even setting"));
-				return false;
-			}
-
-			int steps = segments / stepSize();
-			steps++; // difference 0 means 1 building, see
-			// TerracerActon.terraceBuilding
-			dialog.segments.setText(String.valueOf(steps));
-			dialog.segments.setEditable(false);
-
-		}
-		return true;
-	}
-
-	/**
-	 * Check the number of segments.
-	 * It must be a number and greater than 1. 
-	 * 
-	 * @param message the message
-	 * 
-	 * @return true, if successful
-	 */
-	private boolean checkSegments(final StringBuffer message) {
-		if (segments() == null || segments().intValue() < 1) {
-			appendMessageNewLine(message);
-			message.append(tr("Segment must be a number greater 1"));
-			return false;
-
-		}
-		return true;
-	}
-
-	/**
-	 * Check, if a string field contains a positive integer. 
-	 * 
-	 * @param field the field
-	 * @param label the label
-	 * @param message the message
-	 * 
-	 * @return true, if successful
-	 */
-	private boolean checkNumberStringField(final JTextField field,
-			final String label, final StringBuffer message) {
-		final String content = field.getText();
-		if (content != null && content.length() != 0) {
-			try {
-				int i = Integer.parseInt(content);
-				if (i < 0) {
-					appendMessageNewLine(message);
-					message.append(tr("{0} must be greater than 0", label));
-					return false;
-				}
-			} catch (NumberFormatException e) {
-				appendMessageNewLine(message);
-				message.append(tr("{0} is not a number", label));
-				return false;
-			}
-
-		}
-		return true;
-	}
-
-	/**
-	 * Append a new line to the message, if the message is not empty.
-	 * 
-	 * @param message the message
-	 */
-	private void appendMessageNewLine(final StringBuffer message) {
-		if (message.length() > 0) {
-			message.append("\n");
-		}
-	}
-
-	/* (non-Javadoc)
-	 * @see javax.swing.event.ChangeListener#stateChanged(javax.swing.event.ChangeEvent)
-	 */
-	public void stateChanged(ChangeEvent e) {
-		validateInput();
-
-	}
-
-	/* (non-Javadoc)
-	 * @see java.awt.event.ItemListener#itemStateChanged(java.awt.event.ItemEvent)
-	 */
-	public void itemStateChanged(ItemEvent e) {
-		validateInput();
-	}
-
-	/* (non-Javadoc)
-	 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
-	 */
-	public void actionPerformed(final ActionEvent e) {
-
-		// OK or Cancel button-actions
-		if (e.getSource() instanceof JButton) {
-			JButton button = (JButton) e.getSource();
-			if ("OK".equals(button.getName())) {
-				terracerAction.terraceBuilding(way, segments(), numberFrom(),
-						numberTo(), stepSize(), streetName());
-
-				this.dialog.dispose();
-			} else if ("CANCEL".equals(button.getName())) {
-				this.dialog.dispose();
-			}
-		} else {
-			// anything else is a change in the input
-			validateInput();
-		}
-
-	}
-
-	/**
-	 * Calculate the step size between two house numbers,
-	 * based on the interpolation setting.
-	 * 
-	 * @return the stepSize (1 for all, 2 for odd /even)
-	 */
-	public int stepSize() {
-		return (dialog.interpolation.getSelectedItem().equals(tr("All"))) ? 1
-				: 2;
-	}
-
-	/**
-	 * Gets the number of segments, if set.
-	 * 
-	 * @return the number of segments or null, if not set / invalid.
-	 */
-	public Integer segments() {
-		try {
-			return Integer.parseInt(dialog.segments.getText());
-		} catch (NumberFormatException ex) {
-			return null;
-		}
-	}
-
-	/**
-	 * Gets the lowest house number.
-	 * 
-	 * @return the number of lowest house number or null, if not set / invalid.
-	 */
-	public Integer numberFrom() {
-		try {
-			return Integer.parseInt(dialog.lo.getText());
-		} catch (NumberFormatException ex) {
-			return null;
-		}
-	}
-
-	/**
-	 * Gets the highest house number.
-	 * 
-	 * @return the number of highest house number or null, if not set / invalid.
-	 */
-	public Integer numberTo() {
-		try {
-			return Integer.parseInt(dialog.hi.getText());
-		} catch (NumberFormatException ex) {
-			return null;
-		}
-	}
-
-	/**
-	 * Gets the street name.
-	 * 
-	 * @return the  street name or null, if not set / invalid.
-	 */
-	public String streetName() {
-		// Object selected = street.getSelectedItem();
-		Object selected = dialog.street.getSelectedItem();
-		if (selected == null) {
-			return null;
-		} else {
-			String name = selected.toString();
-			if (name.length() == 0) {
-				return null;
-			} else {
-				return name;
-			}
-		}
-	}
-
-	/* (non-Javadoc)
-	 * @see java.awt.event.FocusListener#focusGained(java.awt.event.FocusEvent)
-	 */
-	public void focusGained(FocusEvent e) {
-		validateInput();
-	}
-
-	/* (non-Javadoc)
-	 * @see java.awt.event.FocusListener#focusLost(java.awt.event.FocusEvent)
-	 */
-	public void focusLost(FocusEvent e) {
-		validateInput();
-	}
-
+        ActionListener, FocusListener {
+
+    private TerracerAction terracerAction;
+    private Way outline, street;
+    private Relation associatedStreet;
+    private HouseNumberInputDialog dialog;
+
+    /**
+     * Instantiates a new house number input handler.
+     *
+     * @param terracerAction the terracer action
+     * @param outline the closed, quadrilateral way to terrace.
+     * @param street the street, the buildings belong to (may be null)
+     * @param associatedStreet a relation where we can add the houses (may be null)
+     * @param title the title
+     */
+    public HouseNumberInputHandler(final TerracerAction terracerAction,
+            final Way outline, final Way street, final Relation associatedStreet,
+            final String title) {
+        this.terracerAction = terracerAction;
+        this.outline = outline;
+        this.street = street;
+        this.associatedStreet = associatedStreet;
+        dialog = new HouseNumberInputDialog(street, associatedStreet != null);
+        dialog.addHandler(this);
+
+        dialog.setVisible(true);
+        dialog.setTitle(title);
+
+    }
+
+    /**
+     * Validate the current input fields.
+     * When the validation fails, a red message is
+     * displayed and the OK button is disabled.
+     *
+     * Should be triggered each time the input changes.
+     */
+    private void validateInput() {
+        boolean isOk = true;
+        StringBuffer message = new StringBuffer();
+
+        isOk = isOk && checkNumberOrder(message);
+        isOk = isOk && checkSegmentsFromHousenumber(message);
+        isOk = isOk && checkSegments(message);
+        isOk = isOk
+                && checkNumberStringField(dialog.lo, tr("Lowest number"),
+                        message);
+        isOk = isOk
+                && checkNumberStringField(dialog.hi, tr("Highest number"),
+                        message);
+        isOk = isOk
+                && checkNumberStringField(dialog.segments, tr("Segments"),
+                        message);
+
+        if (isOk) {
+            dialog.okButton.setEnabled(true);
+            dialog.messageLabel.setForeground(Color.black);
+            dialog.messageLabel
+                    .setText(tr(HouseNumberInputDialog.DEFAULT_MESSAGE));
+
+        } else {
+            dialog.okButton.setEnabled(false);
+            dialog.messageLabel.setForeground(Color.red);
+            dialog.messageLabel.setText(message.toString());
+        }
+    }
+
+    /**
+     * Checks, if the lowest house number is indeed lower than the
+     * highest house number.
+     * This check applies only, if the house number fields are used at all.
+     *
+     * @param message the message
+     *
+     * @return true, if successful
+     */
+    private boolean checkNumberOrder(final StringBuffer message) {
+        if (numberFrom() != null && numberTo() != null) {
+            if (numberFrom().intValue() > numberTo().intValue()) {
+                appendMessageNewLine(message);
+                message
+                        .append(tr("Lowest housenumber cannot be higher than highest housenumber"));
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Obtain the number segments from the house number fields and check,
+     * if they are valid.
+     *
+     * Also disables the segments field, if the house numbers contain
+     * valid information.
+     *
+     * @param message the message
+     *
+     * @return true, if successful
+     */
+    private boolean checkSegmentsFromHousenumber(final StringBuffer message) {
+        dialog.segments.setEditable(true);
+
+        if (numberFrom() != null && numberTo() != null) {
+
+            int segments = numberTo().intValue() - numberFrom().intValue();
+
+            if (segments % stepSize() != 0) {
+                appendMessageNewLine(message);
+                message
+                        .append(tr("Housenumbers do not match odd/even setting"));
+                return false;
+            }
+
+            int steps = segments / stepSize();
+            steps++; // difference 0 means 1 building, see
+            // TerracerActon.terraceBuilding
+            dialog.segments.setText(String.valueOf(steps));
+            dialog.segments.setEditable(false);
+
+        }
+        return true;
+    }
+
+    /**
+     * Check the number of segments.
+     * It must be a number and greater than 1.
+     *
+     * @param message the message
+     *
+     * @return true, if successful
+     */
+    private boolean checkSegments(final StringBuffer message) {
+        if (segments() == null || segments().intValue() < 1) {
+            appendMessageNewLine(message);
+            message.append(tr("Segment must be a number greater 1"));
+            return false;
+
+        }
+        return true;
+    }
+
+    /**
+     * Check, if a string field contains a positive integer.
+     *
+     * @param field the field
+     * @param label the label
+     * @param message the message
+     *
+     * @return true, if successful
+     */
+    private boolean checkNumberStringField(final JTextField field,
+            final String label, final StringBuffer message) {
+        final String content = field.getText();
+        if (content != null && content.length() != 0) {
+            try {
+                int i = Integer.parseInt(content);
+                if (i < 0) {
+                    appendMessageNewLine(message);
+                    message.append(tr("{0} must be greater than 0", label));
+                    return false;
+                }
+            } catch (NumberFormatException e) {
+                appendMessageNewLine(message);
+                message.append(tr("{0} is not a number", label));
+                return false;
+            }
+
+        }
+        return true;
+    }
+
+    /**
+     * Append a new line to the message, if the message is not empty.
+     *
+     * @param message the message
+     */
+    private void appendMessageNewLine(final StringBuffer message) {
+        if (message.length() > 0) {
+            message.append("\n");
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see javax.swing.event.ChangeListener#stateChanged(javax.swing.event.ChangeEvent)
+     */
+    public void stateChanged(ChangeEvent e) {
+        validateInput();
+
+    }
+
+    /* (non-Javadoc)
+     * @see java.awt.event.ItemListener#itemStateChanged(java.awt.event.ItemEvent)
+     */
+    public void itemStateChanged(ItemEvent e) {
+        validateInput();
+    }
+
+    /* (non-Javadoc)
+     * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
+     */
+    public void actionPerformed(final ActionEvent e) {
+
+        // OK or Cancel button-actions
+        if (e.getSource() instanceof JButton) {
+            JButton button = (JButton) e.getSource();
+            if ("OK".equals(button.getName())) {
+                saveValues();
+                terracerAction.terraceBuilding(
+                    outline,
+                    street,
+                    associatedStreet,
+                    segments(),
+                    numberFrom(),
+                    numberTo(),
+                    stepSize(),
+                    streetName(),
+                    doHandleRelation(),
+                    doDeleteOutline());
+
+                this.dialog.dispose();
+            } else if ("CANCEL".equals(button.getName())) {
+                this.dialog.dispose();
+            }
+        } else {
+            // anything else is a change in the input
+            validateInput();
+        }
+
+    }
+
+    /**
+     * Calculate the step size between two house numbers,
+     * based on the interpolation setting.
+     *
+     * @return the stepSize (1 for all, 2 for odd /even)
+     */
+    public int stepSize() {
+        return (dialog.interpolation.getSelectedItem().equals(tr("All"))) ? 1
+                : 2;
+    }
+
+    /**
+     * Gets the number of segments, if set.
+     *
+     * @return the number of segments or null, if not set / invalid.
+     */
+    public Integer segments() {
+        try {
+            return Integer.parseInt(dialog.segments.getText());
+        } catch (NumberFormatException ex) {
+            return null;
+        }
+    }
+
+    /**
+     * Gets the lowest house number.
+     *
+     * @return the number of lowest house number or null, if not set / invalid.
+     */
+    public Integer numberFrom() {
+        try {
+            return Integer.parseInt(dialog.lo.getText());
+        } catch (NumberFormatException ex) {
+            return null;
+        }
+    }
+
+    /**
+     * Gets the highest house number.
+     *
+     * @return the number of highest house number or null, if not set / invalid.
+     */
+    public Integer numberTo() {
+        try {
+            return Integer.parseInt(dialog.hi.getText());
+        } catch (NumberFormatException ex) {
+            return null;
+        }
+    }
+
+    /**
+     * Gets the street name.
+     *
+     * @return the  street name or null, if not set / invalid.
+     */
+    public String streetName() {
+        if (street != null)
+            return null;
+        Object selected = dialog.streetComboBox.getSelectedItem();
+        if (selected == null) {
+            return null;
+        } else {
+            String name = selected.toString();
+            if (name.length() == 0) {
+                return null;
+            } else {
+                return name;
+            }
+        }
+    }
+
+    /**
+     * Whether the user likes to create a relation or add to
+     * an existing one.
+     */
+    public boolean doHandleRelation() {
+        return dialog.handleRelationCheckBox.isSelected();
+    }
+
+    /**
+     * Whether the user likes to delete the outline way.
+     */
+    public boolean doDeleteOutline() {
+        return dialog.deleteOutlineCheckBox.isSelected();
+    }
+
+    /* (non-Javadoc)
+     * @see java.awt.event.FocusListener#focusGained(java.awt.event.FocusEvent)
+     */
+    public void focusGained(FocusEvent e) {
+        validateInput();
+    }
+
+    /* (non-Javadoc)
+     * @see java.awt.event.FocusListener#focusLost(java.awt.event.FocusEvent)
+     */
+    public void focusLost(FocusEvent e) {
+        validateInput();
+    }
+
+    /**
+     * Saves settings.
+     */
+    public void saveValues() {
+        Main.pref.put(HouseNumberInputDialog.HANDLE_RELATION, doHandleRelation());
+        Main.pref.put(HouseNumberInputDialog.DELETE_OUTLINE, doDeleteOutline());
+    }
 }
Index: applications/editors/josm/plugins/terracer/src/terracer/ReverseTerraceAction.java
===================================================================
--- applications/editors/josm/plugins/terracer/src/terracer/ReverseTerraceAction.java	(revision 19627)
+++ applications/editors/josm/plugins/terracer/src/terracer/ReverseTerraceAction.java	(revision 19658)
@@ -32,83 +32,83 @@
 public class ReverseTerraceAction extends JosmAction {
 
-	public ReverseTerraceAction() {
-		super(tr("Reverse a terrace"),
-				"reverse_terrace",
-				tr("Reverses house numbers on a terrace."),
-				Shortcut.registerShortcut("tools:ReverseTerrace",
-						tr("Tool: {0}", tr("Reverse a Terrace")),
-						KeyEvent.VK_R, Shortcut.GROUP_EDIT,
-						Shortcut.SHIFT_DEFAULT),
-						true);
-	}
+    public ReverseTerraceAction() {
+        super(tr("Reverse a terrace"),
+                "reverse_terrace",
+                tr("Reverses house numbers on a terrace."),
+                Shortcut.registerShortcut("tools:ReverseTerrace",
+                        tr("Tool: {0}", tr("Reverse a Terrace")),
+                        KeyEvent.VK_R, Shortcut.GROUP_EDIT,
+                        Shortcut.SHIFT_DEFAULT),
+                        true);
+    }
 
-	/**
-	 * Breadth-first searches based on the selection while the selection is a way
-	 * with a building=* tag and then applies the addr:housenumber tag in reverse
-	 * order.
-	 */
-	public void actionPerformed(ActionEvent e) {
-		Collection<OsmPrimitive> sel = Main.main.getCurrentDataSet().getSelected();
+    /**
+     * Breadth-first searches based on the selection while the selection is a way
+     * with a building=* tag and then applies the addr:housenumber tag in reverse
+     * order.
+     */
+    public void actionPerformed(ActionEvent e) {
+        Collection<OsmPrimitive> sel = Main.main.getCurrentDataSet().getSelected();
 
-		// set to keep track of all the nodes that have been visited - that is: if
-		// we encounter them again we will not follow onto the connected ways.
-		HashSet<Node> visitedNodes = new HashSet<Node>();
+        // set to keep track of all the nodes that have been visited - that is: if
+        // we encounter them again we will not follow onto the connected ways.
+        HashSet<Node> visitedNodes = new HashSet<Node>();
 
-		// set to keep track of the ways the algorithm has seen, but not yet visited.
-		// since when a way is visited all of its nodes are marked as visited, there
-		// is no need to keep a visitedWays set.
-		HashSet<Way> front = new HashSet<Way>();
+        // set to keep track of the ways the algorithm has seen, but not yet visited.
+        // since when a way is visited all of its nodes are marked as visited, there
+        // is no need to keep a visitedWays set.
+        HashSet<Way> front = new HashSet<Way>();
 
-		// initialise the set with all the buildings in the selection. this means
-		// there is undefined behaviour when there is a multiple selection, as the
-		// ordering will be based on the hash.
-		for (OsmPrimitive prim : sel) {
-			if (prim.keySet().contains("building") && prim instanceof Way) {
-				front.add((Way)prim);
-			}
-		}
+        // initialise the set with all the buildings in the selection. this means
+        // there is undefined behaviour when there is a multiple selection, as the
+        // ordering will be based on the hash.
+        for (OsmPrimitive prim : sel) {
+            if (prim.keySet().contains("building") && prim instanceof Way) {
+                front.add((Way)prim);
+            }
+        }
 
-		// this is like a visitedWays set, but in a linear order.
-		LinkedList<Way> orderedWays = new LinkedList<Way>();
+        // this is like a visitedWays set, but in a linear order.
+        LinkedList<Way> orderedWays = new LinkedList<Way>();
 
-		// and the tags to reverse on the orderedWays.
-		LinkedList<String> houseNumbers = new LinkedList<String>();
+        // and the tags to reverse on the orderedWays.
+        LinkedList<String> houseNumbers = new LinkedList<String>();
 
-		while (front.size() > 0) {
-			// Java apparently doesn't have useful methods to get single items from sets...
-			Way w = front.iterator().next();
+        while (front.size() > 0) {
+            // Java apparently doesn't have useful methods to get single items from sets...
+            Way w = front.iterator().next();
 
-			// visit all the nodes in the way, adding the building's they're members of
-			// to the front.
-			for (Node n : w.getNodes()) {
-				if (!visitedNodes.contains(n)) {
-					for (OsmPrimitive prim : n.getReferrers()) {
-						if (prim.keySet().contains("building") && prim instanceof Way) {
-							front.add((Way)prim);
-						}
-					}
-					visitedNodes.add(n);
-				}
-			}
+            // visit all the nodes in the way, adding the building's they're members of
+            // to the front.
+            for (Node n : w.getNodes()) {
+                if (!visitedNodes.contains(n)) {
+                    for (OsmPrimitive prim : n.getReferrers()) {
+                        if (prim.keySet().contains("building") && prim instanceof Way) {
+                            front.add((Way)prim);
+                        }
+                    }
+                    visitedNodes.add(n);
+                }
+            }
 
-			// we've finished visiting this way, so record the attributes we're interested
-			// in for re-writing.
-			front.remove(w);
-			orderedWays.addLast(w);
-			houseNumbers.addFirst(w.get("addr:housenumber"));
-		}
+            // we've finished visiting this way, so record the attributes we're interested
+            // in for re-writing.
+            front.remove(w);
+            orderedWays.addLast(w);
+            houseNumbers.addFirst(w.get("addr:housenumber"));
+        }
 
-		Collection<Command> commands = new LinkedList<Command>();
-		// what, no zipWith?
-		for (int i = 0; i < orderedWays.size(); ++i) {
-			commands.add(new ChangePropertyCommand(
-					orderedWays.get(i),
-					"addr:housenumber",
-					houseNumbers.get(i)));
-		}
+        Collection<Command> commands = new LinkedList<Command>();
+        // what, no zipWith?
+        for (int i = 0; i < orderedWays.size(); ++i) {
+            commands.add(new ChangePropertyCommand(
+                    orderedWays.get(i),
+                    "addr:housenumber",
+                    houseNumbers.get(i)));
+        }
 
-		Main.main.undoRedo.add(new SequenceCommand(tr("Reverse Terrace"), commands));
-		Main.main.getCurrentDataSet().setSelected(orderedWays);
-	}
+        Main.main.undoRedo.add(new SequenceCommand(tr("Reverse Terrace"), commands));
+        Main.main.getCurrentDataSet().setSelected(orderedWays);
+    }
 
 }
Index: applications/editors/josm/plugins/terracer/src/terracer/TerracerAction.java
===================================================================
--- applications/editors/josm/plugins/terracer/src/terracer/TerracerAction.java	(revision 19627)
+++ applications/editors/josm/plugins/terracer/src/terracer/TerracerAction.java	(revision 19658)
@@ -16,5 +16,7 @@
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Iterator;
 import java.util.LinkedList;
+import java.util.List;
 
 import javax.swing.JOptionPane;
@@ -23,5 +25,7 @@
 import org.openstreetmap.josm.actions.JosmAction;
 import org.openstreetmap.josm.command.AddCommand;
+import org.openstreetmap.josm.command.ChangeCommand;
 import org.openstreetmap.josm.command.Command;
+import org.openstreetmap.josm.command.DeleteCommand;
 import org.openstreetmap.josm.command.SequenceCommand;
 import org.openstreetmap.josm.data.coor.LatLon;
@@ -36,5 +40,8 @@
 /**
  * Terraces a quadrilateral, closed way into a series of quadrilateral,
- * closed ways.
+ * closed ways. If two ways are selected and one of them can be identified as
+ * a street (highway=*, name=*) then the given street will be added
+ * to the 'associatedStreet' relation.
+ *
  *
  * At present it only works on quadrilaterals, but there is no reason
@@ -46,376 +53,409 @@
 public final class TerracerAction extends JosmAction {
 
-	// smsms1 asked for the last value to be remembered to make it easier to do
-	// repeated terraces. this is the easiest, but not necessarily nicest, way.
-	// private static String lastSelectedValue = "";
-
-	public TerracerAction() {
-		super(tr("Terrace a building"), "terrace",
-				tr("Creates individual buildings from a long building."),
-				Shortcut.registerShortcut("tools:Terracer", tr("Tool: {0}",
-						tr("Terrace a building")), KeyEvent.VK_T,
-						Shortcut.GROUP_EDIT, Shortcut.SHIFT_DEFAULT), true);
-	}
-
-	/**
-	 * Checks that the selection is OK. If not, displays error message. If so
-	 * calls to terraceBuilding(), which does all the real work.
-	 */
-	public void actionPerformed(ActionEvent e) {
-		Collection<OsmPrimitive> sel = Main.main.getCurrentDataSet()
-				.getSelected();
-		boolean badSelect = false;
-
-		if (sel.size() == 1) {
-			OsmPrimitive prim = sel.iterator().next();
-
-			if (prim instanceof Way) {
-				Way way = (Way) prim;
-
-				if ((way.getNodesCount() >= 5) && way.isClosed()) {
-					String title = trn("Change {0} object",
-							"Change {0} objects", sel.size(), sel.size());
-					if (sel.size() == 0)
-						title = tr("Nothing selected!");
-
-					// show input dialog.
-					new HouseNumberInputHandler(this, way, title);
-
-				} else {
-					badSelect = true;
-				}
-			} else {
-				badSelect = true;
-			}
-		} else {
-			badSelect = true;
-		}
-
-		if (badSelect) {
-			JOptionPane.showMessageDialog(Main.parent,
-					tr("Select a single, closed way of at least four nodes."));
-		}
-	}
-
-	/**
-	 * Terraces a single, closed, quadrilateral way.
-	 *
-	 * Any node must be adjacent to both a short and long edge, we naively
-	 * choose the longest edge and its opposite and interpolate along them
-	 * linearly to produce new nodes. Those nodes are then assembled into
-	 * closed, quadrilateral ways and left in the selection.
-	 *
-	 * @param w The closed, quadrilateral way to terrace.
-	 */
-	public void terraceBuilding(Way w, Integer segments, Integer from,
-			Integer to, int step, String streetName) {
-		final int nb;
-		if (to != null && from != null) {
-			nb = 1 + (to.intValue() - from.intValue()) / step;
-		} else if (segments != null) {
-			nb = segments.intValue();
-		} else {
-			// if we get here, there is is a bug in the input validation.
-			throw new TerracerRuntimeException(
-					"Could not determine segments from parameters, this is a bug. "
-							+ "Parameters were: segments " + segments
-							+ " from " + from + " to " + to + " step " + step);
-		}
-
-		// now find which is the longest side connecting the first node
-		Pair<Way, Way> interp = findFrontAndBack(w);
-
-		final double frontLength = wayLength(interp.a);
-		final double backLength = wayLength(interp.b);
-
-		// new nodes array to hold all intermediate nodes
-		Node[][] new_nodes = new Node[2][nb + 1];
-
-		Collection<Command> commands = new LinkedList<Command>();
-		Collection<Way> ways = new LinkedList<Way>();
-
-		// create intermediate nodes by interpolating.
-		for (int i = 0; i <= nb; ++i) {
-			new_nodes[0][i] = interpolateAlong(interp.a, frontLength * (i)
-					/ (nb));
-			new_nodes[1][i] = interpolateAlong(interp.b, backLength * (i)
-					/ (nb));
-			commands.add(new AddCommand(new_nodes[0][i]));
-			commands.add(new AddCommand(new_nodes[1][i]));
-		}
-
-		// create a new relation for addressing
-		Relation relatedStreet = new Relation();
-		relatedStreet.put("type", "relatedStreet");
-		if (streetName != null) {
-			relatedStreet.put("name", streetName);
-		}
-		// note that we don't actually add the street member to the relation, as
-		// the name isn't unambiguous and it could cause confusion if the editor
-		// were
-		// to automatically select one which wasn't the one the user intended.
-
-		// assemble new quadrilateral, closed ways
-		for (int i = 0; i < nb; ++i) {
-			Way terr = new Way();
-			// Using Way.nodes.add rather than Way.addNode because the latter
-			// doesn't
-			// exist in older versions of JOSM.
-			terr.addNode(new_nodes[0][i]);
-			terr.addNode(new_nodes[0][i + 1]);
-			terr.addNode(new_nodes[1][i + 1]);
-			terr.addNode(new_nodes[1][i]);
-			terr.addNode(new_nodes[0][i]);
-
-			if (from != null) {
-				// only, if the user has specified house numbers
-				terr.put("addr:housenumber", "" + (from + i * step));
-			}
-			terr.put("building", "yes");
-			if (streetName != null) {
-				terr.put("addr:street", streetName);
-			}
-			relatedStreet.addMember(new RelationMember("house", terr));
-			ways.add(terr);
-			commands.add(new AddCommand(terr));
-		}
-
-		commands.add(new AddCommand(relatedStreet));
-
-		Main.main.undoRedo.add(new SequenceCommand(tr("Terrace"), commands));
-		Main.main.getCurrentDataSet().setSelected(ways);
-	}
-
-	/**
-	 * Creates a node at a certain distance along a way, as calculated by the
-	 * great circle distance.
-	 *
-	 * Note that this really isn't an efficient way to do this and leads to
-	 * O(N^2) running time for the main algorithm, but its simple and easy
-	 * to understand, and probably won't matter for reasonable-sized ways.
-	 *
-	 * @param w The way to interpolate.
-	 * @param l The length at which to place the node.
-	 * @return A node at a distance l along w from the first point.
-	 */
-	private Node interpolateAlong(Way w, double l) {
-		Node n = null;
-		for (Pair<Node, Node> p : w.getNodePairs(false)) {
-			final double seg_length = p.a.getCoor().greatCircleDistance(
-					p.b.getCoor());
-			if (l <= seg_length) {
-				n = interpolateNode(p.a, p.b, l / seg_length);
-				break;
-			} else {
-				l -= seg_length;
-			}
-		}
-		if (n == null) {
-			// sometimes there is a small overshoot due to numerical roundoff,
-			// so we just
-			// set these cases to be equal to the last node. its not pretty, but
-			// it works ;-)
-			n = w.getNode(w.getNodesCount() - 1);
-		}
-		return n;
-	}
-
-	/**
-	 * Calculates the great circle length of a way by summing the great circle
-	 * distance of each pair of nodes.
-	 *
-	 * @param w The way to calculate length of.
-	 * @return The length of the way.
-	 */
-	private double wayLength(Way w) {
-		double length = 0.0;
-		for (Pair<Node, Node> p : w.getNodePairs(false)) {
-			length += p.a.getCoor().greatCircleDistance(p.b.getCoor());
-		}
-		return length;
-	}
-
-	/**
-	 * Given a way, try and find a definite front and back by looking at the
-	 * segments to find the "sides". Sides are assumed to be single segments
-	 * which cannot be contiguous.
-	 *
-	 * @param w The way to analyse.
-	 * @return A pair of ways (front, back) pointing in the same directions.
-	 */
-	private Pair<Way, Way> findFrontAndBack(Way w) {
-		// calculate the "side-ness" score for each segment of the way
-		double[] sideness = calculateSideness(w);
-
-		// find the largest two sidenesses which are not contiguous
-		int[] indexes = sortedIndexes(sideness);
-		int side1 = indexes[0];
-		int side2 = indexes[1];
-		// if side2 is contiguous with side1 then look further down the
-		// list. we know there are at least 4 sides, as anything smaller
-		// than a quadrilateral would have been rejected at an earlier
-		// stage.
-		if (Math.abs(side1 - side2) < 2) {
-			side2 = indexes[2];
-		}
-		if (Math.abs(side1 - side2) < 2) {
-			side2 = indexes[3];
-		}
-
-		// if the second side has a shorter length and an approximately equal
-		// sideness then its better to choose the shorter, as with
-		// quadrilaterals
-		// created using the orthogonalise tool the sideness will be about the
-		// same for all sides.
-		if (sideLength(w, side1) > sideLength(w, side1 + 1)
-				&& Math.abs(sideness[side1] - sideness[side1 + 1]) < 0.001) {
-			side1 = side1 + 1;
-			side2 = (side2 + 1) % (w.getNodesCount() - 1);
-		}
-
-		// swap side1 and side2 into sorted order.
-		if (side1 > side2) {
-			// i can't believe i have to write swap() myself - surely java
-			// standard
-			// library has this somewhere??!!?ONE!
-			int tmp = side2;
-			side2 = side1;
-			side1 = tmp;
-		}
-
-		Way front = new Way();
-		Way back = new Way();
-		for (int i = side2 + 1; i < w.getNodesCount() - 1; ++i) {
-			front.addNode(w.getNode(i));
-		}
-		for (int i = 0; i <= side1; ++i) {
-			front.addNode(w.getNode(i));
-		}
-		// add the back in reverse order so that the front and back ways point
-		// in the same direction.
-		for (int i = side2; i > side1; --i) {
-			back.addNode(w.getNode(i));
-		}
-
-		return new Pair<Way, Way>(front, back);
-	}
-
-	/**
-	 * Calculate the length of a side (from node i to i+1) in a way. This assumes that
-	 * the way is closed, but I only ever call it for buildings.
-	 */
-	private double sideLength(Way w, int i) {
-		Node a = w.getNode(i);
-		Node b = w.getNode((i + 1) % (w.getNodesCount() - 1));
-		return a.getCoor().greatCircleDistance(b.getCoor());
-	}
-
-	/**
-	 * Given an array of doubles (but this could made generic very easily) sort
-	 * into order and return the array of indexes such that, for a returned array
-	 * x, a[x[i]] is sorted for ascending index i.
-	 *
-	 * This isn't efficient at all, but should be fine for the small arrays we're
-	 * expecting. If this gets slow - replace it with some more efficient algorithm.
-	 *
-	 * @param a The array to sort.
-	 * @return An array of indexes, the same size as the input, such that a[x[i]]
-	 * is in sorted order.
-	 */
-	private int[] sortedIndexes(final double[] a) {
-		class SortWithIndex implements Comparable<SortWithIndex> {
-			public double x;
-			public int i;
-
-			public SortWithIndex(double a, int b) {
-				x = a;
-				i = b;
-			}
-
-			public int compareTo(SortWithIndex o) {
-				return Double.compare(x, o.x);
-			};
-		}
-
-		final int length = a.length;
-		ArrayList<SortWithIndex> sortable = new ArrayList<SortWithIndex>(length);
-		for (int i = 0; i < length; ++i) {
-			sortable.add(new SortWithIndex(a[i], i));
-		}
-		Collections.sort(sortable);
-
-		int[] indexes = new int[length];
-		for (int i = 0; i < length; ++i) {
-			indexes[i] = sortable.get(i).i;
-		}
-
-		return indexes;
-	}
-
-	/**
-	 * Calculate "sideness" metric for each segment in a way.
-	 */
-	private double[] calculateSideness(Way w) {
-		final int length = w.getNodesCount() - 1;
-		double[] sideness = new double[length];
-
-		sideness[0] = calculateSideness(w.getNode(length - 1), w.getNode(0), w
-				.getNode(1), w.getNode(2));
-		for (int i = 1; i < length - 1; ++i) {
-			sideness[i] = calculateSideness(w.getNode(i - 1), w.getNode(i), w
-					.getNode(i + 1), w.getNode(i + 2));
-		}
-		sideness[length - 1] = calculateSideness(w.getNode(length - 2), w
-				.getNode(length - 1), w.getNode(length), w.getNode(1));
-
-		return sideness;
-	}
-
-	/**
-	 * Calculate sideness of a single segment given the nodes which make up that
-	 * segment and its previous and next segments in order. Sideness is calculated
-	 * for the segment b-c.
-	 */
-	private double calculateSideness(Node a, Node b, Node c, Node d) {
-		final double ndx = b.getCoor().getX() - a.getCoor().getX();
-		final double pdx = d.getCoor().getX() - c.getCoor().getX();
-		final double ndy = b.getCoor().getY() - a.getCoor().getY();
-		final double pdy = d.getCoor().getY() - c.getCoor().getY();
-
-		return (ndx * pdx + ndy * pdy)
-				/ Math.sqrt((ndx * ndx + ndy * ndy) * (pdx * pdx + pdy * pdy));
-	}
-
-	/**
-	 * Creates a new node at the interpolated position between the argument
-	 * nodes. Interpolates linearly in Lat/Lon coordinates.
-	 *
-	 * @param a First node, at which f=0.
-	 * @param b Last node, at which f=1.
-	 * @param f Fractional position between first and last nodes.
-	 * @return A new node at the interpolated position.
-	 */
-	private Node interpolateNode(Node a, Node b, double f) {
-		Node n = new Node(interpolateLatLon(a, b, f));
-		return n;
-	}
-
-	/**
-	 * Calculates the interpolated position between the argument nodes. Interpolates
-	 * linearly in Lat/Lon coordinates.
-	 *
-	 * @param a First node, at which f=0.
-	 * @param b Last node, at which f=1.
-	 * @param f Fractional position between first and last nodes.
-	 * @return The interpolated position.
-	 */
-	private LatLon interpolateLatLon(Node a, Node b, double f) {
-		// this isn't quite right - we should probably be interpolating
-		// screen coordinates rather than lat/lon, but it doesn't seem to
-		// make a great deal of difference at the scale of most terraces.
-		return new LatLon(
-				a.getCoor().lat() * (1.0 - f) + b.getCoor().lat() * f, a
-						.getCoor().lon()
-						* (1.0 - f) + b.getCoor().lon() * f);
-	}
+    // smsms1 asked for the last value to be remembered to make it easier to do
+    // repeated terraces. this is the easiest, but not necessarily nicest, way.
+    // private static String lastSelectedValue = "";
+
+    public TerracerAction() {
+        super(tr("Terrace a building"), "terrace",
+                tr("Creates individual buildings from a long building."),
+                Shortcut.registerShortcut("tools:Terracer", tr("Tool: {0}",
+                        tr("Terrace a building")), KeyEvent.VK_T,
+                        Shortcut.GROUP_EDIT, Shortcut.SHIFT_DEFAULT), true);
+    }
+
+    /**
+     * Checks that the selection is OK. If not, displays error message. If so
+     * calls to terraceBuilding(), which does all the real work.
+     */
+    public void actionPerformed(ActionEvent e) {
+        Collection<OsmPrimitive> sel = Main.main.getCurrentDataSet()
+                .getSelected();
+        Way outline = null;
+        Way street = null;
+
+        class InvalidUserInputException extends Exception {
+            InvalidUserInputException(String message) {
+                super(message);
+            }
+            InvalidUserInputException() {
+                super();
+            }
+        }
+
+        try {
+            if (sel.size() == 2) {
+                Iterator<OsmPrimitive> it = sel.iterator();
+                OsmPrimitive prim1 = it.next();
+                OsmPrimitive prim2 = it.next();
+                if (!(prim1 instanceof Way && prim2 instanceof Way))
+                    throw new InvalidUserInputException();
+                Way way1 = (Way) prim1;
+                Way way2 = (Way) prim2;
+                if (way2.get("highway") != null) {
+                    street = way2;
+                    outline = way1;
+                } else if (way1.get("highway") != null) {
+                    street = way1;
+                    outline = way2;
+                } else
+                    throw new InvalidUserInputException();
+                if (street.get("name") == null)
+                    throw new InvalidUserInputException();
+
+            } else if (sel.size() == 1) {
+                OsmPrimitive prim = sel.iterator().next();
+
+                if (!(prim instanceof Way))
+                    throw new InvalidUserInputException();
+
+                outline = (Way)prim;
+            } else
+                throw new InvalidUserInputException();
+
+            if (outline.getNodesCount() < 5)
+                throw new InvalidUserInputException();
+
+            if (!outline.isClosed())
+                throw new InvalidUserInputException();
+        } catch (InvalidUserInputException ex) {
+            JOptionPane.showMessageDialog(Main.parent,
+                    tr("Select a single, closed way of at least four nodes."));
+            return;
+        }
+
+        // If we have a street, try to find a associatedStreet relation that could be reused.
+        Relation associatedStreet = null;
+        if (street != null) {
+            outer:for (OsmPrimitive osm : Main.main.getCurrentDataSet().allNonDeletedPrimitives()) {
+                if (!(osm instanceof Relation)) continue;
+                Relation rel = (Relation) osm;
+                if ("associatedStreet".equals(rel.get("type")) && street.get("name").equals(rel.get("name"))) {
+                    List<RelationMember> members = rel.getMembers();
+                    for (RelationMember m : members) {
+                        if ("street".equals(m.getRole()) && m.isWay() && m.getMember().equals(street)) {
+                            associatedStreet = rel;
+                            break outer;
+                        }
+                    }
+                }
+            }
+        }
+
+        String title = trn("Change {0} object", "Change {0} objects", sel.size(), sel.size());
+        // show input dialog.
+        new HouseNumberInputHandler(this, outline, street, associatedStreet, title);
+    }
+
+    /**
+     * Terraces a single, closed, quadrilateral way.
+     *
+     * Any node must be adjacent to both a short and long edge, we naively
+     * choose the longest edge and its opposite and interpolate along them
+     * linearly to produce new nodes. Those nodes are then assembled into
+     * closed, quadrilateral ways and left in the selection.
+     *
+     * @param outline The closed, quadrilateral way to terrace.
+     * @param street The street, the buildings belong to (may be null)
+     * @param handleRelations If the user likes to add a relation or extend an existing relation
+     * @param deleteOutline If the outline way should be deleted, when done
+     */
+    public void terraceBuilding(Way outline, Way street, Relation associatedStreet, Integer segments, Integer from,
+            Integer to, int step, String streetName, boolean handleRelations, boolean deleteOutline) {
+        final int nb;
+        if (to != null && from != null) {
+            nb = 1 + (to.intValue() - from.intValue()) / step;
+        } else if (segments != null) {
+            nb = segments.intValue();
+        } else {
+            // if we get here, there is is a bug in the input validation.
+            throw new TerracerRuntimeException(
+                    "Could not determine segments from parameters, this is a bug. "
+                            + "Parameters were: segments " + segments
+                            + " from " + from + " to " + to + " step " + step);
+        }
+
+        // now find which is the longest side connecting the first node
+        Pair<Way, Way> interp = findFrontAndBack(outline);
+
+        final double frontLength = wayLength(interp.a);
+        final double backLength = wayLength(interp.b);
+
+        // new nodes array to hold all intermediate nodes
+        Node[][] new_nodes = new Node[2][nb + 1];
+
+        Collection<Command> commands = new LinkedList<Command>();
+        Collection<Way> ways = new LinkedList<Way>();
+
+        // create intermediate nodes by interpolating.
+        for (int i = 0; i <= nb; ++i) {
+            new_nodes[0][i] = interpolateAlong(interp.a, frontLength * (i)
+                    / (nb));
+            new_nodes[1][i] = interpolateAlong(interp.b, backLength * (i)
+                    / (nb));
+            commands.add(new AddCommand(new_nodes[0][i]));
+            commands.add(new AddCommand(new_nodes[1][i]));
+        }
+
+        // assemble new quadrilateral, closed ways
+        for (int i = 0; i < nb; ++i) {
+            Way terr = new Way();
+            // Using Way.nodes.add rather than Way.addNode because the latter
+            // doesn't
+            // exist in older versions of JOSM.
+            terr.addNode(new_nodes[0][i]);
+            terr.addNode(new_nodes[0][i + 1]);
+            terr.addNode(new_nodes[1][i + 1]);
+            terr.addNode(new_nodes[1][i]);
+            terr.addNode(new_nodes[0][i]);
+            if (from != null) {
+                // only, if the user has specified house numbers
+                terr.put("addr:housenumber", "" + (from + i * step));
+            }
+            terr.put("building", "yes");
+            if (street != null) {
+                terr.put("addr:street", street.get("name"));
+            } else if (streetName != null) {
+                terr.put("addr:street", streetName);
+            }
+            ways.add(terr);
+            commands.add(new AddCommand(terr));
+        }
+
+        if (handleRelations) { // create a new relation or merge with existing
+            if (associatedStreet == null) {  // create a new relation
+                associatedStreet = new Relation();
+                associatedStreet.put("type", "associatedStreet");
+                if (street != null) { // a street was part of the selection
+                    associatedStreet.put("name", street.get("name"));
+                    associatedStreet.addMember(new RelationMember("street", street));
+                } else {
+                    associatedStreet.put("name", streetName);
+                }
+                for (Way w : ways) {
+                    associatedStreet.addMember(new RelationMember("house", w));
+                }
+                commands.add(new AddCommand(associatedStreet));
+            }
+            else { // relation exists already - add new members
+                Relation newAssociatedStreet = new Relation(associatedStreet);
+                for (Way w : ways) {
+                    newAssociatedStreet.addMember(new RelationMember("house", w));
+                }
+                commands.add(new ChangeCommand(associatedStreet, newAssociatedStreet));
+            }
+        }
+
+        if (deleteOutline) {
+            commands.add(DeleteCommand.delete(Main.main.getEditLayer(), Collections.singleton(outline), true, true));
+        }
+
+        Main.main.undoRedo.add(new SequenceCommand(tr("Terrace"), commands));
+        Main.main.getCurrentDataSet().setSelected(ways);
+    }
+
+    /**
+     * Creates a node at a certain distance along a way, as calculated by the
+     * great circle distance.
+     *
+     * Note that this really isn't an efficient way to do this and leads to
+     * O(N^2) running time for the main algorithm, but its simple and easy
+     * to understand, and probably won't matter for reasonable-sized ways.
+     *
+     * @param w The way to interpolate.
+     * @param l The length at which to place the node.
+     * @return A node at a distance l along w from the first point.
+     */
+    private Node interpolateAlong(Way w, double l) {
+        List<Pair<Node,Node>> pairs = w.getNodePairs(false);
+        for (int i = 0; i < pairs.size(); ++i) {
+            Pair<Node,Node> p = pairs.get(i);
+            final double seg_length = p.a.getCoor().greatCircleDistance(p.b.getCoor());
+            if (l <= seg_length ||
+                    i == pairs.size() - 1) {    // be generous on the last segment (numerical roudoff can lead to a small overshoot)
+                return interpolateNode(p.a, p.b, l / seg_length);
+            } else {
+                l -= seg_length;
+            }
+        }
+        // we shouldn't get here
+        throw new IllegalStateException();
+    }
+
+    /**
+     * Calculates the great circle length of a way by summing the great circle
+     * distance of each pair of nodes.
+     *
+     * @param w The way to calculate length of.
+     * @return The length of the way.
+     */
+    private double wayLength(Way w) {
+        double length = 0.0;
+        for (Pair<Node, Node> p : w.getNodePairs(false)) {
+            length += p.a.getCoor().greatCircleDistance(p.b.getCoor());
+        }
+        return length;
+    }
+
+    /**
+     * Given a way, try and find a definite front and back by looking at the
+     * segments to find the "sides". Sides are assumed to be single segments
+     * which cannot be contiguous.
+     *
+     * @param w The way to analyse.
+     * @return A pair of ways (front, back) pointing in the same directions.
+     */
+    private Pair<Way, Way> findFrontAndBack(Way w) {
+        // calculate the "side-ness" score for each segment of the way
+        double[] sideness = calculateSideness(w);
+
+        // find the largest two sidenesses which are not contiguous
+        int[] indexes = sortedIndexes(sideness);
+        int side1 = indexes[0];
+        int side2 = indexes[1];
+        // if side2 is contiguous with side1 then look further down the
+        // list. we know there are at least 4 sides, as anything smaller
+        // than a quadrilateral would have been rejected at an earlier
+        // stage.
+        if (Math.abs(side1 - side2) < 2) {
+            side2 = indexes[2];
+        }
+        if (Math.abs(side1 - side2) < 2) {
+            side2 = indexes[3];
+        }
+
+        // if the second side has a shorter length and an approximately equal
+        // sideness then its better to choose the shorter, as with
+        // quadrilaterals
+        // created using the orthogonalise tool the sideness will be about the
+        // same for all sides.
+        if (sideLength(w, side1) > sideLength(w, side1 + 1)
+                && Math.abs(sideness[side1] - sideness[side1 + 1]) < 0.001) {
+            side1 = side1 + 1;
+            side2 = (side2 + 1) % (w.getNodesCount() - 1);
+        }
+
+        // swap side1 and side2 into sorted order.
+        if (side1 > side2) {
+            int tmp = side2;
+            side2 = side1;
+            side1 = tmp;
+        }
+
+        Way front = new Way();
+        Way back = new Way();
+        for (int i = side2 + 1; i < w.getNodesCount() - 1; ++i) {
+            front.addNode(w.getNode(i));
+        }
+        for (int i = 0; i <= side1; ++i) {
+            front.addNode(w.getNode(i));
+        }
+        // add the back in reverse order so that the front and back ways point
+        // in the same direction.
+        for (int i = side2; i > side1; --i) {
+            back.addNode(w.getNode(i));
+        }
+
+        return new Pair<Way, Way>(front, back);
+    }
+
+    /**
+     * Calculate the length of a side (from node i to i+1) in a way. This assumes that
+     * the way is closed, but I only ever call it for buildings.
+     */
+    private double sideLength(Way w, int i) {
+        Node a = w.getNode(i);
+        Node b = w.getNode((i + 1) % (w.getNodesCount() - 1));
+        return a.getCoor().greatCircleDistance(b.getCoor());
+    }
+
+    /**
+     * Given an array of doubles (but this could made generic very easily) sort
+     * into order and return the array of indexes such that, for a returned array
+     * x, a[x[i]] is sorted for ascending index i.
+     *
+     * This isn't efficient at all, but should be fine for the small arrays we're
+     * expecting. If this gets slow - replace it with some more efficient algorithm.
+     *
+     * @param a The array to sort.
+     * @return An array of indexes, the same size as the input, such that a[x[i]]
+     * is in sorted order.
+     */
+    private int[] sortedIndexes(final double[] a) {
+        class SortWithIndex implements Comparable<SortWithIndex> {
+            public double x;
+            public int i;
+
+            public SortWithIndex(double a, int b) {
+                x = a;
+                i = b;
+            }
+
+            public int compareTo(SortWithIndex o) {
+                return Double.compare(x, o.x);
+            };
+        }
+
+        final int length = a.length;
+        ArrayList<SortWithIndex> sortable = new ArrayList<SortWithIndex>(length);
+        for (int i = 0; i < length; ++i) {
+            sortable.add(new SortWithIndex(a[i], i));
+        }
+        Collections.sort(sortable);
+
+        int[] indexes = new int[length];
+        for (int i = 0; i < length; ++i) {
+            indexes[i] = sortable.get(i).i;
+        }
+
+        return indexes;
+    }
+
+    /**
+     * Calculate "sideness" metric for each segment in a way.
+     */
+    private double[] calculateSideness(Way w) {
+        final int length = w.getNodesCount() - 1;
+        double[] sideness = new double[length];
+
+        sideness[0] = calculateSideness(w.getNode(length - 1), w.getNode(0), w
+                .getNode(1), w.getNode(2));
+        for (int i = 1; i < length - 1; ++i) {
+            sideness[i] = calculateSideness(w.getNode(i - 1), w.getNode(i), w
+                    .getNode(i + 1), w.getNode(i + 2));
+        }
+        sideness[length - 1] = calculateSideness(w.getNode(length - 2), w
+                .getNode(length - 1), w.getNode(length), w.getNode(1));
+
+        return sideness;
+    }
+
+    /**
+     * Calculate sideness of a single segment given the nodes which make up that
+     * segment and its previous and next segments in order. Sideness is calculated
+     * for the segment b-c.
+     */
+    private double calculateSideness(Node a, Node b, Node c, Node d) {
+        final double ndx = b.getCoor().getX() - a.getCoor().getX();
+        final double pdx = d.getCoor().getX() - c.getCoor().getX();
+        final double ndy = b.getCoor().getY() - a.getCoor().getY();
+        final double pdy = d.getCoor().getY() - c.getCoor().getY();
+
+        return (ndx * pdx + ndy * pdy)
+                / Math.sqrt((ndx * ndx + ndy * ndy) * (pdx * pdx + pdy * pdy));
+    }
+
+    /**
+     * Creates a new node at the interpolated position between the argument
+     * nodes. Interpolates linearly in projected coordinates.
+     *
+     * @param a First node, at which f=0.
+     * @param b Last node, at which f=1.
+     * @param f Fractional position between first and last nodes.
+     * @return A new node at the interpolated position.
+     */
+    private Node interpolateNode(Node a, Node b, double f) {
+        Node n = new Node(a.getEastNorth().interpolate(b.getEastNorth(), f));
+        return n;
+    }
 }
Index: applications/editors/josm/plugins/terracer/src/terracer/TerracerPlugin.java
===================================================================
--- applications/editors/josm/plugins/terracer/src/terracer/TerracerPlugin.java	(revision 19627)
+++ applications/editors/josm/plugins/terracer/src/terracer/TerracerPlugin.java	(revision 19658)
@@ -19,9 +19,9 @@
  */
 public class TerracerPlugin extends Plugin {
-	public TerracerPlugin(PluginInformation info) {
-		super(info);
-		
-		MainMenu.add(Main.main.menu.toolsMenu, new TerracerAction());
-		MainMenu.add(Main.main.menu.toolsMenu, new ReverseTerraceAction());
-	}
+    public TerracerPlugin(PluginInformation info) {
+        super(info);
+        
+        MainMenu.add(Main.main.menu.toolsMenu, new TerracerAction());
+        MainMenu.add(Main.main.menu.toolsMenu, new ReverseTerraceAction());
+    }
 }
