Index: /trunk/src/org/openstreetmap/josm/io/remotecontrol/AddTagsDialog.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/io/remotecontrol/AddTagsDialog.java	(revision 3850)
+++ /trunk/src/org/openstreetmap/josm/io/remotecontrol/AddTagsDialog.java	(revision 3850)
@@ -0,0 +1,155 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.io.remotecontrol;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.util.Collection;
+
+import javax.swing.JPanel;
+import javax.swing.JTable;
+import javax.swing.table.DefaultTableModel;
+import javax.swing.table.TableCellRenderer;
+import javax.swing.table.TableModel;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.command.ChangePropertyCommand;
+import org.openstreetmap.josm.data.SelectionChangedListener;
+import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.gui.ExtendedDialog;
+import org.openstreetmap.josm.tools.GBC;
+
+/**
+ * 
+ * @author master
+ * 
+ * Dialog to add tags as part of the remotecontrol
+ * Existing Keys get grey color and unchecked selectboxes so they will not overwrite the old Key-Value-Pairs by default.
+ * You can choose the tags you want to add by selectboxes. You can edit the tags before you apply them.
+ *
+ */
+public class AddTagsDialog extends ExtendedDialog implements SelectionChangedListener {
+
+
+	private final JTable propertyTable;
+	private Collection<? extends OsmPrimitive> sel;
+	boolean[] existing;
+
+	public AddTagsDialog(String[][] tags) {
+		super(Main.parent, tr("Add tags to selected objects"), new String[] { tr("Add tags"), tr("Cancel")},
+				false,
+				true);
+
+		DataSet.addSelectionListener(this);
+
+
+		DefaultTableModel tm = new DefaultTableModel(new String[] {tr("Assume"), tr("Key"), tr("Value")}, tags.length) {
+			@Override
+			public Class getColumnClass(int c) {
+				return getValueAt(0, c).getClass();
+			}
+
+		};
+
+		sel = Main.main.getCurrentDataSet().getSelected();
+		existing = new boolean[tags.length];
+
+		for (int i = 0; i<tags.length; i++) {
+			existing[i] = false;
+			String key = tags[i][0];
+			Boolean b = Boolean.TRUE;
+			for (OsmPrimitive osm : sel) {
+				if (osm.keySet().contains(key)) {
+					b = Boolean.FALSE;
+					existing[i]=true;
+					break;
+				}
+			}
+			tm.setValueAt(b, i, 0);
+			tm.setValueAt(tags[i][0], i, 1);
+			tm.setValueAt(tags[i][1], i, 2);
+		}
+
+		propertyTable = new JTable(tm) {
+
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
+				Component c = super.prepareRenderer(renderer, row, column);
+				if (existing[row]) {
+					c.setFont(c.getFont().deriveFont(Font.ITALIC));
+					c.setForeground(new Color(100, 100, 100));
+				} else {
+					c.setFont(c.getFont().deriveFont(Font.PLAIN));
+					c.setForeground(new Color(0, 0, 0));
+				}
+				return c;
+			}
+		};
+
+		// a checkbox has a size of 15 px
+		propertyTable.getColumnModel().getColumn(0).setMaxWidth(15);
+		// get edit results if the table looses the focus, for example if a user clicks "add tags"
+		propertyTable.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
+
+		// set the content of this AddTagsDialog consisting of the tableHeader and the table itself.
+		JPanel tablePanel = new JPanel();
+		tablePanel.setLayout(new GridBagLayout());
+		tablePanel.add(propertyTable.getTableHeader(), GBC.eol().fill(GBC.HORIZONTAL));
+		tablePanel.add(propertyTable, GBC.eol().fill(GBC.BOTH));
+		setContent(tablePanel);
+
+		// set the default Dimensions and show the dialog
+		setPreferredSize(new Dimension(400,tablePanel.getPreferredSize().height+100));
+		showDialog();
+	}
+
+	/**
+	 * This method looks for existing tags in the current selection and sets the corresponding boolean in the boolean array existing[]
+	 */
+	private void findExistingTags() {
+		TableModel tm = propertyTable.getModel();
+		for (int i=0; i<tm.getRowCount(); i++) {
+			String key = (String)tm.getValueAt(i, 1);
+			existing[i] = false;
+			for (OsmPrimitive osm : sel) {
+				if (osm.keySet().contains(key)) {
+					existing[i] = true;
+					break;
+				}
+			}
+		}
+		propertyTable.repaint();
+	}
+
+	/**
+	 * If you click the "Add tags" button build a ChangePropertyCommand for every key that has a checked checkbox to apply the key value pair to all selected osm objects.
+	 * You get a entry for every key in the command queue.
+	 */
+	@Override
+	protected void buttonAction(int buttonIndex, ActionEvent evt) {
+		if (buttonIndex == 0) {
+			TableModel tm = propertyTable.getModel();
+			for (int i=0; i<tm.getRowCount(); i++) {
+				if ((Boolean)tm.getValueAt(i, 0)) {
+					Main.main.undoRedo.add(new ChangePropertyCommand(sel, (String)tm.getValueAt(i, 1), (String)tm.getValueAt(i, 2)));
+				}
+			}
+		}
+		setVisible(false);
+	}
+
+	@Override
+	public void selectionChanged(Collection<? extends OsmPrimitive> newSelection) {
+		sel = newSelection;
+		findExistingTags();
+	}
+
+}
Index: /trunk/src/org/openstreetmap/josm/io/remotecontrol/handler/LoadAndZoomHandler.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/io/remotecontrol/handler/LoadAndZoomHandler.java	(revision 3849)
+++ /trunk/src/org/openstreetmap/josm/io/remotecontrol/handler/LoadAndZoomHandler.java	(revision 3850)
@@ -6,4 +6,6 @@
 import java.awt.geom.Area;
 import java.awt.geom.Rectangle2D;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
 import java.util.HashSet;
 import java.util.concurrent.Future;
@@ -22,4 +24,5 @@
 import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
+import org.openstreetmap.josm.io.remotecontrol.AddTagsDialog;
 
 /**
@@ -28,151 +31,194 @@
 public class LoadAndZoomHandler extends RequestHandler
 {
-    public static final String command = "load_and_zoom";
-    public static final String command2 = "zoom";
-
-    public static final String loadDataPermissionKey = "remotecontrol.permission.load-data";
-    public static final boolean loadDataPermissionDefault = true;
-    public static final String changeSelectionPermissionKey = "remotecontrol.permission.change-selection";
-    public static final boolean changeSelectionPermissionDefault = true;
-    public static final String changeViewportPermissionKey = "remotecontrol.permission.change-viewport";
-    public static final boolean changeViewportPermissionDefault = true;
-
-    @Override
-    public String getPermissionMessage()
-    {
-        return tr("Remote Control has been asked to load data from the API.") +
-        "<br>" + tr("Request details: {0}", request);
-    }
-
-    @Override
-    protected String[] getMandatoryParams()
-    {
-        return new String[] { "bottom", "top", "left", "right" };
-    }
-
-    @Override
-    protected void handleRequest() throws RequestHandlerErrorException
-    {
-        DownloadTask osmTask = new DownloadOsmTask();
-        double minlat = 0;
-        double maxlat = 0;
-        double minlon = 0;
-        double maxlon = 0;
-        try {
-            minlat = Double.parseDouble(args.get("bottom"));
-            maxlat = Double.parseDouble(args.get("top"));
-            minlon = Double.parseDouble(args.get("left"));
-            maxlon = Double.parseDouble(args.get("right"));
-
-            if(command.equals(myCommand))
-            {
-                if (!Main.pref.getBoolean(loadDataPermissionKey, loadDataPermissionDefault))
-                {
-                    System.out.println("RemoteControl: download forbidden by preferences");
-                }
-                else
-                {
-
-                    // find out whether some data has already been downloaded
-                    Area present = null;
-                    Area toDownload = null;
-                    DataSet ds = Main.main.getCurrentDataSet();
-                    if (ds != null)
-                        present = ds.getDataSourceArea();
-                    if (present != null && !present.isEmpty()) {
-                        toDownload = new Area(new Rectangle2D.Double(minlon,minlat,maxlon-minlon,maxlat-minlat));
-                        toDownload.subtract(present);
-                        if (!toDownload.isEmpty())
-                        {
-                            // the result might not be a rectangle (L shaped etc)
-                            Rectangle2D downloadBounds = toDownload.getBounds2D();
-                            minlat = downloadBounds.getMinY();
-                            minlon = downloadBounds.getMinX();
-                            maxlat = downloadBounds.getMaxY();
-                            maxlon = downloadBounds.getMaxX();
-                        }
-                    }
-                    if((toDownload != null) && toDownload.isEmpty())
-                    {
-                        System.out.println("RemoteControl: no download necessary");
-                    }
-                    else
-                    {
-                        Future<?> future = osmTask.download(false /*no new layer*/, new Bounds(minlat,minlon,maxlat,maxlon), null /* let the task manage the progress monitor */);
-                        Main.worker.submit(new PostDownloadHandler(osmTask, future));
-                    }
-                }
-            }
-        } catch (Exception ex) {
-            System.out.println("RemoteControl: Error parsing load_and_zoom remote control request:");
-            ex.printStackTrace();
-            throw new RequestHandlerErrorException();
-        }
-        if (args.containsKey("select") && Main.pref.getBoolean(changeSelectionPermissionKey, changeSelectionPermissionDefault)) {
-            // select objects after downloading, zoom to selection.
-            final String selection = args.get("select");
-            Main.worker.execute(new Runnable() {
-                public void run() {
-                    HashSet<Long> ways = new HashSet<Long>();
-                    HashSet<Long> nodes = new HashSet<Long>();
-                    HashSet<Long> relations = new HashSet<Long>();
-                    HashSet<OsmPrimitive> newSel = new HashSet<OsmPrimitive>();
-                    for (String item : selection.split(",")) {
-                        if (item.startsWith("way")) {
-                            ways.add(Long.parseLong(item.substring(3)));
-                        } else if (item.startsWith("node")) {
-                            nodes.add(Long.parseLong(item.substring(4)));
-                        } else if (item.startsWith("relation")) {
-                            relations.add(Long.parseLong(item.substring(8)));
-                        } else if (item.startsWith("rel")) {
-                            relations.add(Long.parseLong(item.substring(3)));
-                        } else {
-                            System.out.println("RemoteControl: invalid selection '"+item+"' ignored");
-                        }
-                    }
-                    DataSet ds = Main.main.getCurrentDataSet();
-                    if(ds == null) // e.g. download failed
-                        return;
-                    for (Way w : ds.getWays()) {
-                        if (ways.contains(w.getId())) {
-                            newSel.add(w);
-                        }
-                    }
-                    for (Node n : ds.getNodes()) {
-                        if (nodes.contains(n.getId())) {
-                            newSel.add(n);
-                        }
-                    }
-                    for (Relation r : ds.getRelations()) {
-                        if (relations.contains(r.getId())) {
-                            newSel.add(r);
-                        }
-                    }
-                    ds.setSelected(newSel);
-                    if (Main.pref.getBoolean(changeViewportPermissionKey, changeViewportPermissionDefault))
-                        new AutoScaleAction("selection").actionPerformed(null);
-                }
-            });
-        } else if (Main.pref.getBoolean(changeViewportPermissionKey, changeViewportPermissionDefault)) {
-            // after downloading, zoom to downloaded area.
-            zoom(minlat, maxlat, minlon, maxlon);
-        }
-    }
-
-    protected void zoom(double minlat, double maxlat, double minlon, double maxlon) {
-        final Bounds bounds = new Bounds(new LatLon(minlat, minlon),
-                new LatLon(maxlat, maxlon));
-
-        // make sure this isn't called unless there *is* a MapView
-        //
-        if (Main.map != null && Main.map.mapView != null) {
-            Main.worker.execute(new Runnable() {
-                public void run() {
-                    BoundingXYVisitor bbox = new BoundingXYVisitor();
-                    bbox.visit(bounds);
-                    Main.map.mapView.recalculateCenterScale(bbox);
-                }
-            });
-        }
-    }
+	public static final String command = "load_and_zoom";
+	public static final String command2 = "zoom";
+
+	public static final String loadDataPermissionKey = "remotecontrol.permission.load-data";
+	public static final boolean loadDataPermissionDefault = true;
+	public static final String changeSelectionPermissionKey = "remotecontrol.permission.change-selection";
+	public static final boolean changeSelectionPermissionDefault = true;
+	public static final String changeViewportPermissionKey = "remotecontrol.permission.change-viewport";
+	public static final boolean changeViewportPermissionDefault = true;
+
+	@Override
+	public String getPermissionMessage()
+	{
+		return tr("Remote Control has been asked to load data from the API.") +
+		"<br>" + tr("Request details: {0}", request);
+	}
+
+	@Override
+	protected String[] getMandatoryParams()
+	{
+		return new String[] { "bottom", "top", "left", "right" };
+	}
+
+	@Override
+	protected void handleRequest() throws RequestHandlerErrorException
+	{
+		DownloadTask osmTask = new DownloadOsmTask();
+		double minlat = 0;
+		double maxlat = 0;
+		double minlon = 0;
+		double maxlon = 0;
+		try {
+			minlat = Double.parseDouble(args.get("bottom"));
+			maxlat = Double.parseDouble(args.get("top"));
+			minlon = Double.parseDouble(args.get("left"));
+			maxlon = Double.parseDouble(args.get("right"));
+
+			if(command.equals(myCommand))
+			{
+				if (!Main.pref.getBoolean(loadDataPermissionKey, loadDataPermissionDefault))
+				{
+					System.out.println("RemoteControl: download forbidden by preferences");
+				}
+				else
+				{
+
+					// find out whether some data has already been downloaded
+					Area present = null;
+					Area toDownload = null;
+					DataSet ds = Main.main.getCurrentDataSet();
+					if (ds != null)
+						present = ds.getDataSourceArea();
+					if (present != null && !present.isEmpty()) {
+						toDownload = new Area(new Rectangle2D.Double(minlon,minlat,maxlon-minlon,maxlat-minlat));
+						toDownload.subtract(present);
+						if (!toDownload.isEmpty())
+						{
+							// the result might not be a rectangle (L shaped etc)
+							Rectangle2D downloadBounds = toDownload.getBounds2D();
+							minlat = downloadBounds.getMinY();
+							minlon = downloadBounds.getMinX();
+							maxlat = downloadBounds.getMaxY();
+							maxlon = downloadBounds.getMaxX();
+						}
+					}
+					if((toDownload != null) && toDownload.isEmpty())
+					{
+						System.out.println("RemoteControl: no download necessary");
+					}
+					else
+					{
+						Future<?> future = osmTask.download(false /*no new layer*/, new Bounds(minlat,minlon,maxlat,maxlon), null /* let the task manage the progress monitor */);
+						Main.worker.submit(new PostDownloadHandler(osmTask, future));
+					}
+				}
+			}
+		} catch (Exception ex) {
+			System.out.println("RemoteControl: Error parsing load_and_zoom remote control request:");
+			ex.printStackTrace();
+			throw new RequestHandlerErrorException();
+		}
+
+		/**
+		 * deselect objects if parameter addtags given
+		 */
+		if (args.containsKey("addtags")) {
+			Main.worker.execute(new Runnable() {
+				public void run() {
+					DataSet ds = Main.main.getCurrentDataSet();
+					if(ds == null) // e.g. download failed
+						return;
+					ds.clearSelection();
+				}
+			});
+		}
+
+		if (args.containsKey("select") && Main.pref.getBoolean(changeSelectionPermissionKey, changeSelectionPermissionDefault)) {
+			// select objects after downloading, zoom to selection.
+			final String selection = args.get("select");
+			Main.worker.execute(new Runnable() {
+				public void run() {
+					HashSet<Long> ways = new HashSet<Long>();
+					HashSet<Long> nodes = new HashSet<Long>();
+					HashSet<Long> relations = new HashSet<Long>();
+					HashSet<OsmPrimitive> newSel = new HashSet<OsmPrimitive>();
+					for (String item : selection.split(",")) {
+						if (item.startsWith("way")) {
+							ways.add(Long.parseLong(item.substring(3)));
+						} else if (item.startsWith("node")) {
+							nodes.add(Long.parseLong(item.substring(4)));
+						} else if (item.startsWith("relation")) {
+							relations.add(Long.parseLong(item.substring(8)));
+						} else if (item.startsWith("rel")) {
+							relations.add(Long.parseLong(item.substring(3)));
+						} else {
+							System.out.println("RemoteControl: invalid selection '"+item+"' ignored");
+						}
+					}
+					DataSet ds = Main.main.getCurrentDataSet();
+					if(ds == null) // e.g. download failed
+						return;
+					for (Way w : ds.getWays()) {
+						if (ways.contains(w.getId())) {
+							newSel.add(w);
+						}
+					}
+					for (Node n : ds.getNodes()) {
+						if (nodes.contains(n.getId())) {
+							newSel.add(n);
+						}
+					}
+					for (Relation r : ds.getRelations()) {
+						if (relations.contains(r.getId())) {
+							newSel.add(r);
+						}
+					}
+					ds.setSelected(newSel);
+					if (Main.pref.getBoolean(changeViewportPermissionKey, changeViewportPermissionDefault))
+						new AutoScaleAction("selection").actionPerformed(null);
+				}
+			});
+		} else if (Main.pref.getBoolean(changeViewportPermissionKey, changeViewportPermissionDefault)) {
+			// after downloading, zoom to downloaded area.
+			zoom(minlat, maxlat, minlon, maxlon);
+		}
+
+		/*
+		 * parse addtags parameters
+		 * Example URL (part):
+		 * addtags=wikipedia:de%3DResidenzschloss Dresden|name:en%3DDresden Castle
+		 */
+		if (args.containsKey("addtags")) {
+			Main.worker.execute(new Runnable() {
+				public void run() {
+					String[] tags = null;
+					try {
+						tags = URLDecoder.decode(args.get("addtags"), "UTF-8").split("\\|");
+					} catch (UnsupportedEncodingException e) {
+                        new RuntimeException();
+					}
+					String[][] keyValue = new String[tags.length][2];
+					for (int i = 0; i<tags.length; i++) {
+						keyValue[i] = tags[i].split("=");
+
+						keyValue[i][0] = keyValue[i][0];
+						keyValue[i][1] = keyValue[i][1];
+					}
+
+					new AddTagsDialog(keyValue);
+				}
+			});
+		}
+
+	}
+
+	protected void zoom(double minlat, double maxlat, double minlon, double maxlon) {
+		final Bounds bounds = new Bounds(new LatLon(minlat, minlon),
+				new LatLon(maxlat, maxlon));
+
+		// make sure this isn't called unless there *is* a MapView
+		//
+		if (Main.map != null && Main.map.mapView != null) {
+			Main.worker.execute(new Runnable() {
+				public void run() {
+					BoundingXYVisitor bbox = new BoundingXYVisitor();
+					bbox.visit(bounds);
+					Main.map.mapView.recalculateCenterScale(bbox);
+				}
+			});
+		}
+	}
 }
