Index: trunk/images_nodist/followline.svg
===================================================================
--- trunk/images_nodist/followline.svg	(revision 4086)
+++ trunk/images_nodist/followline.svg	(revision 4086)
@@ -0,0 +1,173 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="24"
+   height="24"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.47 r22583"
+   sodipodi:docname="followline.svg"
+   inkscape:export-filename="/home/mancho/followline.png"
+   inkscape:export-xdpi="90"
+   inkscape:export-ydpi="90">
+  <defs
+     id="defs4">
+    <marker
+       inkscape:stockid="TriangleOutL"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="TriangleOutL"
+       style="overflow:visible">
+      <path
+         id="path3773"
+         d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+         transform="scale(0.8)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow2Send"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow2Send"
+       style="overflow:visible;">
+      <path
+         id="path3663"
+         style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+         d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+         transform="scale(0.3) rotate(180) translate(-2.3,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Send"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1Send"
+       style="overflow:visible;">
+      <path
+         id="path3645"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+         transform="scale(0.2) rotate(180) translate(6,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow2Lend"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow2Lend"
+       style="overflow:visible;">
+      <path
+         id="path3651"
+         style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+         d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+         transform="scale(1.1) rotate(180) translate(1,0)" />
+    </marker>
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 526.18109 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="744.09448 : 526.18109 : 1"
+       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+       id="perspective10" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="20.064155"
+     inkscape:cx="10.227492"
+     inkscape:cy="13.845545"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="true"
+     objecttolerance="20"
+     inkscape:window-width="1280"
+     inkscape:window-height="949"
+     inkscape:window-x="0"
+     inkscape:window-y="24"
+     inkscape:window-maximized="1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid2816"
+       empspacing="1"
+       visible="true"
+       enabled="true"
+       snapvisiblegridlinesonly="true"
+       originx="0.5px"
+       originy="0.5px"
+       dotted="false" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(0,-1028.3622)">
+    <path
+       style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 21.5,1030.8622 -12,12"
+       id="path3619"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="fill:none;stroke:#ff0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 9.5,1031.8622 0,11 -5,5"
+       id="path3617"
+       sodipodi:nodetypes="ccc" />
+    <rect
+       style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#ff0000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect2839"
+       width="3.2000117"
+       height="3.1999671"
+       x="19.399921"
+       y="1029.7622" />
+    <rect
+       y="1047.8622"
+       x="1.5"
+       height="3.1999671"
+       width="3.2000117"
+       id="rect3613"
+       style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#ff0000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+    <rect
+       style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#ff0000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect3615"
+       width="3.2000117"
+       height="3.1999671"
+       x="8.3999939"
+       y="1040.7622" />
+    <rect
+       y="1029.7622"
+       x="8.3999939"
+       height="3.1999671"
+       width="3.2000117"
+       id="rect3621"
+       style="color:#000000;fill:#bababa;fill-opacity:1;fill-rule:nonzero;stroke:#757575;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+    <path
+       id="path5021"
+       style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
+       d="m 16.5,1032.8622 1,-2 0,0 m -4.037445,-0.011 4.037445,0.011 -1,-2 0,0" />
+  </g>
+</svg>
Index: trunk/src/org/openstreetmap/josm/actions/FollowLineAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/FollowLineAction.java	(revision 4086)
+++ trunk/src/org/openstreetmap/josm/actions/FollowLineAction.java	(revision 4086)
@@ -0,0 +1,122 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.actions;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.KeyEvent;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.mapmode.DrawAction;
+import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
+import org.openstreetmap.josm.data.osm.Way;
+import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.tools.Shortcut;
+
+/**
+ * Follow line action - Makes easier to draw a line that shares points with another line
+ *
+ * Aimed at those who want to draw two or more lines related with
+ * each other, but carry different information (i.e. a river acts as boundary at
+ * some part of its course. It preferable to have a separated boundary line than to
+ * mix totally different kind of features in one single way).
+ *
+ * @author Germán Márquez Mejía
+ */
+public class FollowLineAction extends JosmAction {
+
+    public FollowLineAction() {
+        super(
+                tr("Follow line"),
+                "followline.png",
+                tr("Continues drawing a line that shares nodes with another line."),
+                Shortcut.registerShortcut("tools:followline", tr(
+                "Tool: {0}", tr("Follow")),
+                KeyEvent.VK_F, Shortcut.GROUP_EDIT), true);
+    }
+
+    @Override
+    protected void updateEnabledState() {
+        if (getCurrentDataSet() == null) {
+            setEnabled(false);
+        } else {
+            updateEnabledState(getCurrentDataSet().getSelected());
+        }
+    }
+
+    @Override
+    protected void updateEnabledState(Collection<? extends OsmPrimitive> selection) {
+        setEnabled(selection != null && !selection.isEmpty());
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent evt) {
+        OsmDataLayer osmLayer = Main.main.getEditLayer();
+        if (osmLayer == null)
+            return;
+        if (!(Main.map.mapMode instanceof DrawAction)) return; // We are not on draw mode
+        
+        Collection<Node> selectedPoints = osmLayer.data.getSelectedNodes();
+        Collection<Way> selectedLines = osmLayer.data.getSelectedWays();
+        if ((selectedPoints.size() > 1) || (selectedLines.size() != 1)) // Unsuitable selection
+            return;
+        
+        Node last = ((DrawAction) Main.map.mapMode).getCurrentBaseNode();
+        Way follower = selectedLines.iterator().next();
+        Node prev = follower.getNode(1);
+        boolean reversed = true;
+        if (follower.lastNode().equals(last)) {
+            prev = follower.getNode(follower.getNodesCount() - 2);
+            reversed = false;
+        }
+        List<OsmPrimitive> referrers = last.getReferrers();
+        if (referrers.size() < 2) return; // There's nothing to follow
+        
+        Iterator<OsmPrimitive> i = referrers.iterator();
+        while (i.hasNext()) {
+            OsmPrimitive referrer = i.next();
+            if (!referrer.getType().equals(OsmPrimitiveType.WAY)) { // Can't follow points or relations
+                continue;
+            }
+            Way toFollow = (Way) referrer;
+            if (toFollow.equals(follower)) {
+                continue;
+            }
+            List<Node> points = toFollow.getNodes();
+            int indexOfLast = points.indexOf(last);
+            int indexOfPrev = points.indexOf(prev);
+            if ((indexOfLast == -1) || (indexOfPrev == -1)) { // Both points must belong to both lines
+                continue;
+            }
+            if (Math.abs(indexOfPrev - indexOfLast) != 1) {  // ...and be consecutive
+                continue;
+            }
+            Node newPoint = null;
+            if (indexOfPrev == (indexOfLast - 1)) {
+                if ((indexOfLast + 1) < points.size()) {
+                    newPoint = points.get(indexOfLast + 1);
+                }
+            } else {
+                if ((indexOfLast - 1) >= 0) {
+                    newPoint = points.get(indexOfLast - 1);
+                }
+            }
+            if (newPoint != null) {
+                if (reversed) {
+                    follower.addNode(0, newPoint);
+                } else {
+                    follower.addNode(newPoint);
+                }
+                osmLayer.data.clearSelection();
+                osmLayer.data.addSelected(follower);
+                osmLayer.data.addSelected(newPoint);
+                return;
+            }
+        }
+    }
+}
Index: trunk/src/org/openstreetmap/josm/actions/mapmode/DrawAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/mapmode/DrawAction.java	(revision 4085)
+++ trunk/src/org/openstreetmap/josm/actions/mapmode/DrawAction.java	(revision 4086)
@@ -752,4 +752,8 @@
     }
 
+    public Node getCurrentBaseNode() {
+        return currentBaseNode;
+    }
+
     private static void pruneSuccsAndReverse(List<Integer> is) {
         //if (is.size() < 2) return;
Index: trunk/src/org/openstreetmap/josm/gui/MainMenu.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/MainMenu.java	(revision 4085)
+++ trunk/src/org/openstreetmap/josm/gui/MainMenu.java	(revision 4086)
@@ -33,4 +33,5 @@
 import org.openstreetmap.josm.actions.DuplicateAction;
 import org.openstreetmap.josm.actions.ExitAction;
+import org.openstreetmap.josm.actions.FollowLineAction;
 import org.openstreetmap.josm.actions.FullscreenToggleAction;
 import org.openstreetmap.josm.actions.GpxExportAction;
@@ -161,4 +162,5 @@
     public final JosmAction joinAreas = new JoinAreasAction();
     public final JosmAction createMultipolygon = new CreateMultipolygonAction();
+    public final JosmAction followLine = new FollowLineAction();
 
     /* Audio menu */
@@ -330,4 +332,5 @@
         add(toolsMenu, mirror);
         toolsMenu.addSeparator();
+        add(toolsMenu, followLine);
         add(toolsMenu, addnode);
         add(toolsMenu, movenode);
