Index: /applications/editors/josm/plugins/public_transport/.settings/org.eclipse.jdt.core.prefs
===================================================================
--- /applications/editors/josm/plugins/public_transport/.settings/org.eclipse.jdt.core.prefs	(revision 32356)
+++ /applications/editors/josm/plugins/public_transport/.settings/org.eclipse.jdt.core.prefs	(revision 32357)
@@ -63,6 +63,6 @@
 org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
 org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
-org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
-org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=warning
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning
 org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
 org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
@@ -86,4 +86,5 @@
 org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
 org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore
 org.eclipse.jdt.core.compiler.problem.unusedImport=warning
 org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
Index: /applications/editors/josm/plugins/public_transport/build.xml
===================================================================
--- /applications/editors/josm/plugins/public_transport/build.xml	(revision 32356)
+++ /applications/editors/josm/plugins/public_transport/build.xml	(revision 32357)
@@ -5,5 +5,5 @@
     <property name="commit.message" value="Commit message"/>
     <!-- enter the *lowest* JOSM version this plugin is currently compatible with -->
-    <property name="plugin.main.version" value="7817"/>
+    <property name="plugin.main.version" value="10279"/>
 
     <property name="plugin.author" value="Roland M. Olbricht"/>
Index: /applications/editors/josm/plugins/public_transport/src/public_transport/AStarAlgorithm.java
===================================================================
--- /applications/editors/josm/plugins/public_transport/src/public_transport/AStarAlgorithm.java	(revision 32356)
+++ /applications/editors/josm/plugins/public_transport/src/public_transport/AStarAlgorithm.java	(revision 32357)
@@ -7,17 +7,16 @@
 import java.util.Vector;
 
-public abstract class AStarAlgorithm
-{
+public abstract class AStarAlgorithm {
     // The following abstract functions and subclasses must be overridden by a class using
     // AStarAlgorithm.
 
-    public static abstract class Vertex implements Comparable< Vertex >
-    {
+    public static abstract class Vertex implements Comparable<Vertex> {
+        @Override
         public abstract int compareTo(Vertex v);
     };
 
-    public static abstract class Edge
-    {
+    public static abstract class Edge {
         public abstract Vertex getBegin();
+
         public abstract Vertex getEnd();
 
@@ -25,5 +24,5 @@
     };
 
-    public abstract Vector< Edge > getNeighbors(Vertex vertex);
+    public abstract Vector<Edge> getNeighbors(Vertex vertex);
 
     public abstract double estimateDistance(Vertex vertex);
@@ -31,30 +30,25 @@
     // end of interface to override -------------------------------------------
 
-    public AStarAlgorithm(Vertex begin, Vertex end)
-    {
+    public AStarAlgorithm(Vertex begin, Vertex end) {
         this.begin = begin;
         this.end = end;
-        openList = new TreeMap< Vertex, Double >();
-        closedList = new TreeSet< Vertex >();
-        pathTail = new TreeMap< Vertex, Edge >();
+        openList = new TreeMap<>();
+        closedList = new TreeSet<>();
+        pathTail = new TreeMap<>();
     }
 
-    public Vertex determineCurrentStart()
-    {
+    public Vertex determineCurrentStart() {
         Vertex minVertex = null;
         double minDist = 0;
-        Iterator< Map.Entry< Vertex, Double > > iter = openList.entrySet().iterator();
-        while (iter.hasNext())
-        {
-            Map.Entry< Vertex, Double > entry = iter.next();
+        Iterator<Map.Entry<Vertex, Double>> iter = openList.entrySet().iterator();
+        while (iter.hasNext()) {
+            Map.Entry<Vertex, Double> entry = iter.next();
             double distance = entry.getValue().doubleValue() + estimateDistance(entry.getKey());
-            if (minVertex == null || distance < minDist)
-            {
+            if (minVertex == null || distance < minDist) {
                 minDist = distance;
                 minVertex = entry.getKey();
             }
         }
-        if (minVertex != null)
-        {
+        if (minVertex != null) {
             System.out.print(openList.get(minVertex).doubleValue());
             System.out.print("\t");
@@ -65,11 +59,9 @@
     }
 
-    Vector< Edge > shortestPath()
-    {
+    Vector<Edge> shortestPath() {
         // Travel through the network
         Vertex currentStart = begin;
         openList.put(currentStart, 0.0);
-        while (currentStart != null && !currentStart.equals(end))
-        {
+        while (currentStart != null && !currentStart.equals(end)) {
             double startDistance = openList.get(currentStart).doubleValue();
 
@@ -78,7 +70,6 @@
             closedList.add(currentStart);
 
-            Iterator< Edge > neighbors = getNeighbors(currentStart).iterator();
-            while (neighbors.hasNext())
-            {
+            Iterator<Edge> neighbors = getNeighbors(currentStart).iterator();
+            while (neighbors.hasNext()) {
                 Edge edge = neighbors.next();
 
@@ -91,7 +82,6 @@
                 double distance = startDistance + edge.getLength();
 
-                if (knownDistance == null || distance < knownDistance.doubleValue())
-                {
-            openList.put(edge.getEnd(), distance);
+                if (knownDistance == null || distance < knownDistance.doubleValue()) {
+                    openList.put(edge.getEnd(), distance);
                     pathTail.put(edge.getEnd(), edge);
                 }
@@ -105,14 +95,13 @@
 
         // Reconstruct the found path
-        Vector< Edge > backwards = new Vector< Edge >();
+        Vector<Edge> backwards = new Vector<>();
         Vertex currentEnd = end;
-        while (!currentEnd.equals(begin))
-        {
+        while (!currentEnd.equals(begin)) {
             backwards.add(pathTail.get(currentEnd));
             currentEnd = pathTail.get(currentEnd).getBegin();
         }
 
-        Vector< Edge > result = new Vector< Edge >();
-        for (int i = backwards.size()-1; i >= 0; --i)
+        Vector<Edge> result = new Vector<>();
+        for (int i = backwards.size() - 1; i >= 0; --i)
             result.add(backwards.elementAt(i));
         return result;
@@ -120,8 +109,11 @@
 
     protected Vertex begin;
+
     protected Vertex end;
 
-    private TreeSet< Vertex > closedList;
-    private TreeMap< Vertex, Double > openList;
-    private TreeMap< Vertex, Edge > pathTail;
-};
+    private TreeSet<Vertex> closedList;
+
+    private TreeMap<Vertex, Double> openList;
+
+    private TreeMap<Vertex, Edge> pathTail;
+}
Index: /applications/editors/josm/plugins/public_transport/src/public_transport/AbstractImporterDialog.java
===================================================================
--- /applications/editors/josm/plugins/public_transport/src/public_transport/AbstractImporterDialog.java	(revision 32356)
+++ /applications/editors/josm/plugins/public_transport/src/public_transport/AbstractImporterDialog.java	(revision 32357)
@@ -20,13 +20,19 @@
 public abstract class AbstractImporterDialog<T extends JosmAction> {
 
-    private static final String[] stoptypes = new String[]{marktr("bus"), marktr("tram"), marktr("light_rail"), marktr("subway"), marktr("rail")};
+    private static final String[] stoptypes = new String[] { marktr("bus"), marktr("tram"),
+            marktr("light_rail"), marktr("subway"), marktr("rail") };
 
     private final JDialog jDialog;
+
     protected final JTabbedPane tabbedPane;
+
     protected final JComboBox<TransText> cbStoptype;
 
     protected final JTextField tfGPSTimeStart;
+
     protected final JTextField tfStopwatchStart;
+
     protected final JTextField tfTimeWindow;
+
     protected final JTextField tfThreshold;
 
@@ -36,12 +42,12 @@
         tabbedPane = new JTabbedPane();
         jDialog.add(tabbedPane);
-        
+
         cbStoptype = new JComboBox<>();
         cbStoptype.setEditable(false);
-        for(String type : stoptypes)
+        for (String type : stoptypes)
             cbStoptype.addItem(new TransText(type));
         cbStoptype.setActionCommand(actionPrefix + ".settingsStoptype");
         cbStoptype.addActionListener(controller);
-        
+
         tfGPSTimeStart = new JTextField("00:00:00", 15);
         tfGPSTimeStart.setActionCommand(actionPrefix + ".settingsGPSTimeStart");
@@ -61,108 +67,85 @@
 
         initDialog(controller);
-        
+
         jDialog.pack();
         jDialog.setLocationRelativeTo(frame);
     }
-    
+
     protected abstract void initDialog(T controller);
-    
-    public void setTrackValid(boolean valid)
-    {
-      tabbedPane.setEnabledAt(2, valid);
+
+    public void setTrackValid(boolean valid) {
+        tabbedPane.setEnabledAt(2, valid);
     }
 
-    public void setVisible(boolean visible)
-    {
-      jDialog.setVisible(visible);
+    public void setVisible(boolean visible) {
+        jDialog.setVisible(visible);
     }
 
-    public void setSettings
-        (String gpsSyncTime, String stopwatchStart,
-         double timeWindow, double threshold)
-    {
-      tfGPSTimeStart.setText(gpsSyncTime);
-      tfStopwatchStart.setText(stopwatchStart);
-      tfTimeWindow.setText(Double.toString(timeWindow));
-      tfThreshold.setText(Double.toString(threshold));
+    public void setSettings(String gpsSyncTime, String stopwatchStart, double timeWindow,
+            double threshold) {
+        tfGPSTimeStart.setText(gpsSyncTime);
+        tfStopwatchStart.setText(stopwatchStart);
+        tfTimeWindow.setText(Double.toString(timeWindow));
+        tfThreshold.setText(Double.toString(threshold));
     }
 
-    public String getStoptype()
-    {
-      return ((TransText)cbStoptype.getSelectedItem()).text;
+    public String getStoptype() {
+        return ((TransText) cbStoptype.getSelectedItem()).text;
     }
 
-    public boolean gpsTimeStartValid()
-    {
-      if (parseTime(tfGPSTimeStart.getText()) >= 0)
-      {
-        return true;
-      }
-      else
-      {
-        JOptionPane.showMessageDialog
-        (null, tr("Can''t parse a time from this string."), tr("Invalid value"),
-         JOptionPane.ERROR_MESSAGE);
-        return false;
-      }
-    }
-    
-    public String getGpsTimeStart()
-    {
-      return tfGPSTimeStart.getText();
+    public boolean gpsTimeStartValid() {
+        if (parseTime(tfGPSTimeStart.getText()) >= 0) {
+            return true;
+        } else {
+            JOptionPane.showMessageDialog(null, tr("Can''t parse a time from this string."),
+                    tr("Invalid value"), JOptionPane.ERROR_MESSAGE);
+            return false;
+        }
     }
 
-    public void setGpsTimeStart(String s)
-    {
-      tfGPSTimeStart.setText(s);
+    public String getGpsTimeStart() {
+        return tfGPSTimeStart.getText();
     }
 
-    public boolean stopwatchStartValid()
-    {
-      if (parseTime(tfStopwatchStart.getText()) >= 0)
-      {
-        return true;
-      }
-      else
-      {
-        JOptionPane.showMessageDialog
-        (null, tr("Can''t parse a time from this string."), tr("Invalid value"),
-         JOptionPane.ERROR_MESSAGE);
-        return false;
-      }
+    public void setGpsTimeStart(String s) {
+        tfGPSTimeStart.setText(s);
     }
 
-    public String getStopwatchStart()
-    {
-      return tfStopwatchStart.getText();
+    public boolean stopwatchStartValid() {
+        if (parseTime(tfStopwatchStart.getText()) >= 0) {
+            return true;
+        } else {
+            JOptionPane.showMessageDialog(null, tr("Can''t parse a time from this string."),
+                    tr("Invalid value"), JOptionPane.ERROR_MESSAGE);
+            return false;
+        }
     }
 
-    public void setStopwatchStart(String s)
-    {
-      tfStopwatchStart.setText(s);
+    public String getStopwatchStart() {
+        return tfStopwatchStart.getText();
     }
 
-    public double getTimeWindow()
-    {
-      return Double.parseDouble(tfTimeWindow.getText());
-    }
-    
-    public double getThreshold()
-    {
-      return Double.parseDouble(tfThreshold.getText());
+    public void setStopwatchStart(String s) {
+        tfStopwatchStart.setText(s);
     }
 
-    public static double parseTime(String s)
-    {
-      if ((s.charAt(2) != ':') || (s.charAt(2) != ':')
-       || (s.length() < 8))
-        return -1;
-      int hour = Integer.parseInt(s.substring(0, 2));
-      int minute = Integer.parseInt(s.substring(3, 5));
-      double second = Double.parseDouble(s.substring(6, s.length()));
-      if ((hour < 0) || (hour > 23) || (minute < 0) || (minute > 59)
-       || (second < 0) || (second >= 60.0))
-        return -1;
-      return (second + minute*60 + hour*60*60);
+    public double getTimeWindow() {
+        return Double.parseDouble(tfTimeWindow.getText());
+    }
+
+    public double getThreshold() {
+        return Double.parseDouble(tfThreshold.getText());
+    }
+
+    public static double parseTime(String s) {
+        if ((s.charAt(2) != ':') || (s.charAt(2) != ':') || (s.length() < 8))
+            return -1;
+        int hour = Integer.parseInt(s.substring(0, 2));
+        int minute = Integer.parseInt(s.substring(3, 5));
+        double second = Double.parseDouble(s.substring(6, s.length()));
+        if ((hour < 0) || (hour > 23) || (minute < 0) || (minute > 59) || (second < 0)
+                || (second >= 60.0))
+            return -1;
+        return (second + minute * 60 + hour * 60 * 60);
     }
 }
Index: /applications/editors/josm/plugins/public_transport/src/public_transport/GTFSAddCommand.java
===================================================================
--- /applications/editors/josm/plugins/public_transport/src/public_transport/GTFSAddCommand.java	(revision 32356)
+++ /applications/editors/josm/plugins/public_transport/src/public_transport/GTFSAddCommand.java	(revision 32357)
@@ -11,80 +11,73 @@
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 
-public class GTFSAddCommand extends Command
-{
-  private Vector< Integer > workingLines = null;
-  private Vector< String > typesForUndo = null;
-  private GTFSStopTableModel gtfsStopTM = null;
-  private String type = null;
+public class GTFSAddCommand extends Command {
+    private Vector<Integer> workingLines = null;
 
-  public GTFSAddCommand(GTFSImporterAction controller)
-  {
-    gtfsStopTM = controller.getGTFSStopTableModel();
-    type = controller.getDialog().getStoptype();
-    workingLines = new Vector< Integer >();
-    typesForUndo = new Vector< String >();
+    private Vector<String> typesForUndo = null;
 
-    // use either selected lines or all lines if no line is selected
-    int[] selectedLines = controller.getDialog().getGTFSStopTable().getSelectedRows();
-    Vector< Integer > consideredLines = new Vector< Integer >();
-    if (selectedLines.length > 0)
-    {
-      for (int i = 0; i < selectedLines.length; ++i)
-    consideredLines.add(selectedLines[i]);
-    }
-    else
-    {
-      for (int i = 0; i < gtfsStopTM.getRowCount(); ++i)
-    consideredLines.add(new Integer(i));
+    private GTFSStopTableModel gtfsStopTM = null;
+
+    private String type = null;
+
+    public GTFSAddCommand(GTFSImporterAction controller) {
+        gtfsStopTM = controller.getGTFSStopTableModel();
+        type = controller.getDialog().getStoptype();
+        workingLines = new Vector<>();
+        typesForUndo = new Vector<>();
+
+        // use either selected lines or all lines if no line is selected
+        int[] selectedLines = controller.getDialog().getGTFSStopTable().getSelectedRows();
+        Vector<Integer> consideredLines = new Vector<>();
+        if (selectedLines.length > 0) {
+            for (int i = 0; i < selectedLines.length; ++i)
+                consideredLines.add(selectedLines[i]);
+        } else {
+            for (int i = 0; i < gtfsStopTM.getRowCount(); ++i)
+                consideredLines.add(new Integer(i));
+        }
+
+        // keep only lines where a node can be added
+        for (int i = 0; i < consideredLines.size(); ++i) {
+            if (gtfsStopTM.nodes.elementAt(consideredLines.elementAt(i)) == null)
+                workingLines.add(consideredLines.elementAt(i));
+        }
     }
 
-    // keep only lines where a node can be added
-    for (int i = 0; i < consideredLines.size(); ++i)
-    {
-      if (gtfsStopTM.nodes.elementAt(consideredLines.elementAt(i)) == null)
-    workingLines.add(consideredLines.elementAt(i));
+    @Override
+    public boolean executeCommand() {
+        typesForUndo.clear();
+        for (int i = 0; i < workingLines.size(); ++i) {
+            int j = workingLines.elementAt(i).intValue();
+            typesForUndo.add((String) gtfsStopTM.getValueAt(j, 2));
+            Node node = GTFSImporterAction.createNode(gtfsStopTM.coors.elementAt(j),
+                    (String) gtfsStopTM.getValueAt(j, 0), (String) gtfsStopTM.getValueAt(j, 1));
+            gtfsStopTM.nodes.set(j, node);
+            gtfsStopTM.setValueAt(tr("added"), j, 2);
+        }
+        return true;
     }
-  }
 
-  public boolean executeCommand()
-  {
-    typesForUndo.clear();
-    for (int i = 0; i < workingLines.size(); ++i)
-    {
-      int j = workingLines.elementAt(i).intValue();
-      typesForUndo.add((String)gtfsStopTM.getValueAt(j, 2));
-      Node node = GTFSImporterAction.createNode
-        (gtfsStopTM.coors.elementAt(j), (String)gtfsStopTM.getValueAt(j, 0),
-         (String)gtfsStopTM.getValueAt(j, 1));
-      gtfsStopTM.nodes.set(j, node);
-      gtfsStopTM.setValueAt(tr("added"), j, 2);
+    @Override
+    public void undoCommand() {
+        for (int i = 0; i < workingLines.size(); ++i) {
+            int j = workingLines.elementAt(i).intValue();
+            Node node = gtfsStopTM.nodes.elementAt(j);
+            gtfsStopTM.nodes.set(j, null);
+            gtfsStopTM.setValueAt(typesForUndo.elementAt(i), j, 2);
+            if (node == null)
+                continue;
+            Main.getLayerManager().getEditDataSet().removePrimitive(node);
+            node.setDeleted(true);
+        }
     }
-    return true;
-  }
 
-  public void undoCommand()
-  {
-    for (int i = 0; i < workingLines.size(); ++i)
-    {
-      int j = workingLines.elementAt(i).intValue();
-      Node node = gtfsStopTM.nodes.elementAt(j);
-      gtfsStopTM.nodes.set(j, null);
-      gtfsStopTM.setValueAt(typesForUndo.elementAt(i), j, 2);
-      if (node == null)
-    continue;
-      Main.main.getCurrentDataSet().removePrimitive(node);
-      node.setDeleted(true);
+    @Override
+    public void fillModifiedData(Collection<OsmPrimitive> modified,
+            Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
     }
-  }
 
-  public void fillModifiedData
-    (Collection< OsmPrimitive > modified, Collection< OsmPrimitive > deleted,
-     Collection< OsmPrimitive > added)
-  {
-  }
-
-  @Override public String getDescriptionText()
-  {
-    return tr("Public Transport: Enable GTFSStops");
-  }
-};
+    @Override
+    public String getDescriptionText() {
+        return tr("Public Transport: Enable GTFSStops");
+    }
+}
Index: /applications/editors/josm/plugins/public_transport/src/public_transport/GTFSCatchCommand.java
===================================================================
--- /applications/editors/josm/plugins/public_transport/src/public_transport/GTFSCatchCommand.java	(revision 32356)
+++ /applications/editors/josm/plugins/public_transport/src/public_transport/GTFSCatchCommand.java	(revision 32357)
@@ -9,105 +9,103 @@
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.command.Command;
+import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 
-public class GTFSCatchCommand extends Command
-{
-  private Vector< Integer > workingLines = null;
-  private Node undoMapNode = null;
-  private Node undoTableNode = null;
-  private GTFSStopTableModel gtfsStopTM = null;
-  private String type = null;
+public class GTFSCatchCommand extends Command {
+    private Vector<Integer> workingLines = null;
 
-  public GTFSCatchCommand(GTFSImporterAction controller)
-  {
-    gtfsStopTM = controller.getGTFSStopTableModel();
-    workingLines = new Vector< Integer >();
+    private Node undoMapNode = null;
 
-    // use either selected lines or all lines if no line is selected
-    int[] selectedLines = controller.getDialog().getGTFSStopTable().getSelectedRows();
-    if (selectedLines.length != 1)
-      return;
-    workingLines.add(selectedLines[0]);
-  }
+    private Node undoTableNode = null;
 
-  public boolean executeCommand()
-  {
-    if (workingLines.size() != 1)
-      return false;
-    Node dest = null;
-    Iterator< Node > iter =
-        Main.main.getCurrentDataSet().getSelectedNodes().iterator();
-    int j = workingLines.elementAt(0);
-    while (iter.hasNext())
-    {
-      Node n = iter.next();
-      if ((n != null) && (n.equals(gtfsStopTM.nodes.elementAt(j))))
-    continue;
-      if (dest != null)
-    return false;
-      dest = n;
-    }
-    if (dest == null)
-      return false;
-    undoMapNode = new Node(dest);
+    private GTFSStopTableModel gtfsStopTM = null;
 
-    Node node = gtfsStopTM.nodes.elementAt(j);
-    undoTableNode = node;
-    if (node != null)
-    {
-      Main.main.getCurrentDataSet().removePrimitive(node);
-      node.setDeleted(true);
+    private String type = null;
+
+    public GTFSCatchCommand(GTFSImporterAction controller) {
+        gtfsStopTM = controller.getGTFSStopTableModel();
+        workingLines = new Vector<>();
+
+        // use either selected lines or all lines if no line is selected
+        int[] selectedLines = controller.getDialog().getGTFSStopTable().getSelectedRows();
+        if (selectedLines.length != 1)
+            return;
+        workingLines.add(selectedLines[0]);
     }
 
-    dest.setCoor(gtfsStopTM.coors.elementAt(j));
-    dest.put("highway", "bus_stop");
-    dest.put("stop_id", (String)gtfsStopTM.getValueAt(j, 0));
-    if (dest.get("name") == null)
-      dest.put("name", (String)gtfsStopTM.getValueAt(j, 1));
-    dest.put("note", "moved by gtfs import");
-    gtfsStopTM.nodes.set(j, dest);
-    type = (String)gtfsStopTM.getValueAt(j, 2);
-    gtfsStopTM.setValueAt("fed", j, 2);
+    @Override
+    public boolean executeCommand() {
+        if (workingLines.size() != 1)
+            return false;
+        Node dest = null;
+        DataSet ds = Main.getLayerManager().getEditDataSet();
+        Iterator<Node> iter = ds.getSelectedNodes().iterator();
+        int j = workingLines.elementAt(0);
+        while (iter.hasNext()) {
+            Node n = iter.next();
+            if ((n != null) && (n.equals(gtfsStopTM.nodes.elementAt(j))))
+                continue;
+            if (dest != null)
+                return false;
+            dest = n;
+        }
+        if (dest == null)
+            return false;
+        undoMapNode = new Node(dest);
 
-    return true;
-  }
+        Node node = gtfsStopTM.nodes.elementAt(j);
+        undoTableNode = node;
+        if (node != null) {
+            ds.removePrimitive(node);
+            node.setDeleted(true);
+        }
 
-  public void undoCommand()
-  {
-    if (workingLines.size() != 1)
-      return;
-    int j = workingLines.elementAt(0);
+        dest.setCoor(gtfsStopTM.coors.elementAt(j));
+        dest.put("highway", "bus_stop");
+        dest.put("stop_id", (String) gtfsStopTM.getValueAt(j, 0));
+        if (dest.get("name") == null)
+            dest.put("name", (String) gtfsStopTM.getValueAt(j, 1));
+        dest.put("note", "moved by gtfs import");
+        gtfsStopTM.nodes.set(j, dest);
+        type = (String) gtfsStopTM.getValueAt(j, 2);
+        gtfsStopTM.setValueAt("fed", j, 2);
 
-    Node node = gtfsStopTM.nodes.elementAt(j);
-    if (node != null)
-    {
-      Main.main.getCurrentDataSet().removePrimitive(node);
-      node.setDeleted(true);
+        return true;
     }
 
-    if (undoMapNode != null)
-    {
-      undoMapNode.setDeleted(false);
-      Main.main.getCurrentDataSet().addPrimitive(undoMapNode);
+    @Override
+    public void undoCommand() {
+        if (workingLines.size() != 1)
+            return;
+        int j = workingLines.elementAt(0);
+
+        DataSet ds = Main.getLayerManager().getEditDataSet();
+        Node node = gtfsStopTM.nodes.elementAt(j);
+        if (node != null) {
+            ds.removePrimitive(node);
+            node.setDeleted(true);
+        }
+
+        if (undoMapNode != null) {
+            undoMapNode.setDeleted(false);
+            ds.addPrimitive(undoMapNode);
+        }
+        if (undoTableNode != null) {
+            undoTableNode.setDeleted(false);
+            ds.addPrimitive(undoTableNode);
+        }
+        gtfsStopTM.nodes.set(j, undoTableNode);
+        gtfsStopTM.setValueAt(type, j, 2);
     }
-    if (undoTableNode != null)
-    {
-      undoTableNode.setDeleted(false);
-      Main.main.getCurrentDataSet().addPrimitive(undoTableNode);
+
+    @Override
+    public void fillModifiedData(Collection<OsmPrimitive> modified,
+            Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
     }
-    gtfsStopTM.nodes.set(j, undoTableNode);
-    gtfsStopTM.setValueAt(type, j, 2);
-  }
 
-  public void fillModifiedData
-    (Collection< OsmPrimitive > modified, Collection< OsmPrimitive > deleted,
-     Collection< OsmPrimitive > added)
-  {
-  }
-
-  @Override public String getDescriptionText()
-  {
-    return tr("Public Transport: Catch GTFS stops");
-  }
-};
+    @Override
+    public String getDescriptionText() {
+        return tr("Public Transport: Catch GTFS stops");
+    }
+}
Index: /applications/editors/josm/plugins/public_transport/src/public_transport/GTFSDeleteCommand.java
===================================================================
--- /applications/editors/josm/plugins/public_transport/src/public_transport/GTFSDeleteCommand.java	(revision 32356)
+++ /applications/editors/josm/plugins/public_transport/src/public_transport/GTFSDeleteCommand.java	(revision 32357)
@@ -11,84 +11,78 @@
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 
-public class GTFSDeleteCommand extends Command
-{
-  private Vector< Integer > workingLines = null;
-  private Vector< Node > nodesForUndo = null;
-  private Vector< String > typesForUndo = null;
-  private GTFSStopTableModel gtfsStopTM = null;
+public class GTFSDeleteCommand extends Command {
+    private Vector<Integer> workingLines = null;
 
-  public GTFSDeleteCommand(GTFSImporterAction controller)
-  {
-    gtfsStopTM = controller.getGTFSStopTableModel();
-    workingLines = new Vector< Integer >();
-    nodesForUndo = new Vector< Node >();
-    typesForUndo = new Vector< String >();
+    private Vector<Node> nodesForUndo = null;
 
-    // use either selected lines or all lines if no line is selected
-    int[] selectedLines = controller.getDialog().getGTFSStopTable().getSelectedRows();
-    Vector< Integer > consideredLines = new Vector< Integer >();
-    if (selectedLines.length > 0)
-    {
-      for (int i = 0; i < selectedLines.length; ++i)
-    consideredLines.add(selectedLines[i]);
-    }
-    else
-    {
-      for (int i = 0; i < gtfsStopTM.getRowCount(); ++i)
-    consideredLines.add(new Integer(i));
+    private Vector<String> typesForUndo = null;
+
+    private GTFSStopTableModel gtfsStopTM = null;
+
+    public GTFSDeleteCommand(GTFSImporterAction controller) {
+        gtfsStopTM = controller.getGTFSStopTableModel();
+        workingLines = new Vector<>();
+        nodesForUndo = new Vector<>();
+        typesForUndo = new Vector<>();
+
+        // use either selected lines or all lines if no line is selected
+        int[] selectedLines = controller.getDialog().getGTFSStopTable().getSelectedRows();
+        Vector<Integer> consideredLines = new Vector<>();
+        if (selectedLines.length > 0) {
+            for (int i = 0; i < selectedLines.length; ++i)
+                consideredLines.add(selectedLines[i]);
+        } else {
+            for (int i = 0; i < gtfsStopTM.getRowCount(); ++i)
+                consideredLines.add(new Integer(i));
+        }
+
+        // keep only lines where a node can be added
+        for (int i = 0; i < consideredLines.size(); ++i) {
+            if (gtfsStopTM.nodes.elementAt(consideredLines.elementAt(i)) != null)
+                workingLines.add(consideredLines.elementAt(i));
+        }
     }
 
-    // keep only lines where a node can be added
-    for (int i = 0; i < consideredLines.size(); ++i)
-    {
-      if (gtfsStopTM.nodes.elementAt(consideredLines.elementAt(i)) != null)
-    workingLines.add(consideredLines.elementAt(i));
+    @Override
+    public boolean executeCommand() {
+        nodesForUndo.clear();
+        typesForUndo.clear();
+        for (int i = 0; i < workingLines.size(); ++i) {
+            int j = workingLines.elementAt(i).intValue();
+            Node node = gtfsStopTM.nodes.elementAt(j);
+            nodesForUndo.add(node);
+            typesForUndo.add((String) gtfsStopTM.getValueAt(j, 2));
+            if (node == null)
+                continue;
+            gtfsStopTM.nodes.set(j, null);
+            gtfsStopTM.setValueAt(tr("skipped"), j, 2);
+            Main.getLayerManager().getEditDataSet().removePrimitive(node);
+            node.setDeleted(true);
+        }
+        return true;
     }
-  }
 
-  public boolean executeCommand()
-  {
-    nodesForUndo.clear();
-    typesForUndo.clear();
-    for (int i = 0; i < workingLines.size(); ++i)
-    {
-      int j = workingLines.elementAt(i).intValue();
-      Node node = gtfsStopTM.nodes.elementAt(j);
-      nodesForUndo.add(node);
-      typesForUndo.add((String)gtfsStopTM.getValueAt(j, 2));
-      if (node == null)
-    continue;
-      gtfsStopTM.nodes.set(j, null);
-      gtfsStopTM.setValueAt(tr("skipped"), j, 2);
-      Main.main.getCurrentDataSet().removePrimitive(node);
-      node.setDeleted(true);
+    @Override
+    public void undoCommand() {
+        for (int i = 0; i < workingLines.size(); ++i) {
+            int j = workingLines.elementAt(i).intValue();
+            Node node = nodesForUndo.elementAt(i);
+            gtfsStopTM.nodes.set(j, node);
+            gtfsStopTM.setValueAt(typesForUndo.elementAt(i), j, 2);
+            if (node == null)
+                continue;
+            node.setDeleted(false);
+            Main.getLayerManager().getEditDataSet().addPrimitive(node);
+        }
     }
-    return true;
-  }
 
-  public void undoCommand()
-  {
-    for (int i = 0; i < workingLines.size(); ++i)
-    {
-      int j = workingLines.elementAt(i).intValue();
-      Node node = nodesForUndo.elementAt(i);
-      gtfsStopTM.nodes.set(j, node);
-      gtfsStopTM.setValueAt(typesForUndo.elementAt(i), j, 2);
-      if (node == null)
-    continue;
-      node.setDeleted(false);
-      Main.main.getCurrentDataSet().addPrimitive(node);
+    @Override
+    public void fillModifiedData(Collection<OsmPrimitive> modified,
+            Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
     }
-  }
 
-  public void fillModifiedData
-    (Collection< OsmPrimitive > modified, Collection< OsmPrimitive > deleted,
-     Collection< OsmPrimitive > added)
-  {
-  }
-
-  @Override public String getDescriptionText()
-  {
-    return tr("Public Transport: Disable GTFS");
-  }
-};
+    @Override
+    public String getDescriptionText() {
+        return tr("Public Transport: Disable GTFS");
+    }
+}
Index: /applications/editors/josm/plugins/public_transport/src/public_transport/GTFSImporterAction.java
===================================================================
--- /applications/editors/josm/plugins/public_transport/src/public_transport/GTFSImporterAction.java	(revision 32356)
+++ /applications/editors/josm/plugins/public_transport/src/public_transport/GTFSImporterAction.java	(revision 32357)
@@ -24,77 +24,78 @@
 import org.openstreetmap.josm.actions.JosmAction;
 import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
 
-public class GTFSImporterAction extends JosmAction
-{
-  private static GTFSImporterDialog dialog = null;
-  private static DefaultListModel tracksListModel = null;
-  private static Vector< String > data = null;
-  private static TrackReference currentTrack = null;
-  private static GTFSStopTableModel gtfsStopTM = null;
-  public boolean inEvent = false;
-
-  public GTFSImporterAction()
-  {
-    super(tr("Create Stops from GTFS ..."), null,
-      tr("Create Stops from a GTFS file"), null, false);
-      putValue("toolbar", "publictransport/gtfsimporter");
-      Main.toolbar.register(this);
-  }
-
-  public GTFSStopTableModel getGTFSStopTableModel()
-  {
-    return gtfsStopTM;
-  }
-
-  public GTFSImporterDialog getDialog()
-  {
-    return dialog;
-  }
-
-  public DefaultListModel getTracksListModel()
-  {
-    if (tracksListModel == null)
-      tracksListModel = new DefaultListModel();
-    return tracksListModel;
-  }
-
-  public TrackReference getCurrentTrack()
-  {
-    return currentTrack;
-  }
-
-  @Override
-public void actionPerformed(ActionEvent event) {
-
-    if (dialog == null)
-      dialog = new GTFSImporterDialog(this);
-
-    dialog.setVisible(true);
-
-    if (tr("Create Stops from GTFS ...").equals(event.getActionCommand()))
-    {
-      String curDir = Main.pref.get("lastDirectory");
-      if (curDir.equals(""))
-      {
-        curDir = ".";
-      }
-      JFileChooser fc = new JFileChooser(new File(curDir));
-      fc.setDialogTitle(tr("Select GTFS file (stops.txt)"));
-      fc.setMultiSelectionEnabled(false);
-
-      int answer = fc.showOpenDialog(Main.parent);
-      if (answer != JFileChooser.APPROVE_OPTION)
-        return;
-
-      if (!fc.getCurrentDirectory().getAbsolutePath().equals(curDir))
-        Main.pref.put("lastDirectory", fc.getCurrentDirectory().getAbsolutePath());
-
-      importData(fc.getSelectedFile());
-
-      refreshData();
-    }
+public class GTFSImporterAction extends JosmAction {
+    private static GTFSImporterDialog dialog = null;
+
+    private static DefaultListModel<?> tracksListModel = null;
+
+    private static Vector<String> data = null;
+
+    private static TrackReference currentTrack = null;
+
+    private static GTFSStopTableModel gtfsStopTM = null;
+
+    public boolean inEvent = false;
+
+    /**
+     * Constructs a new {@code GTFSImporterAction}.
+     */
+    public GTFSImporterAction() {
+        super(tr("Create Stops from GTFS ..."), null, tr("Create Stops from a GTFS file"), null,
+                false);
+        putValue("toolbar", "publictransport/gtfsimporter");
+        Main.toolbar.register(this);
+    }
+
+    public GTFSStopTableModel getGTFSStopTableModel() {
+        return gtfsStopTM;
+    }
+
+    public GTFSImporterDialog getDialog() {
+        return dialog;
+    }
+
+    public DefaultListModel<?> getTracksListModel() {
+        if (tracksListModel == null)
+            tracksListModel = new DefaultListModel<>();
+        return tracksListModel;
+    }
+
+    public TrackReference getCurrentTrack() {
+        return currentTrack;
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent event) {
+
+        if (dialog == null)
+            dialog = new GTFSImporterDialog(this);
+
+        dialog.setVisible(true);
+
+        if (tr("Create Stops from GTFS ...").equals(event.getActionCommand())) {
+            String curDir = Main.pref.get("lastDirectory");
+            if (curDir.isEmpty()) {
+                curDir = ".";
+            }
+            JFileChooser fc = new JFileChooser(new File(curDir));
+            fc.setDialogTitle(tr("Select GTFS file (stops.txt)"));
+            fc.setMultiSelectionEnabled(false);
+
+            int answer = fc.showOpenDialog(Main.parent);
+            if (answer != JFileChooser.APPROVE_OPTION)
+                return;
+
+            if (!fc.getCurrentDirectory().getAbsolutePath().equals(curDir))
+                Main.pref.put("lastDirectory", fc.getCurrentDirectory().getAbsolutePath());
+
+            importData(fc.getSelectedFile());
+
+            refreshData();
+        }
 /*    else if ("stopImporter.settingsGPSTimeStart".equals(event.getActionCommand()))
     {
@@ -130,99 +131,80 @@
       dialog.getStoplistTable().clearSelection();
     }*/
-    else if ("gtfsImporter.gtfsStopsAdd".equals(event.getActionCommand()))
-      Main.main.undoRedo.add(new GTFSAddCommand(this));
-    else if ("gtfsImporter.gtfsStopsDelete".equals(event.getActionCommand()))
-      Main.main.undoRedo.add(new GTFSDeleteCommand(this));
-    else if ("gtfsImporter.gtfsStopsCatch".equals(event.getActionCommand()))
-      Main.main.undoRedo.add(new GTFSCatchCommand(this));
-    else if ("gtfsImporter.gtfsStopsJoin".equals(event.getActionCommand()))
-      Main.main.undoRedo.add(new GTFSJoinCommand(this));
-    else if ("gtfsImporter.gtfsStopsFind".equals(event.getActionCommand()))
-      findNodesInTable(dialog.getGTFSStopTable(), gtfsStopTM.nodes);
-    else if ("gtfsImporter.gtfsStopsShow".equals(event.getActionCommand()))
-      showNodesFromTable(dialog.getGTFSStopTable(), gtfsStopTM.nodes);
-    else if ("gtfsImporter.gtfsStopsMark".equals(event.getActionCommand()))
-      markNodesFromTable(dialog.getGTFSStopTable(), gtfsStopTM.nodes);
-  }
-
-  private void importData(final File file)
-  {
-    try
-    {
-      FileReader is = new FileReader(file);
-      final BufferedReader r = new BufferedReader(is);
-
-      if (data == null)
-    data = new Vector< String >();
-      else
-    data.clear();
-
-      while (r.ready())
-    data.add(r.readLine());
-    }
-    catch (FileNotFoundException e)
-    {
-      e.printStackTrace();
-      JOptionPane.showMessageDialog(null, tr("File \"{0}\" does not exist", file.getName()));
-    }
-    catch (IOException e)
-    {
-      e.printStackTrace();
-      JOptionPane.showMessageDialog(null, tr("IOException \"{0}\" occurred", e.toString()));
-    }
-  }
-
-  private void refreshData()
-  {
-    if (data != null)
-    {
-      Vector< Node > existingStops = new Vector< Node >();
-
-      if (Main.main.getCurrentDataSet() == null)
-      {
-        JOptionPane.showMessageDialog(null, tr("There exists no dataset."
-        + " Try to download data from the server or open an OSM file."),
-        tr("No data found"), JOptionPane.ERROR_MESSAGE);
-
-        return;
-      }
-      else
-      {
-        Iterator< Node > iter =
-        Main.main.getCurrentDataSet().getNodes().iterator();
-        while (iter.hasNext())
-        {
-          Node node = iter.next();
-          if ("bus_stop".equals(node.get("highway")))
-            existingStops.add(node);
-        }
-      }
-
-      Iterator< String > iter = data.iterator();
-      if (iter.hasNext())
-        gtfsStopTM = new GTFSStopTableModel(this, iter.next());
-      else
-      {
-        JOptionPane.showMessageDialog
-        (null, tr("The GTFS file was empty."), tr("No data found"),
-        JOptionPane.ERROR_MESSAGE);
-
-        return;
-      }
-
-      while (iter.hasNext())
-      {
-        String s = iter.next();
-        gtfsStopTM.addRow(s, existingStops);
-      }
-      dialog.setGTFSStopTableModel(gtfsStopTM);
-    }
-    else
-    {
-      JOptionPane.showMessageDialog
-      (null, tr("The GTFS file was empty."), tr("No data found"),
-       JOptionPane.ERROR_MESSAGE);
-    }
-  }
+        else if ("gtfsImporter.gtfsStopsAdd".equals(event.getActionCommand()))
+            Main.main.undoRedo.add(new GTFSAddCommand(this));
+        else if ("gtfsImporter.gtfsStopsDelete".equals(event.getActionCommand()))
+            Main.main.undoRedo.add(new GTFSDeleteCommand(this));
+        else if ("gtfsImporter.gtfsStopsCatch".equals(event.getActionCommand()))
+            Main.main.undoRedo.add(new GTFSCatchCommand(this));
+        else if ("gtfsImporter.gtfsStopsJoin".equals(event.getActionCommand()))
+            Main.main.undoRedo.add(new GTFSJoinCommand(this));
+        else if ("gtfsImporter.gtfsStopsFind".equals(event.getActionCommand()))
+            findNodesInTable(dialog.getGTFSStopTable(), gtfsStopTM.nodes);
+        else if ("gtfsImporter.gtfsStopsShow".equals(event.getActionCommand()))
+            showNodesFromTable(dialog.getGTFSStopTable(), gtfsStopTM.nodes);
+        else if ("gtfsImporter.gtfsStopsMark".equals(event.getActionCommand()))
+            markNodesFromTable(dialog.getGTFSStopTable(), gtfsStopTM.nodes);
+    }
+
+    private void importData(final File file) {
+        try {
+            FileReader is = new FileReader(file);
+            final BufferedReader r = new BufferedReader(is);
+
+            if (data == null)
+                data = new Vector<>();
+            else
+                data.clear();
+
+            while (r.ready())
+                data.add(r.readLine());
+        } catch (FileNotFoundException e) {
+            Main.error(e);
+            JOptionPane.showMessageDialog(null, tr("File \"{0}\" does not exist", file.getName()));
+        } catch (IOException e) {
+            Main.error(e);
+            JOptionPane.showMessageDialog(null, tr("IOException \"{0}\" occurred", e.toString()));
+        }
+    }
+
+    private void refreshData() {
+        if (data != null) {
+            Vector<Node> existingStops = new Vector<>();
+
+            DataSet ds = Main.getLayerManager().getEditDataSet();
+            if (ds == null) {
+                JOptionPane.showMessageDialog(null,
+                        tr("There exists no dataset. Try to download data from the server or open an OSM file."),
+                        tr("No data found"), JOptionPane.ERROR_MESSAGE);
+
+                return;
+            } else {
+                Iterator<Node> iter = ds.getNodes().iterator();
+                while (iter.hasNext()) {
+                    Node node = iter.next();
+                    if ("bus_stop".equals(node.get("highway")))
+                        existingStops.add(node);
+                }
+            }
+
+            Iterator<String> iter = data.iterator();
+            if (iter.hasNext())
+                gtfsStopTM = new GTFSStopTableModel(this, iter.next());
+            else {
+                JOptionPane.showMessageDialog(null, tr("The GTFS file was empty."),
+                        tr("No data found"), JOptionPane.ERROR_MESSAGE);
+                return;
+            }
+
+            while (iter.hasNext()) {
+                String s = iter.next();
+                gtfsStopTM.addRow(s, existingStops);
+            }
+            dialog.setGTFSStopTableModel(gtfsStopTM);
+        } else {
+            JOptionPane.showMessageDialog(null, tr("The GTFS file was empty."), tr("No data found"),
+                    JOptionPane.ERROR_MESSAGE);
+        }
+    }
 
 //   public void tracksSelectionChanged(int selectedPos)
@@ -249,120 +231,111 @@
 //   }
 
-  public static Node createNode(LatLon latLon, String id, String name)
-  {
-    Node node = new Node(latLon);
-    node.put("highway", "bus_stop");
-    node.put("stop_id", id);
-    node.put("name", name);
-    if (Main.main.getCurrentDataSet() == null)
-    {
-      JOptionPane.showMessageDialog(null, tr("There exists no dataset."
-      + " Try to download data from the server or open an OSM file."),
-      tr("No data found"), JOptionPane.ERROR_MESSAGE);
-
-      return null;
-    }
-    Main.main.getCurrentDataSet().addPrimitive(node);
-    return node;
-  }
-
-  /* returns a collection of all selected lines or
-     a collection of all lines otherwise */
-  public static Vector< Integer > getConsideredLines(JTable table)
-  {
-    int[] selectedLines = table.getSelectedRows();
-    Vector< Integer > consideredLines = new Vector< Integer >();
-    if (selectedLines.length > 0)
-    {
-      for (int i = 0; i < selectedLines.length; ++i)
-        consideredLines.add(selectedLines[i]);
-    }
-    else
-    {
-      for (int i = 0; i < table.getRowCount(); ++i)
-        consideredLines.add(new Integer(i));
-    }
-    return consideredLines;
-  }
-
-  /* marks the table items whose nodes are marked on the map */
-  public static void findNodesInTable(JTable table, Vector< Node > nodes)
-  {
-    if (Main.main.getCurrentDataSet() == null)
-      return;
-
-    table.clearSelection();
-
-    for (int i = 0; i < table.getRowCount(); ++i)
-    {
-      if ((nodes.elementAt(i) != null) &&
-      (Main.main.getCurrentDataSet().isSelected(nodes.elementAt(i))))
-        table.addRowSelectionInterval(i, i);
-    }
-  }
-
-  /* shows the nodes that correspond to the marked lines in the table.
-     If no lines are marked in the table, show all nodes from the vector */
-  public static void showNodesFromTable(JTable table, Vector< Node > nodes)
-  {
-    BoundingXYVisitor box = new BoundingXYVisitor();
-    Vector< Integer > consideredLines = getConsideredLines(table);
-    for (int i = 0; i < consideredLines.size(); ++i)
-    {
-      int j = consideredLines.elementAt(i);
-      if (nodes.elementAt(j) != null)
-        nodes.elementAt(j).accept(box);
-    }
-    if (box.getBounds() == null)
-      return;
-    box.enlargeBoundingBox();
-    Main.map.mapView.zoomTo(box);
-  }
-
-  /* marks the nodes that correspond to the marked lines in the table.
-  If no lines are marked in the table, mark all nodes from the vector */
-  public static void markNodesFromTable(JTable table, Vector< Node > nodes)
-  {
-    OsmPrimitive[] osmp = { null };
-    Main.main.getCurrentDataSet().setSelected(osmp);
-    Vector< Integer > consideredLines = getConsideredLines(table);
-    for (int i = 0; i < consideredLines.size(); ++i)
-    {
-      int j = consideredLines.elementAt(i);
-      if (nodes.elementAt(j) != null)
-        Main.main.getCurrentDataSet().addSelected(nodes.elementAt(j));
-    }
-  }
-
-  public static String timeOf(double t)
-  {
-    t -= Math.floor(t/24/60/60)*24*60*60;
-
-    int hour = (int)Math.floor(t/60/60);
-    t -=  Math.floor(t/60/60)*60*60;
-    int minute = (int)Math.floor(t/60);
-    t -=  Math.floor(t/60)*60;
-    double second = t;
-
-    Format format = new DecimalFormat("00");
-    Format formatS = new DecimalFormat("00.###");
-    return (format.format(hour) + ":" + format.format(minute) + ":"
-    + formatS.format(second));
-  }
-
-  public Action getFocusAddAction()
-  {
-    return new FocusAddAction();
-  }
-
-  private class FocusAddAction extends AbstractAction
-  {
-    @Override
-    public void actionPerformed(ActionEvent e)
-    {
-      Main.main.undoRedo.add(new GTFSAddCommand(GTFSImporterAction.this));
-      showNodesFromTable(dialog.getGTFSStopTable(), gtfsStopTM.nodes);
-    }
-  };
+    public static Node createNode(LatLon latLon, String id, String name) {
+        Node node = new Node(latLon);
+        node.put("highway", "bus_stop");
+        node.put("stop_id", id);
+        node.put("name", name);
+        DataSet ds = Main.getLayerManager().getEditDataSet();
+        if (ds == null) {
+            JOptionPane.showMessageDialog(null,
+                    tr("There exists no dataset."
+                            + " Try to download data from the server or open an OSM file."),
+                    tr("No data found"), JOptionPane.ERROR_MESSAGE);
+
+            return null;
+        }
+        ds.addPrimitive(node);
+        return node;
+    }
+
+    /**
+     * returns a collection of all selected lines or a collection of all lines otherwise
+     */
+    public static Vector<Integer> getConsideredLines(JTable table) {
+        int[] selectedLines = table.getSelectedRows();
+        Vector<Integer> consideredLines = new Vector<>();
+        if (selectedLines.length > 0) {
+            for (int i = 0; i < selectedLines.length; ++i)
+                consideredLines.add(selectedLines[i]);
+        } else {
+            for (int i = 0; i < table.getRowCount(); ++i)
+                consideredLines.add(new Integer(i));
+        }
+        return consideredLines;
+    }
+
+    /** marks the table items whose nodes are marked on the map */
+    public static void findNodesInTable(JTable table, Vector<Node> nodes) {
+        DataSet ds = Main.getLayerManager().getEditDataSet();
+        if (ds == null)
+            return;
+
+        table.clearSelection();
+
+        for (int i = 0; i < table.getRowCount(); ++i) {
+            if ((nodes.elementAt(i) != null) && (ds.isSelected(nodes.elementAt(i))))
+                table.addRowSelectionInterval(i, i);
+        }
+    }
+
+    /**
+     * shows the nodes that correspond to the marked lines in the table. 
+     * If no lines are marked in the table, show all nodes from the vector
+     */
+    public static void showNodesFromTable(JTable table, Vector<Node> nodes) {
+        BoundingXYVisitor box = new BoundingXYVisitor();
+        Vector<Integer> consideredLines = getConsideredLines(table);
+        for (int i = 0; i < consideredLines.size(); ++i) {
+            int j = consideredLines.elementAt(i);
+            if (nodes.elementAt(j) != null)
+                nodes.elementAt(j).accept(box);
+        }
+        if (box.getBounds() == null)
+            return;
+        box.enlargeBoundingBox();
+        Main.map.mapView.zoomTo(box);
+    }
+
+    /**
+     * marks the nodes that correspond to the marked lines in the table. 
+     * If no lines are marked in the table, mark all nodes from the vector
+     */
+    public static void markNodesFromTable(JTable table, Vector<Node> nodes) {
+        OsmPrimitive[] osmp = { null };
+        DataSet ds = Main.getLayerManager().getEditDataSet();
+        ds.setSelected(osmp);
+        Vector<Integer> consideredLines = getConsideredLines(table);
+        for (int i = 0; i < consideredLines.size(); ++i) {
+            int j = consideredLines.elementAt(i);
+            if (nodes.elementAt(j) != null)
+                ds.addSelected(nodes.elementAt(j));
+        }
+    }
+
+    public static String timeOf(double t) {
+        t -= Math.floor(t / 24 / 60 / 60) * 24 * 60 * 60;
+
+        int hour = (int) Math.floor(t / 60 / 60);
+        t -= Math.floor(t / 60 / 60) * 60 * 60;
+        int minute = (int) Math.floor(t / 60);
+        t -= Math.floor(t / 60) * 60;
+        double second = t;
+
+        Format format = new DecimalFormat("00");
+        Format formatS = new DecimalFormat("00.###");
+        return format.format(hour) + ":" + format.format(minute) + ":" + formatS.format(second);
+    }
+
+    public Action getFocusAddAction() {
+        return new FocusAddAction();
+    }
+
+    private class FocusAddAction extends AbstractAction {
+        @Override
+        public void actionPerformed(ActionEvent e) {
+            Main.main.undoRedo.add(new GTFSAddCommand(GTFSImporterAction.this));
+            showNodesFromTable(dialog.getGTFSStopTable(), gtfsStopTM.nodes);
+        }
+    }
 
 /*  public Action getFocusWaypointShelterAction(String shelter)
Index: /applications/editors/josm/plugins/public_transport/src/public_transport/GTFSImporterDialog.java
===================================================================
--- /applications/editors/josm/plugins/public_transport/src/public_transport/GTFSImporterDialog.java	(revision 32356)
+++ /applications/editors/josm/plugins/public_transport/src/public_transport/GTFSImporterDialog.java	(revision 32357)
@@ -14,196 +14,194 @@
 import javax.swing.KeyStroke;
 
-public class GTFSImporterDialog extends AbstractImporterDialog<GTFSImporterAction>
-{
-  private JTable gtfsStopTable = null;
-
-  public GTFSImporterDialog(GTFSImporterAction controller)
-  {
-      super(controller, tr("Create Stops from GTFS"), "gtfsImporter");
-  }
-  
-  @Override
-  protected void initDialog(GTFSImporterAction controller) {
-    JPanel tabSettings = new JPanel();
-    tabbedPane.addTab(tr("Settings"), tabSettings);
-    JPanel tabWaypoints = new JPanel();
-    tabbedPane.addTab(tr("GTFS-Stops"), tabWaypoints);
-    tabbedPane.setEnabledAt(0, false);
-    tabbedPane.setEnabledAt(1, true);
-
-    //Settings Tab
-    JPanel contentPane = tabSettings;
-    GridBagLayout gridbag = new GridBagLayout();
-    GridBagConstraints layoutCons = new GridBagConstraints();
-    contentPane.setLayout(gridbag);
-
-    JLabel label = new JLabel(tr("Type of stops to add"));
-
-    layoutCons.gridx = 0;
-    layoutCons.gridy = 0;
-    layoutCons.gridwidth = 2;
-    layoutCons.weightx = 0.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(label, layoutCons);
-    contentPane.add(label);
-
-    layoutCons.gridx = 0;
-    layoutCons.gridy = 1;
-    layoutCons.gridwidth = 1;
-    layoutCons.weightx = 0.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(cbStoptype, layoutCons);
-    contentPane.add(cbStoptype);
-
-    label = new JLabel(tr("Time on your GPS device"));
-
-    layoutCons.gridx = 0;
-    layoutCons.gridy = 2;
-    layoutCons.gridwidth = 2;
-    layoutCons.weightx = 0.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(label, layoutCons);
-    contentPane.add(label);
-
-    layoutCons.gridx = 0;
-    layoutCons.gridy = 3;
-    layoutCons.gridwidth = 1;
-    layoutCons.weightx = 0.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(tfGPSTimeStart, layoutCons);
-    contentPane.add(tfGPSTimeStart);
-
-    /* I18n: Don't change the time format, you only may translate the letters */
-    label = new JLabel(tr("HH:MM:SS.sss"));
-
-    layoutCons.gridx = 1;
-    layoutCons.gridy = 3;
-    layoutCons.gridwidth = 1;
-    layoutCons.weightx = 0.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(label, layoutCons);
-    contentPane.add(label);
-
-    label = new JLabel(tr("Time on your stopwatch"));
-
-    layoutCons.gridx = 0;
-    layoutCons.gridy = 4;
-    layoutCons.gridwidth = 2;
-    layoutCons.weightx = 0.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(label, layoutCons);
-    contentPane.add(label);
-
-    layoutCons.gridx = 0;
-    layoutCons.gridy = 5;
-    layoutCons.gridwidth = 1;
-    layoutCons.weightx = 0.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(tfStopwatchStart, layoutCons);
-    contentPane.add(tfStopwatchStart);
-
-    /* I18n: Don't change the time format, you only may translate the letters */
-    label = new JLabel(tr("HH:MM:SS.sss"));
-
-    layoutCons.gridx = 1;
-    layoutCons.gridy = 5;
-    layoutCons.gridwidth = 1;
-    layoutCons.weightx = 0.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(label, layoutCons);
-    contentPane.add(label);
-
-    label = new JLabel(tr("Time window"));
-
-    layoutCons.gridx = 0;
-    layoutCons.gridy = 6;
-    layoutCons.gridwidth = 2;
-    layoutCons.weightx = 0.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(label, layoutCons);
-    contentPane.add(label);
-
-    layoutCons.gridx = 0;
-    layoutCons.gridy = 7;
-    layoutCons.gridwidth = 1;
-    layoutCons.weightx = 0.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(tfTimeWindow, layoutCons);
-    contentPane.add(tfTimeWindow);
-
-    label = new JLabel(tr("seconds"));
-
-    layoutCons.gridx = 1;
-    layoutCons.gridy = 7;
-    layoutCons.gridwidth = 1;
-    layoutCons.weightx = 0.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(label, layoutCons);
-    contentPane.add(label);
-
-    label = new JLabel(tr("Move Threshold"));
-
-    layoutCons.gridx = 0;
-    layoutCons.gridy = 8;
-    layoutCons.gridwidth = 2;
-    layoutCons.weightx = 0.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(label, layoutCons);
-    contentPane.add(label);
-
-    layoutCons.gridx = 0;
-    layoutCons.gridy = 9;
-    layoutCons.gridwidth = 1;
-    layoutCons.weightx = 0.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(tfThreshold, layoutCons);
-    contentPane.add(tfThreshold);
-
-    label = new JLabel(tr("meters"));
-
-    layoutCons.gridx = 1;
-    layoutCons.gridy = 9;
-    layoutCons.gridwidth = 1;
-    layoutCons.weightx = 0.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(label, layoutCons);
-    contentPane.add(label);
-
-    JButton bSuggestStops = new JButton(tr("Suggest Stops"));
-    bSuggestStops.setActionCommand("gtfsImporter.settingsSuggestStops");
-    bSuggestStops.addActionListener(controller);
-
-    layoutCons.gridx = 0;
-    layoutCons.gridy = 10;
-    layoutCons.gridwidth = 3;
-    layoutCons.weightx = 1.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(bSuggestStops, layoutCons);
-    contentPane.add(bSuggestStops);
-
-    //Waypoints Tab
-    contentPane = tabWaypoints;
-    gridbag = new GridBagLayout();
-    layoutCons = new GridBagConstraints();
-    contentPane.setLayout(gridbag);
-    contentPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put
-        (KeyStroke.getKeyStroke("alt N"), "gtfsImporter.gtfsStopsFocusAdd");
-    contentPane.getActionMap().put
-    ("gtfsImporter.gtfsStopsFocusAdd", controller.getFocusAddAction());
+public class GTFSImporterDialog extends AbstractImporterDialog<GTFSImporterAction> {
+    private JTable gtfsStopTable = null;
+
+    public GTFSImporterDialog(GTFSImporterAction controller) {
+        super(controller, tr("Create Stops from GTFS"), "gtfsImporter");
+    }
+
+    @Override
+    protected void initDialog(GTFSImporterAction controller) {
+        JPanel tabSettings = new JPanel();
+        tabbedPane.addTab(tr("Settings"), tabSettings);
+        JPanel tabWaypoints = new JPanel();
+        tabbedPane.addTab(tr("GTFS-Stops"), tabWaypoints);
+        tabbedPane.setEnabledAt(0, false);
+        tabbedPane.setEnabledAt(1, true);
+
+        // Settings Tab
+        JPanel contentPane = tabSettings;
+        GridBagLayout gridbag = new GridBagLayout();
+        GridBagConstraints layoutCons = new GridBagConstraints();
+        contentPane.setLayout(gridbag);
+
+        JLabel label = new JLabel(tr("Type of stops to add"));
+
+        layoutCons.gridx = 0;
+        layoutCons.gridy = 0;
+        layoutCons.gridwidth = 2;
+        layoutCons.weightx = 0.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(label, layoutCons);
+        contentPane.add(label);
+
+        layoutCons.gridx = 0;
+        layoutCons.gridy = 1;
+        layoutCons.gridwidth = 1;
+        layoutCons.weightx = 0.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(cbStoptype, layoutCons);
+        contentPane.add(cbStoptype);
+
+        label = new JLabel(tr("Time on your GPS device"));
+
+        layoutCons.gridx = 0;
+        layoutCons.gridy = 2;
+        layoutCons.gridwidth = 2;
+        layoutCons.weightx = 0.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(label, layoutCons);
+        contentPane.add(label);
+
+        layoutCons.gridx = 0;
+        layoutCons.gridy = 3;
+        layoutCons.gridwidth = 1;
+        layoutCons.weightx = 0.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(tfGPSTimeStart, layoutCons);
+        contentPane.add(tfGPSTimeStart);
+
+        /* I18n: Don't change the time format, you only may translate the letters */
+        label = new JLabel(tr("HH:MM:SS.sss"));
+
+        layoutCons.gridx = 1;
+        layoutCons.gridy = 3;
+        layoutCons.gridwidth = 1;
+        layoutCons.weightx = 0.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(label, layoutCons);
+        contentPane.add(label);
+
+        label = new JLabel(tr("Time on your stopwatch"));
+
+        layoutCons.gridx = 0;
+        layoutCons.gridy = 4;
+        layoutCons.gridwidth = 2;
+        layoutCons.weightx = 0.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(label, layoutCons);
+        contentPane.add(label);
+
+        layoutCons.gridx = 0;
+        layoutCons.gridy = 5;
+        layoutCons.gridwidth = 1;
+        layoutCons.weightx = 0.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(tfStopwatchStart, layoutCons);
+        contentPane.add(tfStopwatchStart);
+
+        /* I18n: Don't change the time format, you only may translate the letters */
+        label = new JLabel(tr("HH:MM:SS.sss"));
+
+        layoutCons.gridx = 1;
+        layoutCons.gridy = 5;
+        layoutCons.gridwidth = 1;
+        layoutCons.weightx = 0.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(label, layoutCons);
+        contentPane.add(label);
+
+        label = new JLabel(tr("Time window"));
+
+        layoutCons.gridx = 0;
+        layoutCons.gridy = 6;
+        layoutCons.gridwidth = 2;
+        layoutCons.weightx = 0.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(label, layoutCons);
+        contentPane.add(label);
+
+        layoutCons.gridx = 0;
+        layoutCons.gridy = 7;
+        layoutCons.gridwidth = 1;
+        layoutCons.weightx = 0.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(tfTimeWindow, layoutCons);
+        contentPane.add(tfTimeWindow);
+
+        label = new JLabel(tr("seconds"));
+
+        layoutCons.gridx = 1;
+        layoutCons.gridy = 7;
+        layoutCons.gridwidth = 1;
+        layoutCons.weightx = 0.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(label, layoutCons);
+        contentPane.add(label);
+
+        label = new JLabel(tr("Move Threshold"));
+
+        layoutCons.gridx = 0;
+        layoutCons.gridy = 8;
+        layoutCons.gridwidth = 2;
+        layoutCons.weightx = 0.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(label, layoutCons);
+        contentPane.add(label);
+
+        layoutCons.gridx = 0;
+        layoutCons.gridy = 9;
+        layoutCons.gridwidth = 1;
+        layoutCons.weightx = 0.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(tfThreshold, layoutCons);
+        contentPane.add(tfThreshold);
+
+        label = new JLabel(tr("meters"));
+
+        layoutCons.gridx = 1;
+        layoutCons.gridy = 9;
+        layoutCons.gridwidth = 1;
+        layoutCons.weightx = 0.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(label, layoutCons);
+        contentPane.add(label);
+
+        JButton bSuggestStops = new JButton(tr("Suggest Stops"));
+        bSuggestStops.setActionCommand("gtfsImporter.settingsSuggestStops");
+        bSuggestStops.addActionListener(controller);
+
+        layoutCons.gridx = 0;
+        layoutCons.gridy = 10;
+        layoutCons.gridwidth = 3;
+        layoutCons.weightx = 1.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(bSuggestStops, layoutCons);
+        contentPane.add(bSuggestStops);
+
+        // Waypoints Tab
+        contentPane = tabWaypoints;
+        gridbag = new GridBagLayout();
+        layoutCons = new GridBagConstraints();
+        contentPane.setLayout(gridbag);
+        contentPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
+                .put(KeyStroke.getKeyStroke("alt N"), "gtfsImporter.gtfsStopsFocusAdd");
+        contentPane.getActionMap().put("gtfsImporter.gtfsStopsFocusAdd",
+                controller.getFocusAddAction());
 /*    contentPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put
         (KeyStroke.getKeyStroke("alt S"), "gtfsImporter.focusShelterYes");
@@ -227,125 +225,123 @@
      controller.getFocusWaypointDeleteAction());*/
 
-    gtfsStopTable = new JTable();
-    JScrollPane tableSP = new JScrollPane(gtfsStopTable);
-
-    layoutCons.gridx = 0;
-    layoutCons.gridy = 0;
-    layoutCons.gridwidth = 4;
-    layoutCons.weightx = 1.0;
-    layoutCons.weighty = 1.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(tableSP, layoutCons);
-    contentPane.add(tableSP);
-
-    JButton bFind = new JButton(tr("Find"));
-    bFind.setActionCommand("gtfsImporter.gtfsStopsFind");
-    bFind.addActionListener(controller);
-
-    layoutCons.gridx = 0;
-    layoutCons.gridy = 1;
-    layoutCons.gridwidth = 1;
-    layoutCons.weightx = 1.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(bFind, layoutCons);
-    contentPane.add(bFind);
-
-    JButton bShow = new JButton(tr("Show"));
-    bShow.setActionCommand("gtfsImporter.gtfsStopsShow");
-    bShow.addActionListener(controller);
-
-    layoutCons.gridx = 0;
-    layoutCons.gridy = 2;
-    layoutCons.gridwidth = 1;
-    layoutCons.weightx = 1.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(bShow, layoutCons);
-    contentPane.add(bShow);
-
-    JButton bMark = new JButton(tr("Mark"));
-    bMark.setActionCommand("gtfsImporter.gtfsStopsMark");
-    bMark.addActionListener(controller);
-
-    layoutCons.gridx = 1;
-    layoutCons.gridy = 1;
-    layoutCons.gridheight = 2;
-    layoutCons.gridwidth = 1;
-    layoutCons.weightx = 1.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(bMark, layoutCons);
-    contentPane.add(bMark);
-
-    JButton bCatch = new JButton(tr("Catch"));
-    bCatch.setActionCommand("gtfsImporter.gtfsStopsCatch");
-    bCatch.addActionListener(controller);
-
-    layoutCons.gridx = 2;
-    layoutCons.gridy = 1;
-    layoutCons.gridheight = 1;
-    layoutCons.gridwidth = 1;
-    layoutCons.weightx = 1.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(bCatch, layoutCons);
-    contentPane.add(bCatch);
-
-    JButton bJoin = new JButton(tr("Join"));
-    bJoin.setActionCommand("gtfsImporter.gtfsStopsJoin");
-    bJoin.addActionListener(controller);
-
-    layoutCons.gridx = 2;
-    layoutCons.gridy = 2;
-    layoutCons.gridheight = 1;
-    layoutCons.gridwidth = 1;
-    layoutCons.weightx = 1.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(bJoin, layoutCons);
-    contentPane.add(bJoin);
-
-    JButton bAdd = new JButton(tr("Enable"));
-    bAdd.setActionCommand("gtfsImporter.gtfsStopsAdd");
-    bAdd.addActionListener(controller);
-
-    layoutCons.gridx = 3;
-    layoutCons.gridy = 1;
-    layoutCons.gridheight = 1;
-    layoutCons.gridwidth = 1;
-    layoutCons.weightx = 1.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(bAdd, layoutCons);
-    contentPane.add(bAdd);
-
-    JButton bDelete = new JButton(tr("Disable"));
-    bDelete.setActionCommand("gtfsImporter.gtfsStopsDelete");
-    bDelete.addActionListener(controller);
-
-    layoutCons.gridx = 3;
-    layoutCons.gridy = 2;
-    layoutCons.gridwidth = 1;
-    layoutCons.weightx = 1.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(bDelete, layoutCons);
-    contentPane.add(bDelete);
-  }
-
-  public JTable getGTFSStopTable()
-  {
-    return gtfsStopTable;
-  }
-
-  public void setGTFSStopTableModel(GTFSStopTableModel model)
-  {
-    gtfsStopTable.setModel(model);
-    int width = gtfsStopTable.getPreferredSize().width;
-    gtfsStopTable.getColumnModel().getColumn(0).setPreferredWidth((int)(width * 0.3));
-    gtfsStopTable.getColumnModel().getColumn(1).setPreferredWidth((int)(width * 0.6));
-    gtfsStopTable.getColumnModel().getColumn(2).setPreferredWidth((int)(width * 0.1));
-  }
+        gtfsStopTable = new JTable();
+        JScrollPane tableSP = new JScrollPane(gtfsStopTable);
+
+        layoutCons.gridx = 0;
+        layoutCons.gridy = 0;
+        layoutCons.gridwidth = 4;
+        layoutCons.weightx = 1.0;
+        layoutCons.weighty = 1.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(tableSP, layoutCons);
+        contentPane.add(tableSP);
+
+        JButton bFind = new JButton(tr("Find"));
+        bFind.setActionCommand("gtfsImporter.gtfsStopsFind");
+        bFind.addActionListener(controller);
+
+        layoutCons.gridx = 0;
+        layoutCons.gridy = 1;
+        layoutCons.gridwidth = 1;
+        layoutCons.weightx = 1.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(bFind, layoutCons);
+        contentPane.add(bFind);
+
+        JButton bShow = new JButton(tr("Show"));
+        bShow.setActionCommand("gtfsImporter.gtfsStopsShow");
+        bShow.addActionListener(controller);
+
+        layoutCons.gridx = 0;
+        layoutCons.gridy = 2;
+        layoutCons.gridwidth = 1;
+        layoutCons.weightx = 1.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(bShow, layoutCons);
+        contentPane.add(bShow);
+
+        JButton bMark = new JButton(tr("Mark"));
+        bMark.setActionCommand("gtfsImporter.gtfsStopsMark");
+        bMark.addActionListener(controller);
+
+        layoutCons.gridx = 1;
+        layoutCons.gridy = 1;
+        layoutCons.gridheight = 2;
+        layoutCons.gridwidth = 1;
+        layoutCons.weightx = 1.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(bMark, layoutCons);
+        contentPane.add(bMark);
+
+        JButton bCatch = new JButton(tr("Catch"));
+        bCatch.setActionCommand("gtfsImporter.gtfsStopsCatch");
+        bCatch.addActionListener(controller);
+
+        layoutCons.gridx = 2;
+        layoutCons.gridy = 1;
+        layoutCons.gridheight = 1;
+        layoutCons.gridwidth = 1;
+        layoutCons.weightx = 1.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(bCatch, layoutCons);
+        contentPane.add(bCatch);
+
+        JButton bJoin = new JButton(tr("Join"));
+        bJoin.setActionCommand("gtfsImporter.gtfsStopsJoin");
+        bJoin.addActionListener(controller);
+
+        layoutCons.gridx = 2;
+        layoutCons.gridy = 2;
+        layoutCons.gridheight = 1;
+        layoutCons.gridwidth = 1;
+        layoutCons.weightx = 1.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(bJoin, layoutCons);
+        contentPane.add(bJoin);
+
+        JButton bAdd = new JButton(tr("Enable"));
+        bAdd.setActionCommand("gtfsImporter.gtfsStopsAdd");
+        bAdd.addActionListener(controller);
+
+        layoutCons.gridx = 3;
+        layoutCons.gridy = 1;
+        layoutCons.gridheight = 1;
+        layoutCons.gridwidth = 1;
+        layoutCons.weightx = 1.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(bAdd, layoutCons);
+        contentPane.add(bAdd);
+
+        JButton bDelete = new JButton(tr("Disable"));
+        bDelete.setActionCommand("gtfsImporter.gtfsStopsDelete");
+        bDelete.addActionListener(controller);
+
+        layoutCons.gridx = 3;
+        layoutCons.gridy = 2;
+        layoutCons.gridwidth = 1;
+        layoutCons.weightx = 1.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(bDelete, layoutCons);
+        contentPane.add(bDelete);
+    }
+
+    public JTable getGTFSStopTable() {
+        return gtfsStopTable;
+    }
+
+    public void setGTFSStopTableModel(GTFSStopTableModel model) {
+        gtfsStopTable.setModel(model);
+        int width = gtfsStopTable.getPreferredSize().width;
+        gtfsStopTable.getColumnModel().getColumn(0).setPreferredWidth((int) (width * 0.3));
+        gtfsStopTable.getColumnModel().getColumn(1).setPreferredWidth((int) (width * 0.6));
+        gtfsStopTable.getColumnModel().getColumn(2).setPreferredWidth((int) (width * 0.1));
+    }
 
 /*  private class TracksLSL implements ListSelectionListener
Index: /applications/editors/josm/plugins/public_transport/src/public_transport/GTFSJoinCommand.java
===================================================================
--- /applications/editors/josm/plugins/public_transport/src/public_transport/GTFSJoinCommand.java	(revision 32356)
+++ /applications/editors/josm/plugins/public_transport/src/public_transport/GTFSJoinCommand.java	(revision 32357)
@@ -9,103 +9,101 @@
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.command.Command;
+import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 
-public class GTFSJoinCommand extends Command
-{
-  private Vector< Integer > workingLines = null;
-  private Node undoMapNode = null;
-  private Node undoTableNode = null;
-  private GTFSStopTableModel gtfsStopTM = null;
-  private String type = null;
+public class GTFSJoinCommand extends Command {
+    private Vector<Integer> workingLines = null;
 
-  public GTFSJoinCommand(GTFSImporterAction controller)
-  {
-    gtfsStopTM = controller.getGTFSStopTableModel();
-    workingLines = new Vector< Integer >();
+    private Node undoMapNode = null;
 
-    // use either selected lines or all lines if no line is selected
-    int[] selectedLines = controller.getDialog().getGTFSStopTable().getSelectedRows();
-    if (selectedLines.length != 1)
-      return;
-    workingLines.add(selectedLines[0]);
-  }
+    private Node undoTableNode = null;
 
-  public boolean executeCommand()
-  {
-    if (workingLines.size() != 1)
-      return false;
-    Node dest = null;
-    Iterator< Node > iter =
-        Main.main.getCurrentDataSet().getSelectedNodes().iterator();
-    int j = workingLines.elementAt(0);
-    while (iter.hasNext())
-    {
-      Node n = iter.next();
-      if ((n != null) && (n.equals(gtfsStopTM.nodes.elementAt(j))))
-    continue;
-      if (dest != null)
-    return false;
-      dest = n;
-    }
-    if (dest == null)
-      return false;
-    undoMapNode = new Node(dest);
+    private GTFSStopTableModel gtfsStopTM = null;
 
-    Node node = gtfsStopTM.nodes.elementAt(j);
-    undoTableNode = node;
-    if (node != null)
-    {
-      Main.main.getCurrentDataSet().removePrimitive(node);
-      node.setDeleted(true);
+    private String type = null;
+
+    public GTFSJoinCommand(GTFSImporterAction controller) {
+        gtfsStopTM = controller.getGTFSStopTableModel();
+        workingLines = new Vector<>();
+
+        // use either selected lines or all lines if no line is selected
+        int[] selectedLines = controller.getDialog().getGTFSStopTable().getSelectedRows();
+        if (selectedLines.length != 1)
+            return;
+        workingLines.add(selectedLines[0]);
     }
 
-    dest.put("highway", "bus_stop");
-    dest.put("stop_id", (String)gtfsStopTM.getValueAt(j, 0));
-    if (dest.get("name") == null)
-      dest.put("name", (String)gtfsStopTM.getValueAt(j, 1));
-    gtfsStopTM.nodes.set(j, dest);
-    type = (String)gtfsStopTM.getValueAt(j, 2);
-    gtfsStopTM.setValueAt(tr("moved"), j, 2);
+    @Override
+    public boolean executeCommand() {
+        if (workingLines.size() != 1)
+            return false;
+        Node dest = null;
+        DataSet ds = Main.getLayerManager().getEditDataSet();
+        Iterator<Node> iter = ds.getSelectedNodes().iterator();
+        int j = workingLines.elementAt(0);
+        while (iter.hasNext()) {
+            Node n = iter.next();
+            if ((n != null) && (n.equals(gtfsStopTM.nodes.elementAt(j))))
+                continue;
+            if (dest != null)
+                return false;
+            dest = n;
+        }
+        if (dest == null)
+            return false;
+        undoMapNode = new Node(dest);
 
-    return true;
-  }
+        Node node = gtfsStopTM.nodes.elementAt(j);
+        undoTableNode = node;
+        if (node != null) {
+            ds.removePrimitive(node);
+            node.setDeleted(true);
+        }
 
-  public void undoCommand()
-  {
-    if (workingLines.size() != 1)
-      return;
-    int j = workingLines.elementAt(0);
+        dest.put("highway", "bus_stop");
+        dest.put("stop_id", (String) gtfsStopTM.getValueAt(j, 0));
+        if (dest.get("name") == null)
+            dest.put("name", (String) gtfsStopTM.getValueAt(j, 1));
+        gtfsStopTM.nodes.set(j, dest);
+        type = (String) gtfsStopTM.getValueAt(j, 2);
+        gtfsStopTM.setValueAt(tr("moved"), j, 2);
 
-    Node node = gtfsStopTM.nodes.elementAt(j);
-    if (node != null)
-    {
-      Main.main.getCurrentDataSet().removePrimitive(node);
-      node.setDeleted(true);
+        return true;
     }
 
-    if (undoMapNode != null)
-    {
-      undoMapNode.setDeleted(false);
-      Main.main.getCurrentDataSet().addPrimitive(undoMapNode);
+    @Override
+    public void undoCommand() {
+        if (workingLines.size() != 1)
+            return;
+        int j = workingLines.elementAt(0);
+
+        DataSet ds = Main.getLayerManager().getEditDataSet();
+        Node node = gtfsStopTM.nodes.elementAt(j);
+        if (node != null) {
+            ds.removePrimitive(node);
+            node.setDeleted(true);
+        }
+
+        if (undoMapNode != null) {
+            undoMapNode.setDeleted(false);
+            ds.addPrimitive(undoMapNode);
+        }
+        if (undoTableNode != null) {
+            undoTableNode.setDeleted(false);
+            ds.addPrimitive(undoTableNode);
+        }
+        gtfsStopTM.nodes.set(j, undoTableNode);
+        gtfsStopTM.setValueAt(type, j, 2);
     }
-    if (undoTableNode != null)
-    {
-      undoTableNode.setDeleted(false);
-      Main.main.getCurrentDataSet().addPrimitive(undoTableNode);
+
+    @Override
+    public void fillModifiedData(Collection<OsmPrimitive> modified,
+            Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
     }
-    gtfsStopTM.nodes.set(j, undoTableNode);
-    gtfsStopTM.setValueAt(type, j, 2);
-  }
 
-  public void fillModifiedData
-    (Collection< OsmPrimitive > modified, Collection< OsmPrimitive > deleted,
-     Collection< OsmPrimitive > added)
-  {
-  }
-
-  @Override public String getDescriptionText()
-  {
-    return tr("Public Transport: Join GTFS stops");
-  }
+    @Override
+    public String getDescriptionText() {
+        return tr("Public Transport: Join GTFS stops");
+    }
 };
Index: /applications/editors/josm/plugins/public_transport/src/public_transport/GTFSStopTableModel.java
===================================================================
--- /applications/editors/josm/plugins/public_transport/src/public_transport/GTFSStopTableModel.java	(revision 32356)
+++ /applications/editors/josm/plugins/public_transport/src/public_transport/GTFSStopTableModel.java	(revision 32357)
@@ -13,224 +13,205 @@
 import org.openstreetmap.josm.data.DataSource;
 import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.Node;
 
-public class GTFSStopTableModel extends DefaultTableModel
-      implements TableModelListener
-{
-  private GTFSImporterAction controller = null;
-  public Vector< Node > nodes = new Vector< Node >();
-  public Vector< LatLon > coors = new Vector< LatLon >();
-  private int idCol = -1;
-  private int nameCol = -1;
-  private int latCol = -1;
-  private int lonCol = -1;
-  private char separator = ',';
-
-  public GTFSStopTableModel(GTFSImporterAction controller,
-                String columnConfig)
-  {
-    int pos = columnConfig.indexOf(separator);
-    if (pos == -1)
-    {
-      separator = ';';
-      pos = columnConfig.indexOf(separator);
-    }
-    if (pos == -1)
-    {
-      separator = '\t';
-      pos = columnConfig.indexOf(separator);
-    }
-    int oldPos = 0;
-    int i = 0;
-    while (pos > -1)
-    {
-      String title = stripQuot(columnConfig.substring(oldPos, pos));
-      if ("stop_id".equals(title))
-    idCol = i;
-      else if ("stop_name".equals(title))
-    nameCol = i;
-      else if ("stop_lat".equals(title))
-    latCol = i;
-      else if ("stop_lon".equals(title))
-    lonCol = i;
-      ++i;
-      oldPos = pos + 1;
-      pos = columnConfig.indexOf(separator, oldPos);
-    }
-    String title = columnConfig.substring(oldPos);
-    if ("stop_id".equals(title))
-      idCol = i;
-    else if ("stop_name".equals(title))
-      nameCol = i;
-    else if ("stop_lat".equals(title))
-      latCol = i;
-    else if ("stop_lon".equals(title))
-      lonCol = i;
-
-    this.controller = controller;
-    addColumn(tr("Id"));
-    addColumn(tr("Name"));
-    addColumn(tr("State"));
-    addTableModelListener(this);
-  }
-
-  public boolean isCellEditable(int row, int column)
-  {
-    return false;
-  }
-
-  public void addRow(Object[] obj)
-  {
-    throw new UnsupportedOperationException();
-  }
-
-  public void insertRow(int insPos, Object[] obj)
-  {
-    throw new UnsupportedOperationException();
-  }
-
-  public void addRow(String s)
-  {
-    insertRow(-1, s, new Vector< Node >());
-  }
-
-  public void addRow(String s, Vector< Node > existingStops)
-  {
-    insertRow(-1, s, existingStops);
-  }
-
-  /* tokenizes a line as follows:
-     any comma outside a pair of double quotation marks is taken as field separator.
-     In particular, neither \" nor \, have a special meaning.
-     Returns the position of the next field separator, if any. Otherwise it returns -1.
-     s - the string to tokenize.
-     startPos - the position of the last field separator plus 1 or the value 0. */
-  private int tokenize(String s, int startPos)
-  {
-    int pos = startPos;
-    boolean insideDoubleQuoted = false;
-    while (pos < s.length())
-    {
-      if ('"' == s.charAt(pos))
-        insideDoubleQuoted = !insideDoubleQuoted;
-      else if ((separator == s.charAt(pos)) && (!insideDoubleQuoted))
-        break;
-      ++pos;
-    }
-    if (pos < s.length())
-      return pos;
-    else
-      return -1;
-  }
-
-  private String stripQuot(String s)
-  {
-    int pos = s.indexOf('"');
-    while (pos > -1)
-    {
-      s = s.substring(0, pos) + s.substring(pos + 1);
-      pos = s.indexOf('"');
-    }
-    return s;
-  }
-
-  public void insertRow(int insPos, String s, Vector< Node > existingStops)
-  {
-    String[] buf = { "", "", tr("pending") };
-    int pos = tokenize(s, 0);
-    int oldPos = 0;
-    int i = 0;
-    double lat = 0;
-    double lon = 0;
-    while (pos > -1)
-    {
-      if (i == idCol)
-    buf[0] = stripQuot(s.substring(oldPos, pos));
-      else if (i == nameCol)
-    buf[1] = stripQuot(s.substring(oldPos, pos));
-      else if (i == latCol)
-    lat = Double.parseDouble(stripQuot(s.substring(oldPos, pos)));
-      else if (i == lonCol)
-    lon = Double.parseDouble(stripQuot(s.substring(oldPos, pos)));
-      ++i;
-      oldPos = pos + 1;
-      pos = tokenize(s, oldPos);
-    }
-    if (i == idCol)
-      buf[0] = stripQuot(s.substring(oldPos));
-    else if (i == nameCol)
-      buf[1] = stripQuot(s.substring(oldPos));
-    else if (i == latCol)
-      lat = Double.parseDouble(stripQuot(s.substring(oldPos)));
-    else if (i == lonCol)
-      lon = Double.parseDouble(stripQuot(s.substring(oldPos)));
-
-    LatLon coor = new LatLon(lat, lon);
-
-    if (Main.main.getCurrentDataSet() != null)
-    {
-      boolean inside = false;
-      Iterator< DataSource > iter =
-          Main.main.getCurrentDataSet().dataSources.iterator();
-      while (iter.hasNext())
-      {
-        if (iter.next().bounds.contains(coor))
-        {
-          inside = true;
-          break;
-        }
-      }
-      if (!inside)
-        buf[2] = tr("outside");
-    }
-
-    boolean nearBusStop = false;
-    Iterator< Node > iter = existingStops.iterator();
-    while (iter.hasNext())
-    {
-      Node node = iter.next();
-      if (coor.greatCircleDistance(node.getCoor()) < 1000)
-      {
-        nearBusStop = true;
-        break;
-      }
-    }
-
-    if (insPos == -1)
-    {
-      if ((nearBusStop) || !(tr("pending").equals(buf[2])))
-        nodes.addElement(null);
-      else
-      {
-        Node node = GTFSImporterAction.createNode(coor, buf[0], buf[1]);
-        nodes.addElement(node);
-        buf[2] = tr("added");
-      }
-      coors.addElement(coor);
-      super.addRow(buf);
-    }
-    else
-    {
-      if ((nearBusStop) || !(tr("pending").equals(buf[2])))
-        nodes.insertElementAt(null, insPos);
-      else
-      {
-        Node node = GTFSImporterAction.createNode(coor, buf[0], buf[1]);
-        nodes.insertElementAt(node, insPos);
-        buf[2] = tr("added");
-      }
-      coors.insertElementAt(coor, insPos);
-      super.insertRow(insPos, buf);
-    }
-  }
-
-  public void clear()
-  {
-    nodes.clear();
-    super.setRowCount(0);
-  }
-
-  public void tableChanged(TableModelEvent e)
-  {
-  }
-};
+public class GTFSStopTableModel extends DefaultTableModel implements TableModelListener {
+    private GTFSImporterAction controller = null;
+
+    public Vector<Node> nodes = new Vector<Node>();
+
+    public Vector<LatLon> coors = new Vector<LatLon>();
+
+    private int idCol = -1;
+
+    private int nameCol = -1;
+
+    private int latCol = -1;
+
+    private int lonCol = -1;
+
+    private char separator = ',';
+
+    public GTFSStopTableModel(GTFSImporterAction controller, String columnConfig) {
+        int pos = columnConfig.indexOf(separator);
+        if (pos == -1) {
+            separator = ';';
+            pos = columnConfig.indexOf(separator);
+        }
+        if (pos == -1) {
+            separator = '\t';
+            pos = columnConfig.indexOf(separator);
+        }
+        int oldPos = 0;
+        int i = 0;
+        while (pos > -1) {
+            String title = stripQuot(columnConfig.substring(oldPos, pos));
+            if ("stop_id".equals(title))
+                idCol = i;
+            else if ("stop_name".equals(title))
+                nameCol = i;
+            else if ("stop_lat".equals(title))
+                latCol = i;
+            else if ("stop_lon".equals(title))
+                lonCol = i;
+            ++i;
+            oldPos = pos + 1;
+            pos = columnConfig.indexOf(separator, oldPos);
+        }
+        String title = columnConfig.substring(oldPos);
+        if ("stop_id".equals(title))
+            idCol = i;
+        else if ("stop_name".equals(title))
+            nameCol = i;
+        else if ("stop_lat".equals(title))
+            latCol = i;
+        else if ("stop_lon".equals(title))
+            lonCol = i;
+
+        this.controller = controller;
+        addColumn(tr("Id"));
+        addColumn(tr("Name"));
+        addColumn(tr("State"));
+        addTableModelListener(this);
+    }
+
+    @Override
+    public boolean isCellEditable(int row, int column) {
+        return false;
+    }
+
+    @Override
+    public void addRow(Object[] obj) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void insertRow(int insPos, Object[] obj) {
+        throw new UnsupportedOperationException();
+    }
+
+    public void addRow(String s) {
+        insertRow(-1, s, new Vector<Node>());
+    }
+
+    public void addRow(String s, Vector<Node> existingStops) {
+        insertRow(-1, s, existingStops);
+    }
+
+    /*
+     * tokenizes a line as follows: any comma outside a pair of double quotation marks is taken as field separator. In particular, neither \" nor \,
+     * have a special meaning. Returns the position of the next field separator, if any. Otherwise it returns -1. s - the string to tokenize. startPos
+     * - the position of the last field separator plus 1 or the value 0.
+     */
+    private int tokenize(String s, int startPos) {
+        int pos = startPos;
+        boolean insideDoubleQuoted = false;
+        while (pos < s.length()) {
+            if ('"' == s.charAt(pos))
+                insideDoubleQuoted = !insideDoubleQuoted;
+            else if ((separator == s.charAt(pos)) && (!insideDoubleQuoted))
+                break;
+            ++pos;
+        }
+        if (pos < s.length())
+            return pos;
+        else
+            return -1;
+    }
+
+    private String stripQuot(String s) {
+        int pos = s.indexOf('"');
+        while (pos > -1) {
+            s = s.substring(0, pos) + s.substring(pos + 1);
+            pos = s.indexOf('"');
+        }
+        return s;
+    }
+
+    public void insertRow(int insPos, String s, Vector<Node> existingStops) {
+        String[] buf = { "", "", tr("pending") };
+        int pos = tokenize(s, 0);
+        int oldPos = 0;
+        int i = 0;
+        double lat = 0;
+        double lon = 0;
+        while (pos > -1) {
+            if (i == idCol)
+                buf[0] = stripQuot(s.substring(oldPos, pos));
+            else if (i == nameCol)
+                buf[1] = stripQuot(s.substring(oldPos, pos));
+            else if (i == latCol)
+                lat = Double.parseDouble(stripQuot(s.substring(oldPos, pos)));
+            else if (i == lonCol)
+                lon = Double.parseDouble(stripQuot(s.substring(oldPos, pos)));
+            ++i;
+            oldPos = pos + 1;
+            pos = tokenize(s, oldPos);
+        }
+        if (i == idCol)
+            buf[0] = stripQuot(s.substring(oldPos));
+        else if (i == nameCol)
+            buf[1] = stripQuot(s.substring(oldPos));
+        else if (i == latCol)
+            lat = Double.parseDouble(stripQuot(s.substring(oldPos)));
+        else if (i == lonCol)
+            lon = Double.parseDouble(stripQuot(s.substring(oldPos)));
+
+        LatLon coor = new LatLon(lat, lon);
+
+        DataSet ds = Main.getLayerManager().getEditDataSet();
+        if (ds != null) {
+            boolean inside = false;
+            Iterator<DataSource> iter = ds.dataSources.iterator();
+            while (iter.hasNext()) {
+                if (iter.next().bounds.contains(coor)) {
+                    inside = true;
+                    break;
+                }
+            }
+            if (!inside)
+                buf[2] = tr("outside");
+        }
+
+        boolean nearBusStop = false;
+        Iterator<Node> iter = existingStops.iterator();
+        while (iter.hasNext()) {
+            Node node = iter.next();
+            if (coor.greatCircleDistance(node.getCoor()) < 1000) {
+                nearBusStop = true;
+                break;
+            }
+        }
+
+        if (insPos == -1) {
+            if ((nearBusStop) || !(tr("pending").equals(buf[2])))
+                nodes.addElement(null);
+            else {
+                Node node = GTFSImporterAction.createNode(coor, buf[0], buf[1]);
+                nodes.addElement(node);
+                buf[2] = tr("added");
+            }
+            coors.addElement(coor);
+            super.addRow(buf);
+        } else {
+            if ((nearBusStop) || !(tr("pending").equals(buf[2])))
+                nodes.insertElementAt(null, insPos);
+            else {
+                Node node = GTFSImporterAction.createNode(coor, buf[0], buf[1]);
+                nodes.insertElementAt(node, insPos);
+                buf[2] = tr("added");
+            }
+            coors.insertElementAt(coor, insPos);
+            super.insertRow(insPos, buf);
+        }
+    }
+
+    public void clear() {
+        nodes.clear();
+        super.setRowCount(0);
+    }
+
+    @Override
+    public void tableChanged(TableModelEvent e) {
+    }
+}
Index: /applications/editors/josm/plugins/public_transport/src/public_transport/ItineraryTableModel.java
===================================================================
--- /applications/editors/josm/plugins/public_transport/src/public_transport/ItineraryTableModel.java	(revision 32356)
+++ /applications/editors/josm/plugins/public_transport/src/public_transport/ItineraryTableModel.java	(revision 32357)
@@ -12,162 +12,137 @@
 import org.openstreetmap.josm.data.osm.Way;
 
-public class ItineraryTableModel extends DefaultTableModel
-    implements TableModelListener
-{
-  public Vector<Way> ways = new Vector<Way>();
-  public boolean inEvent = false;
+public class ItineraryTableModel extends DefaultTableModel implements TableModelListener {
+    public Vector<Way> ways = new Vector<>();
 
-  public boolean isCellEditable(int row, int column)
-  {
-    if (column != 1)
-      return false;
-    if (ways.elementAt(row) == null)
-      return false;
-    return true;
-  }
+    public boolean inEvent = false;
 
-  public void addRow(Object[] obj)
-  {
-    ways.addElement(null);
-    super.addRow(obj);
-  }
-
-  public void insertRow(int insPos, Object[] obj)
-  {
-    if (insPos == -1)
-    {
-      ways.addElement(null);
-      super.addRow(obj);
-    }
-    else
-    {
-      ways.insertElementAt(null, insPos);
-      super.insertRow(insPos, obj);
-    }
-  }
-
-  public void addRow(Way way, String role)
-  {
-    insertRow(-1, way, role);
-  }
-
-  public void insertRow(int insPos, Way way, String role)
-  {
-    String[] buf = { "", "" };
-    String curName = way.get("name");
-    if (way.isIncomplete())
-      buf[0] = tr("[incomplete]");
-    else if (way.getNodesCount() < 1)
-      buf[0] = tr("[empty way]");
-    else if (curName != null)
-      buf[0] = curName;
-    else
-      buf[0] = tr("[ID] {0}", (new Long(way.getId())).toString());
-    buf[1] = role;
-    if (insPos == -1)
-    {
-      ways.addElement(way);
-      super.addRow(buf);
-    }
-    else
-    {
-      ways.insertElementAt(way, insPos);
-      super.insertRow(insPos, buf);
-    }
-  }
-
-  public void clear()
-  {
-    ways.clear();
-    super.setRowCount(0);
-  }
-
-  public void cleanupGaps()
-  {
-    inEvent = true;
-    Node lastNode = null;
-
-    for (int i = 0; i < getRowCount(); ++i)
-    {
-      if (ways.elementAt(i) == null)
-      {
-        ++i;
-        if (i >= getRowCount())
-          break;
-      }
-      while ((ways.elementAt(i) == null) &&
-      ((i == 0) || (ways.elementAt(i-1) == null)))
-      {
-        ways.removeElementAt(i);
-        removeRow(i);
-        if (i >= getRowCount())
-          break;
-      }
-      if (i >= getRowCount())
-        break;
-
-      boolean gapRequired = gapNecessary
-      (ways.elementAt(i), (String)(getValueAt(i, 1)), lastNode);
-      if ((i > 0) && (!gapRequired) && (ways.elementAt(i-1) == null))
-      {
-        ways.removeElementAt(i-1);
-        removeRow(i-1);
-        --i;
-      }
-      else if ((i > 0) && gapRequired && (ways.elementAt(i-1) != null))
-      {
-        String[] buf = { "", "" };
-        buf[0] = tr("[gap]");
-        insertRow(i, buf);
-        ++i;
-      }
-      lastNode = getLastNode(ways.elementAt(i), (String)(getValueAt(i, 1)));
-    }
-    while ((getRowCount() > 0) &&
-      (ways.elementAt(getRowCount()-1) == null))
-    {
-      ways.removeElementAt(getRowCount()-1);
-      removeRow(getRowCount()-1);
-    }
-    inEvent = false;
-  }
-
-  public void tableChanged(TableModelEvent e)
-  {
-    if (e.getType() == TableModelEvent.UPDATE)
-    {
-      if (inEvent)
-        return;
-      cleanupGaps();
-      RoutePatternAction.rebuildWays();
-    }
-  }
-
-  private Node getLastNode(Way way, String role)
-  {
-    if ((way == null) || (way.isIncomplete()) || (way.getNodesCount() < 1))
-      return null;
-    else
-    {
-      if ("backward".equals(role))
-        return way.getNode(0);
-      else
-        return way.getNode(way.getNodesCount() - 1);
-    }
-  }
-
-  private boolean gapNecessary(Way way, String role, Node lastNode)
-  {
-    if ((way != null) && (!(way.isIncomplete())) && (way.getNodesCount() >= 1))
-    {
-      Node firstNode = null;
-      if ("backward".equals(role))
-        firstNode = way.getNode(way.getNodesCount() - 1);
-      else
-        firstNode = way.getNode(0);
-      if ((lastNode != null) && (!lastNode.equals(firstNode)))
+    @Override
+    public boolean isCellEditable(int row, int column) {
+        if (column != 1)
+            return false;
+        if (ways.elementAt(row) == null)
+            return false;
         return true;
     }
-    return false;
-  }
-};
+
+    @Override
+    public void addRow(Object[] obj) {
+        ways.addElement(null);
+        super.addRow(obj);
+    }
+
+    @Override
+    public void insertRow(int insPos, Object[] obj) {
+        if (insPos == -1) {
+            ways.addElement(null);
+            super.addRow(obj);
+        } else {
+            ways.insertElementAt(null, insPos);
+            super.insertRow(insPos, obj);
+        }
+    }
+
+    public void addRow(Way way, String role) {
+        insertRow(-1, way, role);
+    }
+
+    public void insertRow(int insPos, Way way, String role) {
+        String[] buf = { "", "" };
+        String curName = way.get("name");
+        if (way.isIncomplete())
+            buf[0] = tr("[incomplete]");
+        else if (way.getNodesCount() < 1)
+            buf[0] = tr("[empty way]");
+        else if (curName != null)
+            buf[0] = curName;
+        else
+            buf[0] = tr("[ID] {0}", (new Long(way.getId())).toString());
+        buf[1] = role;
+        if (insPos == -1) {
+            ways.addElement(way);
+            super.addRow(buf);
+        } else {
+            ways.insertElementAt(way, insPos);
+            super.insertRow(insPos, buf);
+        }
+    }
+
+    public void clear() {
+        ways.clear();
+        super.setRowCount(0);
+    }
+
+    public void cleanupGaps() {
+        inEvent = true;
+        Node lastNode = null;
+
+        for (int i = 0; i < getRowCount(); ++i) {
+            if (ways.elementAt(i) == null) {
+                ++i;
+                if (i >= getRowCount())
+                    break;
+            }
+            while ((ways.elementAt(i) == null) && ((i == 0) || (ways.elementAt(i - 1) == null))) {
+                ways.removeElementAt(i);
+                removeRow(i);
+                if (i >= getRowCount())
+                    break;
+            }
+            if (i >= getRowCount())
+                break;
+
+            boolean gapRequired = gapNecessary(ways.elementAt(i), (String) (getValueAt(i, 1)),
+                    lastNode);
+            if ((i > 0) && (!gapRequired) && (ways.elementAt(i - 1) == null)) {
+                ways.removeElementAt(i - 1);
+                removeRow(i - 1);
+                --i;
+            } else if ((i > 0) && gapRequired && (ways.elementAt(i - 1) != null)) {
+                String[] buf = { "", "" };
+                buf[0] = tr("[gap]");
+                insertRow(i, buf);
+                ++i;
+            }
+            lastNode = getLastNode(ways.elementAt(i), (String) (getValueAt(i, 1)));
+        }
+        while ((getRowCount() > 0) && (ways.elementAt(getRowCount() - 1) == null)) {
+            ways.removeElementAt(getRowCount() - 1);
+            removeRow(getRowCount() - 1);
+        }
+        inEvent = false;
+    }
+
+    @Override
+    public void tableChanged(TableModelEvent e) {
+        if (e.getType() == TableModelEvent.UPDATE) {
+            if (inEvent)
+                return;
+            cleanupGaps();
+            RoutePatternAction.rebuildWays();
+        }
+    }
+
+    private Node getLastNode(Way way, String role) {
+        if ((way == null) || (way.isIncomplete()) || (way.getNodesCount() < 1))
+            return null;
+        else {
+            if ("backward".equals(role))
+                return way.getNode(0);
+            else
+                return way.getNode(way.getNodesCount() - 1);
+        }
+    }
+
+    private boolean gapNecessary(Way way, String role, Node lastNode) {
+        if ((way != null) && (!(way.isIncomplete())) && (way.getNodesCount() >= 1)) {
+            Node firstNode = null;
+            if ("backward".equals(role))
+                firstNode = way.getNode(way.getNodesCount() - 1);
+            else
+                firstNode = way.getNode(0);
+            if ((lastNode != null) && (!lastNode.equals(firstNode)))
+                return true;
+        }
+        return false;
+    }
+}
Index: /applications/editors/josm/plugins/public_transport/src/public_transport/PublicTransportAStar.java
===================================================================
--- /applications/editors/josm/plugins/public_transport/src/public_transport/PublicTransportAStar.java	(revision 32356)
+++ /applications/editors/josm/plugins/public_transport/src/public_transport/PublicTransportAStar.java	(revision 32357)
@@ -10,37 +10,31 @@
 import org.openstreetmap.josm.data.osm.Way;
 
-public class PublicTransportAStar extends AStarAlgorithm
-{
-    public PublicTransportAStar(Node start, Node end)
-    {
+public class PublicTransportAStar extends AStarAlgorithm {
+    public PublicTransportAStar(Node start, Node end) {
         super(new NodeVertex(start), new NodeVertex(end));
-    };
+    }
 
-    public static class NodeVertex extends AStarAlgorithm.Vertex
-    {
-        public NodeVertex(Node node)
-        {
+    public static class NodeVertex extends AStarAlgorithm.Vertex {
+        public NodeVertex(Node node) {
             this.node = node;
         }
 
-        public int compareTo(AStarAlgorithm.Vertex v)
-        {
-            return this.node.compareTo(((NodeVertex)v).node);
+        @Override
+        public int compareTo(AStarAlgorithm.Vertex v) {
+            return this.node.compareTo(((NodeVertex) v).node);
         }
 
-        public boolean equals(Object o)
-        {
-            if ((NodeVertex)o == null)
+        @Override
+        public boolean equals(Object o) {
+            if ((NodeVertex) o == null)
                 return false;
-            return node.equals(((NodeVertex)o).node);
+            return node.equals(((NodeVertex) o).node);
         }
 
         public Node node;
-    };
+    }
 
-    public static class PartialWayEdge extends AStarAlgorithm.Edge
-    {
-        public PartialWayEdge(Way way, int beginIndex, int endIndex)
-        {
+    public static class PartialWayEdge extends AStarAlgorithm.Edge {
+        public PartialWayEdge(Way way, int beginIndex, int endIndex) {
             this.way = way;
             this.beginIndex = beginIndex;
@@ -48,20 +42,19 @@
         }
 
-        public AStarAlgorithm.Vertex getBegin()
-        {
+        @Override
+        public AStarAlgorithm.Vertex getBegin() {
             return new NodeVertex(way.getNode(beginIndex));
         }
 
-        public AStarAlgorithm.Vertex getEnd()
-        {
+        @Override
+        public AStarAlgorithm.Vertex getEnd() {
             return new NodeVertex(way.getNode(endIndex));
         }
 
-        public double getLength()
-        {
+        @Override
+        public double getLength() {
             int min = beginIndex;
             int max = endIndex;
-            if (endIndex < beginIndex)
-            {
+            if (endIndex < beginIndex) {
                 min = endIndex;
                 max = beginIndex;
@@ -70,22 +63,23 @@
             double totalDistance = 0;
             for (int i = min; i < max; ++i)
-                totalDistance += way.getNode(i).getCoor().greatCircleDistance(way.getNode(i+1).getCoor());
+                totalDistance += way.getNode(i).getCoor()
+                        .greatCircleDistance(way.getNode(i + 1).getCoor());
             return totalDistance;
         }
 
         public Way way;
+
         public int beginIndex;
+
         public int endIndex;
-    };
+    }
 
-    public Vector< AStarAlgorithm.Edge > getNeighbors(AStarAlgorithm.Vertex vertex)
-    {
-        if (waysPerNode == null)
-        {
-            waysPerNode = new TreeMap< Node, TreeSet< Way > >();
+    @Override
+    public Vector<AStarAlgorithm.Edge> getNeighbors(AStarAlgorithm.Vertex vertex) {
+        if (waysPerNode == null) {
+            waysPerNode = new TreeMap<>();
 
-            Iterator< Way > iter = Main.main.getCurrentDataSet().getWays().iterator();
-            while (iter.hasNext())
-            {
+            Iterator<Way> iter = Main.getLayerManager().getEditDataSet().getWays().iterator();
+            while (iter.hasNext()) {
                 Way way = iter.next();
 
@@ -96,8 +90,7 @@
                 // Further tests whether the way is eligible.
 
-                for (int i = 0; i < way.getNodesCount(); ++i)
-                {
+                for (int i = 0; i < way.getNodesCount(); ++i) {
                     if (waysPerNode.get(way.getNode(i)) == null)
-                        waysPerNode.put(way.getNode(i), new TreeSet< Way >());
+                        waysPerNode.put(way.getNode(i), new TreeSet<Way>());
                     waysPerNode.get(way.getNode(i)).add(way);
                 }
@@ -105,12 +98,11 @@
         }
 
-        NodeVertex nodeVertex = (NodeVertex)vertex;
+        NodeVertex nodeVertex = (NodeVertex) vertex;
         System.out.println(nodeVertex.node.getUniqueId());
 
-        Vector< AStarAlgorithm.Edge > result = new Vector< AStarAlgorithm.Edge >();
+        Vector<AStarAlgorithm.Edge> result = new Vector<>();
         // Determine all ways in which nodeVertex.node is contained.
-        Iterator< Way > iter = waysPerNode.get(nodeVertex.node).iterator();
-        while (iter.hasNext())
-        {
+        Iterator<Way> iter = waysPerNode.get(nodeVertex.node).iterator();
+        while (iter.hasNext()) {
             Way way = iter.next();
 
@@ -121,12 +113,10 @@
             // Further tests whether the way is eligible.
 
-            for (int i = 0; i < way.getNodesCount(); ++i)
-            {
-                if (way.getNode(i).equals(nodeVertex.node))
-                {
+            for (int i = 0; i < way.getNodesCount(); ++i) {
+                if (way.getNode(i).equals(nodeVertex.node)) {
                     if (i > 0)
-                        result.add(new PartialWayEdge(way, i, i-1));
-                    if (i < way.getNodesCount()-1)
-                        result.add(new PartialWayEdge(way, i, i+1));
+                        result.add(new PartialWayEdge(way, i, i - 1));
+                    if (i < way.getNodesCount() - 1)
+                        result.add(new PartialWayEdge(way, i, i + 1));
                 }
             }
@@ -136,10 +126,11 @@
     }
 
-    TreeMap< Node, TreeSet< Way > > waysPerNode = null;
+    TreeMap<Node, TreeSet<Way>> waysPerNode = null;
 
-    public double estimateDistance(AStarAlgorithm.Vertex vertex)
-    {
-        NodeVertex nodeVertex = (NodeVertex)vertex;
-        return ((NodeVertex)super.end).node.getCoor().greatCircleDistance(nodeVertex.node.getCoor());
+    @Override
+    public double estimateDistance(AStarAlgorithm.Vertex vertex) {
+        NodeVertex nodeVertex = (NodeVertex) vertex;
+        return ((NodeVertex) super.end).node.getCoor()
+                .greatCircleDistance(nodeVertex.node.getCoor());
     }
 };
Index: /applications/editors/josm/plugins/public_transport/src/public_transport/PublicTransportPlugin.java
===================================================================
--- /applications/editors/josm/plugins/public_transport/src/public_transport/PublicTransportPlugin.java	(revision 32356)
+++ /applications/editors/josm/plugins/public_transport/src/public_transport/PublicTransportPlugin.java	(revision 32357)
@@ -15,35 +15,34 @@
 public class PublicTransportPlugin extends Plugin {
 
-  static JMenu jMenu;
+    static JMenu jMenu;
 
-  public PublicTransportPlugin(PluginInformation info)
-  {
-    super(info);
-    refreshMenu();
-  }
+    public PublicTransportPlugin(PluginInformation info) {
+        super(info);
+        refreshMenu();
+    }
 
-  public static void refreshMenu()
-  {
-    MainMenu menu = Main.main.menu;
+    public static void refreshMenu() {
+        MainMenu menu = Main.main.menu;
 
-    if (jMenu == null)
-      jMenu = menu.addMenu("Public Transport", tr("Public Transport"), KeyEvent.VK_COMMA, menu.getDefaultMenuPos(), "help");
-    else
-      jMenu.removeAll();
+        if (jMenu == null)
+            jMenu = menu.addMenu("Public Transport", tr("Public Transport"), KeyEvent.VK_COMMA,
+                    menu.getDefaultMenuPos(), "help");
+        else
+            jMenu.removeAll();
 
-    jMenu.addSeparator();
-    jMenu.add(new JMenuItem(new StopImporterAction()));
-    jMenu.add(new JMenuItem(new RoutePatternAction()));
-    jMenu.add(new JMenuItem(new GTFSImporterAction()));
-    setEnabledAll(true);
-  }
+        jMenu.addSeparator();
+        jMenu.add(new JMenuItem(new StopImporterAction()));
+        jMenu.add(new JMenuItem(new RoutePatternAction()));
+        jMenu.add(new JMenuItem(new GTFSImporterAction()));
+        setEnabledAll(true);
+    }
 
-  private static void setEnabledAll(boolean isEnabled)
-  {
-    for(int i=0; i < jMenu.getItemCount(); i++) {
-      JMenuItem item = jMenu.getItem(i);
+    private static void setEnabledAll(boolean isEnabled) {
+        for (int i = 0; i < jMenu.getItemCount(); i++) {
+            JMenuItem item = jMenu.getItem(i);
 
-      if(item != null) item.setEnabled(isEnabled);
+            if (item != null)
+                item.setEnabled(isEnabled);
+        }
     }
-  }
 }
Index: /applications/editors/josm/plugins/public_transport/src/public_transport/RoutePatternAction.java
===================================================================
--- /applications/editors/josm/plugins/public_transport/src/public_transport/RoutePatternAction.java	(revision 32356)
+++ /applications/editors/josm/plugins/public_transport/src/public_transport/RoutePatternAction.java	(revision 32357)
@@ -55,2249 +55,2020 @@
 public class RoutePatternAction extends JosmAction {
 
-  public static int STOPLIST_ROLE_COLUMN = 2;
-
-  private class RoutesLSL implements ListSelectionListener {
-    RoutePatternAction root = null;
-
-    public RoutesLSL(RoutePatternAction rpa) {
-      root = rpa;
+    public static int STOPLIST_ROLE_COLUMN = 2;
+
+    private class RoutesLSL implements ListSelectionListener {
+        RoutePatternAction root = null;
+
+        public RoutesLSL(RoutePatternAction rpa) {
+            root = rpa;
+        }
+
+        @Override
+        public void valueChanged(ListSelectionEvent e) {
+            root.routesSelectionChanged();
+        }
     }
 
+    private class RouteReference implements Comparable<RouteReference> {
+        Relation route;
+
+        public RouteReference(Relation route) {
+            this.route = route;
+        }
+
+        @Override
+        public int compareTo(RouteReference rr) {
+            if (route.get("route") != null) {
+                if (rr.route.get("route") == null)
+                    return -1;
+                int result = route.get("route").compareTo(rr.route.get("route"));
+                if (result != 0)
+                    return result;
+            } else if (rr.route.get("route") != null)
+                return 1;
+            if (route.get("ref") != null) {
+                if (rr.route.get("ref") == null)
+                    return -1;
+                int result = route.get("ref").compareTo(rr.route.get("ref"));
+                if (result != 0)
+                    return result;
+            } else if (rr.route.get("ref") != null)
+                return 1;
+            if (route.get("to") != null) {
+                if (rr.route.get("to") == null)
+                    return -1;
+                int result = route.get("to").compareTo(rr.route.get("to"));
+                if (result != 0)
+                    return result;
+            } else if (rr.route.get("to") != null)
+                return 1;
+            if (route.get("direction") != null) {
+                if (rr.route.get("direction") == null)
+                    return -1;
+                int result = route.get("direction").compareTo(rr.route.get("direction"));
+                if (result != 0)
+                    return result;
+            } else if (rr.route.get("direction") != null)
+                return 1;
+            if (route.getId() < rr.route.getId())
+                return -1;
+            else if (route.getId() > rr.route.getId())
+                return 1;
+            return 0;
+        }
+
+        @Override
+        public String toString() {
+            String buf = route.get("route");
+            if ((route.get("ref") != null) && (route.get("ref") != "")) {
+                buf += " " + route.get("ref");
+            }
+            if ((route.get("loc_ref") != null) && (route.get("loc_ref") != "")) {
+                buf += " [" + route.get("loc_ref") + "]";
+            }
+
+            if ((route.get("to") != null) && (route.get("to") != "")) {
+                buf += ": " + route.get("to");
+            } else if ((route.get("direction") != null) && (route.get("direction") != "")) {
+                buf += " " + route.get("ref") + ": " + route.get("direction");
+            } else {
+                buf += " " + route.get("ref");
+            }
+            buf += tr(" [ID] {0}", Long.toString(route.getId()));
+
+            return buf;
+        }
+    }
+
+    private class TagTableModel extends DefaultTableModel implements TableModelListener {
+        Relation relation = null;
+
+        TreeSet<String> blacklist = null;
+
+        boolean hasFixedKeys = true;
+
+        public TagTableModel(boolean hasFixedKeys) {
+            this.hasFixedKeys = hasFixedKeys;
+        }
+
+        @Override
+        public boolean isCellEditable(int row, int column) {
+            if ((column == 0) && (hasFixedKeys))
+                return false;
+            return true;
+        }
+
+        public void readRelation(Relation rel) {
+            relation = rel;
+
+            for (int i = 0; i < getRowCount(); ++i) {
+                String value = rel.get((String) getValueAt(i, 0));
+                if (value == null)
+                    value = "";
+                setValueAt(value, i, 1);
+            }
+        }
+
+        public void readRelation(Relation rel, TreeSet<String> blacklist) {
+            relation = rel;
+            this.blacklist = blacklist;
+
+            setRowCount(0);
+            Iterator<Map.Entry<String, String>> iter = rel.getKeys().entrySet().iterator();
+            while (iter.hasNext()) {
+                Map.Entry<String, String> entry = iter.next();
+                if (!blacklist.contains(entry.getKey())) {
+                    Vector<String> newRow = new Vector<>();
+                    newRow.add(entry.getKey());
+                    newRow.add(entry.getValue());
+                    addRow(newRow);
+                }
+            }
+
+            for (int i = 0; i < getRowCount(); ++i) {
+                String value = rel.get((String) getValueAt(i, 0));
+                if (value == null)
+                    value = "";
+                setValueAt(value, i, 1);
+            }
+        }
+
+        @Override
+        public void tableChanged(TableModelEvent e) {
+            if (e.getType() == TableModelEvent.UPDATE) {
+                relation.setModified(true);
+
+                String key = (String) getValueAt(e.getFirstRow(), 0);
+                if (key == null)
+                    return;
+                if ((blacklist == null) || (!blacklist.contains(key))) {
+                    relation.setModified(true);
+                    if ("".equals(getValueAt(e.getFirstRow(), 1)))
+                        relation.remove(key);
+                    else
+                        relation.put(key, (String) getValueAt(e.getFirstRow(), 1));
+                } else {
+                    if (e.getColumn() == 0)
+                        setValueAt("", e.getFirstRow(), 0);
+                }
+            }
+        }
+    }
+
+    private class CustomCellEditorTable extends JTable {
+        TreeMap<Integer, TableCellEditor> col1 = null;
+
+        TreeMap<Integer, TableCellEditor> col2 = null;
+
+        public CustomCellEditorTable() {
+            col1 = new TreeMap<>();
+            col2 = new TreeMap<>();
+        }
+
+        @Override
+        public TableCellEditor getCellEditor(int row, int column) {
+            TableCellEditor editor = null;
+            if (column == 0)
+                editor = col1.get(new Integer(row));
+            else
+                editor = col2.get(new Integer(row));
+            if (editor == null)
+                return new DefaultCellEditor(new JTextField());
+            else
+                return editor;
+        }
+
+        public void setCellEditor(int row, int column, TableCellEditor editor) {
+            if (column == 0)
+                col1.put(new Integer(row), editor);
+            else
+                col2.put(new Integer(row), editor);
+        }
+    }
+
+    private class StoplistTableModel extends DefaultTableModel {
+
+        public Vector<Node> nodes = new Vector<>();
+
+        @Override
+        public boolean isCellEditable(int row, int column) {
+            if (column != STOPLIST_ROLE_COLUMN)
+                return false;
+            return true;
+        }
+
+        @Override
+        public void addRow(Object[] obj) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public void insertRow(int insPos, Object[] obj) {
+            throw new UnsupportedOperationException();
+        }
+
+        public void addRow(Node node, String role, double distance) {
+            insertRow(-1, node, role, distance);
+        }
+
+        public void insertRow(int insPos, Node node, String role, double distance) {
+            String[] buf = { "", "", "", "" };
+            String curName = node.get("name");
+            if (curName != null) {
+                buf[0] = curName;
+            } else {
+                buf[0] = tr("[ID] {0}", (new Long(node.getId())).toString());
+            }
+            String curRef = node.get("ref");
+            if (curRef != null) {
+                buf[1] = curRef;
+            }
+            buf[STOPLIST_ROLE_COLUMN] = role;
+            buf[3] = Double.toString(((double) (int) (distance * 40000 / 360.0 * 100)) / 100);
+
+            if (insPos == -1) {
+                nodes.addElement(node);
+                super.addRow(buf);
+            } else {
+                nodes.insertElementAt(node, insPos);
+                super.insertRow(insPos, buf);
+            }
+        }
+
+        public void clear() {
+            nodes.clear();
+            super.setRowCount(0);
+        }
+    }
+
+    private class StoplistTableModelListener implements TableModelListener {
+        @Override
+        public void tableChanged(TableModelEvent e) {
+            if (e.getType() == TableModelEvent.UPDATE) {
+                rebuildNodes();
+            }
+        }
+    }
+
+    private class SegmentMetric {
+        public double aLat, aLon;
+
+        public double length;
+
+        public double d1, d2, o1, o2;
+
+        public double distance;
+
+        public SegmentMetric(double fromLat, double fromLon, double toLat, double toLon,
+                double distance) {
+            this.distance = distance;
+
+            aLat = fromLat;
+            aLon = fromLon;
+
+            // Compute length and direction
+            // length is in units of latitude degrees
+            d1 = toLat - fromLat;
+            d2 = (toLon - fromLon) * Math.cos(fromLat * Math.PI / 180.0);
+            length = Math.sqrt(d1 * d1 + d2 * d2);
+
+            // Normalise direction
+            d1 = d1 / length;
+            d2 = d2 / length;
+
+            // Compute orthogonal direction (right hand size is positive)
+            o1 = -d2;
+            o2 = d1;
+
+            // Prepare lon direction to reduce the number of necessary multiplications
+            d2 = d2 * Math.cos(fromLat * Math.PI / 180.0);
+            o2 = o2 * Math.cos(fromLat * Math.PI / 180.0);
+        }
+    }
+
+    private class StopReference implements Comparable<StopReference> {
+        public int index = 0;
+
+        public double pos = 0;
+
+        public double distance = 0;
+
+        public String name = "";
+
+        public String role = "";
+
+        public Node node;
+
+        public StopReference(int inIndex, double inPos, double inDistance, String inName,
+                String inRole, Node inNode) {
+            index = inIndex;
+            pos = inPos;
+            distance = inDistance;
+            name = inName;
+            role = inRole;
+            node = inNode;
+        }
+
+        @Override
+        public int compareTo(StopReference sr) {
+            if (this.index < sr.index)
+                return -1;
+            if (this.index > sr.index)
+                return 1;
+            if (this.pos < sr.pos)
+                return -1;
+            if (this.pos > sr.pos)
+                return 1;
+            return 0;
+        }
+    }
+
+    private static JDialog jDialog = null;
+
+    private static JTabbedPane tabbedPane = null;
+
+    private static DefaultListModel<RouteReference> relsListModel = null;
+
+    private static TagTableModel requiredTagsData = null;
+
+    private static CustomCellEditorTable requiredTagsTable = null;
+
+    private static TagTableModel commonTagsData = null;
+
+    private static CustomCellEditorTable commonTagsTable = null;
+
+    private static TagTableModel otherTagsData = null;
+
+    private static TreeSet<String> tagBlacklist = null;
+
+    private static CustomCellEditorTable otherTagsTable = null;
+
+    private static ItineraryTableModel itineraryData = null;
+
+    private static JTable itineraryTable = null;
+
+    private static StoplistTableModel stoplistData = null;
+
+    private static JTable stoplistTable = null;
+
+    private static JList<RouteReference> relsList = null;
+
+    private static JCheckBox cbRight = null;
+
+    private static JCheckBox cbLeft = null;
+
+    private static JTextField tfSuggestStopsLimit = null;
+
+    private static Relation currentRoute = null;
+
+    private static Vector<SegmentMetric> segmentMetrics = null;
+
+    private static Vector<RelationMember> markedWays = new Vector<>();
+
+    private static Vector<RelationMember> markedNodes = new Vector<>();
+
+    public RoutePatternAction() {
+        super(tr("Route patterns ..."), null, tr("Edit Route patterns for public transport"), null,
+                false);
+        putValue("toolbar", "publictransport/routepattern");
+        Main.toolbar.register(this);
+    }
+
     @Override
-    public void valueChanged(ListSelectionEvent e) {
-      root.routesSelectionChanged();
+    public void actionPerformed(ActionEvent event) {
+        Frame frame = JOptionPane.getFrameForComponent(Main.parent);
+        DataSet mainDataSet = Main.getLayerManager().getEditDataSet();
+
+        if (jDialog == null) {
+            jDialog = new JDialog(frame, tr("Route Patterns"), false);
+            tabbedPane = new JTabbedPane();
+            JPanel tabOverview = new JPanel();
+            tabbedPane.addTab(tr("Overview"), tabOverview);
+            JPanel tabTags = new JPanel();
+            tabbedPane.addTab(tr("Tags"), tabTags);
+            JPanel tabItinerary = new JPanel();
+            tabbedPane.addTab(tr("Itinerary"), tabItinerary);
+            JPanel tabStoplist = new JPanel();
+            tabbedPane.addTab(tr("Stops"), tabStoplist);
+            JPanel tabMeta = new JPanel();
+            tabbedPane.addTab(tr("Meta"), tabMeta);
+            tabbedPane.setEnabledAt(0, true);
+            tabbedPane.setEnabledAt(1, false);
+            tabbedPane.setEnabledAt(2, false);
+            tabbedPane.setEnabledAt(3, false);
+            tabbedPane.setEnabledAt(4, false);
+            jDialog.add(tabbedPane);
+
+            // Overview Tab
+            Container contentPane = tabOverview;
+            GridBagLayout gridbag = new GridBagLayout();
+            GridBagConstraints layoutCons = new GridBagConstraints();
+            contentPane.setLayout(gridbag);
+
+            JLabel headline = new JLabel(tr("Existing route patterns:"));
+
+            layoutCons.gridx = 0;
+            layoutCons.gridy = 0;
+            layoutCons.gridwidth = 3;
+            layoutCons.weightx = 0.0;
+            layoutCons.weighty = 0.0;
+            layoutCons.fill = GridBagConstraints.BOTH;
+            gridbag.setConstraints(headline, layoutCons);
+            contentPane.add(headline);
+
+            relsListModel = new DefaultListModel<>();
+            relsList = new JList<>(relsListModel);
+            JScrollPane rpListSP = new JScrollPane(relsList);
+            String[] data = { "1", "2", "3", "4", "5", "6" };
+            relsListModel.copyInto(data);
+            relsList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+            relsList.addListSelectionListener(new RoutesLSL(this));
+
+            layoutCons.gridx = 0;
+            layoutCons.gridy = 1;
+            layoutCons.gridwidth = 3;
+            layoutCons.weightx = 1.0;
+            layoutCons.weighty = 1.0;
+            layoutCons.fill = GridBagConstraints.BOTH;
+            gridbag.setConstraints(rpListSP, layoutCons);
+            contentPane.add(rpListSP);
+
+            JButton bRefresh = new JButton(tr("Refresh"));
+            bRefresh.setActionCommand("routePattern.refresh");
+            bRefresh.addActionListener(this);
+
+            layoutCons.gridx = 0;
+            layoutCons.gridy = 2;
+            layoutCons.gridwidth = 1;
+            layoutCons.gridheight = 2;
+            layoutCons.weightx = 1.0;
+            layoutCons.weighty = 0.0;
+            layoutCons.fill = GridBagConstraints.BOTH;
+            gridbag.setConstraints(bRefresh, layoutCons);
+            contentPane.add(bRefresh);
+
+            JButton bNew = new JButton(tr("New"));
+            bNew.setActionCommand("routePattern.overviewNew");
+            bNew.addActionListener(this);
+
+            layoutCons.gridx = 1;
+            layoutCons.gridy = 2;
+            layoutCons.gridwidth = 1;
+            layoutCons.gridheight = 1;
+            layoutCons.weightx = 1.0;
+            layoutCons.weighty = 0.0;
+            layoutCons.fill = GridBagConstraints.BOTH;
+            gridbag.setConstraints(bNew, layoutCons);
+            contentPane.add(bNew);
+
+            JButton bDelete = new JButton(tr("Delete"));
+            bDelete.setActionCommand("routePattern.overviewDelete");
+            bDelete.addActionListener(this);
+
+            layoutCons.gridx = 1;
+            layoutCons.gridy = 3;
+            layoutCons.gridwidth = 1;
+            layoutCons.gridheight = 1;
+            layoutCons.weightx = 1.0;
+            layoutCons.weighty = 0.0;
+            layoutCons.fill = GridBagConstraints.BOTH;
+            gridbag.setConstraints(bDelete, layoutCons);
+            contentPane.add(bDelete);
+
+            JButton bDuplicate = new JButton(tr("Duplicate"));
+            bDuplicate.setActionCommand("routePattern.overviewDuplicate");
+            bDuplicate.addActionListener(this);
+
+            layoutCons.gridx = 2;
+            layoutCons.gridy = 2;
+            layoutCons.gridwidth = 1;
+            layoutCons.gridheight = 1;
+            layoutCons.weightx = 1.0;
+            layoutCons.weighty = 0.0;
+            layoutCons.fill = GridBagConstraints.BOTH;
+            gridbag.setConstraints(bDuplicate, layoutCons);
+            contentPane.add(bDuplicate);
+
+            JButton bReflect = new JButton(tr("Reflect"));
+            bReflect.setActionCommand("routePattern.overviewReflect");
+            bReflect.addActionListener(this);
+
+            layoutCons.gridx = 2;
+            layoutCons.gridy = 3;
+            layoutCons.gridwidth = 1;
+            layoutCons.gridheight = 1;
+            layoutCons.weightx = 1.0;
+            layoutCons.weighty = 0.0;
+            layoutCons.fill = GridBagConstraints.BOTH;
+            gridbag.setConstraints(bReflect, layoutCons);
+            contentPane.add(bReflect);
+
+            // Tags Tab
+            /* Container */ contentPane = tabTags;
+            /* GridBagLayout */ gridbag = new GridBagLayout();
+            /* GridBagConstraints */ layoutCons = new GridBagConstraints();
+            contentPane.setLayout(gridbag);
+
+            /* JLabel */ headline = new JLabel(tr("Required tags:"));
+
+            layoutCons.gridx = 0;
+            layoutCons.gridy = 0;
+            layoutCons.weightx = 0.0;
+            layoutCons.weighty = 0.0;
+            layoutCons.fill = GridBagConstraints.BOTH;
+            gridbag.setConstraints(headline, layoutCons);
+            contentPane.add(headline);
+
+            requiredTagsTable = new CustomCellEditorTable();
+            requiredTagsData = new TagTableModel(true);
+            requiredTagsData.addColumn(tr("Key"));
+            requiredTagsData.addColumn(tr("Value"));
+            tagBlacklist = new TreeSet<>();
+            Vector<String> rowContent = new Vector<>();
+            /* TODO: keys and values should also be translated using TransText class */
+            rowContent.add("type");
+            tagBlacklist.add("type");
+            rowContent.add("route");
+            requiredTagsData.addRow(rowContent);
+            JComboBox<String> comboBox = new JComboBox<>();
+            comboBox.addItem("route");
+            requiredTagsTable.setCellEditor(0, 1, new DefaultCellEditor(comboBox));
+            rowContent = new Vector<>();
+            rowContent.add(0, "route");
+            tagBlacklist.add("route");
+            rowContent.add(1, "bus");
+            requiredTagsData.addRow(rowContent);
+            /* JComboBox */ comboBox = new JComboBox<>();
+            comboBox.addItem("bus");
+            comboBox.addItem("trolleybus");
+            comboBox.addItem("tram");
+            comboBox.addItem("light_rail");
+            comboBox.addItem("subway");
+            comboBox.addItem("rail");
+            requiredTagsTable.setCellEditor(1, 1, new DefaultCellEditor(comboBox));
+            rowContent = new Vector<>();
+            rowContent.add(0, "ref");
+            tagBlacklist.add("ref");
+            rowContent.add(1, "");
+            requiredTagsData.addRow(rowContent);
+            rowContent = new Vector<>();
+            rowContent.add(0, "to");
+            tagBlacklist.add("to");
+            rowContent.add(1, "");
+            requiredTagsData.addRow(rowContent);
+            rowContent = new Vector<>();
+            rowContent.add(0, "network");
+            tagBlacklist.add("network");
+            rowContent.add(1, "");
+            requiredTagsData.addRow(rowContent);
+            requiredTagsTable.setModel(requiredTagsData);
+            JScrollPane tableSP = new JScrollPane(requiredTagsTable);
+            requiredTagsData.addTableModelListener(requiredTagsData);
+
+            layoutCons.gridx = 0;
+            layoutCons.gridy = 1;
+            layoutCons.weightx = 1.0;
+            layoutCons.weighty = 0.25;
+            layoutCons.fill = GridBagConstraints.BOTH;
+            gridbag.setConstraints(tableSP, layoutCons);
+            Dimension preferredSize = tableSP.getPreferredSize();
+            preferredSize.setSize(tableSP.getPreferredSize().getWidth(),
+                    tableSP.getPreferredSize().getHeight() / 4.0);
+            tableSP.setPreferredSize(preferredSize);
+            contentPane.add(tableSP);
+
+            headline = new JLabel(tr("Common tags:"));
+
+            layoutCons.gridx = 0;
+            layoutCons.gridy = 2;
+            layoutCons.weightx = 0.0;
+            layoutCons.weighty = 0.0;
+            layoutCons.fill = GridBagConstraints.BOTH;
+            gridbag.setConstraints(headline, layoutCons);
+            contentPane.add(headline);
+
+            commonTagsTable = new CustomCellEditorTable();
+            commonTagsData = new TagTableModel(true);
+            commonTagsData.addColumn(tr("Key"));
+            commonTagsData.addColumn(tr("Value"));
+            rowContent = new Vector<>();
+            rowContent.add(0, "loc_ref");
+            tagBlacklist.add("loc_ref");
+            rowContent.add(1, "");
+            commonTagsData.addRow(rowContent);
+            rowContent = new Vector<>();
+            rowContent.add(0, "direction");
+            tagBlacklist.add("direction");
+            rowContent.add(1, "");
+            commonTagsData.addRow(rowContent);
+            rowContent = new Vector<>();
+            rowContent.add(0, "from");
+            tagBlacklist.add("from");
+            rowContent.add(1, "");
+            commonTagsData.addRow(rowContent);
+            rowContent = new Vector<>();
+            rowContent.add(0, "operator");
+            tagBlacklist.add("operator");
+            rowContent.add(1, "");
+            commonTagsData.addRow(rowContent);
+            rowContent = new Vector<>();
+            rowContent.add(0, "color");
+            tagBlacklist.add("color");
+            rowContent.add(1, "");
+            commonTagsData.addRow(rowContent);
+            rowContent = new Vector<>();
+            rowContent.add(0, "name");
+            tagBlacklist.add("name");
+            rowContent.add(1, "");
+            commonTagsData.addRow(rowContent);
+            commonTagsTable.setModel(commonTagsData);
+            /* JScrollPane */ tableSP = new JScrollPane(commonTagsTable);
+            commonTagsData.addTableModelListener(commonTagsData);
+
+            layoutCons.gridx = 0;
+            layoutCons.gridy = 3;
+            layoutCons.weightx = 1.0;
+            layoutCons.weighty = 0.25;
+            layoutCons.fill = GridBagConstraints.BOTH;
+            gridbag.setConstraints(tableSP, layoutCons);
+            /* Dimension */ preferredSize = tableSP.getPreferredSize();
+            preferredSize.setSize(tableSP.getPreferredSize().getWidth(),
+                    tableSP.getPreferredSize().getHeight() / 4.0);
+            tableSP.setPreferredSize(preferredSize);
+            contentPane.add(tableSP);
+
+            headline = new JLabel(tr("Additional tags:"));
+
+            layoutCons.gridx = 0;
+            layoutCons.gridy = 4;
+            layoutCons.weightx = 0.0;
+            layoutCons.weighty = 0.0;
+            layoutCons.fill = GridBagConstraints.BOTH;
+            gridbag.setConstraints(headline, layoutCons);
+            contentPane.add(headline);
+
+            otherTagsTable = new CustomCellEditorTable();
+            otherTagsData = new TagTableModel(false);
+            otherTagsData.addColumn(tr("Key"));
+            otherTagsData.addColumn(tr("Value"));
+            otherTagsTable.setModel(otherTagsData);
+            /* JScrollPane */ tableSP = new JScrollPane(otherTagsTable);
+            otherTagsData.addTableModelListener(otherTagsData);
+
+            layoutCons.gridx = 0;
+            layoutCons.gridy = 5;
+            layoutCons.weightx = 1.0;
+            layoutCons.weighty = 1.0;
+            layoutCons.fill = GridBagConstraints.BOTH;
+            gridbag.setConstraints(tableSP, layoutCons);
+            /* Dimension */ preferredSize = tableSP.getPreferredSize();
+            preferredSize.setSize(tableSP.getPreferredSize().getWidth(),
+                    tableSP.getPreferredSize().getHeight() / 2.0);
+            tableSP.setPreferredSize(preferredSize);
+            contentPane.add(tableSP);
+
+            JButton bAddTag = new JButton(tr("Add a new Tag"));
+            bAddTag.setActionCommand("routePattern.tagAddTag");
+            bAddTag.addActionListener(this);
+
+            layoutCons.gridx = 0;
+            layoutCons.gridy = 6;
+            layoutCons.gridwidth = 1;
+            layoutCons.weightx = 1.0;
+            layoutCons.weighty = 0.0;
+            layoutCons.fill = GridBagConstraints.BOTH;
+            gridbag.setConstraints(bAddTag, layoutCons);
+            contentPane.add(bAddTag);
+
+            // Itinerary Tab
+            contentPane = tabItinerary;
+            gridbag = new GridBagLayout();
+            layoutCons = new GridBagConstraints();
+            contentPane.setLayout(gridbag);
+
+            itineraryTable = new JTable();
+            itineraryData = new ItineraryTableModel();
+            itineraryData.addColumn(tr("Name/Id"));
+            itineraryData.addColumn(tr("Role"));
+            itineraryTable.setModel(itineraryData);
+            /* JScrollPane */ tableSP = new JScrollPane(itineraryTable);
+            /* JComboBox */ comboBox = new JComboBox<>();
+            comboBox.addItem("");
+            comboBox.addItem("forward");
+            comboBox.addItem("backward");
+            itineraryTable.getColumnModel().getColumn(1)
+                    .setCellEditor(new DefaultCellEditor(comboBox));
+            itineraryData.addTableModelListener(itineraryData);
+
+            layoutCons.gridx = 0;
+            layoutCons.gridy = 0;
+            layoutCons.gridwidth = 4;
+            layoutCons.weightx = 1.0;
+            layoutCons.weighty = 1.0;
+            layoutCons.fill = GridBagConstraints.BOTH;
+            gridbag.setConstraints(tableSP, layoutCons);
+            contentPane.add(tableSP);
+
+            JButton bFind = new JButton(tr("Find"));
+            bFind.setActionCommand("routePattern.itineraryFind");
+            bFind.addActionListener(this);
+
+            layoutCons.gridx = 0;
+            layoutCons.gridy = 1;
+            layoutCons.gridwidth = 1;
+            layoutCons.weightx = 1.0;
+            layoutCons.weighty = 0.0;
+            layoutCons.fill = GridBagConstraints.BOTH;
+            gridbag.setConstraints(bFind, layoutCons);
+            contentPane.add(bFind);
+
+            JButton bShow = new JButton(tr("Show"));
+            bShow.setActionCommand("routePattern.itineraryShow");
+            bShow.addActionListener(this);
+
+            layoutCons.gridx = 0;
+            layoutCons.gridy = 2;
+            layoutCons.gridwidth = 1;
+            layoutCons.weightx = 1.0;
+            layoutCons.weighty = 0.0;
+            layoutCons.fill = GridBagConstraints.BOTH;
+            gridbag.setConstraints(bShow, layoutCons);
+            contentPane.add(bShow);
+
+            JButton bMark = new JButton(tr("Mark"));
+            bMark.setActionCommand("routePattern.itineraryMark");
+            bMark.addActionListener(this);
+
+            layoutCons.gridx = 1;
+            layoutCons.gridy = 1;
+            layoutCons.gridheight = 2;
+            layoutCons.gridwidth = 1;
+            layoutCons.weightx = 1.0;
+            layoutCons.weighty = 0.0;
+            layoutCons.fill = GridBagConstraints.BOTH;
+            gridbag.setConstraints(bMark, layoutCons);
+            contentPane.add(bMark);
+
+            JButton bAdd = new JButton(tr("Add"));
+            bAdd.setActionCommand("routePattern.itineraryAdd");
+            bAdd.addActionListener(this);
+
+            layoutCons.gridx = 2;
+            layoutCons.gridy = 1;
+            layoutCons.gridheight = 1;
+            layoutCons.gridwidth = 1;
+            layoutCons.weightx = 1.0;
+            layoutCons.weighty = 0.0;
+            layoutCons.fill = GridBagConstraints.BOTH;
+            gridbag.setConstraints(bAdd, layoutCons);
+            contentPane.add(bAdd);
+
+            /* JButton */ bDelete = new JButton(tr("Delete"));
+            bDelete.setActionCommand("routePattern.itineraryDelete");
+            bDelete.addActionListener(this);
+
+            layoutCons.gridx = 2;
+            layoutCons.gridy = 2;
+            layoutCons.gridwidth = 1;
+            layoutCons.weightx = 1.0;
+            layoutCons.weighty = 0.0;
+            layoutCons.fill = GridBagConstraints.BOTH;
+            gridbag.setConstraints(bDelete, layoutCons);
+            contentPane.add(bDelete);
+
+            JButton bSort = new JButton(tr("Sort"));
+            bSort.setActionCommand("routePattern.itinerarySort");
+            bSort.addActionListener(this);
+
+            layoutCons.gridx = 3;
+            layoutCons.gridy = 1;
+            layoutCons.gridwidth = 1;
+            layoutCons.weightx = 1.0;
+            layoutCons.weighty = 0.0;
+            layoutCons.fill = GridBagConstraints.BOTH;
+            gridbag.setConstraints(bSort, layoutCons);
+            contentPane.add(bSort);
+
+            /* JButton */ bReflect = new JButton(tr("Reflect"));
+            bReflect.setActionCommand("routePattern.itineraryReflect");
+            bReflect.addActionListener(this);
+
+            layoutCons.gridx = 3;
+            layoutCons.gridy = 2;
+            layoutCons.gridwidth = 1;
+            layoutCons.weightx = 1.0;
+            layoutCons.weighty = 0.0;
+            layoutCons.fill = GridBagConstraints.BOTH;
+            gridbag.setConstraints(bReflect, layoutCons);
+            contentPane.add(bReflect);
+
+            // Stoplist Tab
+            contentPane = tabStoplist;
+            gridbag = new GridBagLayout();
+            layoutCons = new GridBagConstraints();
+            contentPane.setLayout(gridbag);
+
+            stoplistTable = new JTable();
+            stoplistData = new StoplistTableModel();
+            stoplistData.addColumn(tr("Name/Id"));
+            stoplistData.addColumn(tr("Ref"));
+            stoplistData.addColumn(tr("Role"));
+            stoplistData.addColumn(tr("km"));
+            stoplistTable.setModel(stoplistData);
+            /* JScrollPane */ tableSP = new JScrollPane(stoplistTable);
+            /* JComboBox */ comboBox = new JComboBox<>();
+            comboBox.addItem("");
+            comboBox.addItem("forward_stop");
+            comboBox.addItem("backward_stop");
+            stoplistTable.getColumnModel().getColumn(STOPLIST_ROLE_COLUMN)
+                    .setCellEditor(new DefaultCellEditor(comboBox));
+            stoplistData.addTableModelListener(new StoplistTableModelListener());
+
+            layoutCons.gridx = 0;
+            layoutCons.gridy = 0;
+            layoutCons.gridwidth = 4;
+            layoutCons.weightx = 1.0;
+            layoutCons.weighty = 1.0;
+            layoutCons.fill = GridBagConstraints.BOTH;
+            gridbag.setConstraints(tableSP, layoutCons);
+            contentPane.add(tableSP);
+
+            /* JButton */ bFind = new JButton(tr("Find"));
+            bFind.setActionCommand("routePattern.stoplistFind");
+            bFind.addActionListener(this);
+
+            layoutCons.gridx = 0;
+            layoutCons.gridy = 1;
+            layoutCons.gridwidth = 1;
+            layoutCons.weightx = 1.0;
+            layoutCons.weighty = 0.0;
+            layoutCons.fill = GridBagConstraints.BOTH;
+            gridbag.setConstraints(bFind, layoutCons);
+            contentPane.add(bFind);
+
+            /* JButton */ bShow = new JButton(tr("Show"));
+            bShow.setActionCommand("routePattern.stoplistShow");
+            bShow.addActionListener(this);
+
+            layoutCons.gridx = 0;
+            layoutCons.gridy = 2;
+            layoutCons.gridwidth = 1;
+            layoutCons.weightx = 1.0;
+            layoutCons.weighty = 0.0;
+            layoutCons.fill = GridBagConstraints.BOTH;
+            gridbag.setConstraints(bShow, layoutCons);
+            contentPane.add(bShow);
+
+            /* JButton */ bMark = new JButton(tr("Mark"));
+            bMark.setActionCommand("routePattern.stoplistMark");
+            bMark.addActionListener(this);
+
+            layoutCons.gridx = 1;
+            layoutCons.gridy = 1;
+            layoutCons.gridheight = 2;
+            layoutCons.gridwidth = 1;
+            layoutCons.weightx = 1.0;
+            layoutCons.weighty = 0.0;
+            layoutCons.fill = GridBagConstraints.BOTH;
+            gridbag.setConstraints(bMark, layoutCons);
+            contentPane.add(bMark);
+
+            /* JButton */ bAdd = new JButton(tr("Add"));
+            bAdd.setActionCommand("routePattern.stoplistAdd");
+            bAdd.addActionListener(this);
+
+            layoutCons.gridx = 2;
+            layoutCons.gridy = 1;
+            layoutCons.gridheight = 1;
+            layoutCons.gridwidth = 1;
+            layoutCons.weightx = 1.0;
+            layoutCons.weighty = 0.0;
+            layoutCons.fill = GridBagConstraints.BOTH;
+            gridbag.setConstraints(bAdd, layoutCons);
+            contentPane.add(bAdd);
+
+            /* JButton */ bDelete = new JButton(tr("Delete"));
+            bDelete.setActionCommand("routePattern.stoplistDelete");
+            bDelete.addActionListener(this);
+
+            layoutCons.gridx = 2;
+            layoutCons.gridy = 2;
+            layoutCons.gridwidth = 1;
+            layoutCons.weightx = 1.0;
+            layoutCons.weighty = 0.0;
+            layoutCons.fill = GridBagConstraints.BOTH;
+            gridbag.setConstraints(bDelete, layoutCons);
+            contentPane.add(bDelete);
+
+            /* JButton */ bSort = new JButton(tr("Sort"));
+            bSort.setActionCommand("routePattern.stoplistSort");
+            bSort.addActionListener(this);
+
+            layoutCons.gridx = 3;
+            layoutCons.gridy = 1;
+            layoutCons.gridwidth = 1;
+            layoutCons.weightx = 1.0;
+            layoutCons.weighty = 0.0;
+            layoutCons.fill = GridBagConstraints.BOTH;
+            gridbag.setConstraints(bSort, layoutCons);
+            contentPane.add(bSort);
+
+            /* JButton */ bReflect = new JButton(tr("Reflect"));
+            bReflect.setActionCommand("routePattern.stoplistReflect");
+            bReflect.addActionListener(this);
+
+            layoutCons.gridx = 3;
+            layoutCons.gridy = 2;
+            layoutCons.gridwidth = 1;
+            layoutCons.weightx = 1.0;
+            layoutCons.weighty = 0.0;
+            layoutCons.fill = GridBagConstraints.BOTH;
+            gridbag.setConstraints(bReflect, layoutCons);
+            contentPane.add(bReflect);
+
+            // Meta Tab
+            contentPane = tabMeta;
+            gridbag = new GridBagLayout();
+            layoutCons = new GridBagConstraints();
+            contentPane.setLayout(gridbag);
+
+            JLabel rightleft = new JLabel(tr("Stops are possible on the"));
+
+            layoutCons.gridx = 0;
+            layoutCons.gridy = 1;
+            layoutCons.gridwidth = 2;
+            layoutCons.weightx = 0.0;
+            layoutCons.weighty = 0.0;
+            layoutCons.fill = GridBagConstraints.BOTH;
+            gridbag.setConstraints(rightleft, layoutCons);
+            contentPane.add(rightleft);
+
+            cbRight = new JCheckBox(tr("right hand side"), true);
+
+            layoutCons.gridx = 0;
+            layoutCons.gridy = 2;
+            layoutCons.gridwidth = 2;
+            layoutCons.weightx = 0.0;
+            layoutCons.weighty = 0.0;
+            layoutCons.fill = GridBagConstraints.BOTH;
+            gridbag.setConstraints(cbRight, layoutCons);
+            contentPane.add(cbRight);
+
+            cbLeft = new JCheckBox(tr("left hand side"), false);
+
+            layoutCons.gridx = 0;
+            layoutCons.gridy = 3;
+            layoutCons.gridwidth = 2;
+            layoutCons.weightx = 0.0;
+            layoutCons.weighty = 0.0;
+            layoutCons.fill = GridBagConstraints.BOTH;
+            gridbag.setConstraints(cbLeft, layoutCons);
+            contentPane.add(cbLeft);
+
+            JLabel maxdist = new JLabel(tr("Maximum distance from route"));
+
+            layoutCons.gridx = 0;
+            layoutCons.gridy = 4;
+            layoutCons.gridwidth = 2;
+            layoutCons.weightx = 0.0;
+            layoutCons.weighty = 0.0;
+            layoutCons.fill = GridBagConstraints.BOTH;
+            gridbag.setConstraints(maxdist, layoutCons);
+            contentPane.add(maxdist);
+
+            tfSuggestStopsLimit = new JTextField("20", 4);
+
+            layoutCons.gridx = 0;
+            layoutCons.gridy = 5;
+            layoutCons.gridwidth = 1;
+            layoutCons.weightx = 0.0;
+            layoutCons.weighty = 0.0;
+            layoutCons.fill = GridBagConstraints.BOTH;
+            gridbag.setConstraints(tfSuggestStopsLimit, layoutCons);
+            contentPane.add(tfSuggestStopsLimit);
+
+            JLabel meters = new JLabel(tr("meters"));
+
+            layoutCons.gridx = 1;
+            layoutCons.gridy = 5;
+            layoutCons.gridwidth = 1;
+            layoutCons.weightx = 0.0;
+            layoutCons.weighty = 0.0;
+            layoutCons.fill = GridBagConstraints.BOTH;
+            gridbag.setConstraints(meters, layoutCons);
+            contentPane.add(meters);
+
+            JButton bSuggestStops = new JButton(tr("Suggest Stops"));
+            bSuggestStops.setActionCommand("routePattern.metaSuggestStops");
+            bSuggestStops.addActionListener(this);
+
+            layoutCons.gridx = 0;
+            layoutCons.gridy = 6;
+            layoutCons.gridwidth = 3;
+            layoutCons.weightx = 1.0;
+            layoutCons.weighty = 0.0;
+            layoutCons.fill = GridBagConstraints.BOTH;
+            gridbag.setConstraints(bSuggestStops, layoutCons);
+            contentPane.add(bSuggestStops);
+
+            jDialog.pack();
+        }
+
+        if ("routePattern.refresh".equals(event.getActionCommand())) {
+            refreshData();
+        } else if ("routePattern.overviewNew".equals(event.getActionCommand())) {
+            currentRoute = new Relation();
+            currentRoute.put("type", "route");
+            currentRoute.put("route", "bus");
+            mainDataSet.addPrimitive(currentRoute);
+
+            refreshData();
+
+            for (int i = 0; i < relsListModel.size(); ++i) {
+                if (currentRoute == relsListModel.elementAt(i).route)
+                    relsList.setSelectedIndex(i);
+            }
+        } else if ("routePattern.overviewDuplicate".equals(event.getActionCommand())) {
+            currentRoute = new Relation(currentRoute, true);
+            currentRoute.put("type", "route");
+            currentRoute.put("route", "bus");
+            mainDataSet.addPrimitive(currentRoute);
+
+            refreshData();
+
+            for (int i = 0; i < relsListModel.size(); ++i) {
+                if (currentRoute == relsListModel.elementAt(i).route)
+                    relsList.setSelectedIndex(i);
+            }
+        } else if ("routePattern.overviewReflect".equals(event.getActionCommand())) {
+            currentRoute.setModified(true);
+            String tag_from = currentRoute.get("from");
+            String tag_to = currentRoute.get("to");
+            currentRoute.put("from", tag_to);
+            currentRoute.put("to", tag_from);
+
+            Vector<RelationMember> itemsToReflect = new Vector<>();
+            Vector<RelationMember> otherItems = new Vector<>();
+
+            // Temp
+            Node firstNode = null;
+            // Node lastNode = null;
+
+            for (int i = 0; i < currentRoute.getMembersCount(); ++i) {
+                RelationMember item = currentRoute.getMember(i);
+
+                if (item.isWay()) {
+                    String role = item.getRole();
+                    if ("backward".equals(role))
+                        role = "forward";
+                    else if ("forward".equals(role))
+                        role = "backward";
+                    else
+                        role = "backward";
+
+                    itemsToReflect.add(new RelationMember(role, item.getWay()));
+
+                    // Temp
+                    if (firstNode == null) {
+                        firstNode = item.getWay().getNode(0);
+                    }
+                    // lastNode = item.getWay().getNode(item.getWay().getNodesCount() - 1);
+                } else if (item.isNode())
+                    itemsToReflect.add(item);
+                else
+                    otherItems.add(item);
+            }
+
+            currentRoute.setMembers(null);
+            for (int i = itemsToReflect.size() - 1; i >= 0; --i)
+                currentRoute.addMember(itemsToReflect.elementAt(i));
+            for (int i = 0; i < otherItems.size(); ++i)
+                currentRoute.addMember(otherItems.elementAt(i));
+
+            refreshData();
+
+            for (int i = 0; i < relsListModel.size(); ++i) {
+                if (currentRoute == relsListModel.elementAt(i).route)
+                    relsList.setSelectedIndex(i);
+            }
+
+            // Temp
+            /*
+             * if (firstNode != null) { Vector< AStarAlgorithm.Edge > path = new PublicTransportAStar(firstNode, lastNode).shortestPath(); Iterator<
+             * AStarAlgorithm.Edge > iter = path.iterator(); while (iter.hasNext()) { PublicTransportAStar.PartialWayEdge edge =
+             * (PublicTransportAStar.PartialWayEdge)iter.next(); System.out.print(edge.way.getUniqueId()); System.out.print("\t");
+             * System.out.print(edge.beginIndex); System.out.print("\t"); System.out.print(edge.endIndex); System.out.print("\n"); } }
+             */
+        } else if ("routePattern.overviewDelete".equals(event.getActionCommand())) {
+            DeleteAction.deleteRelation(Main.getLayerManager().getEditLayer(), currentRoute);
+
+            currentRoute = null;
+            tabbedPane.setEnabledAt(1, false);
+            tabbedPane.setEnabledAt(2, false);
+            tabbedPane.setEnabledAt(3, false);
+            tabbedPane.setEnabledAt(4, false);
+
+            refreshData();
+        } else if ("routePattern.tagAddTag".equals(event.getActionCommand())) {
+            Vector<String> rowContent = new Vector<>();
+            rowContent.add("");
+            rowContent.add("");
+            otherTagsData.addRow(rowContent);
+        } else if ("routePattern.itineraryFind".equals(event.getActionCommand())) {
+            if (mainDataSet == null)
+                return;
+
+            itineraryTable.clearSelection();
+
+            for (int i = 0; i < itineraryData.getRowCount(); ++i) {
+                if ((itineraryData.ways.elementAt(i) != null)
+                        && (mainDataSet.isSelected(itineraryData.ways.elementAt(i))))
+                    itineraryTable.addRowSelectionInterval(i, i);
+            }
+        } else if ("routePattern.itineraryShow".equals(event.getActionCommand())) {
+            BoundingXYVisitor box = new BoundingXYVisitor();
+            if (itineraryTable.getSelectedRowCount() > 0) {
+                for (int i = 0; i < itineraryData.getRowCount(); ++i) {
+                    if ((itineraryTable.isRowSelected(i))
+                            && (itineraryData.ways.elementAt(i) != null)) {
+                        itineraryData.ways.elementAt(i).accept(box);
+                    }
+                }
+            } else {
+                for (int i = 0; i < itineraryData.getRowCount(); ++i) {
+                    if (itineraryData.ways.elementAt(i) != null) {
+                        itineraryData.ways.elementAt(i).accept(box);
+                    }
+                }
+            }
+            if (box.getBounds() == null)
+                return;
+            box.enlargeBoundingBox();
+            Main.map.mapView.zoomTo(box);
+        } else if ("routePattern.itineraryMark".equals(event.getActionCommand())) {
+            OsmPrimitive[] osmp = { null };
+            Main.getLayerManager().getEditDataSet().setSelected(osmp);
+            markedWays.clear();
+            if (itineraryTable.getSelectedRowCount() > 0) {
+                for (int i = 0; i < itineraryData.getRowCount(); ++i) {
+                    if ((itineraryTable.isRowSelected(i))
+                            && (itineraryData.ways.elementAt(i) != null)) {
+                        mainDataSet.addSelected(itineraryData.ways.elementAt(i));
+
+                        RelationMember markedWay = new RelationMember(
+                                (String) (itineraryData.getValueAt(i, 1)),
+                                itineraryData.ways.elementAt(i));
+                        markedWays.addElement(markedWay);
+                    }
+                }
+            } else {
+                for (int i = 0; i < itineraryData.getRowCount(); ++i) {
+                    if (itineraryData.ways.elementAt(i) != null) {
+                        mainDataSet.addSelected(itineraryData.ways.elementAt(i));
+
+                        RelationMember markedWay = new RelationMember(
+                                (String) (itineraryData.getValueAt(i, 1)),
+                                itineraryData.ways.elementAt(i));
+                        markedWays.addElement(markedWay);
+                    }
+                }
+            }
+        } else if ("routePattern.itineraryAdd".equals(event.getActionCommand())) {
+            int insPos = itineraryTable.getSelectedRow();
+            Iterator<RelationMember> relIter = markedWays.iterator();
+            TreeSet<Way> addedWays = new TreeSet<>();
+            if (mainDataSet == null)
+                return;
+
+            while (relIter.hasNext()) {
+                RelationMember curMember = relIter.next();
+                if ((curMember.isWay()) && (mainDataSet.isSelected(curMember.getWay()))) {
+                    itineraryData.insertRow(insPos, curMember.getWay(), curMember.getRole());
+                    if (insPos >= 0)
+                        ++insPos;
+
+                    addedWays.add(curMember.getWay());
+                }
+            }
+
+            Collection<Way> selectedWays = mainDataSet.getSelectedWays();
+            Iterator<Way> wayIter = selectedWays.iterator();
+
+            while (wayIter.hasNext()) {
+                Way curMember = wayIter.next();
+                if (!(addedWays.contains(curMember))) {
+                    itineraryData.insertRow(insPos, curMember, "");
+                    if (insPos >= 0)
+                        ++insPos;
+                }
+            }
+
+            if ((insPos > 0) && (insPos < itineraryData.getRowCount())) {
+                while ((insPos < itineraryData.getRowCount())
+                        && (itineraryData.ways.elementAt(insPos) == null))
+                    ++insPos;
+                itineraryTable.removeRowSelectionInterval(0, itineraryData.getRowCount() - 1);
+                if (insPos < itineraryData.getRowCount())
+                    itineraryTable.addRowSelectionInterval(insPos, insPos);
+            }
+
+            itineraryData.cleanupGaps();
+            segmentMetrics = fillSegmentMetrics();
+            rebuildWays();
+        } else if ("routePattern.itineraryDelete".equals(event.getActionCommand())) {
+            for (int i = itineraryData.getRowCount() - 1; i >= 0; --i) {
+                if ((itineraryTable.isRowSelected(i))
+                        && (itineraryData.ways.elementAt(i) != null)) {
+                    itineraryData.ways.removeElementAt(i);
+                    itineraryData.removeRow(i);
+                }
+            }
+
+            itineraryData.cleanupGaps();
+            segmentMetrics = fillSegmentMetrics();
+            rebuildWays();
+        } else if ("routePattern.itinerarySort".equals(event.getActionCommand())) {
+            TreeSet<Way> usedWays = new TreeSet<>();
+            TreeMap<Node, LinkedList<RelationMember>> frontNodes = new TreeMap<>();
+            TreeMap<Node, LinkedList<RelationMember>> backNodes = new TreeMap<>();
+            Vector<LinkedList<RelationMember>> loops = new Vector<>();
+            int insPos = itineraryTable.getSelectedRow();
+
+            if (itineraryTable.getSelectedRowCount() > 0) {
+                for (int i = itineraryData.getRowCount() - 1; i >= 0; --i) {
+                    if ((itineraryTable.isRowSelected(i))
+                            && (itineraryData.ways.elementAt(i) != null)) {
+                        if (!(usedWays.contains(itineraryData.ways.elementAt(i)))) {
+                            addWayToSortingData(itineraryData.ways.elementAt(i), frontNodes,
+                                    backNodes, loops);
+                            usedWays.add(itineraryData.ways.elementAt(i));
+                        }
+
+                        itineraryData.ways.removeElementAt(i);
+                        itineraryData.removeRow(i);
+                    }
+                }
+            } else {
+                for (int i = itineraryData.getRowCount() - 1; i >= 0; --i) {
+                    if (itineraryData.ways.elementAt(i) != null) {
+                        if (!(usedWays.contains(itineraryData.ways.elementAt(i)))) {
+                            addWayToSortingData(itineraryData.ways.elementAt(i), frontNodes,
+                                    backNodes, loops);
+                            usedWays.add(itineraryData.ways.elementAt(i));
+                        }
+                    }
+                }
+
+                itineraryData.clear();
+            }
+
+            Iterator<Map.Entry<Node, LinkedList<RelationMember>>> entryIter = frontNodes.entrySet()
+                    .iterator();
+            while (entryIter.hasNext()) {
+                Iterator<RelationMember> relIter = entryIter.next().getValue().iterator();
+                while (relIter.hasNext()) {
+                    RelationMember curMember = relIter.next();
+                    itineraryData.insertRow(insPos, curMember.getWay(), curMember.getRole());
+                    if (insPos >= 0)
+                        ++insPos;
+                }
+            }
+
+            Iterator<LinkedList<RelationMember>> listIter = loops.iterator();
+            while (listIter.hasNext()) {
+                Iterator<RelationMember> relIter = listIter.next().iterator();
+                while (relIter.hasNext()) {
+                    RelationMember curMember = relIter.next();
+                    itineraryData.insertRow(insPos, curMember.getWay(), curMember.getRole());
+                    if (insPos >= 0)
+                        ++insPos;
+                }
+            }
+
+            itineraryData.cleanupGaps();
+            segmentMetrics = fillSegmentMetrics();
+            rebuildWays();
+        } else if ("routePattern.itineraryReflect".equals(event.getActionCommand())) {
+            Vector<RelationMember> itemsToReflect = new Vector<>();
+            int insPos = itineraryTable.getSelectedRow();
+
+            if (itineraryTable.getSelectedRowCount() > 0) {
+                for (int i = itineraryData.getRowCount() - 1; i >= 0; --i) {
+                    if ((itineraryTable.isRowSelected(i))
+                            && (itineraryData.ways.elementAt(i) != null)) {
+                        String role = (String) (itineraryData.getValueAt(i, 1));
+                        if ("backward".equals(role))
+                            role = "forward";
+                        else if ("forward".equals(role))
+                            role = "backward";
+                        else
+                            role = "backward";
+                        RelationMember markedWay = new RelationMember(role,
+                                itineraryData.ways.elementAt(i));
+                        itemsToReflect.addElement(markedWay);
+
+                        itineraryData.ways.removeElementAt(i);
+                        itineraryData.removeRow(i);
+                    }
+                }
+            } else {
+                for (int i = itineraryData.getRowCount() - 1; i >= 0; --i) {
+                    if (itineraryData.ways.elementAt(i) != null) {
+                        String role = (String) (itineraryData.getValueAt(i, 1));
+                        if ("backward".equals(role))
+                            role = "forward";
+                        else if ("forward".equals(role))
+                            role = "backward";
+                        else
+                            role = "backward";
+                        RelationMember markedWay = new RelationMember(role,
+                                itineraryData.ways.elementAt(i));
+                        itemsToReflect.addElement(markedWay);
+                    }
+                }
+
+                itineraryData.clear();
+            }
+
+            int startPos = insPos;
+            Iterator<RelationMember> relIter = itemsToReflect.iterator();
+            while (relIter.hasNext()) {
+                RelationMember curMember = relIter.next();
+                if (curMember.isWay()) {
+                    itineraryData.insertRow(insPos, curMember.getWay(), curMember.getRole());
+                    if (insPos >= 0)
+                        ++insPos;
+                }
+            }
+            if (insPos >= 0)
+                itineraryTable.addRowSelectionInterval(startPos, insPos - 1);
+
+            itineraryData.cleanupGaps();
+            segmentMetrics = fillSegmentMetrics();
+            rebuildWays();
+        } else if ("routePattern.stoplistFind".equals(event.getActionCommand())) {
+            if (mainDataSet == null)
+                return;
+
+            stoplistTable.clearSelection();
+
+            for (int i = 0; i < stoplistData.getRowCount(); ++i) {
+                if ((stoplistData.nodes.elementAt(i) != null)
+                        && (mainDataSet.isSelected(stoplistData.nodes.elementAt(i))))
+                    stoplistTable.addRowSelectionInterval(i, i);
+            }
+        } else if ("routePattern.stoplistShow".equals(event.getActionCommand())) {
+            BoundingXYVisitor box = new BoundingXYVisitor();
+            if (stoplistTable.getSelectedRowCount() > 0) {
+                for (int i = 0; i < stoplistData.getRowCount(); ++i) {
+                    if (stoplistTable.isRowSelected(i)) {
+                        stoplistData.nodes.elementAt(i).accept(box);
+                    }
+                }
+            } else {
+                for (int i = 0; i < stoplistData.getRowCount(); ++i) {
+                    stoplistData.nodes.elementAt(i).accept(box);
+                }
+            }
+            if (box.getBounds() == null)
+                return;
+            box.enlargeBoundingBox();
+            Main.map.mapView.zoomTo(box);
+        } else if ("routePattern.stoplistMark".equals(event.getActionCommand())) {
+            OsmPrimitive[] osmp = { null };
+            Main.getLayerManager().getEditDataSet().setSelected(osmp);
+            markedNodes.clear();
+            if (stoplistTable.getSelectedRowCount() > 0) {
+                for (int i = 0; i < stoplistData.getRowCount(); ++i) {
+                    if (stoplistTable.isRowSelected(i)) {
+                        mainDataSet.addSelected(stoplistData.nodes.elementAt(i));
+
+                        RelationMember markedNode = new RelationMember(
+                                (String) (stoplistData.getValueAt(i, 1)),
+                                stoplistData.nodes.elementAt(i));
+                        markedNodes.addElement(markedNode);
+                    }
+                }
+            } else {
+                for (int i = 0; i < stoplistData.getRowCount(); ++i) {
+                    mainDataSet.addSelected(stoplistData.nodes.elementAt(i));
+
+                    RelationMember markedNode = new RelationMember(
+                            (String) (stoplistData.getValueAt(i, 1)),
+                            stoplistData.nodes.elementAt(i));
+                    markedNodes.addElement(markedNode);
+                }
+            }
+        } else if ("routePattern.stoplistAdd".equals(event.getActionCommand())) {
+            int insPos = stoplistTable.getSelectedRow();
+            Iterator<RelationMember> relIter = markedNodes.iterator();
+            TreeSet<Node> addedNodes = new TreeSet<>();
+            if (mainDataSet == null)
+                return;
+
+            while (relIter.hasNext()) {
+                RelationMember curMember = relIter.next();
+                if ((curMember.isNode()) && (mainDataSet.isSelected(curMember.getNode()))) {
+                    StopReference sr = detectMinDistance(curMember.getNode(), segmentMetrics,
+                            cbRight.isSelected(), cbLeft.isSelected());
+                    stoplistData.insertRow(insPos, curMember.getNode(), curMember.getRole(),
+                            calcOffset(sr, segmentMetrics));
+                    if (insPos >= 0)
+                        ++insPos;
+
+                    addedNodes.add(curMember.getNode());
+                }
+            }
+
+            Collection<Node> selectedNodes = mainDataSet.getSelectedNodes();
+            Iterator<Node> nodeIter = selectedNodes.iterator();
+
+            while (nodeIter.hasNext()) {
+                Node curMember = nodeIter.next();
+                if (!(addedNodes.contains(curMember))) {
+                    StopReference sr = detectMinDistance(curMember, segmentMetrics,
+                            cbRight.isSelected(), cbLeft.isSelected());
+                    stoplistData.insertRow(insPos, curMember, "", calcOffset(sr, segmentMetrics));
+                    if (insPos >= 0)
+                        ++insPos;
+                }
+            }
+
+            if ((insPos > 0) && (insPos < stoplistData.getRowCount())) {
+                while ((insPos < stoplistData.getRowCount())
+                        && (stoplistData.nodes.elementAt(insPos) == null))
+                    ++insPos;
+                stoplistTable.removeRowSelectionInterval(0, stoplistData.getRowCount() - 1);
+                if (insPos < stoplistData.getRowCount())
+                    stoplistTable.addRowSelectionInterval(insPos, insPos);
+            }
+
+            rebuildNodes();
+        } else if ("routePattern.stoplistDelete".equals(event.getActionCommand())) {
+            for (int i = stoplistData.getRowCount() - 1; i >= 0; --i) {
+                if (stoplistTable.isRowSelected(i)) {
+                    stoplistData.nodes.removeElementAt(i);
+                    stoplistData.removeRow(i);
+                }
+            }
+
+            rebuildNodes();
+        } else if ("routePattern.stoplistSort".equals(event.getActionCommand())) {
+            // Prepare Segments: The segments of all usable ways are arranged in a linear
+            // list such that a coor can directly be checked concerning position and offset
+            Vector<StopReference> srm = new Vector<>();
+            int insPos = stoplistTable.getSelectedRow();
+            if (stoplistTable.getSelectedRowCount() > 0) {
+                // Determine for each member its position on the itinerary: position means here the
+                // point on the itinerary that has minimal distance to the coor
+                for (int i = stoplistData.getRowCount() - 1; i >= 0; --i) {
+                    if (stoplistTable.isRowSelected(i)) {
+                        StopReference sr = detectMinDistance(stoplistData.nodes.elementAt(i),
+                                segmentMetrics, cbRight.isSelected(), cbLeft.isSelected());
+                        if (sr != null) {
+                            if (sr.distance < Double.parseDouble(tfSuggestStopsLimit.getText())
+                                    * 9.0 / 1000000.0) {
+                                sr.role = (String) stoplistData.getValueAt(i, STOPLIST_ROLE_COLUMN);
+                                srm.addElement(sr);
+                            } else {
+                                sr.role = (String) stoplistData.getValueAt(i, STOPLIST_ROLE_COLUMN);
+                                sr.index = segmentMetrics.size() * 2;
+                                sr.pos = 0;
+                                srm.addElement(sr);
+                            }
+
+                            stoplistData.nodes.removeElementAt(i);
+                            stoplistData.removeRow(i);
+                        }
+                    }
+                }
+            } else {
+                // Determine for each member its position on the itinerary: position means here the
+                // point on the itinerary that has minimal distance to the coor
+                for (int i = stoplistData.getRowCount() - 1; i >= 0; --i) {
+                    StopReference sr = detectMinDistance(stoplistData.nodes.elementAt(i),
+                            segmentMetrics, cbRight.isSelected(), cbLeft.isSelected());
+                    if (sr != null) {
+                        if (sr.distance < Double.parseDouble(tfSuggestStopsLimit.getText()) * 9.0
+                                / 1000000.0) {
+                            sr.role = (String) stoplistData.getValueAt(i, STOPLIST_ROLE_COLUMN);
+                            srm.addElement(sr);
+                        } else {
+                            sr.role = (String) stoplistData.getValueAt(i, STOPLIST_ROLE_COLUMN);
+                            sr.index = segmentMetrics.size() * 2;
+                            sr.pos = 0;
+                            srm.addElement(sr);
+                        }
+                    }
+                }
+
+                stoplistData.clear();
+            }
+
+            Collections.sort(srm);
+
+            for (int i = 0; i < srm.size(); ++i) {
+                StopReference sr = detectMinDistance(srm.elementAt(i).node, segmentMetrics,
+                        cbRight.isSelected(), cbLeft.isSelected());
+                stoplistData.insertRow(insPos, srm.elementAt(i).node, srm.elementAt(i).role,
+                        calcOffset(sr, segmentMetrics));
+                if (insPos >= 0)
+                    ++insPos;
+            }
+
+            rebuildNodes();
+        } else if ("routePattern.stoplistReflect".equals(event.getActionCommand())) {
+            Vector<RelationMember> itemsToReflect = new Vector<>();
+            int insPos = stoplistTable.getSelectedRow();
+
+            if (stoplistTable.getSelectedRowCount() > 0) {
+                for (int i = stoplistData.getRowCount() - 1; i >= 0; --i) {
+                    if (stoplistTable.isRowSelected(i)) {
+                        String role = (String) (stoplistData.getValueAt(i, STOPLIST_ROLE_COLUMN));
+                        RelationMember markedNode = new RelationMember(role,
+                                stoplistData.nodes.elementAt(i));
+                        itemsToReflect.addElement(markedNode);
+
+                        stoplistData.nodes.removeElementAt(i);
+                        stoplistData.removeRow(i);
+                    }
+                }
+            } else {
+                for (int i = stoplistData.getRowCount() - 1; i >= 0; --i) {
+                    String role = (String) (stoplistData.getValueAt(i, STOPLIST_ROLE_COLUMN));
+                    RelationMember markedNode = new RelationMember(role,
+                            stoplistData.nodes.elementAt(i));
+                    itemsToReflect.addElement(markedNode);
+                }
+
+                stoplistData.clear();
+            }
+
+            int startPos = insPos;
+            Iterator<RelationMember> relIter = itemsToReflect.iterator();
+            while (relIter.hasNext()) {
+                RelationMember curMember = relIter.next();
+                if (curMember.isNode()) {
+                    StopReference sr = detectMinDistance(curMember.getNode(), segmentMetrics,
+                            cbRight.isSelected(), cbLeft.isSelected());
+                    stoplistData.insertRow(insPos, curMember.getNode(), curMember.getRole(),
+                            calcOffset(sr, segmentMetrics));
+                    if (insPos >= 0)
+                        ++insPos;
+                }
+            }
+            if (insPos >= 0)
+                stoplistTable.addRowSelectionInterval(startPos, insPos - 1);
+
+            rebuildNodes();
+        } else if ("routePattern.metaSuggestStops".equals(event.getActionCommand())) {
+            // Prepare Segments: The segments of all usable ways are arranged in a linear
+            // list such that a coor can directly be checked concerning position and offset
+            Vector<StopReference> srm = new Vector<>();
+            // Determine for each member its position on the itinerary: position means here the
+            // point on the itinerary that has minimal distance to the coor
+            mainDataSet = Main.getLayerManager().getEditDataSet();
+            if (mainDataSet != null) {
+                String stopKey = "";
+                String stopValue = "";
+                if ("bus".equals(currentRoute.get("route"))) {
+                    stopKey = "highway";
+                    stopValue = "bus_stop";
+                } else if ("trolleybus".equals(currentRoute.get("route"))) {
+                    stopKey = "highway";
+                    stopValue = "bus_stop";
+                } else if ("tram".equals(currentRoute.get("route"))) {
+                    stopKey = "railway";
+                    stopValue = "tram_stop";
+                } else if ("light_rail".equals(currentRoute.get("route"))) {
+                    stopKey = "railway";
+                    stopValue = "station";
+                } else if ("subway".equals(currentRoute.get("route"))) {
+                    stopKey = "railway";
+                    stopValue = "station";
+                } else if ("rail".equals(currentRoute.get("route"))) {
+                    stopKey = "railway";
+                    stopValue = "station";
+                }
+
+                Collection<Node> nodeCollection = mainDataSet.getNodes();
+                Iterator<Node> nodeIter = nodeCollection.iterator();
+                while (nodeIter.hasNext()) {
+                    Node currentNode = nodeIter.next();
+                    if (!currentNode.isUsable())
+                        continue;
+                    if (stopValue.equals(currentNode.get(stopKey))) {
+                        StopReference sr = detectMinDistance(currentNode, segmentMetrics,
+                                cbRight.isSelected(), cbLeft.isSelected());
+                        if ((sr != null)
+                                && (sr.distance < Double.parseDouble(tfSuggestStopsLimit.getText())
+                                        * 9.0 / 1000000.0))
+                            srm.addElement(sr);
+                    }
+                }
+            } else {
+                JOptionPane.showMessageDialog(null,
+                        tr("There exists no dataset."
+                                + " Try to download data from the server or open an OSM file."),
+                        tr("No data found"), JOptionPane.ERROR_MESSAGE);
+            }
+
+            Collections.sort(srm);
+
+            stoplistData.clear();
+            for (int i = 0; i < srm.size(); ++i) {
+                StopReference sr = detectMinDistance(srm.elementAt(i).node, segmentMetrics,
+                        cbRight.isSelected(), cbLeft.isSelected());
+                stoplistData.addRow(srm.elementAt(i).node, srm.elementAt(i).role,
+                        calcOffset(sr, segmentMetrics));
+            }
+
+            rebuildNodes();
+        } else {
+            refreshData();
+
+            jDialog.setLocationRelativeTo(frame);
+            jDialog.setVisible(true);
+        }
     }
-  };
-
-  private class RouteReference implements Comparable< RouteReference > {
-    Relation route;
-
-    public RouteReference(Relation route) {
-      this.route = route;
+
+    private void refreshData() {
+        Relation copy = currentRoute;
+        relsListModel.clear();
+        currentRoute = copy;
+
+        DataSet mainDataSet = Main.getLayerManager().getEditDataSet();
+        if (mainDataSet != null) {
+            Vector<RouteReference> relRefs = new Vector<>();
+            Collection<Relation> relCollection = mainDataSet.getRelations();
+            Iterator<Relation> relIter = relCollection.iterator();
+
+            while (relIter.hasNext()) {
+                Relation currentRel = relIter.next();
+                if (!currentRel.isDeleted()) {
+                    String routeVal = currentRel.get("route");
+                    if ("bus".equals(routeVal))
+                        relRefs.add(new RouteReference(currentRel));
+                    else if ("trolleybus".equals(routeVal))
+                        relRefs.add(new RouteReference(currentRel));
+                    else if ("tram".equals(routeVal))
+                        relRefs.add(new RouteReference(currentRel));
+                    else if ("light_rail".equals(routeVal))
+                        relRefs.add(new RouteReference(currentRel));
+                    else if ("subway".equals(routeVal))
+                        relRefs.add(new RouteReference(currentRel));
+                    else if ("rail".equals(routeVal))
+                        relRefs.add(new RouteReference(currentRel));
+                }
+            }
+
+            Collections.sort(relRefs);
+
+            Iterator<RouteReference> iter = relRefs.iterator();
+            while (iter.hasNext())
+                relsListModel.addElement(iter.next());
+        } else {
+            JOptionPane.showMessageDialog(null,
+                    tr("There exists no dataset."
+                            + " Try to download data from the server or open an OSM file."),
+                    tr("No data found"), JOptionPane.ERROR_MESSAGE);
+        }
     }
 
-    @Override
-    public int compareTo(RouteReference rr) {
-      if (route.get("route") != null)
-      {
-        if (rr.route.get("route") == null)
-          return -1;
-        int result = route.get("route").compareTo(rr.route.get("route"));
-        if (result != 0)
-          return result;
-      }
-      else if (rr.route.get("route") != null)
-        return 1;
-      if (route.get("ref") != null)
-      {
-        if (rr.route.get("ref") == null)
-          return -1;
-        int result = route.get("ref").compareTo(rr.route.get("ref"));
-        if (result != 0)
-      return result;
-      }
-      else if (rr.route.get("ref") != null)
-        return 1;
-      if (route.get("to") != null)
-      {
-        if (rr.route.get("to") == null)
-          return -1;
-        int result = route.get("to").compareTo(rr.route.get("to"));
-        if (result != 0)
-          return result;
-      }
-      else if (rr.route.get("to") != null)
-        return 1;
-      if (route.get("direction") != null)
-      {
-        if (rr.route.get("direction") == null)
-          return -1;
-        int result = route.get("direction").compareTo(rr.route.get("direction"));
-        if (result != 0)
-          return result;
-      }
-      else if (rr.route.get("direction") != null)
-        return 1;
-      if (route.getId() < rr.route.getId())
-        return -1;
-      else if (route.getId() > rr.route.getId())
-        return 1;
-      return 0;
+    // Rebuild ways in the relation currentRoute
+    public static void rebuildWays() {
+        currentRoute.setModified(true);
+        List<RelationMember> members = currentRoute.getMembers();
+        ListIterator<RelationMember> iter = members.listIterator();
+        while (iter.hasNext()) {
+            if (iter.next().isWay())
+                iter.remove();
+        }
+        for (int i = 0; i < itineraryData.getRowCount(); ++i) {
+            if (itineraryData.ways.elementAt(i) != null) {
+                RelationMember member = new RelationMember(
+                        (String) (itineraryData.getValueAt(i, 1)), itineraryData.ways.elementAt(i));
+                members.add(member);
+            }
+        }
+        currentRoute.setMembers(members);
     }
 
-    @Override
-    public String toString() {
-      String buf = route.get("route");
-      if ((route.get("ref") != null) && (route.get("ref") != ""))
-      {
-        buf += " " + route.get("ref");
-      }
-      if ((route.get("loc_ref") != null) && (route.get("loc_ref") != ""))
-      {
-        buf += " [" + route.get("loc_ref") + "]";
-      }
-
-      if ((route.get("to") != null) && (route.get("to") != ""))
-      {
-        buf += ": " + route.get("to");
-      }
-      else if ((route.get("direction") != null) && (route.get("direction") != ""))
-      {
-        buf += " " + route.get("ref") + ": " + route.get("direction");
-      }
-      else
-      {
-        buf += " " + route.get("ref");
-      }
-      buf += tr(" [ID] {0}", Long.toString(route.getId()));
-
-      return buf;
+    // Rebuild nodes in the relation currentRoute
+    private void rebuildNodes() {
+        currentRoute.setModified(true);
+        for (int i = currentRoute.getMembersCount() - 1; i >= 0; --i) {
+            if (currentRoute.getMember(i).isNode()) {
+                currentRoute.removeMember(i);
+            }
+        }
+        for (int i = 0; i < stoplistData.getRowCount(); ++i) {
+            RelationMember member = new RelationMember(
+                    (String) (stoplistData.getValueAt(i, STOPLIST_ROLE_COLUMN)),
+                    stoplistData.nodes.elementAt(i));
+            currentRoute.addMember(member);
+        }
     }
-  };
-
-  private class TagTableModel extends DefaultTableModel implements TableModelListener {
-    Relation relation = null;
-    TreeSet< String > blacklist = null;
-    boolean hasFixedKeys = true;
-
-    public TagTableModel(boolean hasFixedKeys) {
-      this.hasFixedKeys = hasFixedKeys;
+
+    private void addWayToSortingData(Way way, TreeMap<Node, LinkedList<RelationMember>> frontNodes,
+            TreeMap<Node, LinkedList<RelationMember>> backNodes,
+            Vector<LinkedList<RelationMember>> loops) {
+        if (way.getNodesCount() < 1)
+            return;
+
+        Node firstNode = way.getNode(0);
+        Node lastNode = way.getNode(way.getNodesCount() - 1);
+
+        if (frontNodes.get(firstNode) != null) {
+            LinkedList<RelationMember> list = frontNodes.get(firstNode);
+            list.addFirst(new RelationMember("backward", way));
+            frontNodes.remove(firstNode);
+
+            Node lastListNode;
+            if ("backward".equals(list.getLast().getRole()))
+                lastListNode = list.getLast().getWay().getNode(0);
+            else
+                lastListNode = list.getLast().getWay()
+                        .getNode(list.getLast().getWay().getNodesCount() - 1);
+            if (lastNode.equals(lastListNode)) {
+                backNodes.remove(lastListNode);
+                loops.add(list);
+            } else if (frontNodes.get(lastNode) != null) {
+                backNodes.remove(lastListNode);
+                LinkedList<RelationMember> listToAppend = frontNodes.get(lastNode);
+                Iterator<RelationMember> memberIter = list.iterator();
+                while (memberIter.hasNext()) {
+                    RelationMember member = memberIter.next();
+                    if ("backward".equals(member.getRole()))
+                        listToAppend.addFirst(new RelationMember("forward", member.getWay()));
+                    else
+                        listToAppend.addFirst(new RelationMember("backward", member.getWay()));
+                }
+                frontNodes.remove(lastNode);
+                frontNodes.put(lastListNode, listToAppend);
+            } else if (backNodes.get(lastNode) != null) {
+                backNodes.remove(lastListNode);
+                LinkedList<RelationMember> listToAppend = backNodes.get(lastNode);
+                Iterator<RelationMember> memberIter = list.iterator();
+                while (memberIter.hasNext()) {
+                    RelationMember member = memberIter.next();
+                    listToAppend.addLast(member);
+                }
+                backNodes.remove(lastNode);
+                backNodes.put(lastListNode, listToAppend);
+            } else
+                frontNodes.put(lastNode, list);
+        } else if (backNodes.get(firstNode) != null) {
+            LinkedList<RelationMember> list = backNodes.get(firstNode);
+            list.addLast(new RelationMember("forward", way));
+            backNodes.remove(firstNode);
+
+            Node firstListNode;
+            if ("backward".equals(list.getFirst().getRole()))
+                firstListNode = list.getFirst().getWay()
+                        .getNode(list.getFirst().getWay().getNodesCount() - 1);
+            else
+                firstListNode = list.getFirst().getWay().getNode(0);
+            if (lastNode.equals(firstListNode)) {
+                frontNodes.remove(firstListNode);
+                loops.add(list);
+            } else if (frontNodes.get(lastNode) != null) {
+                frontNodes.remove(firstListNode);
+                LinkedList<RelationMember> listToAppend = frontNodes.get(lastNode);
+                ListIterator<RelationMember> memberIter = list.listIterator(list.size());
+                while (memberIter.hasPrevious()) {
+                    RelationMember member = memberIter.previous();
+                    listToAppend.addFirst(member);
+                }
+                frontNodes.remove(lastNode);
+                frontNodes.put(firstListNode, listToAppend);
+            } else if (backNodes.get(lastNode) != null) {
+                frontNodes.remove(firstListNode);
+                LinkedList<RelationMember> listToAppend = backNodes.get(lastNode);
+                ListIterator<RelationMember> memberIter = list.listIterator(list.size());
+                while (memberIter.hasPrevious()) {
+                    RelationMember member = memberIter.previous();
+                    if ("backward".equals(member.getRole()))
+                        listToAppend.addLast(new RelationMember("forward", member.getWay()));
+                    else
+                        listToAppend.addLast(new RelationMember("backward", member.getWay()));
+                }
+                backNodes.remove(lastNode);
+                backNodes.put(firstListNode, listToAppend);
+            } else
+                backNodes.put(lastNode, list);
+        } else if (frontNodes.get(lastNode) != null) {
+            LinkedList<RelationMember> list = frontNodes.get(lastNode);
+            list.addFirst(new RelationMember("forward", way));
+            frontNodes.remove(lastNode);
+            frontNodes.put(firstNode, list);
+        } else if (backNodes.get(lastNode) != null) {
+            LinkedList<RelationMember> list = backNodes.get(lastNode);
+            list.addLast(new RelationMember("backward", way));
+            backNodes.remove(lastNode);
+            backNodes.put(firstNode, list);
+        } else {
+            LinkedList<RelationMember> newList = new LinkedList<>();
+            newList.add(new RelationMember("forward", way));
+            frontNodes.put(firstNode, newList);
+            backNodes.put(lastNode, newList);
+        }
     }
 
-    @Override
-    public boolean isCellEditable(int row, int column) {
-      if ((column == 0) && (hasFixedKeys))
-        return false;
-      return true;
+    private void routesSelectionChanged() {
+        int selectedPos = relsList.getAnchorSelectionIndex();
+        if (relsList.isSelectedIndex(selectedPos)) {
+            currentRoute = relsListModel.elementAt(selectedPos).route;
+            tabbedPane.setEnabledAt(1, true);
+            tabbedPane.setEnabledAt(2, true);
+            tabbedPane.setEnabledAt(3, true);
+            tabbedPane.setEnabledAt(4, true);
+
+            // Prepare Tags
+            requiredTagsData.readRelation(currentRoute);
+            commonTagsData.readRelation(currentRoute);
+            otherTagsData.readRelation(currentRoute, tagBlacklist);
+
+            // Prepare Itinerary
+            itineraryData.clear();
+            List<RelationMember> relMembers = currentRoute.getMembers();
+            Iterator<RelationMember> relIter = relMembers.iterator();
+            fillItineraryTable(relIter, 0, -1);
+
+            // Prepare Stoplist
+            stoplistData.clear();
+            /* List<RelationMember> */ relMembers = currentRoute.getMembers();
+            /* Iterator<RelationMember> */ relIter = relMembers.iterator();
+            fillStoplistTable(relIter, -1);
+        } else {
+            currentRoute = null;
+            tabbedPane.setEnabledAt(1, false);
+            tabbedPane.setEnabledAt(2, false);
+            tabbedPane.setEnabledAt(3, false);
+            tabbedPane.setEnabledAt(4, false);
+        }
     }
 
-    public void readRelation(Relation rel) {
-      relation = rel;
-
-      for (int i = 0; i < getRowCount(); ++i)
-      {
-        String value = rel.get((String)getValueAt(i, 0));
-        if (value == null)
-          value = "";
-        setValueAt(value, i, 1);
-      }
+    private void fillItineraryTable(Iterator<RelationMember> relIter, long lastNodeId, int insPos) {
+        while (relIter.hasNext()) {
+            RelationMember curMember = relIter.next();
+            if (curMember.isWay()) {
+                itineraryData.insertRow(insPos, curMember.getWay(), curMember.getRole());
+                if (insPos >= 0)
+                    ++insPos;
+            }
+        }
+        itineraryData.cleanupGaps();
+        segmentMetrics = fillSegmentMetrics();
     }
 
-    public void readRelation(Relation rel, TreeSet< String > blacklist) {
-      relation = rel;
-      this.blacklist = blacklist;
-
-      setRowCount(0);
-      Iterator< Map.Entry< String, String > > iter = rel.getKeys().entrySet().iterator();
-      while (iter.hasNext())
-      {
-        Map.Entry< String, String > entry = iter.next();
-        if (!blacklist.contains(entry.getKey()))
-        {
-          Vector< String > newRow = new Vector< String >();
-          newRow.add(entry.getKey());
-          newRow.add(entry.getValue());
-          addRow(newRow);
-        }
-      }
-
-      for (int i = 0; i < getRowCount(); ++i)
-      {
-        String value = rel.get((String)getValueAt(i, 0));
-        if (value == null)
-          value = "";
-        setValueAt(value, i, 1);
-      }
+    private double calcOffset(StopReference sr, Vector<SegmentMetric> segmentMetrics) {
+        double offset = 0;
+        if ((sr.index + 1) / 2 < segmentMetrics.size()) {
+            offset = segmentMetrics.elementAt((sr.index + 1) / 2).distance;
+            if (sr.index % 2 == 0)
+                offset += sr.pos;
+        } else
+            offset = segmentMetrics.elementAt(segmentMetrics.size() - 1).distance
+                    + segmentMetrics.elementAt(segmentMetrics.size() - 1).length;
+
+        return offset;
     }
 
-    @Override
-    public void tableChanged(TableModelEvent e)
-    {
-      if (e.getType() == TableModelEvent.UPDATE)
-      {
-        relation.setModified(true);
-
-        String key = (String)getValueAt(e.getFirstRow(), 0);
-        if (key == null)
-          return;
-        if ((blacklist == null) || (!blacklist.contains(key)))
-        {
-          relation.setModified(true);
-          if ("".equals(getValueAt(e.getFirstRow(), 1)))
-            relation.remove(key);
-          else
-            relation.put(key, (String)getValueAt(e.getFirstRow(), 1));
-        }
-        else
-        {
-          if (e.getColumn() == 0)
-            setValueAt("", e.getFirstRow(), 0);
-        }
-      }
+    private void fillStoplistTable(Iterator<RelationMember> relIter, int insPos) {
+
+        while (relIter.hasNext()) {
+            RelationMember curMember = relIter.next();
+            if (curMember.isNode()) {
+                StopReference sr = detectMinDistance(curMember.getNode(), segmentMetrics,
+                        cbRight.isSelected(), cbLeft.isSelected());
+                if (sr == null)
+                    stoplistData.insertRow(insPos, curMember.getNode(), curMember.getRole(), 360.0);
+                else {
+                    stoplistData.insertRow(insPos, curMember.getNode(), curMember.getRole(),
+                            calcOffset(sr, segmentMetrics));
+                    if (insPos >= 0)
+                        ++insPos;
+                }
+            }
+        }
     }
-  };
-
-  private class CustomCellEditorTable extends JTable {
-    TreeMap< Integer, TableCellEditor > col1 = null;
-    TreeMap< Integer, TableCellEditor > col2 = null;
-
-    public CustomCellEditorTable() {
-      col1 = new TreeMap< Integer, TableCellEditor >();
-      col2 = new TreeMap< Integer, TableCellEditor >();
+
+    private Vector<SegmentMetric> fillSegmentMetrics() {
+        Vector<SegmentMetric> segmentMetrics = new Vector<>();
+        double distance = 0;
+        for (int i = 0; i < itineraryData.getRowCount(); ++i) {
+            if (itineraryData.ways.elementAt(i) != null) {
+                Way way = itineraryData.ways.elementAt(i);
+                if (!(way.isIncomplete())) {
+                    if ("backward".equals((itineraryData.getValueAt(i, 1)))) {
+                        for (int j = way.getNodesCount() - 2; j >= 0; --j) {
+                            SegmentMetric sm = new SegmentMetric(way.getNode(j + 1).getCoor().lat(),
+                                    way.getNode(j + 1).getCoor().lon(),
+                                    way.getNode(j).getCoor().lat(), way.getNode(j).getCoor().lon(),
+                                    distance);
+                            segmentMetrics.add(sm);
+                            distance += sm.length;
+                        }
+                    } else {
+                        for (int j = 0; j < way.getNodesCount() - 1; ++j) {
+                            SegmentMetric sm = new SegmentMetric(way.getNode(j).getCoor().lat(),
+                                    way.getNode(j).getCoor().lon(),
+                                    way.getNode(j + 1).getCoor().lat(),
+                                    way.getNode(j + 1).getCoor().lon(), distance);
+                            segmentMetrics.add(sm);
+                            distance += sm.length;
+                        }
+                    }
+                }
+            } else
+                segmentMetrics.add(null);
+        }
+        return segmentMetrics;
     }
 
-    @Override
-    public TableCellEditor getCellEditor(int row, int column) {
-      TableCellEditor editor = null;
-      if (column == 0)
-        editor = col1.get(new Integer(row));
-      else
-        editor = col2.get(new Integer(row));
-      if (editor == null)
-        return new DefaultCellEditor(new JTextField());
-      else
-        return editor;
+    private StopReference detectMinDistance(Node node, Vector<SegmentMetric> segmentMetrics,
+            boolean rhsPossible, boolean lhsPossible) {
+        if (node == null || node.getCoor() == null)
+            return null;
+
+        int minIndex = -1;
+        double position = -1.0;
+        double distance = 180.0;
+        double lat = node.getCoor().lat();
+        double lon = node.getCoor().lon();
+
+        int curIndex = -2;
+        double angleLat = 100.0;
+        double angleLon = 200.0;
+        Iterator<SegmentMetric> iter = segmentMetrics.iterator();
+        while (iter.hasNext()) {
+            curIndex += 2;
+            SegmentMetric sm = iter.next();
+
+            if (sm == null) {
+                angleLat = 100.0;
+                angleLon = 200.0;
+
+                continue;
+            }
+
+            double curPosition = (lat - sm.aLat) * sm.d1 + (lon - sm.aLon) * sm.d2;
+
+            if (curPosition < 0) {
+                if (angleLat <= 90.0) {
+                    double lastSegAngle = Math.atan2(angleLat - sm.aLat, angleLon - sm.aLon);
+                    double segAngle = Math.atan2(sm.d1, -sm.o1);
+                    double vertexAngle = Math.atan2(lat - sm.aLat, lon - sm.aLon);
+
+                    boolean vertexOnSeg = (vertexAngle == segAngle)
+                            || (vertexAngle == lastSegAngle);
+                    boolean vertexOnTheLeft = (!vertexOnSeg)
+                            && (((lastSegAngle > vertexAngle) && (vertexAngle > segAngle))
+                                    || ((vertexAngle > segAngle) && (segAngle > lastSegAngle))
+                                    || ((segAngle > lastSegAngle) && (lastSegAngle > vertexAngle)));
+
+                    double currentDistance = Math
+                            .sqrt((lat - sm.aLat) * (lat - sm.aLat) + (lon - sm.aLon)
+                                    * (lon - sm.aLon) * Math.cos(sm.aLat * Math.PI / 180.0)
+                                    * Math.cos(sm.aLat * Math.PI / 180.0));
+                    curPosition = vertexAngle - segAngle;
+                    if (vertexOnTheLeft)
+                        curPosition = -curPosition;
+                    if (curPosition < 0)
+                        curPosition += 2 * Math.PI;
+                    if ((Math.abs(currentDistance) < distance)
+                            && (((!vertexOnTheLeft) && (rhsPossible))
+                                    || ((vertexOnTheLeft) && (lhsPossible)) || (vertexOnSeg))) {
+                        distance = Math.abs(currentDistance);
+                        minIndex = curIndex - 1;
+                        position = curPosition;
+                    }
+                }
+                angleLat = 100.0;
+                angleLon = 200.0;
+            } else if (curPosition > sm.length) {
+                angleLat = sm.aLat;
+                angleLon = sm.aLon;
+            } else {
+                double currentDistance = (lat - sm.aLat) * sm.o1 + (lon - sm.aLon) * sm.o2;
+                if ((Math.abs(currentDistance) < distance)
+                        && (((currentDistance >= 0) && (rhsPossible))
+                                || ((currentDistance <= 0) && (lhsPossible)))) {
+                    distance = Math.abs(currentDistance);
+                    minIndex = curIndex;
+                    position = curPosition;
+                }
+
+                angleLat = 100.0;
+                angleLon = 200.0;
+            }
+        }
+
+        if (minIndex == -1)
+            return new StopReference(segmentMetrics.size() * 2, 0, 180.0, node.get("name"), "",
+                    node);
+
+        return new StopReference(minIndex, position, distance, node.get("name"), "", node);
     }
-
-    public void setCellEditor(int row, int column, TableCellEditor editor) {
-      if (column == 0)
-        col1.put(new Integer(row), editor);
-      else
-        col2.put(new Integer(row), editor);
-    }
-  };
-
-  private class StoplistTableModel extends DefaultTableModel {
-
-    public Vector<Node> nodes = new Vector<Node>();
-
-    @Override
-    public boolean isCellEditable(int row, int column) {
-      if (column != STOPLIST_ROLE_COLUMN)
-        return false;
-      return true;
-    }
-
-    @Override
-    public void addRow(Object[] obj) {
-      throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void insertRow(int insPos, Object[] obj) {
-      throw new UnsupportedOperationException();
-    }
-
-    public void addRow(Node node, String role, double distance) {
-      insertRow(-1, node, role, distance);
-    }
-
-    public void insertRow(int insPos, Node node, String role, double distance) {
-      String[] buf = { "", "", "", "" };
-      String curName = node.get("name");
-      if (curName != null)
-      {
-        buf[0] = curName;
-      }
-      else
-      {
-        buf[0] = tr("[ID] {0}", (new Long(node.getId())).toString());
-      }
-      String curRef = node.get("ref");
-      if (curRef != null)
-      {
-        buf[1] = curRef;
-      }
-      buf[STOPLIST_ROLE_COLUMN] = role;
-      buf[3] = Double.toString(((double)(int)(distance*40000/360.0*100))/100);
-
-      if (insPos == -1)
-      {
-        nodes.addElement(node);
-        super.addRow(buf);
-      }
-      else
-      {
-        nodes.insertElementAt(node, insPos);
-        super.insertRow(insPos, buf);
-      }
-    }
-
-    public void clear()
-    {
-      nodes.clear();
-      super.setRowCount(0);
-    }
-  };
-
-  private class StoplistTableModelListener implements TableModelListener {
-    @Override
-    public void tableChanged(TableModelEvent e)
-    {
-      if (e.getType() == TableModelEvent.UPDATE)
-      {
-        rebuildNodes();
-      }
-    }
-  };
-
-  private class SegmentMetric {
-    public double aLat, aLon;
-    public double length;
-    public double d1, d2, o1, o2;
-    public double distance;
-
-    public SegmentMetric(double fromLat, double fromLon, double toLat, double toLon,
-                         double distance) {
-      this.distance = distance;
-
-      aLat = fromLat;
-      aLon = fromLon;
-
-      //Compute length and direction
-      //length is in units of latitude degrees
-      d1 = toLat - fromLat;
-      d2 = (toLon - fromLon) * Math.cos(fromLat * Math.PI/180.0);
-      length = Math.sqrt(d1*d1 + d2*d2);
-
-      //Normalise direction
-      d1 = d1 / length;
-      d2 = d2 / length;
-
-      //Compute orthogonal direction (right hand size is positive)
-      o1 = - d2;
-      o2 = d1;
-
-      //Prepare lon direction to reduce the number of necessary multiplications
-      d2 = d2 * Math.cos(fromLat * Math.PI/180.0);
-      o2 = o2 * Math.cos(fromLat * Math.PI/180.0);
-    }
-  };
-
-  private class StopReference implements Comparable< StopReference > {
-    public int index = 0;
-    public double pos = 0;
-    public double distance = 0;
-    public String name = "";
-    public String role = "";
-    public Node node;
-
-    public StopReference(int inIndex, double inPos, double inDistance,
-             String inName, String inRole, Node inNode) {
-      index = inIndex;
-      pos = inPos;
-      distance = inDistance;
-      name = inName;
-      role = inRole;
-      node = inNode;
-    }
-
-    @Override
-    public int compareTo(StopReference sr) {
-      if (this.index < sr.index)
-    return -1;
-      if (this.index > sr.index)
-    return 1;
-      if (this.pos < sr.pos)
-    return -1;
-      if (this.pos > sr.pos)
-    return 1;
-      return 0;
-    }
-  };
-
-  private static JDialog jDialog = null;
-  private static JTabbedPane tabbedPane = null;
-  private static DefaultListModel<RouteReference> relsListModel = null;
-  private static TagTableModel requiredTagsData = null;
-  private static CustomCellEditorTable requiredTagsTable = null;
-  private static TagTableModel commonTagsData = null;
-  private static CustomCellEditorTable commonTagsTable = null;
-  private static TagTableModel otherTagsData = null;
-  private static TreeSet< String > tagBlacklist = null;
-  private static CustomCellEditorTable otherTagsTable = null;
-  private static ItineraryTableModel itineraryData = null;
-  private static JTable itineraryTable = null;
-  private static StoplistTableModel stoplistData = null;
-  private static JTable stoplistTable = null;
-  private static JList<RouteReference> relsList = null;
-  private static JCheckBox cbRight = null;
-  private static JCheckBox cbLeft = null;
-  private static JTextField tfSuggestStopsLimit = null;
-  private static Relation currentRoute = null;
-  private static Vector< SegmentMetric > segmentMetrics = null;
-  private static Vector< RelationMember > markedWays = new Vector< RelationMember >();
-  private static Vector< RelationMember > markedNodes = new Vector< RelationMember >();
-
-  public RoutePatternAction() {
-    super(tr("Route patterns ..."), null,
-      tr("Edit Route patterns for public transport"), null, false);
-    putValue("toolbar", "publictransport/routepattern");
-    Main.toolbar.register(this);
-  }
-
-  @Override
-public void actionPerformed(ActionEvent event) {
-    Frame frame = JOptionPane.getFrameForComponent(Main.parent);
-    DataSet mainDataSet = Main.main.getCurrentDataSet();
-
-    if (jDialog == null)
-    {
-      jDialog = new JDialog(frame, tr("Route Patterns"), false);
-      tabbedPane = new JTabbedPane();
-      JPanel tabOverview = new JPanel();
-      tabbedPane.addTab(tr("Overview"), tabOverview);
-      JPanel tabTags = new JPanel();
-      tabbedPane.addTab(tr("Tags"), tabTags);
-      JPanel tabItinerary = new JPanel();
-      tabbedPane.addTab(tr("Itinerary"), tabItinerary);
-      JPanel tabStoplist = new JPanel();
-      tabbedPane.addTab(tr("Stops"), tabStoplist);
-      JPanel tabMeta = new JPanel();
-      tabbedPane.addTab(tr("Meta"), tabMeta);
-      tabbedPane.setEnabledAt(0, true);
-      tabbedPane.setEnabledAt(1, false);
-      tabbedPane.setEnabledAt(2, false);
-      tabbedPane.setEnabledAt(3, false);
-      tabbedPane.setEnabledAt(4, false);
-      jDialog.add(tabbedPane);
-
-      //Overview Tab
-      Container contentPane = tabOverview;
-      GridBagLayout gridbag = new GridBagLayout();
-      GridBagConstraints layoutCons = new GridBagConstraints();
-      contentPane.setLayout(gridbag);
-
-      JLabel headline = new JLabel(tr("Existing route patterns:"));
-
-      layoutCons.gridx = 0;
-      layoutCons.gridy = 0;
-      layoutCons.gridwidth = 3;
-      layoutCons.weightx = 0.0;
-      layoutCons.weighty = 0.0;
-      layoutCons.fill = GridBagConstraints.BOTH;
-      gridbag.setConstraints(headline, layoutCons);
-      contentPane.add(headline);
-
-      relsListModel = new DefaultListModel<>();
-      relsList = new JList<>(relsListModel);
-      JScrollPane rpListSP = new JScrollPane(relsList);
-      String[] data = {"1", "2", "3", "4", "5", "6"};
-      relsListModel.copyInto(data);
-      relsList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
-      relsList.addListSelectionListener(new RoutesLSL(this));
-
-      layoutCons.gridx = 0;
-      layoutCons.gridy = 1;
-      layoutCons.gridwidth = 3;
-      layoutCons.weightx = 1.0;
-      layoutCons.weighty = 1.0;
-      layoutCons.fill = GridBagConstraints.BOTH;
-      gridbag.setConstraints(rpListSP, layoutCons);
-      contentPane.add(rpListSP);
-
-      JButton bRefresh = new JButton(tr("Refresh"));
-      bRefresh.setActionCommand("routePattern.refresh");
-      bRefresh.addActionListener(this);
-
-      layoutCons.gridx = 0;
-      layoutCons.gridy = 2;
-      layoutCons.gridwidth = 1;
-      layoutCons.gridheight = 2;
-      layoutCons.weightx = 1.0;
-      layoutCons.weighty = 0.0;
-      layoutCons.fill = GridBagConstraints.BOTH;
-      gridbag.setConstraints(bRefresh, layoutCons);
-      contentPane.add(bRefresh);
-
-      JButton bNew = new JButton(tr("New"));
-      bNew.setActionCommand("routePattern.overviewNew");
-      bNew.addActionListener(this);
-
-      layoutCons.gridx = 1;
-      layoutCons.gridy = 2;
-      layoutCons.gridwidth = 1;
-      layoutCons.gridheight = 1;
-      layoutCons.weightx = 1.0;
-      layoutCons.weighty = 0.0;
-      layoutCons.fill = GridBagConstraints.BOTH;
-      gridbag.setConstraints(bNew, layoutCons);
-      contentPane.add(bNew);
-
-      JButton bDelete = new JButton(tr("Delete"));
-      bDelete.setActionCommand("routePattern.overviewDelete");
-      bDelete.addActionListener(this);
-
-      layoutCons.gridx = 1;
-      layoutCons.gridy = 3;
-      layoutCons.gridwidth = 1;
-      layoutCons.gridheight = 1;
-      layoutCons.weightx = 1.0;
-      layoutCons.weighty = 0.0;
-      layoutCons.fill = GridBagConstraints.BOTH;
-      gridbag.setConstraints(bDelete, layoutCons);
-      contentPane.add(bDelete);
-
-      JButton bDuplicate = new JButton(tr("Duplicate"));
-      bDuplicate.setActionCommand("routePattern.overviewDuplicate");
-      bDuplicate.addActionListener(this);
-
-      layoutCons.gridx = 2;
-      layoutCons.gridy = 2;
-      layoutCons.gridwidth = 1;
-      layoutCons.gridheight = 1;
-      layoutCons.weightx = 1.0;
-      layoutCons.weighty = 0.0;
-      layoutCons.fill = GridBagConstraints.BOTH;
-      gridbag.setConstraints(bDuplicate, layoutCons);
-      contentPane.add(bDuplicate);
-
-      JButton bReflect = new JButton(tr("Reflect"));
-      bReflect.setActionCommand("routePattern.overviewReflect");
-      bReflect.addActionListener(this);
-
-      layoutCons.gridx = 2;
-      layoutCons.gridy = 3;
-      layoutCons.gridwidth = 1;
-      layoutCons.gridheight = 1;
-      layoutCons.weightx = 1.0;
-      layoutCons.weighty = 0.0;
-      layoutCons.fill = GridBagConstraints.BOTH;
-      gridbag.setConstraints(bReflect, layoutCons);
-      contentPane.add(bReflect);
-
-      //Tags Tab
-      /*Container*/ contentPane = tabTags;
-      /*GridBagLayout*/ gridbag = new GridBagLayout();
-      /*GridBagConstraints*/ layoutCons = new GridBagConstraints();
-      contentPane.setLayout(gridbag);
-
-      /*JLabel*/ headline = new JLabel(tr("Required tags:"));
-
-      layoutCons.gridx = 0;
-      layoutCons.gridy = 0;
-      layoutCons.weightx = 0.0;
-      layoutCons.weighty = 0.0;
-      layoutCons.fill = GridBagConstraints.BOTH;
-      gridbag.setConstraints(headline, layoutCons);
-      contentPane.add(headline);
-
-      requiredTagsTable = new CustomCellEditorTable();
-      requiredTagsData = new TagTableModel(true);
-      requiredTagsData.addColumn(tr("Key"));
-      requiredTagsData.addColumn(tr("Value"));
-      tagBlacklist = new TreeSet< String >();
-      Vector< String > rowContent = new Vector< String >();
-      /* TODO: keys and values should also be translated using TransText class */
-      rowContent.add("type");
-      tagBlacklist.add("type");
-      rowContent.add("route");
-      requiredTagsData.addRow(rowContent);
-      JComboBox<String> comboBox = new JComboBox<>();
-      comboBox.addItem("route");
-      requiredTagsTable.setCellEditor(0, 1, new DefaultCellEditor(comboBox));
-      rowContent = new Vector< String >();
-      rowContent.add(0, "route");
-      tagBlacklist.add("route");
-      rowContent.add(1, "bus");
-      requiredTagsData.addRow(rowContent);
-      /*JComboBox*/ comboBox = new JComboBox<>();
-      comboBox.addItem("bus");
-      comboBox.addItem("trolleybus");
-      comboBox.addItem("tram");
-      comboBox.addItem("light_rail");
-      comboBox.addItem("subway");
-      comboBox.addItem("rail");
-      requiredTagsTable.setCellEditor(1, 1, new DefaultCellEditor(comboBox));
-      rowContent = new Vector< String >();
-      rowContent.add(0, "ref");
-      tagBlacklist.add("ref");
-      rowContent.add(1, "");
-      requiredTagsData.addRow(rowContent);
-      rowContent = new Vector< String >();
-      rowContent.add(0, "to");
-      tagBlacklist.add("to");
-      rowContent.add(1, "");
-      requiredTagsData.addRow(rowContent);
-      rowContent = new Vector< String >();
-      rowContent.add(0, "network");
-      tagBlacklist.add("network");
-      rowContent.add(1, "");
-      requiredTagsData.addRow(rowContent);
-      requiredTagsTable.setModel(requiredTagsData);
-      JScrollPane tableSP = new JScrollPane(requiredTagsTable);
-      requiredTagsData.addTableModelListener(requiredTagsData);
-
-      layoutCons.gridx = 0;
-      layoutCons.gridy = 1;
-      layoutCons.weightx = 1.0;
-      layoutCons.weighty = 0.25;
-      layoutCons.fill = GridBagConstraints.BOTH;
-      gridbag.setConstraints(tableSP, layoutCons);
-      Dimension preferredSize = tableSP.getPreferredSize();
-      preferredSize.setSize(tableSP.getPreferredSize().getWidth(), tableSP.getPreferredSize().getHeight()/4.0);
-      tableSP.setPreferredSize(preferredSize);
-      contentPane.add(tableSP);
-
-      headline = new JLabel(tr("Common tags:"));
-
-      layoutCons.gridx = 0;
-      layoutCons.gridy = 2;
-      layoutCons.weightx = 0.0;
-      layoutCons.weighty = 0.0;
-      layoutCons.fill = GridBagConstraints.BOTH;
-      gridbag.setConstraints(headline, layoutCons);
-      contentPane.add(headline);
-
-      commonTagsTable = new CustomCellEditorTable();
-      commonTagsData = new TagTableModel(true);
-      commonTagsData.addColumn(tr("Key"));
-      commonTagsData.addColumn(tr("Value"));
-      rowContent = new Vector< String >();
-      rowContent.add(0, "loc_ref");
-      tagBlacklist.add("loc_ref");
-      rowContent.add(1, "");
-      commonTagsData.addRow(rowContent);
-      rowContent = new Vector< String >();
-      rowContent.add(0, "direction");
-      tagBlacklist.add("direction");
-      rowContent.add(1, "");
-      commonTagsData.addRow(rowContent);
-      rowContent = new Vector< String >();
-      rowContent.add(0, "from");
-      tagBlacklist.add("from");
-      rowContent.add(1, "");
-      commonTagsData.addRow(rowContent);
-      rowContent = new Vector< String >();
-      rowContent.add(0, "operator");
-      tagBlacklist.add("operator");
-      rowContent.add(1, "");
-      commonTagsData.addRow(rowContent);
-      rowContent = new Vector< String >();
-      rowContent.add(0, "color");
-      tagBlacklist.add("color");
-      rowContent.add(1, "");
-      commonTagsData.addRow(rowContent);
-      rowContent = new Vector< String >();
-      rowContent.add(0, "name");
-      tagBlacklist.add("name");
-      rowContent.add(1, "");
-      commonTagsData.addRow(rowContent);
-      commonTagsTable.setModel(commonTagsData);
-      /*JScrollPane*/ tableSP = new JScrollPane(commonTagsTable);
-      commonTagsData.addTableModelListener(commonTagsData);
-
-      layoutCons.gridx = 0;
-      layoutCons.gridy = 3;
-      layoutCons.weightx = 1.0;
-      layoutCons.weighty = 0.25;
-      layoutCons.fill = GridBagConstraints.BOTH;
-      gridbag.setConstraints(tableSP, layoutCons);
-      /*Dimension*/ preferredSize = tableSP.getPreferredSize();
-      preferredSize.setSize(tableSP.getPreferredSize().getWidth(), tableSP.getPreferredSize().getHeight()/4.0);
-      tableSP.setPreferredSize(preferredSize);
-      contentPane.add(tableSP);
-
-      headline = new JLabel(tr("Additional tags:"));
-
-      layoutCons.gridx = 0;
-      layoutCons.gridy = 4;
-      layoutCons.weightx = 0.0;
-      layoutCons.weighty = 0.0;
-      layoutCons.fill = GridBagConstraints.BOTH;
-      gridbag.setConstraints(headline, layoutCons);
-      contentPane.add(headline);
-
-      otherTagsTable = new CustomCellEditorTable();
-      otherTagsData = new TagTableModel(false);
-      otherTagsData.addColumn(tr("Key"));
-      otherTagsData.addColumn(tr("Value"));
-      otherTagsTable.setModel(otherTagsData);
-      /*JScrollPane*/ tableSP = new JScrollPane(otherTagsTable);
-      otherTagsData.addTableModelListener(otherTagsData);
-
-      layoutCons.gridx = 0;
-      layoutCons.gridy = 5;
-      layoutCons.weightx = 1.0;
-      layoutCons.weighty = 1.0;
-      layoutCons.fill = GridBagConstraints.BOTH;
-      gridbag.setConstraints(tableSP, layoutCons);
-      /*Dimension*/ preferredSize = tableSP.getPreferredSize();
-      preferredSize.setSize(tableSP.getPreferredSize().getWidth(), tableSP.getPreferredSize().getHeight()/2.0);
-      tableSP.setPreferredSize(preferredSize);
-      contentPane.add(tableSP);
-
-      JButton bAddTag = new JButton(tr("Add a new Tag"));
-      bAddTag.setActionCommand("routePattern.tagAddTag");
-      bAddTag.addActionListener(this);
-
-      layoutCons.gridx = 0;
-      layoutCons.gridy = 6;
-      layoutCons.gridwidth = 1;
-      layoutCons.weightx = 1.0;
-      layoutCons.weighty = 0.0;
-      layoutCons.fill = GridBagConstraints.BOTH;
-      gridbag.setConstraints(bAddTag, layoutCons);
-      contentPane.add(bAddTag);
-
-      //Itinerary Tab
-      contentPane = tabItinerary;
-      gridbag = new GridBagLayout();
-      layoutCons = new GridBagConstraints();
-      contentPane.setLayout(gridbag);
-
-      itineraryTable = new JTable();
-      itineraryData = new ItineraryTableModel();
-      itineraryData.addColumn(tr("Name/Id"));
-      itineraryData.addColumn(tr("Role"));
-      itineraryTable.setModel(itineraryData);
-      /*JScrollPane*/ tableSP = new JScrollPane(itineraryTable);
-      /*JComboBox*/ comboBox = new JComboBox<>();
-      comboBox.addItem("");
-      comboBox.addItem("forward");
-      comboBox.addItem("backward");
-      itineraryTable.getColumnModel().getColumn(1)
-      .setCellEditor(new DefaultCellEditor(comboBox));
-      itineraryData.addTableModelListener(itineraryData);
-
-      layoutCons.gridx = 0;
-      layoutCons.gridy = 0;
-      layoutCons.gridwidth = 4;
-      layoutCons.weightx = 1.0;
-      layoutCons.weighty = 1.0;
-      layoutCons.fill = GridBagConstraints.BOTH;
-      gridbag.setConstraints(tableSP, layoutCons);
-      contentPane.add(tableSP);
-
-      JButton bFind = new JButton(tr("Find"));
-      bFind.setActionCommand("routePattern.itineraryFind");
-      bFind.addActionListener(this);
-
-      layoutCons.gridx = 0;
-      layoutCons.gridy = 1;
-      layoutCons.gridwidth = 1;
-      layoutCons.weightx = 1.0;
-      layoutCons.weighty = 0.0;
-      layoutCons.fill = GridBagConstraints.BOTH;
-      gridbag.setConstraints(bFind, layoutCons);
-      contentPane.add(bFind);
-
-      JButton bShow = new JButton(tr("Show"));
-      bShow.setActionCommand("routePattern.itineraryShow");
-      bShow.addActionListener(this);
-
-      layoutCons.gridx = 0;
-      layoutCons.gridy = 2;
-      layoutCons.gridwidth = 1;
-      layoutCons.weightx = 1.0;
-      layoutCons.weighty = 0.0;
-      layoutCons.fill = GridBagConstraints.BOTH;
-      gridbag.setConstraints(bShow, layoutCons);
-      contentPane.add(bShow);
-
-      JButton bMark = new JButton(tr("Mark"));
-      bMark.setActionCommand("routePattern.itineraryMark");
-      bMark.addActionListener(this);
-
-      layoutCons.gridx = 1;
-      layoutCons.gridy = 1;
-      layoutCons.gridheight = 2;
-      layoutCons.gridwidth = 1;
-      layoutCons.weightx = 1.0;
-      layoutCons.weighty = 0.0;
-      layoutCons.fill = GridBagConstraints.BOTH;
-      gridbag.setConstraints(bMark, layoutCons);
-      contentPane.add(bMark);
-
-      JButton bAdd = new JButton(tr("Add"));
-      bAdd.setActionCommand("routePattern.itineraryAdd");
-      bAdd.addActionListener(this);
-
-      layoutCons.gridx = 2;
-      layoutCons.gridy = 1;
-      layoutCons.gridheight = 1;
-      layoutCons.gridwidth = 1;
-      layoutCons.weightx = 1.0;
-      layoutCons.weighty = 0.0;
-      layoutCons.fill = GridBagConstraints.BOTH;
-      gridbag.setConstraints(bAdd, layoutCons);
-      contentPane.add(bAdd);
-
-      /*JButton*/ bDelete = new JButton(tr("Delete"));
-      bDelete.setActionCommand("routePattern.itineraryDelete");
-      bDelete.addActionListener(this);
-
-      layoutCons.gridx = 2;
-      layoutCons.gridy = 2;
-      layoutCons.gridwidth = 1;
-      layoutCons.weightx = 1.0;
-      layoutCons.weighty = 0.0;
-      layoutCons.fill = GridBagConstraints.BOTH;
-      gridbag.setConstraints(bDelete, layoutCons);
-      contentPane.add(bDelete);
-
-      JButton bSort = new JButton(tr("Sort"));
-      bSort.setActionCommand("routePattern.itinerarySort");
-      bSort.addActionListener(this);
-
-      layoutCons.gridx = 3;
-      layoutCons.gridy = 1;
-      layoutCons.gridwidth = 1;
-      layoutCons.weightx = 1.0;
-      layoutCons.weighty = 0.0;
-      layoutCons.fill = GridBagConstraints.BOTH;
-      gridbag.setConstraints(bSort, layoutCons);
-      contentPane.add(bSort);
-
-      /*JButton*/ bReflect = new JButton(tr("Reflect"));
-      bReflect.setActionCommand("routePattern.itineraryReflect");
-      bReflect.addActionListener(this);
-
-      layoutCons.gridx = 3;
-      layoutCons.gridy = 2;
-      layoutCons.gridwidth = 1;
-      layoutCons.weightx = 1.0;
-      layoutCons.weighty = 0.0;
-      layoutCons.fill = GridBagConstraints.BOTH;
-      gridbag.setConstraints(bReflect, layoutCons);
-      contentPane.add(bReflect);
-
-      //Stoplist Tab
-      contentPane = tabStoplist;
-      gridbag = new GridBagLayout();
-      layoutCons = new GridBagConstraints();
-      contentPane.setLayout(gridbag);
-
-      stoplistTable = new JTable();
-      stoplistData = new StoplistTableModel();
-      stoplistData.addColumn(tr("Name/Id"));
-      stoplistData.addColumn(tr("Ref"));
-      stoplistData.addColumn(tr("Role"));
-      stoplistData.addColumn(tr("km"));
-      stoplistTable.setModel(stoplistData);
-      /*JScrollPane*/ tableSP = new JScrollPane(stoplistTable);
-      /*JComboBox*/ comboBox = new JComboBox<>();
-      comboBox.addItem("");
-      comboBox.addItem("forward_stop");
-      comboBox.addItem("backward_stop");
-      stoplistTable.getColumnModel().getColumn(STOPLIST_ROLE_COLUMN)
-                   .setCellEditor(new DefaultCellEditor(comboBox));
-      stoplistData.addTableModelListener(new StoplistTableModelListener());
-
-      layoutCons.gridx = 0;
-      layoutCons.gridy = 0;
-      layoutCons.gridwidth = 4;
-      layoutCons.weightx = 1.0;
-      layoutCons.weighty = 1.0;
-      layoutCons.fill = GridBagConstraints.BOTH;
-      gridbag.setConstraints(tableSP, layoutCons);
-      contentPane.add(tableSP);
-
-      /*JButton*/ bFind = new JButton(tr("Find"));
-      bFind.setActionCommand("routePattern.stoplistFind");
-      bFind.addActionListener(this);
-
-      layoutCons.gridx = 0;
-      layoutCons.gridy = 1;
-      layoutCons.gridwidth = 1;
-      layoutCons.weightx = 1.0;
-      layoutCons.weighty = 0.0;
-      layoutCons.fill = GridBagConstraints.BOTH;
-      gridbag.setConstraints(bFind, layoutCons);
-      contentPane.add(bFind);
-
-      /*JButton*/ bShow = new JButton(tr("Show"));
-      bShow.setActionCommand("routePattern.stoplistShow");
-      bShow.addActionListener(this);
-
-      layoutCons.gridx = 0;
-      layoutCons.gridy = 2;
-      layoutCons.gridwidth = 1;
-      layoutCons.weightx = 1.0;
-      layoutCons.weighty = 0.0;
-      layoutCons.fill = GridBagConstraints.BOTH;
-      gridbag.setConstraints(bShow, layoutCons);
-      contentPane.add(bShow);
-
-      /*JButton*/ bMark = new JButton(tr("Mark"));
-      bMark.setActionCommand("routePattern.stoplistMark");
-      bMark.addActionListener(this);
-
-      layoutCons.gridx = 1;
-      layoutCons.gridy = 1;
-      layoutCons.gridheight = 2;
-      layoutCons.gridwidth = 1;
-      layoutCons.weightx = 1.0;
-      layoutCons.weighty = 0.0;
-      layoutCons.fill = GridBagConstraints.BOTH;
-      gridbag.setConstraints(bMark, layoutCons);
-      contentPane.add(bMark);
-
-      /*JButton*/ bAdd = new JButton(tr("Add"));
-      bAdd.setActionCommand("routePattern.stoplistAdd");
-      bAdd.addActionListener(this);
-
-      layoutCons.gridx = 2;
-      layoutCons.gridy = 1;
-      layoutCons.gridheight = 1;
-      layoutCons.gridwidth = 1;
-      layoutCons.weightx = 1.0;
-      layoutCons.weighty = 0.0;
-      layoutCons.fill = GridBagConstraints.BOTH;
-      gridbag.setConstraints(bAdd, layoutCons);
-      contentPane.add(bAdd);
-
-      /*JButton*/ bDelete = new JButton(tr("Delete"));
-      bDelete.setActionCommand("routePattern.stoplistDelete");
-      bDelete.addActionListener(this);
-
-      layoutCons.gridx = 2;
-      layoutCons.gridy = 2;
-      layoutCons.gridwidth = 1;
-      layoutCons.weightx = 1.0;
-      layoutCons.weighty = 0.0;
-      layoutCons.fill = GridBagConstraints.BOTH;
-      gridbag.setConstraints(bDelete, layoutCons);
-      contentPane.add(bDelete);
-
-      /*JButton*/ bSort = new JButton(tr("Sort"));
-      bSort.setActionCommand("routePattern.stoplistSort");
-      bSort.addActionListener(this);
-
-      layoutCons.gridx = 3;
-      layoutCons.gridy = 1;
-      layoutCons.gridwidth = 1;
-      layoutCons.weightx = 1.0;
-      layoutCons.weighty = 0.0;
-      layoutCons.fill = GridBagConstraints.BOTH;
-      gridbag.setConstraints(bSort, layoutCons);
-      contentPane.add(bSort);
-
-      /*JButton*/ bReflect = new JButton(tr("Reflect"));
-      bReflect.setActionCommand("routePattern.stoplistReflect");
-      bReflect.addActionListener(this);
-
-      layoutCons.gridx = 3;
-      layoutCons.gridy = 2;
-      layoutCons.gridwidth = 1;
-      layoutCons.weightx = 1.0;
-      layoutCons.weighty = 0.0;
-      layoutCons.fill = GridBagConstraints.BOTH;
-      gridbag.setConstraints(bReflect, layoutCons);
-      contentPane.add(bReflect);
-
-      //Meta Tab
-      contentPane = tabMeta;
-      gridbag = new GridBagLayout();
-      layoutCons = new GridBagConstraints();
-      contentPane.setLayout(gridbag);
-
-      JLabel rightleft = new JLabel(tr("Stops are possible on the"));
-
-      layoutCons.gridx = 0;
-      layoutCons.gridy = 1;
-      layoutCons.gridwidth = 2;
-      layoutCons.weightx = 0.0;
-      layoutCons.weighty = 0.0;
-      layoutCons.fill = GridBagConstraints.BOTH;
-      gridbag.setConstraints(rightleft, layoutCons);
-      contentPane.add(rightleft);
-
-      cbRight = new JCheckBox(tr("right hand side"), true);
-
-      layoutCons.gridx = 0;
-      layoutCons.gridy = 2;
-      layoutCons.gridwidth = 2;
-      layoutCons.weightx = 0.0;
-      layoutCons.weighty = 0.0;
-      layoutCons.fill = GridBagConstraints.BOTH;
-      gridbag.setConstraints(cbRight, layoutCons);
-      contentPane.add(cbRight);
-
-      cbLeft = new JCheckBox(tr("left hand side"), false);
-
-      layoutCons.gridx = 0;
-      layoutCons.gridy = 3;
-      layoutCons.gridwidth = 2;
-      layoutCons.weightx = 0.0;
-      layoutCons.weighty = 0.0;
-      layoutCons.fill = GridBagConstraints.BOTH;
-      gridbag.setConstraints(cbLeft, layoutCons);
-      contentPane.add(cbLeft);
-
-      JLabel maxdist = new JLabel(tr("Maximum distance from route"));
-
-      layoutCons.gridx = 0;
-      layoutCons.gridy = 4;
-      layoutCons.gridwidth = 2;
-      layoutCons.weightx = 0.0;
-      layoutCons.weighty = 0.0;
-      layoutCons.fill = GridBagConstraints.BOTH;
-      gridbag.setConstraints(maxdist, layoutCons);
-      contentPane.add(maxdist);
-
-      tfSuggestStopsLimit = new JTextField("20", 4);
-
-      layoutCons.gridx = 0;
-      layoutCons.gridy = 5;
-      layoutCons.gridwidth = 1;
-      layoutCons.weightx = 0.0;
-      layoutCons.weighty = 0.0;
-      layoutCons.fill = GridBagConstraints.BOTH;
-      gridbag.setConstraints(tfSuggestStopsLimit, layoutCons);
-      contentPane.add(tfSuggestStopsLimit);
-
-      JLabel meters = new JLabel(tr("meters"));
-
-      layoutCons.gridx = 1;
-      layoutCons.gridy = 5;
-      layoutCons.gridwidth = 1;
-      layoutCons.weightx = 0.0;
-      layoutCons.weighty = 0.0;
-      layoutCons.fill = GridBagConstraints.BOTH;
-      gridbag.setConstraints(meters, layoutCons);
-      contentPane.add(meters);
-
-      JButton bSuggestStops = new JButton(tr("Suggest Stops"));
-      bSuggestStops.setActionCommand("routePattern.metaSuggestStops");
-      bSuggestStops.addActionListener(this);
-
-      layoutCons.gridx = 0;
-      layoutCons.gridy = 6;
-      layoutCons.gridwidth = 3;
-      layoutCons.weightx = 1.0;
-      layoutCons.weighty = 0.0;
-      layoutCons.fill = GridBagConstraints.BOTH;
-      gridbag.setConstraints(bSuggestStops, layoutCons);
-      contentPane.add(bSuggestStops);
-
-      jDialog.pack();
-    }
-
-    if ("routePattern.refresh".equals(event.getActionCommand()))
-    {
-      refreshData();
-    }
-    else if ("routePattern.overviewNew".equals(event.getActionCommand()))
-    {
-      currentRoute = new Relation();
-      currentRoute.put("type", "route");
-      currentRoute.put("route", "bus");
-      mainDataSet.addPrimitive(currentRoute);
-
-      refreshData();
-
-      for (int i = 0; i < relsListModel.size(); ++i)
-      {
-    if (currentRoute == relsListModel.elementAt(i).route)
-      relsList.setSelectedIndex(i);
-      }
-    }
-    else if ("routePattern.overviewDuplicate".equals(event.getActionCommand()))
-    {
-      currentRoute = new Relation(currentRoute, true);
-      currentRoute.put("type", "route");
-      currentRoute.put("route", "bus");
-      mainDataSet.addPrimitive(currentRoute);
-
-      refreshData();
-
-      for (int i = 0; i < relsListModel.size(); ++i)
-      {
-    if (currentRoute == relsListModel.elementAt(i).route)
-      relsList.setSelectedIndex(i);
-      }
-    }
-    else if ("routePattern.overviewReflect".equals(event.getActionCommand()))
-    {
-      currentRoute.setModified(true);
-      String tag_from = currentRoute.get("from");
-      String tag_to = currentRoute.get("to");
-      currentRoute.put("from", tag_to);
-      currentRoute.put("to", tag_from);
-
-      Vector< RelationMember > itemsToReflect = new Vector< RelationMember >();
-      Vector< RelationMember > otherItems = new Vector< RelationMember >();
-
-      // Temp
-      Node firstNode = null;
-      //Node lastNode = null;
-
-      for (int i = 0; i < currentRoute.getMembersCount(); ++i)
-      {
-        RelationMember item = currentRoute.getMember(i);
-
-        if (item.isWay())
-        {
-          String role = item.getRole();
-          if ("backward".equals(role))
-            role = "forward";
-          else if ("forward".equals(role))
-            role = "backward";
-          else
-            role = "backward";
-
-          itemsToReflect.add(new RelationMember(role, item.getWay()));
-
-          // Temp
-          if (firstNode == null)
-          {
-              firstNode = item.getWay().getNode(0);
-          }
-          //lastNode = item.getWay().getNode(item.getWay().getNodesCount() - 1);
-        }
-        else if (item.isNode())
-          itemsToReflect.add(item);
-        else
-          otherItems.add(item);
-      }
-
-      currentRoute.setMembers(null);
-      for (int i = itemsToReflect.size()-1; i >= 0; --i)
-        currentRoute.addMember(itemsToReflect.elementAt(i));
-      for (int i = 0; i < otherItems.size(); ++i)
-        currentRoute.addMember(otherItems.elementAt(i));
-
-      refreshData();
-
-      for (int i = 0; i < relsListModel.size(); ++i)
-      {
-        if (currentRoute == relsListModel.elementAt(i).route)
-          relsList.setSelectedIndex(i);
-      }
-
-      // Temp
-/*      if (firstNode != null)
-      {
-        Vector< AStarAlgorithm.Edge > path = new PublicTransportAStar(firstNode, lastNode).shortestPath();
-        Iterator< AStarAlgorithm.Edge > iter = path.iterator();
-        while (iter.hasNext())
-        {
-          PublicTransportAStar.PartialWayEdge edge = (PublicTransportAStar.PartialWayEdge)iter.next();
-          System.out.print(edge.way.getUniqueId());
-          System.out.print("\t");
-          System.out.print(edge.beginIndex);
-          System.out.print("\t");
-          System.out.print(edge.endIndex);
-          System.out.print("\n");
-        }
-      }*/
-    }
-    else if ("routePattern.overviewDelete".equals(event.getActionCommand()))
-    {
-      DeleteAction.deleteRelation(Main.main.getEditLayer(), currentRoute);
-
-      currentRoute = null;
-      tabbedPane.setEnabledAt(1, false);
-      tabbedPane.setEnabledAt(2, false);
-      tabbedPane.setEnabledAt(3, false);
-      tabbedPane.setEnabledAt(4, false);
-
-      refreshData();
-    }
-    else if ("routePattern.tagAddTag".equals(event.getActionCommand()))
-    {
-      Vector< String > rowContent = new Vector< String >();
-      rowContent.add("");
-      rowContent.add("");
-      otherTagsData.addRow(rowContent);
-    }
-    else if ("routePattern.itineraryFind".equals(event.getActionCommand()))
-    {
-      if (mainDataSet == null)
-        return;
-
-      itineraryTable.clearSelection();
-
-      for (int i = 0; i < itineraryData.getRowCount(); ++i)
-      {
-        if ((itineraryData.ways.elementAt(i) != null) &&
-            (mainDataSet.isSelected(itineraryData.ways.elementAt(i))))
-            itineraryTable.addRowSelectionInterval(i, i);
-      }
-    }
-    else if ("routePattern.itineraryShow".equals(event.getActionCommand()))
-    {
-      BoundingXYVisitor box = new BoundingXYVisitor();
-      if (itineraryTable.getSelectedRowCount() > 0)
-      {
-        for (int i = 0; i < itineraryData.getRowCount(); ++i)
-        {
-          if ((itineraryTable.isRowSelected(i)) && (itineraryData.ways.elementAt(i) != null))
-          {
-            itineraryData.ways.elementAt(i).accept(box);
-          }
-        }
-      }
-      else
-      {
-        for (int i = 0; i < itineraryData.getRowCount(); ++i)
-        {
-          if (itineraryData.ways.elementAt(i) != null)
-          {
-            itineraryData.ways.elementAt(i).accept(box);
-          }
-        }
-      }
-      if (box.getBounds() == null)
-        return;
-      box.enlargeBoundingBox();
-      Main.map.mapView.zoomTo(box);
-    }
-    else if ("routePattern.itineraryMark".equals(event.getActionCommand()))
-    {
-      OsmPrimitive[] osmp = { null };
-      Main.main.getCurrentDataSet().setSelected(osmp);
-      markedWays.clear();
-      if (itineraryTable.getSelectedRowCount() > 0)
-      {
-        for (int i = 0; i < itineraryData.getRowCount(); ++i)
-        {
-          if ((itineraryTable.isRowSelected(i)) && (itineraryData.ways.elementAt(i) != null))
-          {
-            mainDataSet.addSelected(itineraryData.ways.elementAt(i));
-
-            RelationMember markedWay = new RelationMember
-            ((String)(itineraryData.getValueAt(i, 1)), itineraryData.ways.elementAt(i));
-            markedWays.addElement(markedWay);
-          }
-        }
-      }
-      else
-      {
-        for (int i = 0; i < itineraryData.getRowCount(); ++i)
-        {
-          if (itineraryData.ways.elementAt(i) != null)
-          {
-            mainDataSet.addSelected(itineraryData.ways.elementAt(i));
-
-            RelationMember markedWay = new RelationMember
-            ((String)(itineraryData.getValueAt(i, 1)), itineraryData.ways.elementAt(i));
-            markedWays.addElement(markedWay);
-          }
-        }
-      }
-    }
-    else if ("routePattern.itineraryAdd".equals(event.getActionCommand()))
-    {
-      int insPos = itineraryTable.getSelectedRow();
-      Iterator<RelationMember> relIter = markedWays.iterator();
-      TreeSet<Way> addedWays = new TreeSet<Way>();
-      if (mainDataSet == null)
-        return;
-
-      while (relIter.hasNext())
-      {
-        RelationMember curMember = relIter.next();
-        if ((curMember.isWay()) && (mainDataSet.isSelected(curMember.getWay())))
-        {
-          itineraryData.insertRow(insPos, curMember.getWay(), curMember.getRole());
-          if (insPos >= 0)
-            ++insPos;
-
-          addedWays.add(curMember.getWay());
-        }
-      }
-
-      Collection<Way> selectedWays = mainDataSet.getSelectedWays();
-      Iterator<Way> wayIter = selectedWays.iterator();
-
-      while (wayIter.hasNext())
-      {
-        Way curMember = wayIter.next();
-        if (!(addedWays.contains(curMember)))
-        {
-          itineraryData.insertRow(insPos, curMember, "");
-          if (insPos >= 0)
-            ++insPos;
-        }
-      }
-
-      if ((insPos > 0) && (insPos < itineraryData.getRowCount()))
-      {
-        while ((insPos < itineraryData.getRowCount())
-                  && (itineraryData.ways.elementAt(insPos) == null))
-          ++insPos;
-        itineraryTable.removeRowSelectionInterval(0, itineraryData.getRowCount()-1);
-        if (insPos < itineraryData.getRowCount())
-          itineraryTable.addRowSelectionInterval(insPos, insPos);
-      }
-
-      itineraryData.cleanupGaps();
-      segmentMetrics = fillSegmentMetrics();
-      rebuildWays();
-    }
-    else if ("routePattern.itineraryDelete".equals(event.getActionCommand()))
-    {
-      for (int i = itineraryData.getRowCount()-1; i >=0; --i)
-      {
-        if ((itineraryTable.isRowSelected(i)) && (itineraryData.ways.elementAt(i) != null))
-        {
-          itineraryData.ways.removeElementAt(i);
-          itineraryData.removeRow(i);
-        }
-      }
-
-      itineraryData.cleanupGaps();
-      segmentMetrics = fillSegmentMetrics();
-      rebuildWays();
-    }
-    else if ("routePattern.itinerarySort".equals(event.getActionCommand()))
-    {
-      TreeSet<Way> usedWays = new TreeSet<Way>();
-      TreeMap<Node, LinkedList<RelationMember> > frontNodes =
-      new TreeMap<Node, LinkedList<RelationMember> >();
-      TreeMap<Node, LinkedList<RelationMember> > backNodes =
-      new TreeMap<Node, LinkedList<RelationMember> >();
-      Vector< LinkedList<RelationMember> > loops =
-      new Vector< LinkedList<RelationMember> >();
-      int insPos = itineraryTable.getSelectedRow();
-
-      if (itineraryTable.getSelectedRowCount() > 0)
-      {
-        for (int i = itineraryData.getRowCount()-1; i >=0; --i)
-        {
-          if ((itineraryTable.isRowSelected(i)) && (itineraryData.ways.elementAt(i) != null))
-          {
-            if (!(usedWays.contains(itineraryData.ways.elementAt(i))))
-            {
-              addWayToSortingData
-              (itineraryData.ways.elementAt(i), frontNodes, backNodes, loops);
-              usedWays.add(itineraryData.ways.elementAt(i));
-            }
-
-            itineraryData.ways.removeElementAt(i);
-            itineraryData.removeRow(i);
-          }
-        }
-      }
-      else
-      {
-        for (int i = itineraryData.getRowCount()-1; i >=0; --i)
-        {
-          if (itineraryData.ways.elementAt(i) != null)
-          {
-            if (!(usedWays.contains(itineraryData.ways.elementAt(i))))
-            {
-              addWayToSortingData
-              (itineraryData.ways.elementAt(i), frontNodes, backNodes, loops);
-              usedWays.add(itineraryData.ways.elementAt(i));
-            }
-          }
-        }
-
-        itineraryData.clear();
-      }
-
-      Iterator< Map.Entry< Node, LinkedList<RelationMember> > > entryIter
-      = frontNodes.entrySet().iterator();
-      while (entryIter.hasNext())
-      {
-        Iterator<RelationMember> relIter = entryIter.next().getValue().iterator();
-        while (relIter.hasNext())
-        {
-          RelationMember curMember = relIter.next();
-          itineraryData.insertRow(insPos, curMember.getWay(), curMember.getRole());
-          if (insPos >= 0)
-            ++insPos;
-        }
-      }
-
-      Iterator< LinkedList<RelationMember> > listIter = loops.iterator();
-      while (listIter.hasNext())
-      {
-        Iterator<RelationMember> relIter = listIter.next().iterator();
-        while (relIter.hasNext())
-        {
-          RelationMember curMember = relIter.next();
-          itineraryData.insertRow(insPos, curMember.getWay(), curMember.getRole());
-          if (insPos >= 0)
-            ++insPos;
-        }
-      }
-
-      itineraryData.cleanupGaps();
-      segmentMetrics = fillSegmentMetrics();
-      rebuildWays();
-    }
-    else if ("routePattern.itineraryReflect".equals(event.getActionCommand()))
-    {
-      Vector<RelationMember> itemsToReflect = new Vector<RelationMember>();
-      int insPos = itineraryTable.getSelectedRow();
-
-      if (itineraryTable.getSelectedRowCount() > 0)
-      {
-        for (int i = itineraryData.getRowCount()-1; i >=0; --i)
-        {
-          if ((itineraryTable.isRowSelected(i)) && (itineraryData.ways.elementAt(i) != null))
-          {
-            String role = (String)(itineraryData.getValueAt(i, 1));
-            if ("backward".equals(role))
-              role = "forward";
-            else if ("forward".equals(role))
-              role = "backward";
-            else
-              role = "backward";
-            RelationMember markedWay = new RelationMember
-            (role, itineraryData.ways.elementAt(i));
-            itemsToReflect.addElement(markedWay);
-
-            itineraryData.ways.removeElementAt(i);
-            itineraryData.removeRow(i);
-          }
-        }
-      }
-      else
-      {
-        for (int i = itineraryData.getRowCount()-1; i >=0; --i)
-        {
-          if (itineraryData.ways.elementAt(i) != null)
-          {
-            String role = (String)(itineraryData.getValueAt(i, 1));
-            if ("backward".equals(role))
-              role = "forward";
-            else if ("forward".equals(role))
-              role = "backward";
-            else
-              role = "backward";
-            RelationMember markedWay = new RelationMember
-            (role, itineraryData.ways.elementAt(i));
-            itemsToReflect.addElement(markedWay);
-          }
-        }
-
-        itineraryData.clear();
-      }
-
-      int startPos = insPos;
-      Iterator<RelationMember> relIter = itemsToReflect.iterator();
-      while (relIter.hasNext())
-      {
-        RelationMember curMember = relIter.next();
-        if (curMember.isWay())
-        {
-          itineraryData.insertRow(insPos, curMember.getWay(), curMember.getRole());
-          if (insPos >= 0)
-            ++insPos;
-        }
-      }
-      if (insPos >= 0)
-        itineraryTable.addRowSelectionInterval(startPos, insPos-1);
-
-      itineraryData.cleanupGaps();
-      segmentMetrics = fillSegmentMetrics();
-      rebuildWays();
-    }
-    else if ("routePattern.stoplistFind".equals(event.getActionCommand()))
-    {
-      if (mainDataSet == null)
-        return;
-
-      stoplistTable.clearSelection();
-
-      for (int i = 0; i < stoplistData.getRowCount(); ++i)
-      {
-        if ((stoplistData.nodes.elementAt(i) != null) &&
-              (mainDataSet.isSelected(stoplistData.nodes.elementAt(i))))
-          stoplistTable.addRowSelectionInterval(i, i);
-      }
-    }
-    else if ("routePattern.stoplistShow".equals(event.getActionCommand()))
-    {
-      BoundingXYVisitor box = new BoundingXYVisitor();
-      if (stoplistTable.getSelectedRowCount() > 0)
-      {
-        for (int i = 0; i < stoplistData.getRowCount(); ++i)
-        {
-          if (stoplistTable.isRowSelected(i))
-          {
-            stoplistData.nodes.elementAt(i).accept(box);
-          }
-        }
-      }
-      else
-      {
-        for (int i = 0; i < stoplistData.getRowCount(); ++i)
-        {
-          stoplistData.nodes.elementAt(i).accept(box);
-        }
-      }
-      if (box.getBounds() == null)
-        return;
-      box.enlargeBoundingBox();
-      Main.map.mapView.zoomTo(box);
-    }
-    else if ("routePattern.stoplistMark".equals(event.getActionCommand()))
-    {
-      OsmPrimitive[] osmp = { null };
-      Main.main.getCurrentDataSet().setSelected(osmp);
-      markedNodes.clear();
-      if (stoplistTable.getSelectedRowCount() > 0)
-      {
-        for (int i = 0; i < stoplistData.getRowCount(); ++i)
-        {
-          if (stoplistTable.isRowSelected(i))
-          {
-            mainDataSet.addSelected(stoplistData.nodes.elementAt(i));
-
-            RelationMember markedNode = new RelationMember
-            ((String)(stoplistData.getValueAt(i, 1)), stoplistData.nodes.elementAt(i));
-            markedNodes.addElement(markedNode);
-          }
-        }
-      }
-      else
-      {
-        for (int i = 0; i < stoplistData.getRowCount(); ++i)
-        {
-          mainDataSet.addSelected(stoplistData.nodes.elementAt(i));
-
-          RelationMember markedNode = new RelationMember
-              ((String)(stoplistData.getValueAt(i, 1)), stoplistData.nodes.elementAt(i));
-          markedNodes.addElement(markedNode);
-        }
-      }
-    }
-    else if ("routePattern.stoplistAdd".equals(event.getActionCommand()))
-    {
-      int insPos = stoplistTable.getSelectedRow();
-      Iterator<RelationMember> relIter = markedNodes.iterator();
-      TreeSet<Node> addedNodes = new TreeSet<Node>();
-      if (mainDataSet == null)
-        return;
-
-      while (relIter.hasNext())
-      {
-        RelationMember curMember = relIter.next();
-        if ((curMember.isNode()) && (mainDataSet.isSelected(curMember.getNode())))
-        {
-          StopReference sr = detectMinDistance
-              (curMember.getNode(), segmentMetrics, cbRight.isSelected(), cbLeft.isSelected());
-          stoplistData.insertRow(insPos, curMember.getNode(), curMember.getRole(),
-              calcOffset(sr, segmentMetrics));
-          if (insPos >= 0)
-            ++insPos;
-
-          addedNodes.add(curMember.getNode());
-        }
-      }
-
-      Collection<Node> selectedNodes = mainDataSet.getSelectedNodes();
-      Iterator<Node> nodeIter = selectedNodes.iterator();
-
-      while (nodeIter.hasNext())
-      {
-        Node curMember = nodeIter.next();
-        if (!(addedNodes.contains(curMember)))
-        {
-          StopReference sr = detectMinDistance
-              (curMember, segmentMetrics, cbRight.isSelected(), cbLeft.isSelected());
-          stoplistData.insertRow(insPos, curMember, "", calcOffset(sr, segmentMetrics));
-          if (insPos >= 0)
-            ++insPos;
-        }
-      }
-
-      if ((insPos > 0) && (insPos < stoplistData.getRowCount()))
-      {
-        while ((insPos < stoplistData.getRowCount())
-                  && (stoplistData.nodes.elementAt(insPos) == null))
-          ++insPos;
-        stoplistTable.removeRowSelectionInterval(0, stoplistData.getRowCount()-1);
-        if (insPos < stoplistData.getRowCount())
-          stoplistTable.addRowSelectionInterval(insPos, insPos);
-      }
-
-      rebuildNodes();
-    }
-    else if ("routePattern.stoplistDelete".equals(event.getActionCommand()))
-    {
-      for (int i = stoplistData.getRowCount()-1; i >=0; --i)
-      {
-        if (stoplistTable.isRowSelected(i))
-        {
-          stoplistData.nodes.removeElementAt(i);
-          stoplistData.removeRow(i);
-        }
-      }
-
-      rebuildNodes();
-    }
-    else if ("routePattern.stoplistSort".equals(event.getActionCommand()))
-    {
-      // Prepare Segments: The segments of all usable ways are arranged in a linear
-      // list such that a coor can directly be checked concerning position and offset
-      Vector< StopReference > srm = new Vector< StopReference >();
-      int insPos = stoplistTable.getSelectedRow();
-      if (stoplistTable.getSelectedRowCount() > 0)
-      {
-        // Determine for each member its position on the itinerary: position means here the
-        // point on the itinerary that has minimal distance to the coor
-        for (int i = stoplistData.getRowCount()-1; i >= 0; --i)
-        {
-          if (stoplistTable.isRowSelected(i))
-          {
-            StopReference sr = detectMinDistance
-                (stoplistData.nodes.elementAt(i), segmentMetrics,
-                cbRight.isSelected(), cbLeft.isSelected());
-            if (sr != null)
-            {
-              if (sr.distance <
-                  Double.parseDouble(tfSuggestStopsLimit.getText()) * 9.0 / 1000000.0 )
-              {
-                sr.role = (String)stoplistData.getValueAt(i, STOPLIST_ROLE_COLUMN);
-                srm.addElement(sr);
-              }
-              else
-              {
-                sr.role = (String)stoplistData.getValueAt(i, STOPLIST_ROLE_COLUMN);
-                sr.index = segmentMetrics.size()*2;
-                sr.pos = 0;
-                srm.addElement(sr);
-              }
-
-              stoplistData.nodes.removeElementAt(i);
-              stoplistData.removeRow(i);
-            }
-
-          }
-        }
-      }
-      else
-      {
-        // Determine for each member its position on the itinerary: position means here the
-            // point on the itinerary that has minimal distance to the coor
-        for (int i = stoplistData.getRowCount()-1; i >= 0; --i)
-        {
-          StopReference sr = detectMinDistance
-              (stoplistData.nodes.elementAt(i), segmentMetrics,
-              cbRight.isSelected(), cbLeft.isSelected());
-          if (sr != null)
-          {
-            if (sr.distance <
-                  Double.parseDouble(tfSuggestStopsLimit.getText()) * 9.0 / 1000000.0 )
-            {
-              sr.role = (String)stoplistData.getValueAt(i, STOPLIST_ROLE_COLUMN);
-              srm.addElement(sr);
-            }
-            else
-            {
-              sr.role = (String)stoplistData.getValueAt(i, STOPLIST_ROLE_COLUMN);
-              sr.index = segmentMetrics.size()*2;
-              sr.pos = 0;
-              srm.addElement(sr);
-            }
-          }
-        }
-
-        stoplistData.clear();
-      }
-
-      Collections.sort(srm);
-
-      for (int i = 0; i < srm.size(); ++i)
-      {
-        StopReference sr = detectMinDistance
-            (srm.elementAt(i).node, segmentMetrics, cbRight.isSelected(), cbLeft.isSelected());
-        stoplistData.insertRow(insPos, srm.elementAt(i).node, srm.elementAt(i).role,
-            calcOffset(sr, segmentMetrics));
-        if (insPos >= 0)
-          ++insPos;
-      }
-
-      rebuildNodes();
-    }
-    else if ("routePattern.stoplistReflect".equals(event.getActionCommand()))
-    {
-      Vector< RelationMember > itemsToReflect = new Vector< RelationMember >();
-      int insPos = stoplistTable.getSelectedRow();
-
-      if (stoplistTable.getSelectedRowCount() > 0)
-      {
-        for (int i = stoplistData.getRowCount()-1; i >=0; --i)
-        {
-          if (stoplistTable.isRowSelected(i))
-          {
-            String role = (String)(stoplistData.getValueAt(i, STOPLIST_ROLE_COLUMN));
-            RelationMember markedNode = new RelationMember
-                (role, stoplistData.nodes.elementAt(i));
-            itemsToReflect.addElement(markedNode);
-
-            stoplistData.nodes.removeElementAt(i);
-            stoplistData.removeRow(i);
-          }
-        }
-      }
-      else
-      {
-        for (int i = stoplistData.getRowCount()-1; i >=0; --i)
-        {
-          String role = (String)(stoplistData.getValueAt(i, STOPLIST_ROLE_COLUMN));
-          RelationMember markedNode = new RelationMember
-              (role, stoplistData.nodes.elementAt(i));
-          itemsToReflect.addElement(markedNode);
-        }
-
-        stoplistData.clear();
-      }
-
-      int startPos = insPos;
-      Iterator<RelationMember> relIter = itemsToReflect.iterator();
-      while (relIter.hasNext())
-      {
-        RelationMember curMember = relIter.next();
-        if (curMember.isNode())
-        {
-          StopReference sr = detectMinDistance
-              (curMember.getNode(), segmentMetrics, cbRight.isSelected(), cbLeft.isSelected());
-          stoplistData.insertRow(insPos, curMember.getNode(), curMember.getRole(),
-              calcOffset(sr, segmentMetrics));
-          if (insPos >= 0)
-            ++insPos;
-        }
-      }
-      if (insPos >= 0)
-        stoplistTable.addRowSelectionInterval(startPos, insPos-1);
-
-      rebuildNodes();
-    }
-    else if ("routePattern.metaSuggestStops".equals(event.getActionCommand()))
-    {
-      // Prepare Segments: The segments of all usable ways are arranged in a linear
-      // list such that a coor can directly be checked concerning position and offset
-      Vector< StopReference > srm = new Vector< StopReference >();
-      // Determine for each member its position on the itinerary: position means here the
-      // point on the itinerary that has minimal distance to the coor
-      mainDataSet = Main.main.getCurrentDataSet();
-      if (mainDataSet != null)
-      {
-        String stopKey = "";
-        String stopValue = "";
-        if ("bus".equals(currentRoute.get("route")))
-        {
-          stopKey = "highway";
-          stopValue = "bus_stop";
-        }
-        else if ("trolleybus".equals(currentRoute.get("route")))
-        {
-          stopKey = "highway";
-          stopValue = "bus_stop";
-        }
-        else if ("tram".equals(currentRoute.get("route")))
-        {
-          stopKey = "railway";
-          stopValue = "tram_stop";
-        }
-        else if ("light_rail".equals(currentRoute.get("route")))
-        {
-          stopKey = "railway";
-          stopValue = "station";
-        }
-        else if ("subway".equals(currentRoute.get("route")))
-        {
-          stopKey = "railway";
-          stopValue = "station";
-        }
-        else if ("rail".equals(currentRoute.get("route")))
-        {
-          stopKey = "railway";
-          stopValue = "station";
-        }
-
-        Collection< Node > nodeCollection = mainDataSet.getNodes();
-        Iterator< Node > nodeIter = nodeCollection.iterator();
-        while (nodeIter.hasNext())
-        {
-          Node currentNode = nodeIter.next();
-          if (!currentNode.isUsable())
-            continue;
-          if (stopValue.equals(currentNode.get(stopKey)))
-          {
-            StopReference sr = detectMinDistance
-                (currentNode, segmentMetrics, cbRight.isSelected(), cbLeft.isSelected());
-            if ((sr != null) && (sr.distance <
-                Double.parseDouble(tfSuggestStopsLimit.getText()) * 9.0 / 1000000.0 ))
-              srm.addElement(sr);
-          }
-        }
-      }
-      else
-      {
-        JOptionPane.showMessageDialog(null, tr("There exists no dataset."
-            + " Try to download data from the server or open an OSM file."),
-        tr("No data found"), JOptionPane.ERROR_MESSAGE);
-      }
-
-      Collections.sort(srm);
-
-      stoplistData.clear();
-      for (int i = 0; i < srm.size(); ++i)
-      {
-        StopReference sr = detectMinDistance
-            (srm.elementAt(i).node, segmentMetrics, cbRight.isSelected(), cbLeft.isSelected());
-        stoplistData.addRow(srm.elementAt(i).node, srm.elementAt(i).role,
-            calcOffset(sr, segmentMetrics));
-      }
-
-      rebuildNodes();
-    }
-    else
-    {
-      refreshData();
-
-      jDialog.setLocationRelativeTo(frame);
-      jDialog.setVisible(true);
-    }
-  }
-
-  private void refreshData() {
-    Relation copy = currentRoute;
-    relsListModel.clear();
-    currentRoute = copy;
-
-    DataSet mainDataSet = Main.main.getCurrentDataSet();
-    if (mainDataSet != null)
-    {
-      Vector< RouteReference > relRefs = new Vector< RouteReference >();
-      Collection< Relation > relCollection = mainDataSet.getRelations();
-      Iterator< Relation > relIter = relCollection.iterator();
-
-      while (relIter.hasNext())
-      {
-        Relation currentRel = relIter.next();
-        if (!currentRel.isDeleted())
-        {
-          String routeVal = currentRel.get("route");
-          if ("bus".equals(routeVal))
-            relRefs.add(new RouteReference(currentRel));
-          else if ("trolleybus".equals(routeVal))
-            relRefs.add(new RouteReference(currentRel));
-          else if ("tram".equals(routeVal))
-            relRefs.add(new RouteReference(currentRel));
-          else if ("light_rail".equals(routeVal))
-            relRefs.add(new RouteReference(currentRel));
-          else if ("subway".equals(routeVal))
-            relRefs.add(new RouteReference(currentRel));
-          else if ("rail".equals(routeVal))
-            relRefs.add(new RouteReference(currentRel));
-        }
-      }
-
-      Collections.sort(relRefs);
-
-      Iterator< RouteReference > iter = relRefs.iterator();
-      while (iter.hasNext())
-        relsListModel.addElement(iter.next());
-    }
-    else
-    {
-      JOptionPane.showMessageDialog(null, tr("There exists no dataset."
-      + " Try to download data from the server or open an OSM file."),
-      tr("No data found"), JOptionPane.ERROR_MESSAGE);
-    }
-  }
-
-  //Rebuild ways in the relation currentRoute
-  public static void rebuildWays() {
-    currentRoute.setModified(true);
-    List< RelationMember > members = currentRoute.getMembers();
-    ListIterator< RelationMember > iter = members.listIterator();
-    while (iter.hasNext())
-    {
-      if (iter.next().isWay())
-    iter.remove();
-    }
-    for (int i = 0; i < itineraryData.getRowCount(); ++i)
-    {
-      if (itineraryData.ways.elementAt(i) != null)
-      {
-        RelationMember member = new RelationMember
-        ((String)(itineraryData.getValueAt(i, 1)),
-         itineraryData.ways.elementAt(i));
-        members.add(member);
-      }
-    }
-    currentRoute.setMembers(members);
-  }
-
-  //Rebuild nodes in the relation currentRoute
-  private void rebuildNodes() {
-    currentRoute.setModified(true);
-    for (int i = currentRoute.getMembersCount()-1; i >=0; --i)
-    {
-      if (currentRoute.getMember(i).isNode())
-      {
-        currentRoute.removeMember(i);
-      }
-    }
-    for (int i = 0; i < stoplistData.getRowCount(); ++i)
-    {
-      RelationMember member = new RelationMember
-          ((String)(stoplistData.getValueAt(i, STOPLIST_ROLE_COLUMN)),
-           stoplistData.nodes.elementAt(i));
-      currentRoute.addMember(member);
-    }
-  }
-
-  private void addWayToSortingData
-      (Way way, TreeMap<Node, LinkedList<RelationMember> > frontNodes,
-       TreeMap<Node, LinkedList<RelationMember> > backNodes,
-       Vector< LinkedList<RelationMember> > loops)
-  {
-    if (way.getNodesCount() < 1)
-      return;
-
-    Node firstNode = way.getNode(0);
-    Node lastNode = way.getNode(way.getNodesCount() - 1);
-
-    if (frontNodes.get(firstNode) != null)
-    {
-      LinkedList<RelationMember> list = frontNodes.get(firstNode);
-      list.addFirst(new RelationMember("backward", way));
-      frontNodes.remove(firstNode);
-
-      Node lastListNode = null;
-      if ("backward".equals(list.getLast().getRole()))
-        lastListNode = list.getLast().getWay().getNode(0);
-      else
-        lastListNode = list.getLast().getWay().getNode
-        (list.getLast().getWay().getNodesCount() - 1);
-      if (lastNode.equals(lastListNode))
-      {
-        backNodes.remove(lastListNode);
-        loops.add(list);
-      }
-      else if (frontNodes.get(lastNode) != null)
-      {
-        backNodes.remove(lastListNode);
-        LinkedList<RelationMember> listToAppend = frontNodes.get(lastNode);
-        Iterator<RelationMember> memberIter = list.iterator();
-        while (memberIter.hasNext())
-        {
-          RelationMember member = memberIter.next();
-          if ("backward".equals(member.getRole()))
-            listToAppend.addFirst(new RelationMember("forward", member.getWay()));
-          else
-            listToAppend.addFirst(new RelationMember("backward", member.getWay()));
-        }
-        frontNodes.remove(lastNode);
-        frontNodes.put(lastListNode, listToAppend);
-      }
-      else if (backNodes.get(lastNode) != null)
-      {
-        backNodes.remove(lastListNode);
-        LinkedList<RelationMember> listToAppend = backNodes.get(lastNode);
-        Iterator<RelationMember> memberIter = list.iterator();
-        while (memberIter.hasNext())
-        {
-          RelationMember member = memberIter.next();
-          listToAppend.addLast(member);
-        }
-        backNodes.remove(lastNode);
-        backNodes.put(lastListNode, listToAppend);
-      }
-      else
-        frontNodes.put(lastNode, list);
-    }
-    else if (backNodes.get(firstNode) != null)
-    {
-      LinkedList<RelationMember> list = backNodes.get(firstNode);
-      list.addLast(new RelationMember("forward", way));
-      backNodes.remove(firstNode);
-
-      Node firstListNode = null;
-      if ("backward".equals(list.getFirst().getRole()))
-        firstListNode = list.getFirst().getWay().getNode
-        (list.getFirst().getWay().getNodesCount() - 1);
-      else
-        firstListNode = list.getFirst().getWay().getNode(0);
-      if (lastNode.equals(firstListNode))
-      {
-        frontNodes.remove(firstListNode);
-        loops.add(list);
-      }
-      else if (frontNodes.get(lastNode) != null)
-      {
-        frontNodes.remove(firstListNode);
-        LinkedList<RelationMember> listToAppend = frontNodes.get(lastNode);
-        ListIterator<RelationMember> memberIter = list.listIterator(list.size());
-        while (memberIter.hasPrevious())
-        {
-          RelationMember member = memberIter.previous();
-          listToAppend.addFirst(member);
-        }
-        frontNodes.remove(lastNode);
-        frontNodes.put(firstListNode, listToAppend);
-      }
-      else if (backNodes.get(lastNode) != null)
-      {
-        frontNodes.remove(firstListNode);
-        LinkedList<RelationMember> listToAppend = backNodes.get(lastNode);
-        ListIterator<RelationMember> memberIter = list.listIterator(list.size());
-        while (memberIter.hasPrevious())
-        {
-          RelationMember member = memberIter.previous();
-          if ("backward".equals(member.getRole()))
-            listToAppend.addLast(new RelationMember("forward", member.getWay()));
-          else
-            listToAppend.addLast(new RelationMember("backward", member.getWay()));
-        }
-        backNodes.remove(lastNode);
-        backNodes.put(firstListNode, listToAppend);
-      }
-      else
-        backNodes.put(lastNode, list);
-    }
-    else if (frontNodes.get(lastNode) != null)
-    {
-      LinkedList<RelationMember> list = frontNodes.get(lastNode);
-      list.addFirst(new RelationMember("forward", way));
-      frontNodes.remove(lastNode);
-      frontNodes.put(firstNode, list);
-    }
-    else if (backNodes.get(lastNode) != null)
-    {
-      LinkedList<RelationMember> list = backNodes.get(lastNode);
-      list.addLast(new RelationMember("backward", way));
-      backNodes.remove(lastNode);
-      backNodes.put(firstNode, list);
-    }
-    else
-    {
-      LinkedList<RelationMember> newList = new LinkedList<RelationMember>();
-      newList.add(new RelationMember("forward", way));
-      frontNodes.put(firstNode, newList);
-      backNodes.put(lastNode, newList);
-    }
-  }
-
-  private void routesSelectionChanged() {
-    int selectedPos = relsList.getAnchorSelectionIndex();
-    if (relsList.isSelectedIndex(selectedPos))
-    {
-      currentRoute = relsListModel.elementAt(selectedPos).route;
-      tabbedPane.setEnabledAt(1, true);
-      tabbedPane.setEnabledAt(2, true);
-      tabbedPane.setEnabledAt(3, true);
-      tabbedPane.setEnabledAt(4, true);
-
-      //Prepare Tags
-      requiredTagsData.readRelation(currentRoute);
-      commonTagsData.readRelation(currentRoute);
-      otherTagsData.readRelation(currentRoute, tagBlacklist);
-
-      //Prepare Itinerary
-      itineraryData.clear();
-      List<RelationMember> relMembers = currentRoute.getMembers();
-      Iterator<RelationMember> relIter = relMembers.iterator();
-      fillItineraryTable(relIter, 0, -1);
-
-      //Prepare Stoplist
-      stoplistData.clear();
-      /*List<RelationMember>*/ relMembers = currentRoute.getMembers();
-      /*Iterator<RelationMember>*/ relIter = relMembers.iterator();
-      fillStoplistTable(relIter, -1);
-    }
-    else
-    {
-      currentRoute = null;
-      tabbedPane.setEnabledAt(1, false);
-      tabbedPane.setEnabledAt(2, false);
-      tabbedPane.setEnabledAt(3, false);
-      tabbedPane.setEnabledAt(4, false);
-    }
-  }
-
-  private void fillItineraryTable
-      (Iterator<RelationMember> relIter, long lastNodeId, int insPos) {
-    while (relIter.hasNext())
-    {
-      RelationMember curMember = relIter.next();
-      if (curMember.isWay())
-      {
-        itineraryData.insertRow(insPos, curMember.getWay(), curMember.getRole());
-        if (insPos >= 0)
-          ++insPos;
-      }
-    }
-    itineraryData.cleanupGaps();
-    segmentMetrics = fillSegmentMetrics();
-  }
-
-  private double calcOffset(StopReference sr, Vector< SegmentMetric > segmentMetrics)
-  {
-    double offset = 0;
-    if ((sr.index+1) / 2 < segmentMetrics.size())
-    {
-      offset = segmentMetrics.elementAt((sr.index+1) / 2).distance;
-      if (sr.index % 2 == 0)
-        offset += sr.pos;
-    }
-    else
-      offset = segmentMetrics.elementAt(segmentMetrics.size() - 1).distance
-          + segmentMetrics.elementAt(segmentMetrics.size() - 1).length;
-
-    return offset;
-  }
-
-  private void fillStoplistTable
-      (Iterator<RelationMember> relIter, int insPos) {
-
-    while (relIter.hasNext())
-    {
-      RelationMember curMember = relIter.next();
-      if (curMember.isNode())
-      {
-        StopReference sr = detectMinDistance
-            (curMember.getNode(), segmentMetrics, cbRight.isSelected(), cbLeft.isSelected());
-        if (sr == null)
-          stoplistData.insertRow(insPos, curMember.getNode(), curMember.getRole(), 360.0);
-        else
-        {
-          stoplistData.insertRow(insPos, curMember.getNode(), curMember.getRole(),
-              calcOffset(sr, segmentMetrics));
-          if (insPos >= 0)
-            ++insPos;
-        }
-      }
-    }
-  }
-
-  private Vector< SegmentMetric > fillSegmentMetrics()
-  {
-    Vector< SegmentMetric > segmentMetrics = new Vector< SegmentMetric >();
-    double distance = 0;
-    for (int i = 0; i < itineraryData.getRowCount(); ++i)
-    {
-      if (itineraryData.ways.elementAt(i) != null)
-      {
-        Way way = itineraryData.ways.elementAt(i);
-        if (!(way.isIncomplete()))
-        {
-          if ("backward".equals((itineraryData.getValueAt(i, 1))))
-          {
-            for (int j = way.getNodesCount()-2; j >= 0; --j)
-            {
-              SegmentMetric sm = new SegmentMetric
-                  (way.getNode(j+1).getCoor().lat(), way.getNode(j+1).getCoor().lon(),
-                  way.getNode(j).getCoor().lat(), way.getNode(j).getCoor().lon(), distance);
-              segmentMetrics.add(sm);
-              distance += sm.length;
-            }
-          }
-          else
-          {
-            for (int j = 0; j < way.getNodesCount()-1; ++j)
-            {
-              SegmentMetric sm = new SegmentMetric
-                  (way.getNode(j).getCoor().lat(), way.getNode(j).getCoor().lon(),
-                  way.getNode(j+1).getCoor().lat(), way.getNode(j+1).getCoor().lon(), distance);
-              segmentMetrics.add(sm);
-              distance += sm.length;
-            }
-          }
-        }
-      }
-      else
-        segmentMetrics.add(null);
-    }
-    return segmentMetrics;
-  }
-
-  private StopReference detectMinDistance
-      (Node node, Vector< SegmentMetric > segmentMetrics,
-       boolean rhsPossible, boolean lhsPossible) {
-    if (node == null || node.getCoor() == null)
-      return null;
-
-    int minIndex = -1;
-    double position = -1.0;
-    double distance = 180.0;
-    double lat = node.getCoor().lat();
-    double lon = node.getCoor().lon();
-
-    int curIndex = -2;
-    double angleLat = 100.0;
-    double angleLon = 200.0;
-    Iterator<SegmentMetric> iter = segmentMetrics.iterator();
-    while (iter.hasNext())
-    {
-      curIndex += 2;
-      SegmentMetric sm = iter.next();
-
-      if (sm == null)
-      {
-        angleLat = 100.0;
-        angleLon = 200.0;
-
-        continue;
-      }
-
-      double curPosition = (lat - sm.aLat)*sm.d1 + (lon - sm.aLon)*sm.d2;
-
-      if (curPosition < 0)
-      {
-        if (angleLat <= 90.0)
-        {
-          double lastSegAngle = Math.atan2(angleLat - sm.aLat, angleLon - sm.aLon);
-          double segAngle = Math.atan2(sm.d1, -sm.o1);
-          double vertexAngle = Math.atan2(lat - sm.aLat, lon - sm.aLon);
-
-          boolean vertexOnSeg = (vertexAngle == segAngle) ||
-              (vertexAngle == lastSegAngle);
-          boolean vertexOnTheLeft = (!vertexOnSeg) &&
-              (((lastSegAngle > vertexAngle) && (vertexAngle > segAngle))
-              || ((vertexAngle > segAngle) && (segAngle > lastSegAngle))
-              || ((segAngle > lastSegAngle) && (lastSegAngle > vertexAngle)));
-
-          double currentDistance = Math.sqrt((lat - sm.aLat)*(lat - sm.aLat)
-            + (lon - sm.aLon)*(lon - sm.aLon)
-            *Math.cos(sm.aLat * Math.PI/180.0)*Math.cos(sm.aLat * Math.PI/180.0));
-          curPosition = vertexAngle - segAngle;
-          if (vertexOnTheLeft)
-            curPosition = -curPosition;
-          if (curPosition < 0)
-            curPosition += 2*Math.PI;
-          if ((Math.abs(currentDistance) < distance)
-            && (((!vertexOnTheLeft) && (rhsPossible))
-            || ((vertexOnTheLeft) && (lhsPossible))
-              || (vertexOnSeg)))
-          {
-            distance = Math.abs(currentDistance);
-            minIndex = curIndex-1;
-            position = curPosition;
-          }
-        }
-        angleLat = 100.0;
-        angleLon = 200.0;
-      }
-      else if (curPosition > sm.length)
-      {
-        angleLat = sm.aLat;
-        angleLon = sm.aLon;
-      }
-      else
-      {
-        double currentDistance = (lat - sm.aLat)*sm.o1 + (lon - sm.aLon)*sm.o2;
-        if ((Math.abs(currentDistance) < distance)
-                && (((currentDistance >= 0) && (rhsPossible))
-                || ((currentDistance <= 0) && (lhsPossible))))
-        {
-          distance = Math.abs(currentDistance);
-          minIndex = curIndex;
-          position = curPosition;
-        }
-
-        angleLat = 100.0;
-        angleLon = 200.0;
-      }
-    }
-
-    if (minIndex == -1)
-      return new StopReference(segmentMetrics.size()*2, 0, 180.0, node.get("name"),
-                   "", node);
-
-    return new StopReference(minIndex, position, distance, node.get("name"),
-                 "", node);
-  }
 }
Index: /applications/editors/josm/plugins/public_transport/src/public_transport/SettingsStoptypeCommand.java
===================================================================
--- /applications/editors/josm/plugins/public_transport/src/public_transport/SettingsStoptypeCommand.java	(revision 32356)
+++ /applications/editors/josm/plugins/public_transport/src/public_transport/SettingsStoptypeCommand.java	(revision 32357)
@@ -12,81 +12,74 @@
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 
-public class SettingsStoptypeCommand extends Command
-{
-  private class HighwayRailway
-  {
-    public HighwayRailway(Node node)
-    {
-      this.node = node;
-      highway = node.get("highway");
-      railway = node.get("railway");
+public class SettingsStoptypeCommand extends Command {
+    private class HighwayRailway {
+        public HighwayRailway(Node node) {
+            this.node = node;
+            highway = node.get("highway");
+            railway = node.get("railway");
+        }
+
+        public Node node;
+
+        public String highway;
+
+        public String railway;
     }
 
-    public Node node;
-    public String highway;
-    public String railway;
-  };
+    private Vector<HighwayRailway> oldStrings = null;
 
-  private Vector< HighwayRailway > oldStrings = null;
-  private WaypointTableModel waypointTM = null;
-  private DefaultListModel tracksListModel = null;
-  private String type = null;
+    private WaypointTableModel waypointTM = null;
 
-  public SettingsStoptypeCommand(StopImporterAction controller)
-  {
-    waypointTM = controller.getWaypointTableModel();
-    tracksListModel = controller.getTracksListModel();
-    type = controller.getDialog().getStoptype();
-    oldStrings = new Vector< HighwayRailway >();
-  }
+    private DefaultListModel<?> tracksListModel = null;
 
-  public boolean executeCommand()
-  {
-    oldStrings.clear();
-    for (int i = 0; i < waypointTM.getRowCount(); ++i)
-    {
-      if ((Node)waypointTM.nodes.elementAt(i) != null)
-      {
-        Node node = (Node)waypointTM.nodes.elementAt(i);
-        oldStrings.add(new HighwayRailway(node));
-        StopImporterAction.setTagsWrtType(node, type);
-      }
+    private String type = null;
+
+    public SettingsStoptypeCommand(StopImporterAction controller) {
+        waypointTM = controller.getWaypointTableModel();
+        tracksListModel = controller.getTracksListModel();
+        type = controller.getDialog().getStoptype();
+        oldStrings = new Vector<>();
     }
-    for (int j = 0; j < tracksListModel.size(); ++j)
-    {
-      TrackReference track = (TrackReference)tracksListModel.elementAt(j);
-      for (int i = 0; i < track.stoplistTM.getRowCount(); ++i)
-      {
-        if (track.stoplistTM.nodeAt(i) != null)
-        {
-          Node node = track.stoplistTM.nodeAt(i);
-          oldStrings.add(new HighwayRailway(node));
-          StopImporterAction.setTagsWrtType(node, type);
+
+    @Override
+    public boolean executeCommand() {
+        oldStrings.clear();
+        for (int i = 0; i < waypointTM.getRowCount(); ++i) {
+            if (waypointTM.nodes.elementAt(i) != null) {
+                Node node = waypointTM.nodes.elementAt(i);
+                oldStrings.add(new HighwayRailway(node));
+                StopImporterAction.setTagsWrtType(node, type);
+            }
         }
-      }
+        for (int j = 0; j < tracksListModel.size(); ++j) {
+            TrackReference track = (TrackReference) tracksListModel.elementAt(j);
+            for (int i = 0; i < track.stoplistTM.getRowCount(); ++i) {
+                if (track.stoplistTM.nodeAt(i) != null) {
+                    Node node = track.stoplistTM.nodeAt(i);
+                    oldStrings.add(new HighwayRailway(node));
+                    StopImporterAction.setTagsWrtType(node, type);
+                }
+            }
+        }
+        return true;
     }
-    return true;
-  }
 
-  public void undoCommand()
-  {
-    for (int i = 0; i < oldStrings.size(); ++i)
-    {
-      HighwayRailway hr = oldStrings.elementAt(i);
-      hr.node.put("highway", hr.highway);
-      hr.node.put("railway", hr.railway);
+    @Override
+    public void undoCommand() {
+        for (int i = 0; i < oldStrings.size(); ++i) {
+            HighwayRailway hr = oldStrings.elementAt(i);
+            hr.node.put("highway", hr.highway);
+            hr.node.put("railway", hr.railway);
+        }
     }
-  }
 
-  public void fillModifiedData
-    (Collection< OsmPrimitive > modified, Collection< OsmPrimitive > deleted,
-     Collection< OsmPrimitive > added)
-  {
-  }
+    @Override
+    public void fillModifiedData(Collection<OsmPrimitive> modified,
+            Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
+    }
 
-  @Override public String getDescriptionText()
-  {
-    return tr("Public Transport: Change stop type");
-  }
-
-};
+    @Override
+    public String getDescriptionText() {
+        return tr("Public Transport: Change stop type");
+    }
+}
Index: /applications/editors/josm/plugins/public_transport/src/public_transport/StopImporterAction.java
===================================================================
--- /applications/editors/josm/plugins/public_transport/src/public_transport/StopImporterAction.java	(revision 32356)
+++ /applications/editors/josm/plugins/public_transport/src/public_transport/StopImporterAction.java	(revision 32357)
@@ -29,4 +29,5 @@
 import org.openstreetmap.josm.data.gpx.GpxTrack;
 import org.openstreetmap.josm.data.gpx.WayPoint;
+import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
@@ -35,524 +36,450 @@
 import org.xml.sax.SAXException;
 
-public class StopImporterAction extends JosmAction
-{
-  private static StopImporterDialog dialog = null;
-  private static DefaultListModel<TrackReference> tracksListModel = null;
-  private static GpxData data = null;
-  private static TrackReference currentTrack = null;
-  private static WaypointTableModel waypointTM = null;
-  public boolean inEvent = false;
-
-  public StopImporterAction()
-  {
-    super(tr("Create Stops from GPX ..."), null,
-      tr("Create Stops from a GPX file"), null, false);
-    putValue("toolbar", "publictransport/stopimporter");
-    Main.toolbar.register(this);
-  }
-
-  public WaypointTableModel getWaypointTableModel()
-  {
-    return waypointTM;
-  }
-
-  public StopImporterDialog getDialog()
-  {
-    return dialog;
-  }
-
-  public DefaultListModel<TrackReference> getTracksListModel()
-  {
-    if (tracksListModel == null)
-      tracksListModel = new DefaultListModel<>();
-    return tracksListModel;
-  }
-
-  public TrackReference getCurrentTrack()
-  {
-    return currentTrack;
-  }
-
-  @Override
-public void actionPerformed(ActionEvent event)
-  {
-    if (dialog == null)
-      dialog = new StopImporterDialog(this);
-
-    dialog.setVisible(true);
-
-    if (tr("Create Stops from GPX ...").equals(event.getActionCommand()))
-    {
-      String curDir = Main.pref.get("lastDirectory");
-      if (curDir.equals(""))
-      {
-        curDir = ".";
-      }
-      JFileChooser fc = new JFileChooser(new File(curDir));
-      fc.setDialogTitle(tr("Select GPX file"));
-      fc.setMultiSelectionEnabled(false);
-
-      int answer = fc.showOpenDialog(Main.parent);
-      if (answer != JFileChooser.APPROVE_OPTION)
-        return;
-
-      if (!fc.getCurrentDirectory().getAbsolutePath().equals(curDir))
-        Main.pref.put("lastDirectory", fc.getCurrentDirectory().getAbsolutePath());
-
-      importData(fc.getSelectedFile());
-
-      refreshData();
-    }
-    else if ("stopImporter.settingsGPSTimeStart".equals(event.getActionCommand()))
-    {
-      if ((!inEvent) && (dialog.gpsTimeStartValid()) && (currentTrack != null))
-      Main.main.undoRedo.add(new TrackStoplistRelocateCommand(this));
-    }
-    else if ("stopImporter.settingsStopwatchStart".equals(event.getActionCommand()))
-    {
-      if ((!inEvent) && (dialog.stopwatchStartValid()) && (currentTrack != null))
-      Main.main.undoRedo.add(new TrackStoplistRelocateCommand(this));
-    }
-    else if ("stopImporter.settingsTimeWindow".equals(event.getActionCommand()))
-    {
-      if (currentTrack != null)
-      currentTrack.timeWindow = dialog.getTimeWindow();
-    }
-    else if ("stopImporter.settingsThreshold".equals(event.getActionCommand()))
-    {
-      if (currentTrack != null)
-        currentTrack.threshold = dialog.getThreshold();
-    }
-    else if ("stopImporter.settingsSuggestStops".equals(event.getActionCommand()))
-      Main.main.undoRedo.add(new TrackSuggestStopsCommand(this));
-    else if ("stopImporter.stoplistFind".equals(event.getActionCommand()))
-      findNodesInTable(dialog.getStoplistTable(), currentTrack.stoplistTM.getNodes());
-    else if ("stopImporter.stoplistShow".equals(event.getActionCommand()))
-      showNodesFromTable(dialog.getStoplistTable(), currentTrack.stoplistTM.getNodes());
-    else if ("stopImporter.stoplistMark".equals(event.getActionCommand()))
-      markNodesFromTable(dialog.getStoplistTable(), currentTrack.stoplistTM.getNodes());
-    else if ("stopImporter.stoplistDetach".equals(event.getActionCommand()))
-    {
-      Main.main.undoRedo.add(new TrackStoplistDetachCommand(this));
-      dialog.getStoplistTable().clearSelection();
-    }
-    else if ("stopImporter.stoplistAdd".equals(event.getActionCommand()))
-      Main.main.undoRedo.add(new TrackStoplistAddCommand(this));
-    else if ("stopImporter.stoplistDelete".equals(event.getActionCommand()))
-      Main.main.undoRedo.add(new TrackStoplistDeleteCommand(this));
-    else if ("stopImporter.stoplistSort".equals(event.getActionCommand()))
-      Main.main.undoRedo.add(new TrackStoplistSortCommand(this));
-    else if ("stopImporter.waypointsFind".equals(event.getActionCommand()))
-      findNodesInTable(dialog.getWaypointsTable(), waypointTM.nodes);
-    else if ("stopImporter.waypointsShow".equals(event.getActionCommand()))
-      showNodesFromTable(dialog.getWaypointsTable(), waypointTM.nodes);
-    else if ("stopImporter.waypointsMark".equals(event.getActionCommand()))
-      markNodesFromTable(dialog.getWaypointsTable(), waypointTM.nodes);
-    else if ("stopImporter.waypointsDetach".equals(event.getActionCommand()))
-    {
-      Main.main.undoRedo.add(new WaypointsDetachCommand(this));
-      dialog.getWaypointsTable().clearSelection();
-    }
-    else if ("stopImporter.waypointsAdd".equals(event.getActionCommand()))
-      Main.main.undoRedo.add(new WaypointsEnableCommand(this));
-    else if ("stopImporter.waypointsDelete".equals(event.getActionCommand()))
-      Main.main.undoRedo.add(new WaypointsDisableCommand(this));
-    else if ("stopImporter.settingsStoptype".equals(event.getActionCommand()))
-      Main.main.undoRedo.add(new SettingsStoptypeCommand(this));
-  }
-
-  private void importData(final File file)
-  {
-    try
-    {
-      InputStream is;
-      if (file.getName().endsWith(".gpx.gz"))
-        is = new GZIPInputStream(new FileInputStream(file));
-      else
-        is = new FileInputStream(file);
-      // Workaround for SAX BOM bug
-      // https://bugs.openjdk.java.net/browse/JDK-6206835
-      if (!((is.read() == 0xef) && (is.read() == 0xbb) && (is.read() == 0xbf)))
-      {
-        is.close();
-        if (file.getName().endsWith(".gpx.gz"))
-          is = new GZIPInputStream(new FileInputStream(file));
-        else
-          is = new FileInputStream(file);
-      }
-      final GpxReader r = new GpxReader(is);
-      final boolean parsedProperly = r.parse(true);
-      data = r.getGpxData();
-
-      if (!parsedProperly)
-      {
-        JOptionPane.showMessageDialog(null, tr("Error occurred while parsing gpx file {0}. Only a part of the file will be available.", file.getName()));
-      }
-    }
-    catch (FileNotFoundException e)
-    {
-      e.printStackTrace();
-      JOptionPane.showMessageDialog(null, tr("File \"{0}\" does not exist", file.getName()));
-    }
-    catch (SAXException e)
-    {
-      e.printStackTrace();
-      JOptionPane.showMessageDialog(null, tr("Parsing file \"{0}\" failed", file.getName()));
-    }
-    catch (IOException e)
-    {
-      e.printStackTrace();
-      JOptionPane.showMessageDialog(null, tr("IOException \"{0}\" occurred", e.toString()));
-    }
-  }
-
-  private void refreshData()
-  {
-    tracksListModel.clear();
-    if (data != null)
-    {
-      Vector< TrackReference > trackRefs = new Vector< TrackReference >();
-      Iterator< GpxTrack > trackIter = data.tracks.iterator();
-      while (trackIter.hasNext())
-      {
-        GpxTrack track = trackIter.next();
-        trackRefs.add(new TrackReference(track, this));
-      }
-
-      Collections.sort(trackRefs);
-
-      Iterator< TrackReference > iter = trackRefs.iterator();
-      while (iter.hasNext())
-        tracksListModel.addElement(iter.next());
-
-      waypointTM = new WaypointTableModel(this);
-      Iterator< WayPoint > waypointIter = data.waypoints.iterator();
-      while (waypointIter.hasNext())
-      {
-        WayPoint waypoint = waypointIter.next();
-        waypointTM.addRow(waypoint);
-      }
-      dialog.setWaypointsTableModel(waypointTM);
-    }
-    else
-    {
-      JOptionPane.showMessageDialog
-      (null, tr("The GPX file contained no tracks or waypoints."), tr("No data found"),
-       JOptionPane.ERROR_MESSAGE);
-    }
-  }
-
-  public void tracksSelectionChanged(int selectedPos)
-  {
-    if (selectedPos >= 0)
-    {
-      currentTrack = (tracksListModel.elementAt(selectedPos));
-      dialog.setTrackValid(true);
-
-      //Prepare Settings
-      dialog.setSettings
-      (currentTrack.gpsSyncTime, currentTrack.stopwatchStart,
-       currentTrack.timeWindow, currentTrack.threshold);
-
-      //Prepare Stoplist
-      dialog.setStoplistTableModel
-          (tracksListModel.elementAt(selectedPos).stoplistTM);
-    }
-    else
-    {
-      currentTrack = null;
-      dialog.setTrackValid(false);
-    }
-  }
-
-  public Node createNode(LatLon latLon, String name)
-  {
-    return createNode(latLon, dialog.getStoptype(), name);
-  }
-
-  public static Node createNode(LatLon latLon, String type, String name)
-  {
-    Node node = new Node(latLon);
-    setTagsWrtType(node, type);
-    node.put("name", name);
-    if (Main.main.getCurrentDataSet() == null)
-    {
-      JOptionPane.showMessageDialog(null, tr("There exists no dataset."
-      + " Try to download data from the server or open an OSM file."),
-     tr("No data found"), JOptionPane.ERROR_MESSAGE);
-
-      return null;
-    }
-    Main.main.getCurrentDataSet().addPrimitive(node);
-    return node;
-  }
-
-  /* sets the tags of the node according to the type */
-  public static void setTagsWrtType(Node node, String type)
-  {
-    node.remove("highway");
-    node.remove("railway");
-    if ("bus".equals(type))
-      node.put("highway", "bus_stop");
-    else if ("tram".equals(type))
-      node.put("railway", "tram_stop");
-    else if ("light_rail".equals(type))
-      node.put("railway", "station");
-    else if ("subway".equals(type))
-      node.put("railway", "station");
-    else if ("rail".equals(type))
-      node.put("railway", "station");
-  }
-
-  /* returns a collection of all selected lines or
-     a collection of all lines otherwise */
-  public static Vector< Integer > getConsideredLines(JTable table)
-  {
-    int[] selectedLines = table.getSelectedRows();
-    Vector< Integer > consideredLines = new Vector< Integer >();
-    if (selectedLines.length > 0)
-    {
-      for (int i = 0; i < selectedLines.length; ++i)
-        consideredLines.add(selectedLines[i]);
-    }
-    else
-    {
-      for (int i = 0; i < table.getRowCount(); ++i)
-        consideredLines.add(new Integer(i));
-    }
-    return consideredLines;
-  }
-
-  /* marks the table items whose nodes are marked on the map */
-  public static void findNodesInTable(JTable table, Vector< Node > nodes)
-  {
-    if (Main.main.getCurrentDataSet() == null)
-      return;
-
-    table.clearSelection();
-
-    for (int i = 0; i < table.getRowCount(); ++i)
-    {
-      if ((nodes.elementAt(i) != null) &&
-      (Main.main.getCurrentDataSet().isSelected(nodes.elementAt(i))))
-        table.addRowSelectionInterval(i, i);
-    }
-  }
-
-  /* shows the nodes that correspond to the marked lines in the table.
-     If no lines are marked in the table, show all nodes from the vector */
-  public static void showNodesFromTable(JTable table, Vector< Node > nodes)
-  {
-    BoundingXYVisitor box = new BoundingXYVisitor();
-    Vector< Integer > consideredLines = getConsideredLines(table);
-    for (int i = 0; i < consideredLines.size(); ++i)
-    {
-      int j = consideredLines.elementAt(i);
-      if (nodes.elementAt(j) != null)
-        nodes.elementAt(j).accept(box);
-    }
-    if (box.getBounds() == null)
-      return;
-    box.enlargeBoundingBox();
-    Main.map.mapView.zoomTo(box);
-  }
-
-  /* marks the nodes that correspond to the marked lines in the table.
-  If no lines are marked in the table, mark all nodes from the vector */
-  public static void markNodesFromTable(JTable table, Vector< Node > nodes)
-  {
-    OsmPrimitive[] osmp = { null };
-    Main.main.getCurrentDataSet().setSelected(osmp);
-    Vector< Integer > consideredLines = getConsideredLines(table);
-    for (int i = 0; i < consideredLines.size(); ++i)
-    {
-      int j = consideredLines.elementAt(i);
-      if (nodes.elementAt(j) != null)
-        Main.main.getCurrentDataSet().addSelected(nodes.elementAt(j));
-    }
-  }
-
-  public static String timeOf(double t)
-  {
-    t -= Math.floor(t/24/60/60)*24*60*60;
-
-    int hour = (int)Math.floor(t/60/60);
-    t -=  Math.floor(t/60/60)*60*60;
-    int minute = (int)Math.floor(t/60);
-    t -=  Math.floor(t/60)*60;
-    double second = t;
-
-    Format format = new DecimalFormat("00");
-    Format formatS = new DecimalFormat("00.###");
-    return (format.format(hour) + ":" + format.format(minute) + ":"
-    + formatS.format(second));
-  }
-
-  public Action getFocusWaypointNameAction()
-  {
-    return new FocusWaypointNameAction();
-  }
-
-  public Action getFocusWaypointShelterAction(String shelter)
-  {
-    return new FocusWaypointShelterAction(shelter);
-  }
-
-  public Action getFocusWaypointDeleteAction()
-  {
-    return new AbstractAction()
-    {
-      @Override
-    public void actionPerformed(ActionEvent e)
-      {
-        JTable table = dialog.getWaypointsTable();
-        int row = table.getEditingRow();
-        if (row < 0)
-          return;
+public class StopImporterAction extends JosmAction {
+    private static StopImporterDialog dialog = null;
+
+    private static DefaultListModel<TrackReference> tracksListModel = null;
+
+    private static GpxData data = null;
+
+    private static TrackReference currentTrack = null;
+
+    private static WaypointTableModel waypointTM = null;
+
+    public boolean inEvent = false;
+
+    /**
+     * Constructs a new {@code StopImporterAction}.
+     */
+    public StopImporterAction() {
+        super(tr("Create Stops from GPX ..."), null, tr("Create Stops from a GPX file"), null,
+                false);
+        putValue("toolbar", "publictransport/stopimporter");
+        Main.toolbar.register(this);
+    }
+
+    public WaypointTableModel getWaypointTableModel() {
+        return waypointTM;
+    }
+
+    public StopImporterDialog getDialog() {
+        return dialog;
+    }
+
+    public DefaultListModel<TrackReference> getTracksListModel() {
+        if (tracksListModel == null)
+            tracksListModel = new DefaultListModel<>();
+        return tracksListModel;
+    }
+
+    public TrackReference getCurrentTrack() {
+        return currentTrack;
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent event) {
+        if (dialog == null)
+            dialog = new StopImporterDialog(this);
+
+        dialog.setVisible(true);
+
+        if (tr("Create Stops from GPX ...").equals(event.getActionCommand())) {
+            String curDir = Main.pref.get("lastDirectory");
+            if (curDir.equals("")) {
+                curDir = ".";
+            }
+            JFileChooser fc = new JFileChooser(new File(curDir));
+            fc.setDialogTitle(tr("Select GPX file"));
+            fc.setMultiSelectionEnabled(false);
+
+            int answer = fc.showOpenDialog(Main.parent);
+            if (answer != JFileChooser.APPROVE_OPTION)
+                return;
+
+            if (!fc.getCurrentDirectory().getAbsolutePath().equals(curDir))
+                Main.pref.put("lastDirectory", fc.getCurrentDirectory().getAbsolutePath());
+
+            importData(fc.getSelectedFile());
+
+            refreshData();
+        } else if ("stopImporter.settingsGPSTimeStart".equals(event.getActionCommand())) {
+            if ((!inEvent) && (dialog.gpsTimeStartValid()) && (currentTrack != null))
+                Main.main.undoRedo.add(new TrackStoplistRelocateCommand(this));
+        } else if ("stopImporter.settingsStopwatchStart".equals(event.getActionCommand())) {
+            if ((!inEvent) && (dialog.stopwatchStartValid()) && (currentTrack != null))
+                Main.main.undoRedo.add(new TrackStoplistRelocateCommand(this));
+        } else if ("stopImporter.settingsTimeWindow".equals(event.getActionCommand())) {
+            if (currentTrack != null)
+                currentTrack.timeWindow = dialog.getTimeWindow();
+        } else if ("stopImporter.settingsThreshold".equals(event.getActionCommand())) {
+            if (currentTrack != null)
+                currentTrack.threshold = dialog.getThreshold();
+        } else if ("stopImporter.settingsSuggestStops".equals(event.getActionCommand()))
+            Main.main.undoRedo.add(new TrackSuggestStopsCommand(this));
+        else if ("stopImporter.stoplistFind".equals(event.getActionCommand()))
+            findNodesInTable(dialog.getStoplistTable(), currentTrack.stoplistTM.getNodes());
+        else if ("stopImporter.stoplistShow".equals(event.getActionCommand()))
+            showNodesFromTable(dialog.getStoplistTable(), currentTrack.stoplistTM.getNodes());
+        else if ("stopImporter.stoplistMark".equals(event.getActionCommand()))
+            markNodesFromTable(dialog.getStoplistTable(), currentTrack.stoplistTM.getNodes());
+        else if ("stopImporter.stoplistDetach".equals(event.getActionCommand())) {
+            Main.main.undoRedo.add(new TrackStoplistDetachCommand(this));
+            dialog.getStoplistTable().clearSelection();
+        } else if ("stopImporter.stoplistAdd".equals(event.getActionCommand()))
+            Main.main.undoRedo.add(new TrackStoplistAddCommand(this));
+        else if ("stopImporter.stoplistDelete".equals(event.getActionCommand()))
+            Main.main.undoRedo.add(new TrackStoplistDeleteCommand(this));
+        else if ("stopImporter.stoplistSort".equals(event.getActionCommand()))
+            Main.main.undoRedo.add(new TrackStoplistSortCommand(this));
+        else if ("stopImporter.waypointsFind".equals(event.getActionCommand()))
+            findNodesInTable(dialog.getWaypointsTable(), waypointTM.nodes);
+        else if ("stopImporter.waypointsShow".equals(event.getActionCommand()))
+            showNodesFromTable(dialog.getWaypointsTable(), waypointTM.nodes);
+        else if ("stopImporter.waypointsMark".equals(event.getActionCommand()))
+            markNodesFromTable(dialog.getWaypointsTable(), waypointTM.nodes);
+        else if ("stopImporter.waypointsDetach".equals(event.getActionCommand())) {
+            Main.main.undoRedo.add(new WaypointsDetachCommand(this));
+            dialog.getWaypointsTable().clearSelection();
+        } else if ("stopImporter.waypointsAdd".equals(event.getActionCommand()))
+            Main.main.undoRedo.add(new WaypointsEnableCommand(this));
+        else if ("stopImporter.waypointsDelete".equals(event.getActionCommand()))
+            Main.main.undoRedo.add(new WaypointsDisableCommand(this));
+        else if ("stopImporter.settingsStoptype".equals(event.getActionCommand()))
+            Main.main.undoRedo.add(new SettingsStoptypeCommand(this));
+    }
+
+    private void importData(final File file) {
+        try {
+            InputStream is;
+            if (file.getName().endsWith(".gpx.gz"))
+                is = new GZIPInputStream(new FileInputStream(file));
+            else
+                is = new FileInputStream(file);
+            // Workaround for SAX BOM bug
+            // https://bugs.openjdk.java.net/browse/JDK-6206835
+            if (!((is.read() == 0xef) && (is.read() == 0xbb) && (is.read() == 0xbf))) {
+                is.close();
+                if (file.getName().endsWith(".gpx.gz"))
+                    is = new GZIPInputStream(new FileInputStream(file));
+                else
+                    is = new FileInputStream(file);
+            }
+            final GpxReader r = new GpxReader(is);
+            final boolean parsedProperly = r.parse(true);
+            data = r.getGpxData();
+
+            if (!parsedProperly) {
+                JOptionPane.showMessageDialog(null,
+                        tr("Error occurred while parsing gpx file {0}. Only a part of the file will be available.",
+                                file.getName()));
+            }
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+            JOptionPane.showMessageDialog(null, tr("File \"{0}\" does not exist", file.getName()));
+        } catch (SAXException e) {
+            e.printStackTrace();
+            JOptionPane.showMessageDialog(null, tr("Parsing file \"{0}\" failed", file.getName()));
+        } catch (IOException e) {
+            e.printStackTrace();
+            JOptionPane.showMessageDialog(null, tr("IOException \"{0}\" occurred", e.toString()));
+        }
+    }
+
+    private void refreshData() {
+        tracksListModel.clear();
+        if (data != null) {
+            Vector<TrackReference> trackRefs = new Vector<>();
+            Iterator<GpxTrack> trackIter = data.tracks.iterator();
+            while (trackIter.hasNext()) {
+                GpxTrack track = trackIter.next();
+                trackRefs.add(new TrackReference(track, this));
+            }
+
+            Collections.sort(trackRefs);
+
+            Iterator<TrackReference> iter = trackRefs.iterator();
+            while (iter.hasNext())
+                tracksListModel.addElement(iter.next());
+
+            waypointTM = new WaypointTableModel(this);
+            Iterator<WayPoint> waypointIter = data.waypoints.iterator();
+            while (waypointIter.hasNext()) {
+                WayPoint waypoint = waypointIter.next();
+                waypointTM.addRow(waypoint);
+            }
+            dialog.setWaypointsTableModel(waypointTM);
+        } else {
+            JOptionPane.showMessageDialog(null,
+                    tr("The GPX file contained no tracks or waypoints."), tr("No data found"),
+                    JOptionPane.ERROR_MESSAGE);
+        }
+    }
+
+    public void tracksSelectionChanged(int selectedPos) {
+        if (selectedPos >= 0) {
+            currentTrack = (tracksListModel.elementAt(selectedPos));
+            dialog.setTrackValid(true);
+
+            // Prepare Settings
+            dialog.setSettings(currentTrack.gpsSyncTime, currentTrack.stopwatchStart,
+                    currentTrack.timeWindow, currentTrack.threshold);
+
+            // Prepare Stoplist
+            dialog.setStoplistTableModel(tracksListModel.elementAt(selectedPos).stoplistTM);
+        } else {
+            currentTrack = null;
+            dialog.setTrackValid(false);
+        }
+    }
+
+    public Node createNode(LatLon latLon, String name) {
+        return createNode(latLon, dialog.getStoptype(), name);
+    }
+
+    public static Node createNode(LatLon latLon, String type, String name) {
+        Node node = new Node(latLon);
+        setTagsWrtType(node, type);
+        node.put("name", name);
+        DataSet ds = Main.getLayerManager().getEditDataSet();
+        if (ds == null) {
+            JOptionPane.showMessageDialog(null,
+                    tr("There exists no dataset."
+                            + " Try to download data from the server or open an OSM file."),
+                    tr("No data found"), JOptionPane.ERROR_MESSAGE);
+
+            return null;
+        }
+        ds.addPrimitive(node);
+        return node;
+    }
+
+    /** sets the tags of the node according to the type */
+    public static void setTagsWrtType(Node node, String type) {
+        node.remove("highway");
+        node.remove("railway");
+        if ("bus".equals(type))
+            node.put("highway", "bus_stop");
+        else if ("tram".equals(type))
+            node.put("railway", "tram_stop");
+        else if ("light_rail".equals(type))
+            node.put("railway", "station");
+        else if ("subway".equals(type))
+            node.put("railway", "station");
+        else if ("rail".equals(type))
+            node.put("railway", "station");
+    }
+
+    /**
+     * returns a collection of all selected lines or a collection of all lines otherwise
+     */
+    public static Vector<Integer> getConsideredLines(JTable table) {
+        int[] selectedLines = table.getSelectedRows();
+        Vector<Integer> consideredLines = new Vector<>();
+        if (selectedLines.length > 0) {
+            for (int i = 0; i < selectedLines.length; ++i)
+                consideredLines.add(selectedLines[i]);
+        } else {
+            for (int i = 0; i < table.getRowCount(); ++i)
+                consideredLines.add(new Integer(i));
+        }
+        return consideredLines;
+    }
+
+    /** marks the table items whose nodes are marked on the map */
+    public static void findNodesInTable(JTable table, Vector<Node> nodes) {
+        DataSet ds = Main.getLayerManager().getEditDataSet();
+        if (ds == null)
+            return;
+
         table.clearSelection();
-        table.addRowSelectionInterval(row, row);
-        Main.main.undoRedo.add
-        (new WaypointsDisableCommand(StopImporterAction.this));
-      }
-    };
-  }
-
-  public Action getFocusTrackStoplistNameAction()
-  {
-    return new FocusTrackStoplistNameAction();
-  }
-
-  public Action getFocusTrackStoplistShelterAction(String shelter)
-  {
-    return new FocusTrackStoplistShelterAction(shelter);
-  }
-
-  public Action getFocusStoplistDeleteAction()
-  {
-    return new AbstractAction()
-    {
-      @Override
-    public void actionPerformed(ActionEvent e)
-      {
-        JTable table = dialog.getStoplistTable();
-        int row = table.getEditingRow();
-        if (row < 0)
-          return;
-        table.clearSelection();
-        table.addRowSelectionInterval(row, row);
-        Main.main.undoRedo.add
-            (new TrackStoplistDeleteCommand(StopImporterAction.this));
-      }
-    };
-  }
-
-  private class FocusWaypointNameAction extends AbstractAction
-  {
-    @Override
-    public void actionPerformed(ActionEvent e)
-    {
-      JTable table = dialog.getWaypointsTable();
-      showNodesFromTable(table, waypointTM.nodes);
-      markNodesFromTable(table, waypointTM.nodes);
-      int row = table.getEditingRow();
-      if (row < 0)
-        row = 0;
-      waypointTM.inEvent = true;
-      if (table.getCellEditor() != null)
-      {
-        if (!table.getCellEditor().stopCellEditing())
-          table.getCellEditor().cancelCellEditing();
-      }
-      table.editCellAt(row, 1);
-      table.getCellEditor().getTableCellEditorComponent
-      (table, "", true, row, 1);
-      waypointTM.inEvent = false;
-    }
-  };
-
-  private class FocusWaypointShelterAction extends AbstractAction
-  {
-    private String defaultShelter = null;
-
-    public FocusWaypointShelterAction(String defaultShelter)
-    {
-      this.defaultShelter = defaultShelter;
-    }
-
-    @Override
-    public void actionPerformed(ActionEvent e)
-    {
-      JTable table = dialog.getWaypointsTable();
-      showNodesFromTable(table, waypointTM.nodes);
-      markNodesFromTable(table, waypointTM.nodes);
-      int row = table.getEditingRow();
-      if (row < 0)
-        row = 0;
-      waypointTM.inEvent = true;
-      if (table.getCellEditor() != null)
-      {
-        if (!table.getCellEditor().stopCellEditing())
-          table.getCellEditor().cancelCellEditing();
-      }
-      table.editCellAt(row, 2);
-      waypointTM.inEvent = false;
-      table.getCellEditor().getTableCellEditorComponent
-          (table, defaultShelter, true, row, 2);
-    }
-  };
-
-  private class FocusTrackStoplistNameAction extends AbstractAction
-  {
-    @Override
-    public void actionPerformed(ActionEvent e)
-    {
-      JTable table = dialog.getStoplistTable();
-      showNodesFromTable(table, currentTrack.stoplistTM.getNodes());
-      markNodesFromTable(table, currentTrack.stoplistTM.getNodes());
-      int row = table.getEditingRow();
-      if (row < 0)
-        row = 0;
-      currentTrack.inEvent = true;
-      if (table.getCellEditor() != null)
-      {
-        if (!table.getCellEditor().stopCellEditing())
-          table.getCellEditor().cancelCellEditing();
-      }
-      table.editCellAt(row, 1);
-      table.getCellEditor().getTableCellEditorComponent
-          (table, "", true, row, 1);
-      currentTrack.inEvent = false;
-    }
-  };
-
-  private class FocusTrackStoplistShelterAction extends AbstractAction
-  {
-    private String defaultShelter = null;
-
-    public FocusTrackStoplistShelterAction(String defaultShelter)
-    {
-      this.defaultShelter = defaultShelter;
-    }
-
-    @Override
-    public void actionPerformed(ActionEvent e)
-    {
-      JTable table = dialog.getStoplistTable();
-      showNodesFromTable(table, currentTrack.stoplistTM.getNodes());
-      markNodesFromTable(table, currentTrack.stoplistTM.getNodes());
-      int row = table.getEditingRow();
-      if (row < 0)
-        row = 0;
-      currentTrack.inEvent = true;
-      if (table.getCellEditor() != null)
-      {
-        if (!table.getCellEditor().stopCellEditing())
-          table.getCellEditor().cancelCellEditing();
-      }
-      table.editCellAt(row, 2);
-      currentTrack.inEvent = false;
-      table.getCellEditor().getTableCellEditorComponent
-          (table, defaultShelter, true, row, 2);
-    }
-  };
+
+        for (int i = 0; i < table.getRowCount(); ++i) {
+            if ((nodes.elementAt(i) != null) && (ds.isSelected(nodes.elementAt(i))))
+                table.addRowSelectionInterval(i, i);
+        }
+    }
+
+    /**
+     * shows the nodes that correspond to the marked lines in the table. If no lines are marked in the table, show all nodes from the vector
+     */
+    public static void showNodesFromTable(JTable table, Vector<Node> nodes) {
+        BoundingXYVisitor box = new BoundingXYVisitor();
+        Vector<Integer> consideredLines = getConsideredLines(table);
+        for (int i = 0; i < consideredLines.size(); ++i) {
+            int j = consideredLines.elementAt(i);
+            if (nodes.elementAt(j) != null)
+                nodes.elementAt(j).accept(box);
+        }
+        if (box.getBounds() == null)
+            return;
+        box.enlargeBoundingBox();
+        Main.map.mapView.zoomTo(box);
+    }
+
+    /**
+     * marks the nodes that correspond to the marked lines in the table. If no lines are marked in the table, mark all nodes from the vector
+     */
+    public static void markNodesFromTable(JTable table, Vector<Node> nodes) {
+        OsmPrimitive[] osmp = { null };
+        DataSet ds = Main.getLayerManager().getEditDataSet();
+        ds.setSelected(osmp);
+        Vector<Integer> consideredLines = getConsideredLines(table);
+        for (int i = 0; i < consideredLines.size(); ++i) {
+            int j = consideredLines.elementAt(i);
+            if (nodes.elementAt(j) != null)
+                ds.addSelected(nodes.elementAt(j));
+        }
+    }
+
+    public static String timeOf(double t) {
+        t -= Math.floor(t / 24 / 60 / 60) * 24 * 60 * 60;
+
+        int hour = (int) Math.floor(t / 60 / 60);
+        t -= Math.floor(t / 60 / 60) * 60 * 60;
+        int minute = (int) Math.floor(t / 60);
+        t -= Math.floor(t / 60) * 60;
+        double second = t;
+
+        Format format = new DecimalFormat("00");
+        Format formatS = new DecimalFormat("00.###");
+        return (format.format(hour) + ":" + format.format(minute) + ":" + formatS.format(second));
+    }
+
+    public Action getFocusWaypointNameAction() {
+        return new FocusWaypointNameAction();
+    }
+
+    public Action getFocusWaypointShelterAction(String shelter) {
+        return new FocusWaypointShelterAction(shelter);
+    }
+
+    public Action getFocusWaypointDeleteAction() {
+        return new AbstractAction() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                JTable table = dialog.getWaypointsTable();
+                int row = table.getEditingRow();
+                if (row < 0)
+                    return;
+                table.clearSelection();
+                table.addRowSelectionInterval(row, row);
+                Main.main.undoRedo.add(new WaypointsDisableCommand(StopImporterAction.this));
+            }
+        };
+    }
+
+    public Action getFocusTrackStoplistNameAction() {
+        return new FocusTrackStoplistNameAction();
+    }
+
+    public Action getFocusTrackStoplistShelterAction(String shelter) {
+        return new FocusTrackStoplistShelterAction(shelter);
+    }
+
+    public Action getFocusStoplistDeleteAction() {
+        return new AbstractAction() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                JTable table = dialog.getStoplistTable();
+                int row = table.getEditingRow();
+                if (row < 0)
+                    return;
+                table.clearSelection();
+                table.addRowSelectionInterval(row, row);
+                Main.main.undoRedo.add(new TrackStoplistDeleteCommand(StopImporterAction.this));
+            }
+        };
+    }
+
+    private class FocusWaypointNameAction extends AbstractAction {
+        @Override
+        public void actionPerformed(ActionEvent e) {
+            JTable table = dialog.getWaypointsTable();
+            showNodesFromTable(table, waypointTM.nodes);
+            markNodesFromTable(table, waypointTM.nodes);
+            int row = table.getEditingRow();
+            if (row < 0)
+                row = 0;
+            waypointTM.inEvent = true;
+            if (table.getCellEditor() != null) {
+                if (!table.getCellEditor().stopCellEditing())
+                    table.getCellEditor().cancelCellEditing();
+            }
+            table.editCellAt(row, 1);
+            table.getCellEditor().getTableCellEditorComponent(table, "", true, row, 1);
+            waypointTM.inEvent = false;
+        }
+    }
+
+    private class FocusWaypointShelterAction extends AbstractAction {
+        private String defaultShelter = null;
+
+        public FocusWaypointShelterAction(String defaultShelter) {
+            this.defaultShelter = defaultShelter;
+        }
+
+        @Override
+        public void actionPerformed(ActionEvent e) {
+            JTable table = dialog.getWaypointsTable();
+            showNodesFromTable(table, waypointTM.nodes);
+            markNodesFromTable(table, waypointTM.nodes);
+            int row = table.getEditingRow();
+            if (row < 0)
+                row = 0;
+            waypointTM.inEvent = true;
+            if (table.getCellEditor() != null) {
+                if (!table.getCellEditor().stopCellEditing())
+                    table.getCellEditor().cancelCellEditing();
+            }
+            table.editCellAt(row, 2);
+            waypointTM.inEvent = false;
+            table.getCellEditor().getTableCellEditorComponent(table, defaultShelter, true, row, 2);
+        }
+    }
+
+    private class FocusTrackStoplistNameAction extends AbstractAction {
+        @Override
+        public void actionPerformed(ActionEvent e) {
+            JTable table = dialog.getStoplistTable();
+            showNodesFromTable(table, currentTrack.stoplistTM.getNodes());
+            markNodesFromTable(table, currentTrack.stoplistTM.getNodes());
+            int row = table.getEditingRow();
+            if (row < 0)
+                row = 0;
+            currentTrack.inEvent = true;
+            if (table.getCellEditor() != null) {
+                if (!table.getCellEditor().stopCellEditing())
+                    table.getCellEditor().cancelCellEditing();
+            }
+            table.editCellAt(row, 1);
+            table.getCellEditor().getTableCellEditorComponent(table, "", true, row, 1);
+            currentTrack.inEvent = false;
+        }
+    }
+
+    private class FocusTrackStoplistShelterAction extends AbstractAction {
+        private String defaultShelter = null;
+
+        public FocusTrackStoplistShelterAction(String defaultShelter) {
+            this.defaultShelter = defaultShelter;
+        }
+
+        @Override
+        public void actionPerformed(ActionEvent e) {
+            JTable table = dialog.getStoplistTable();
+            showNodesFromTable(table, currentTrack.stoplistTM.getNodes());
+            markNodesFromTable(table, currentTrack.stoplistTM.getNodes());
+            int row = table.getEditingRow();
+            if (row < 0)
+                row = 0;
+            currentTrack.inEvent = true;
+            if (table.getCellEditor() != null) {
+                if (!table.getCellEditor().stopCellEditing())
+                    table.getCellEditor().cancelCellEditing();
+            }
+            table.editCellAt(row, 2);
+            currentTrack.inEvent = false;
+            table.getCellEditor().getTableCellEditorComponent(table, defaultShelter, true, row, 2);
+        }
+    }
 }
Index: /applications/editors/josm/plugins/public_transport/src/public_transport/StopImporterDialog.java
===================================================================
--- /applications/editors/josm/plugins/public_transport/src/public_transport/StopImporterDialog.java	(revision 32356)
+++ /applications/editors/josm/plugins/public_transport/src/public_transport/StopImporterDialog.java	(revision 32357)
@@ -22,548 +22,531 @@
 import javax.swing.event.ListSelectionListener;
 
-public class StopImporterDialog extends AbstractImporterDialog<StopImporterAction>
-{
-  private JList<TrackReference> tracksList = null;
-  private JTable stoplistTable = null;
-  private JTable waypointTable = null;
-
-  public StopImporterDialog(StopImporterAction controller)
-  {
-      super(controller, tr("Create Stops from GPX"), "stopImporter");
-  }
-  
-  @Override
-  protected void initDialog(StopImporterAction controller) {
-    JPanel tabTracks = new JPanel();
-    tabbedPane.addTab(tr("Tracks"), tabTracks);
-    JPanel tabSettings = new JPanel();
-    tabbedPane.addTab(tr("Settings"), tabSettings);
-    JPanel tabStops = new JPanel();
-    tabbedPane.addTab(tr("Stops"), tabStops);
-    JPanel tabWaypoints = new JPanel();
-    tabbedPane.addTab(tr("Waypoints"), tabWaypoints);
-    tabbedPane.setEnabledAt(0, true);
-    tabbedPane.setEnabledAt(1, true);
-    tabbedPane.setEnabledAt(2, false);
-    tabbedPane.setEnabledAt(3, true);
-
-    //Tracks Tab
-    JPanel contentPane = tabTracks;
-    GridBagLayout gridbag = new GridBagLayout();
-    GridBagConstraints layoutCons = new GridBagConstraints();
-    contentPane.setLayout(gridbag);
-
-    JLabel label = new JLabel(tr("Tracks in this GPX file:"));
-
-    layoutCons.gridx = 0;
-    layoutCons.gridy = 0;
-    layoutCons.gridwidth = 3;
-    layoutCons.weightx = 0.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(label, layoutCons);
-    contentPane.add(label);
-
-    DefaultListModel<TrackReference> tracksListModel = controller.getTracksListModel();
-    tracksList = new JList<>(tracksListModel);
-    JScrollPane rpListSP = new JScrollPane(tracksList);
-    String[] data = {"1", "2", "3", "4", "5", "6"};
-    tracksListModel.copyInto(data);
-    tracksList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
-    tracksList.addListSelectionListener(new TracksLSL(controller));
-
-    layoutCons.gridx = 0;
-    layoutCons.gridy = 1;
-    layoutCons.gridwidth = 3;
-    layoutCons.weightx = 1.0;
-    layoutCons.weighty = 1.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(rpListSP, layoutCons);
-    contentPane.add(rpListSP);
-
-    //Settings Tab
-    contentPane = tabSettings;
-    gridbag = new GridBagLayout();
-    layoutCons = new GridBagConstraints();
-    contentPane.setLayout(gridbag);
-
-    label = new JLabel(tr("Type of stops to add"));
-
-    layoutCons.gridx = 0;
-    layoutCons.gridy = 0;
-    layoutCons.gridwidth = 2;
-    layoutCons.weightx = 0.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(label, layoutCons);
-    contentPane.add(label);
-
-    layoutCons.gridx = 0;
-    layoutCons.gridy = 1;
-    layoutCons.gridwidth = 1;
-    layoutCons.weightx = 0.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(cbStoptype, layoutCons);
-    contentPane.add(cbStoptype);
-
-    label = new JLabel(tr("Time on your GPS device"));
-
-    layoutCons.gridx = 0;
-    layoutCons.gridy = 2;
-    layoutCons.gridwidth = 2;
-    layoutCons.weightx = 0.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(label, layoutCons);
-    contentPane.add(label);
-
-    layoutCons.gridx = 0;
-    layoutCons.gridy = 3;
-    layoutCons.gridwidth = 1;
-    layoutCons.weightx = 0.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(tfGPSTimeStart, layoutCons);
-    contentPane.add(tfGPSTimeStart);
-
-    label = new JLabel(tr("HH:MM:SS.sss"));
-
-    layoutCons.gridx = 1;
-    layoutCons.gridy = 3;
-    layoutCons.gridwidth = 1;
-    layoutCons.weightx = 0.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(label, layoutCons);
-    contentPane.add(label);
-
-    label = new JLabel(tr("Time on your stopwatch"));
-
-    layoutCons.gridx = 0;
-    layoutCons.gridy = 4;
-    layoutCons.gridwidth = 2;
-    layoutCons.weightx = 0.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(label, layoutCons);
-    contentPane.add(label);
-
-    layoutCons.gridx = 0;
-    layoutCons.gridy = 5;
-    layoutCons.gridwidth = 1;
-    layoutCons.weightx = 0.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(tfStopwatchStart, layoutCons);
-    contentPane.add(tfStopwatchStart);
-
-    label = new JLabel(tr("HH:MM:SS.sss"));
-
-    layoutCons.gridx = 1;
-    layoutCons.gridy = 5;
-    layoutCons.gridwidth = 1;
-    layoutCons.weightx = 0.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(label, layoutCons);
-    contentPane.add(label);
-
-    label = new JLabel(tr("Time window"));
-
-    layoutCons.gridx = 0;
-    layoutCons.gridy = 6;
-    layoutCons.gridwidth = 2;
-    layoutCons.weightx = 0.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(label, layoutCons);
-    contentPane.add(label);
-
-    layoutCons.gridx = 0;
-    layoutCons.gridy = 7;
-    layoutCons.gridwidth = 1;
-    layoutCons.weightx = 0.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(tfTimeWindow, layoutCons);
-    contentPane.add(tfTimeWindow);
-
-    label = new JLabel(tr("seconds"));
-
-    layoutCons.gridx = 1;
-    layoutCons.gridy = 7;
-    layoutCons.gridwidth = 1;
-    layoutCons.weightx = 0.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(label, layoutCons);
-    contentPane.add(label);
-
-    label = new JLabel(tr("Move Threshold"));
-
-    layoutCons.gridx = 0;
-    layoutCons.gridy = 8;
-    layoutCons.gridwidth = 2;
-    layoutCons.weightx = 0.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(label, layoutCons);
-    contentPane.add(label);
-
-    layoutCons.gridx = 0;
-    layoutCons.gridy = 9;
-    layoutCons.gridwidth = 1;
-    layoutCons.weightx = 0.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(tfThreshold, layoutCons);
-    contentPane.add(tfThreshold);
-
-    label = new JLabel(tr("meters"));
-
-    layoutCons.gridx = 1;
-    layoutCons.gridy = 9;
-    layoutCons.gridwidth = 1;
-    layoutCons.weightx = 0.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(label, layoutCons);
-    contentPane.add(label);
-
-    JButton bSuggestStops = new JButton(tr("Suggest Stops"));
-    bSuggestStops.setActionCommand("stopImporter.settingsSuggestStops");
-    bSuggestStops.addActionListener(controller);
-
-    layoutCons.gridx = 0;
-    layoutCons.gridy = 10;
-    layoutCons.gridwidth = 3;
-    layoutCons.weightx = 1.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(bSuggestStops, layoutCons);
-    contentPane.add(bSuggestStops);
-
-    //Stops Tab
-    contentPane = tabStops;
-    gridbag = new GridBagLayout();
-    layoutCons = new GridBagConstraints();
-    contentPane.setLayout(gridbag);
-    contentPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put
-        (KeyStroke.getKeyStroke("alt N"), "stopImporter.focusName");
-    contentPane.getActionMap().put
-    ("stopImporter.focusName", controller.getFocusTrackStoplistNameAction());
-    contentPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put
-        (KeyStroke.getKeyStroke("alt S"), "stopImporter.focusShelterYes");
-    contentPane.getActionMap().put
-    ("stopImporter.focusShelterYes",
-     controller.getFocusTrackStoplistShelterAction("yes"));
-    contentPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put
-        (KeyStroke.getKeyStroke("alt T"), "stopImporter.focusShelterNo");
-    contentPane.getActionMap().put
-    ("stopImporter.focusShelterNo",
-     controller.getFocusTrackStoplistShelterAction("no"));
-    contentPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put
-        (KeyStroke.getKeyStroke("alt U"), "stopImporter.focusShelterImplicit");
-    contentPane.getActionMap().put
-    ("stopImporter.focusShelterImplicit",
-     controller.getFocusTrackStoplistShelterAction("implicit"));
-    contentPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put
-        (KeyStroke.getKeyStroke("alt D"), "stopImporter.stoplistDelete");
-    contentPane.getActionMap().put
-    ("stopImporter.stoplistDelete",
-     controller.getFocusStoplistDeleteAction());
-
-    stoplistTable = new JTable();
-    JScrollPane tableSP = new JScrollPane(stoplistTable);
-
-    layoutCons.gridx = 0;
-    layoutCons.gridy = 0;
-    layoutCons.gridwidth = 4;
-    layoutCons.weightx = 1.0;
-    layoutCons.weighty = 1.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(tableSP, layoutCons);
-    contentPane.add(tableSP);
-
-    JButton bFind = new JButton(tr("Find"));
-    bFind.setActionCommand("stopImporter.stoplistFind");
-    bFind.addActionListener(controller);
-
-    layoutCons.gridx = 0;
-    layoutCons.gridy = 1;
-    layoutCons.gridwidth = 1;
-    layoutCons.weightx = 1.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(bFind, layoutCons);
-    contentPane.add(bFind);
-
-    JButton bShow = new JButton(tr("Show"));
-    bShow.setActionCommand("stopImporter.stoplistShow");
-    bShow.addActionListener(controller);
-
-    layoutCons.gridx = 0;
-    layoutCons.gridy = 2;
-    layoutCons.gridwidth = 1;
-    layoutCons.weightx = 1.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(bShow, layoutCons);
-    contentPane.add(bShow);
-
-    JButton bMark = new JButton(tr("Mark"));
-    bMark.setActionCommand("stopImporter.stoplistMark");
-    bMark.addActionListener(controller);
-
-    layoutCons.gridx = 1;
-    layoutCons.gridy = 1;
-    layoutCons.gridheight = 1;
-    layoutCons.gridwidth = 1;
-    layoutCons.weightx = 1.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(bMark, layoutCons);
-    contentPane.add(bMark);
-
-    JButton bDetach = new JButton(tr("Detach"));
-    bDetach.setActionCommand("stopImporter.stoplistDetach");
-    bDetach.addActionListener(controller);
-
-    layoutCons.gridx = 1;
-    layoutCons.gridy = 2;
-    layoutCons.gridheight = 1;
-    layoutCons.gridwidth = 1;
-    layoutCons.weightx = 1.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(bDetach, layoutCons);
-    contentPane.add(bDetach);
-
-    JButton bAdd = new JButton(tr("Add"));
-    bAdd.setActionCommand("stopImporter.stoplistAdd");
-    bAdd.addActionListener(controller);
-
-    layoutCons.gridx = 2;
-    layoutCons.gridy = 1;
-    layoutCons.gridheight = 1;
-    layoutCons.gridwidth = 1;
-    layoutCons.weightx = 1.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(bAdd, layoutCons);
-    contentPane.add(bAdd);
-
-    JButton bDelete = new JButton(tr("Delete"));
-    bDelete.setActionCommand("stopImporter.stoplistDelete");
-    bDelete.addActionListener(controller);
-
-    layoutCons.gridx = 2;
-    layoutCons.gridy = 2;
-    layoutCons.gridwidth = 1;
-    layoutCons.weightx = 1.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(bDelete, layoutCons);
-    contentPane.add(bDelete);
-
-    JButton bSort = new JButton(tr("Sort"));
-    bSort.setActionCommand("stopImporter.stoplistSort");
-    bSort.addActionListener(controller);
-
-    layoutCons.gridx = 3;
-    layoutCons.gridy = 1;
-    layoutCons.gridheight = 2;
-    layoutCons.gridwidth = 1;
-    layoutCons.weightx = 1.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(bSort, layoutCons);
-    contentPane.add(bSort);
-
-    //Waypoints Tab
-    contentPane = tabWaypoints;
-    gridbag = new GridBagLayout();
-    layoutCons = new GridBagConstraints();
-    contentPane.setLayout(gridbag);
-    contentPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put
-        (KeyStroke.getKeyStroke("alt N"), "stopImporter.focusName");
-    contentPane.getActionMap().put
-    ("stopImporter.focusName", controller.getFocusWaypointNameAction());
-    contentPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put
-        (KeyStroke.getKeyStroke("alt S"), "stopImporter.focusShelterYes");
-    contentPane.getActionMap().put
-    ("stopImporter.focusShelterYes",
-     controller.getFocusWaypointShelterAction("yes"));
-    contentPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put
-        (KeyStroke.getKeyStroke("alt T"), "stopImporter.focusShelterNo");
-    contentPane.getActionMap().put
-    ("stopImporter.focusShelterNo",
-     controller.getFocusWaypointShelterAction("no"));
-    contentPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put
-        (KeyStroke.getKeyStroke("alt U"), "stopImporter.focusShelterImplicit");
-    contentPane.getActionMap().put
-    ("stopImporter.focusShelterImplicit",
-     controller.getFocusWaypointShelterAction("implicit"));
-    contentPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put
-        (KeyStroke.getKeyStroke("alt D"), "stopImporter.waypointsDelete");
-    contentPane.getActionMap().put
-    ("stopImporter.waypointsDelete",
-     controller.getFocusWaypointDeleteAction());
-
-    waypointTable = new JTable();
-    tableSP = new JScrollPane(waypointTable);
-
-    layoutCons.gridx = 0;
-    layoutCons.gridy = 0;
-    layoutCons.gridwidth = 3;
-    layoutCons.weightx = 1.0;
-    layoutCons.weighty = 1.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(tableSP, layoutCons);
-    contentPane.add(tableSP);
-
-    bFind = new JButton(tr("Find"));
-    bFind.setActionCommand("stopImporter.waypointsFind");
-    bFind.addActionListener(controller);
-
-    layoutCons.gridx = 0;
-    layoutCons.gridy = 1;
-    layoutCons.gridwidth = 1;
-    layoutCons.weightx = 1.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(bFind, layoutCons);
-    contentPane.add(bFind);
-
-    bShow = new JButton(tr("Show"));
-    bShow.setActionCommand("stopImporter.waypointsShow");
-    bShow.addActionListener(controller);
-
-    layoutCons.gridx = 0;
-    layoutCons.gridy = 2;
-    layoutCons.gridwidth = 1;
-    layoutCons.weightx = 1.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(bShow, layoutCons);
-    contentPane.add(bShow);
-
-    bMark = new JButton(tr("Mark"));
-    bMark.setActionCommand("stopImporter.waypointsMark");
-    bMark.addActionListener(controller);
-
-    layoutCons.gridx = 1;
-    layoutCons.gridy = 1;
-    layoutCons.gridheight = 1;
-    layoutCons.gridwidth = 1;
-    layoutCons.weightx = 1.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(bMark, layoutCons);
-    contentPane.add(bMark);
-
-    bDetach = new JButton(tr("Detach"));
-    bDetach.setActionCommand("stopImporter.waypointsDetach");
-    bDetach.addActionListener(controller);
-
-    layoutCons.gridx = 1;
-    layoutCons.gridy = 2;
-    layoutCons.gridheight = 1;
-    layoutCons.gridwidth = 1;
-    layoutCons.weightx = 1.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(bDetach, layoutCons);
-    contentPane.add(bDetach);
-
-    bAdd = new JButton(tr("Enable"));
-    bAdd.setActionCommand("stopImporter.waypointsAdd");
-    bAdd.addActionListener(controller);
-
-    layoutCons.gridx = 2;
-    layoutCons.gridy = 1;
-    layoutCons.gridheight = 1;
-    layoutCons.gridwidth = 1;
-    layoutCons.weightx = 1.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(bAdd, layoutCons);
-    contentPane.add(bAdd);
-
-    bDelete = new JButton(tr("Disable"));
-    bDelete.setActionCommand("stopImporter.waypointsDelete");
-    bDelete.addActionListener(controller);
-
-    layoutCons.gridx = 2;
-    layoutCons.gridy = 2;
-    layoutCons.gridwidth = 1;
-    layoutCons.weightx = 1.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(bDelete, layoutCons);
-    contentPane.add(bDelete);
-  }
-
-  public JTable getStoplistTable()
-  {
-    return stoplistTable;
-  }
-
-  public void setStoplistTableModel(TrackStoplistTableModel model)
-  {
-    stoplistTable.setModel(model);
-    JComboBox<TransText> comboBox = new JComboBox<>();
-    comboBox.addItem(new TransText(null));
-    comboBox.addItem(new TransText(marktr("yes")));
-    comboBox.addItem(new TransText(marktr("no")));
-    comboBox.addItem(new TransText(marktr("implicit")));
-    stoplistTable.getColumnModel().getColumn(2)
-    .setCellEditor(new DefaultCellEditor(comboBox));
-    int width = stoplistTable.getPreferredSize().width;
-    stoplistTable.getColumnModel().getColumn(0).setPreferredWidth((int)(width * 0.4));
-    stoplistTable.getColumnModel().getColumn(1).setPreferredWidth((int)(width * 0.5));
-    stoplistTable.getColumnModel().getColumn(2).setPreferredWidth((int)(width * 0.1));
-  }
-
-  public JTable getWaypointsTable()
-  {
-    return waypointTable;
-  }
-
-  public void setWaypointsTableModel(WaypointTableModel model)
-  {
-    waypointTable.setModel(model);
-    JComboBox<TransText> comboBox = new JComboBox<>();
-    comboBox.addItem(new TransText(null));
-    comboBox.addItem(new TransText(marktr("yes")));
-    comboBox.addItem(new TransText(marktr("no")));
-    comboBox.addItem(new TransText(marktr("implicit")));
-    waypointTable.getColumnModel().getColumn(2)
-    .setCellEditor(new DefaultCellEditor(comboBox));
-    int width = waypointTable.getPreferredSize().width;
-    waypointTable.getColumnModel().getColumn(0).setPreferredWidth((int)(width * 0.4));
-    waypointTable.getColumnModel().getColumn(1).setPreferredWidth((int)(width * 0.5));
-    waypointTable.getColumnModel().getColumn(2).setPreferredWidth((int)(width * 0.1));
-  }
-
-  private class TracksLSL implements ListSelectionListener
-  {
-    StopImporterAction root = null;
-
-    public TracksLSL(StopImporterAction sia)
-    {
-      root = sia;
+public class StopImporterDialog extends AbstractImporterDialog<StopImporterAction> {
+    private JList<TrackReference> tracksList = null;
+
+    private JTable stoplistTable = null;
+
+    private JTable waypointTable = null;
+
+    public StopImporterDialog(StopImporterAction controller) {
+        super(controller, tr("Create Stops from GPX"), "stopImporter");
     }
 
     @Override
-    public void valueChanged(ListSelectionEvent e)
-    {
-      int selectedPos = tracksList.getAnchorSelectionIndex();
-      if (tracksList.isSelectedIndex(selectedPos))
-        root.tracksSelectionChanged(selectedPos);
-      else
-        root.tracksSelectionChanged(-1);
+    protected void initDialog(StopImporterAction controller) {
+        JPanel tabTracks = new JPanel();
+        tabbedPane.addTab(tr("Tracks"), tabTracks);
+        JPanel tabSettings = new JPanel();
+        tabbedPane.addTab(tr("Settings"), tabSettings);
+        JPanel tabStops = new JPanel();
+        tabbedPane.addTab(tr("Stops"), tabStops);
+        JPanel tabWaypoints = new JPanel();
+        tabbedPane.addTab(tr("Waypoints"), tabWaypoints);
+        tabbedPane.setEnabledAt(0, true);
+        tabbedPane.setEnabledAt(1, true);
+        tabbedPane.setEnabledAt(2, false);
+        tabbedPane.setEnabledAt(3, true);
+
+        // Tracks Tab
+        JPanel contentPane = tabTracks;
+        GridBagLayout gridbag = new GridBagLayout();
+        GridBagConstraints layoutCons = new GridBagConstraints();
+        contentPane.setLayout(gridbag);
+
+        JLabel label = new JLabel(tr("Tracks in this GPX file:"));
+
+        layoutCons.gridx = 0;
+        layoutCons.gridy = 0;
+        layoutCons.gridwidth = 3;
+        layoutCons.weightx = 0.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(label, layoutCons);
+        contentPane.add(label);
+
+        DefaultListModel<TrackReference> tracksListModel = controller.getTracksListModel();
+        tracksList = new JList<>(tracksListModel);
+        JScrollPane rpListSP = new JScrollPane(tracksList);
+        String[] data = { "1", "2", "3", "4", "5", "6" };
+        tracksListModel.copyInto(data);
+        tracksList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+        tracksList.addListSelectionListener(new TracksLSL(controller));
+
+        layoutCons.gridx = 0;
+        layoutCons.gridy = 1;
+        layoutCons.gridwidth = 3;
+        layoutCons.weightx = 1.0;
+        layoutCons.weighty = 1.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(rpListSP, layoutCons);
+        contentPane.add(rpListSP);
+
+        // Settings Tab
+        contentPane = tabSettings;
+        gridbag = new GridBagLayout();
+        layoutCons = new GridBagConstraints();
+        contentPane.setLayout(gridbag);
+
+        label = new JLabel(tr("Type of stops to add"));
+
+        layoutCons.gridx = 0;
+        layoutCons.gridy = 0;
+        layoutCons.gridwidth = 2;
+        layoutCons.weightx = 0.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(label, layoutCons);
+        contentPane.add(label);
+
+        layoutCons.gridx = 0;
+        layoutCons.gridy = 1;
+        layoutCons.gridwidth = 1;
+        layoutCons.weightx = 0.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(cbStoptype, layoutCons);
+        contentPane.add(cbStoptype);
+
+        label = new JLabel(tr("Time on your GPS device"));
+
+        layoutCons.gridx = 0;
+        layoutCons.gridy = 2;
+        layoutCons.gridwidth = 2;
+        layoutCons.weightx = 0.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(label, layoutCons);
+        contentPane.add(label);
+
+        layoutCons.gridx = 0;
+        layoutCons.gridy = 3;
+        layoutCons.gridwidth = 1;
+        layoutCons.weightx = 0.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(tfGPSTimeStart, layoutCons);
+        contentPane.add(tfGPSTimeStart);
+
+        label = new JLabel(tr("HH:MM:SS.sss"));
+
+        layoutCons.gridx = 1;
+        layoutCons.gridy = 3;
+        layoutCons.gridwidth = 1;
+        layoutCons.weightx = 0.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(label, layoutCons);
+        contentPane.add(label);
+
+        label = new JLabel(tr("Time on your stopwatch"));
+
+        layoutCons.gridx = 0;
+        layoutCons.gridy = 4;
+        layoutCons.gridwidth = 2;
+        layoutCons.weightx = 0.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(label, layoutCons);
+        contentPane.add(label);
+
+        layoutCons.gridx = 0;
+        layoutCons.gridy = 5;
+        layoutCons.gridwidth = 1;
+        layoutCons.weightx = 0.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(tfStopwatchStart, layoutCons);
+        contentPane.add(tfStopwatchStart);
+
+        label = new JLabel(tr("HH:MM:SS.sss"));
+
+        layoutCons.gridx = 1;
+        layoutCons.gridy = 5;
+        layoutCons.gridwidth = 1;
+        layoutCons.weightx = 0.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(label, layoutCons);
+        contentPane.add(label);
+
+        label = new JLabel(tr("Time window"));
+
+        layoutCons.gridx = 0;
+        layoutCons.gridy = 6;
+        layoutCons.gridwidth = 2;
+        layoutCons.weightx = 0.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(label, layoutCons);
+        contentPane.add(label);
+
+        layoutCons.gridx = 0;
+        layoutCons.gridy = 7;
+        layoutCons.gridwidth = 1;
+        layoutCons.weightx = 0.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(tfTimeWindow, layoutCons);
+        contentPane.add(tfTimeWindow);
+
+        label = new JLabel(tr("seconds"));
+
+        layoutCons.gridx = 1;
+        layoutCons.gridy = 7;
+        layoutCons.gridwidth = 1;
+        layoutCons.weightx = 0.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(label, layoutCons);
+        contentPane.add(label);
+
+        label = new JLabel(tr("Move Threshold"));
+
+        layoutCons.gridx = 0;
+        layoutCons.gridy = 8;
+        layoutCons.gridwidth = 2;
+        layoutCons.weightx = 0.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(label, layoutCons);
+        contentPane.add(label);
+
+        layoutCons.gridx = 0;
+        layoutCons.gridy = 9;
+        layoutCons.gridwidth = 1;
+        layoutCons.weightx = 0.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(tfThreshold, layoutCons);
+        contentPane.add(tfThreshold);
+
+        label = new JLabel(tr("meters"));
+
+        layoutCons.gridx = 1;
+        layoutCons.gridy = 9;
+        layoutCons.gridwidth = 1;
+        layoutCons.weightx = 0.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(label, layoutCons);
+        contentPane.add(label);
+
+        JButton bSuggestStops = new JButton(tr("Suggest Stops"));
+        bSuggestStops.setActionCommand("stopImporter.settingsSuggestStops");
+        bSuggestStops.addActionListener(controller);
+
+        layoutCons.gridx = 0;
+        layoutCons.gridy = 10;
+        layoutCons.gridwidth = 3;
+        layoutCons.weightx = 1.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(bSuggestStops, layoutCons);
+        contentPane.add(bSuggestStops);
+
+        // Stops Tab
+        contentPane = tabStops;
+        gridbag = new GridBagLayout();
+        layoutCons = new GridBagConstraints();
+        contentPane.setLayout(gridbag);
+        contentPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
+                .put(KeyStroke.getKeyStroke("alt N"), "stopImporter.focusName");
+        contentPane.getActionMap().put("stopImporter.focusName",
+                controller.getFocusTrackStoplistNameAction());
+        contentPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
+                .put(KeyStroke.getKeyStroke("alt S"), "stopImporter.focusShelterYes");
+        contentPane.getActionMap().put("stopImporter.focusShelterYes",
+                controller.getFocusTrackStoplistShelterAction("yes"));
+        contentPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
+                .put(KeyStroke.getKeyStroke("alt T"), "stopImporter.focusShelterNo");
+        contentPane.getActionMap().put("stopImporter.focusShelterNo",
+                controller.getFocusTrackStoplistShelterAction("no"));
+        contentPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
+                .put(KeyStroke.getKeyStroke("alt U"), "stopImporter.focusShelterImplicit");
+        contentPane.getActionMap().put("stopImporter.focusShelterImplicit",
+                controller.getFocusTrackStoplistShelterAction("implicit"));
+        contentPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
+                .put(KeyStroke.getKeyStroke("alt D"), "stopImporter.stoplistDelete");
+        contentPane.getActionMap().put("stopImporter.stoplistDelete",
+                controller.getFocusStoplistDeleteAction());
+
+        stoplistTable = new JTable();
+        JScrollPane tableSP = new JScrollPane(stoplistTable);
+
+        layoutCons.gridx = 0;
+        layoutCons.gridy = 0;
+        layoutCons.gridwidth = 4;
+        layoutCons.weightx = 1.0;
+        layoutCons.weighty = 1.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(tableSP, layoutCons);
+        contentPane.add(tableSP);
+
+        JButton bFind = new JButton(tr("Find"));
+        bFind.setActionCommand("stopImporter.stoplistFind");
+        bFind.addActionListener(controller);
+
+        layoutCons.gridx = 0;
+        layoutCons.gridy = 1;
+        layoutCons.gridwidth = 1;
+        layoutCons.weightx = 1.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(bFind, layoutCons);
+        contentPane.add(bFind);
+
+        JButton bShow = new JButton(tr("Show"));
+        bShow.setActionCommand("stopImporter.stoplistShow");
+        bShow.addActionListener(controller);
+
+        layoutCons.gridx = 0;
+        layoutCons.gridy = 2;
+        layoutCons.gridwidth = 1;
+        layoutCons.weightx = 1.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(bShow, layoutCons);
+        contentPane.add(bShow);
+
+        JButton bMark = new JButton(tr("Mark"));
+        bMark.setActionCommand("stopImporter.stoplistMark");
+        bMark.addActionListener(controller);
+
+        layoutCons.gridx = 1;
+        layoutCons.gridy = 1;
+        layoutCons.gridheight = 1;
+        layoutCons.gridwidth = 1;
+        layoutCons.weightx = 1.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(bMark, layoutCons);
+        contentPane.add(bMark);
+
+        JButton bDetach = new JButton(tr("Detach"));
+        bDetach.setActionCommand("stopImporter.stoplistDetach");
+        bDetach.addActionListener(controller);
+
+        layoutCons.gridx = 1;
+        layoutCons.gridy = 2;
+        layoutCons.gridheight = 1;
+        layoutCons.gridwidth = 1;
+        layoutCons.weightx = 1.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(bDetach, layoutCons);
+        contentPane.add(bDetach);
+
+        JButton bAdd = new JButton(tr("Add"));
+        bAdd.setActionCommand("stopImporter.stoplistAdd");
+        bAdd.addActionListener(controller);
+
+        layoutCons.gridx = 2;
+        layoutCons.gridy = 1;
+        layoutCons.gridheight = 1;
+        layoutCons.gridwidth = 1;
+        layoutCons.weightx = 1.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(bAdd, layoutCons);
+        contentPane.add(bAdd);
+
+        JButton bDelete = new JButton(tr("Delete"));
+        bDelete.setActionCommand("stopImporter.stoplistDelete");
+        bDelete.addActionListener(controller);
+
+        layoutCons.gridx = 2;
+        layoutCons.gridy = 2;
+        layoutCons.gridwidth = 1;
+        layoutCons.weightx = 1.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(bDelete, layoutCons);
+        contentPane.add(bDelete);
+
+        JButton bSort = new JButton(tr("Sort"));
+        bSort.setActionCommand("stopImporter.stoplistSort");
+        bSort.addActionListener(controller);
+
+        layoutCons.gridx = 3;
+        layoutCons.gridy = 1;
+        layoutCons.gridheight = 2;
+        layoutCons.gridwidth = 1;
+        layoutCons.weightx = 1.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(bSort, layoutCons);
+        contentPane.add(bSort);
+
+        // Waypoints Tab
+        contentPane = tabWaypoints;
+        gridbag = new GridBagLayout();
+        layoutCons = new GridBagConstraints();
+        contentPane.setLayout(gridbag);
+        contentPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
+                .put(KeyStroke.getKeyStroke("alt N"), "stopImporter.focusName");
+        contentPane.getActionMap().put("stopImporter.focusName",
+                controller.getFocusWaypointNameAction());
+        contentPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
+                .put(KeyStroke.getKeyStroke("alt S"), "stopImporter.focusShelterYes");
+        contentPane.getActionMap().put("stopImporter.focusShelterYes",
+                controller.getFocusWaypointShelterAction("yes"));
+        contentPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
+                .put(KeyStroke.getKeyStroke("alt T"), "stopImporter.focusShelterNo");
+        contentPane.getActionMap().put("stopImporter.focusShelterNo",
+                controller.getFocusWaypointShelterAction("no"));
+        contentPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
+                .put(KeyStroke.getKeyStroke("alt U"), "stopImporter.focusShelterImplicit");
+        contentPane.getActionMap().put("stopImporter.focusShelterImplicit",
+                controller.getFocusWaypointShelterAction("implicit"));
+        contentPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
+                .put(KeyStroke.getKeyStroke("alt D"), "stopImporter.waypointsDelete");
+        contentPane.getActionMap().put("stopImporter.waypointsDelete",
+                controller.getFocusWaypointDeleteAction());
+
+        waypointTable = new JTable();
+        tableSP = new JScrollPane(waypointTable);
+
+        layoutCons.gridx = 0;
+        layoutCons.gridy = 0;
+        layoutCons.gridwidth = 3;
+        layoutCons.weightx = 1.0;
+        layoutCons.weighty = 1.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(tableSP, layoutCons);
+        contentPane.add(tableSP);
+
+        bFind = new JButton(tr("Find"));
+        bFind.setActionCommand("stopImporter.waypointsFind");
+        bFind.addActionListener(controller);
+
+        layoutCons.gridx = 0;
+        layoutCons.gridy = 1;
+        layoutCons.gridwidth = 1;
+        layoutCons.weightx = 1.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(bFind, layoutCons);
+        contentPane.add(bFind);
+
+        bShow = new JButton(tr("Show"));
+        bShow.setActionCommand("stopImporter.waypointsShow");
+        bShow.addActionListener(controller);
+
+        layoutCons.gridx = 0;
+        layoutCons.gridy = 2;
+        layoutCons.gridwidth = 1;
+        layoutCons.weightx = 1.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(bShow, layoutCons);
+        contentPane.add(bShow);
+
+        bMark = new JButton(tr("Mark"));
+        bMark.setActionCommand("stopImporter.waypointsMark");
+        bMark.addActionListener(controller);
+
+        layoutCons.gridx = 1;
+        layoutCons.gridy = 1;
+        layoutCons.gridheight = 1;
+        layoutCons.gridwidth = 1;
+        layoutCons.weightx = 1.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(bMark, layoutCons);
+        contentPane.add(bMark);
+
+        bDetach = new JButton(tr("Detach"));
+        bDetach.setActionCommand("stopImporter.waypointsDetach");
+        bDetach.addActionListener(controller);
+
+        layoutCons.gridx = 1;
+        layoutCons.gridy = 2;
+        layoutCons.gridheight = 1;
+        layoutCons.gridwidth = 1;
+        layoutCons.weightx = 1.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(bDetach, layoutCons);
+        contentPane.add(bDetach);
+
+        bAdd = new JButton(tr("Enable"));
+        bAdd.setActionCommand("stopImporter.waypointsAdd");
+        bAdd.addActionListener(controller);
+
+        layoutCons.gridx = 2;
+        layoutCons.gridy = 1;
+        layoutCons.gridheight = 1;
+        layoutCons.gridwidth = 1;
+        layoutCons.weightx = 1.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(bAdd, layoutCons);
+        contentPane.add(bAdd);
+
+        bDelete = new JButton(tr("Disable"));
+        bDelete.setActionCommand("stopImporter.waypointsDelete");
+        bDelete.addActionListener(controller);
+
+        layoutCons.gridx = 2;
+        layoutCons.gridy = 2;
+        layoutCons.gridwidth = 1;
+        layoutCons.weightx = 1.0;
+        layoutCons.weighty = 0.0;
+        layoutCons.fill = GridBagConstraints.BOTH;
+        gridbag.setConstraints(bDelete, layoutCons);
+        contentPane.add(bDelete);
     }
-  };
+
+    public JTable getStoplistTable() {
+        return stoplistTable;
+    }
+
+    public void setStoplistTableModel(TrackStoplistTableModel model) {
+        stoplistTable.setModel(model);
+        JComboBox<TransText> comboBox = new JComboBox<>();
+        comboBox.addItem(new TransText(null));
+        comboBox.addItem(new TransText(marktr("yes")));
+        comboBox.addItem(new TransText(marktr("no")));
+        comboBox.addItem(new TransText(marktr("implicit")));
+        stoplistTable.getColumnModel().getColumn(2).setCellEditor(new DefaultCellEditor(comboBox));
+        int width = stoplistTable.getPreferredSize().width;
+        stoplistTable.getColumnModel().getColumn(0).setPreferredWidth((int) (width * 0.4));
+        stoplistTable.getColumnModel().getColumn(1).setPreferredWidth((int) (width * 0.5));
+        stoplistTable.getColumnModel().getColumn(2).setPreferredWidth((int) (width * 0.1));
+    }
+
+    public JTable getWaypointsTable() {
+        return waypointTable;
+    }
+
+    public void setWaypointsTableModel(WaypointTableModel model) {
+        waypointTable.setModel(model);
+        JComboBox<TransText> comboBox = new JComboBox<>();
+        comboBox.addItem(new TransText(null));
+        comboBox.addItem(new TransText(marktr("yes")));
+        comboBox.addItem(new TransText(marktr("no")));
+        comboBox.addItem(new TransText(marktr("implicit")));
+        waypointTable.getColumnModel().getColumn(2).setCellEditor(new DefaultCellEditor(comboBox));
+        int width = waypointTable.getPreferredSize().width;
+        waypointTable.getColumnModel().getColumn(0).setPreferredWidth((int) (width * 0.4));
+        waypointTable.getColumnModel().getColumn(1).setPreferredWidth((int) (width * 0.5));
+        waypointTable.getColumnModel().getColumn(2).setPreferredWidth((int) (width * 0.1));
+    }
+
+    private class TracksLSL implements ListSelectionListener {
+        StopImporterAction root = null;
+
+        public TracksLSL(StopImporterAction sia) {
+            root = sia;
+        }
+
+        @Override
+        public void valueChanged(ListSelectionEvent e) {
+            int selectedPos = tracksList.getAnchorSelectionIndex();
+            if (tracksList.isSelectedIndex(selectedPos))
+                root.tracksSelectionChanged(selectedPos);
+            else
+                root.tracksSelectionChanged(-1);
+        }
+    };
 }
Index: /applications/editors/josm/plugins/public_transport/src/public_transport/TrackReference.java
===================================================================
--- /applications/editors/josm/plugins/public_transport/src/public_transport/TrackReference.java	(revision 32356)
+++ /applications/editors/josm/plugins/public_transport/src/public_transport/TrackReference.java	(revision 32357)
@@ -18,180 +18,166 @@
 import org.openstreetmap.josm.data.osm.Node;
 
-public class TrackReference
-    implements Comparable< TrackReference >, TableModelListener
-{
-  public GpxTrack track;
-  public TrackStoplistTableModel stoplistTM;
-  public String stopwatchStart;
-  public String gpsStartTime;
-  public String gpsSyncTime;
-  public double timeWindow;
-  public double threshold;
-  private StopImporterAction controller = null;
-  public boolean inEvent = false;
+public class TrackReference implements Comparable<TrackReference>, TableModelListener {
+    public GpxTrack track;
 
-  public TrackReference(GpxTrack track, StopImporterAction controller)
-  {
-    this.track = track;
-    this.stoplistTM = new TrackStoplistTableModel(this);
-    this.stopwatchStart = "00:00:00";
-    this.gpsStartTime = null;
-    this.gpsSyncTime = null;
-    this.controller = controller;
-    if (track != null)
-    {
-      Iterator< GpxTrackSegment > siter = track.getSegments().iterator();
-      while ((siter.hasNext()) && (this.gpsSyncTime == null))
-      {
-    Iterator< WayPoint > witer = siter.next().getWayPoints().iterator();
-    if (witer.hasNext())
-    {
-      this.gpsStartTime = witer.next().getString("time");
-      if (this.gpsStartTime != null)
-        this.gpsSyncTime = this.gpsStartTime.substring(11, 19);
-    }
-      }
-      if (this.gpsSyncTime == null)
-      {
-    JOptionPane.showMessageDialog
-        (null, tr("The GPX file doesn''t contain valid trackpoints. "
-        + "Please use a GPX file that has trackpoints."), tr("GPX File Trouble"),
-     JOptionPane.ERROR_MESSAGE);
+    public TrackStoplistTableModel stoplistTM;
 
-    this.gpsStartTime = "1970-01-01T00:00:00Z";
-    this.gpsSyncTime = this.stopwatchStart;
-      }
-    }
-    else
-      this.gpsSyncTime = this.stopwatchStart;
-    this.timeWindow = 20;
-    this.threshold = 20;
-  }
+    public String stopwatchStart;
 
-  public GpxTrack getGpxTrack()
-  {
-    return track;
-  }
+    public String gpsStartTime;
 
-  public int compareTo(TrackReference tr)
-  {
-    String name = (String)track.getAttributes().get("name");
-    String tr_name = (String)tr.track.getAttributes().get("name");
-    if (name != null)
-    {
-      if (tr_name == null)
-    return -1;
-      return name.compareTo(tr_name);
-    }
-    return 1;
-  }
+    public String gpsSyncTime;
 
-  public String toString()
-  {
-    String buf = (String)track.getAttributes().get("name");
-    if (buf == null)
-      return tr("unnamed");
-    return buf;
-  }
+    public double timeWindow;
 
-  public void tableChanged(TableModelEvent e)
-  {
-    if ((e.getType() == TableModelEvent.UPDATE) && (e.getFirstRow() >= 0))
-    {
-      if (inEvent)
-    return;
+    public double threshold;
 
-      double time = StopImporterDialog.parseTime
-        ((String)stoplistTM.getValueAt(e.getFirstRow(), 0));
-      if (time < 0)
-      {
-    stoplistTM.setValueAt
-        (stoplistTM.timeAt(e.getFirstRow()), e.getFirstRow(), 0);
-    JOptionPane.showMessageDialog
-        (null, tr("Can''t parse a time from this string."), tr("Invalid value"),
-         JOptionPane.ERROR_MESSAGE);
-    return;
-      }
+    private StopImporterAction controller = null;
 
-      Main.main.undoRedo.add(new TrackStoplistNameCommand
-              (this, e.getFirstRow()));
-      stoplistTM.setTimeAt
-      (e.getFirstRow(), (String)stoplistTM.getValueAt(e.getFirstRow(), 0));
-    }
-  }
+    public boolean inEvent = false;
 
-  public LatLon computeCoor(double time)
-  {
-    double gpsSyncTime = StopImporterDialog.parseTime(this.gpsSyncTime);
-    double dGpsStartTime = StopImporterDialog.parseTime(gpsStartTime);
-    if (gpsSyncTime < dGpsStartTime - 12*60*60)
-      gpsSyncTime += 24*60*60;
-    double timeDelta = gpsSyncTime - StopImporterDialog.parseTime(stopwatchStart);
-    time += timeDelta;
+    public TrackReference(GpxTrack track, StopImporterAction controller) {
+        this.track = track;
+        this.stoplistTM = new TrackStoplistTableModel(this);
+        this.stopwatchStart = "00:00:00";
+        this.gpsStartTime = null;
+        this.gpsSyncTime = null;
+        this.controller = controller;
+        if (track != null) {
+            Iterator<GpxTrackSegment> siter = track.getSegments().iterator();
+            while ((siter.hasNext()) && (this.gpsSyncTime == null)) {
+                Iterator<WayPoint> witer = siter.next().getWayPoints().iterator();
+                if (witer.hasNext()) {
+                    this.gpsStartTime = witer.next().getString("time");
+                    if (this.gpsStartTime != null)
+                        this.gpsSyncTime = this.gpsStartTime.substring(11, 19);
+                }
+            }
+            if (this.gpsSyncTime == null) {
+                JOptionPane.showMessageDialog(null,
+                        tr("The GPX file doesn''t contain valid trackpoints. "
+                                + "Please use a GPX file that has trackpoints."),
+                        tr("GPX File Trouble"), JOptionPane.ERROR_MESSAGE);
 
-    WayPoint wayPoint = null;
-    WayPoint lastWayPoint = null;
-    double wayPointTime = 0;
-    double lastWayPointTime = 0;
-    Iterator< GpxTrackSegment > siter = track.getSegments().iterator();
-    while (siter.hasNext())
-    {
-      Iterator< WayPoint > witer = siter.next().getWayPoints().iterator();
-      while (witer.hasNext())
-      {
-    wayPoint = witer.next();
-    String startTime = wayPoint.getString("time");
-    wayPointTime = StopImporterDialog.parseTime(startTime.substring(11, 19));
-    if (startTime.substring(11, 19).compareTo(gpsStartTime.substring(11, 19)) == -1)
-      wayPointTime += 24*60*60;
-    if (wayPointTime >= time)
-      break;
-    lastWayPoint = wayPoint;
-    lastWayPointTime = wayPointTime;
-      }
-      if (wayPointTime >= time)
-    break;
+                this.gpsStartTime = "1970-01-01T00:00:00Z";
+                this.gpsSyncTime = this.stopwatchStart;
+            }
+        } else
+            this.gpsSyncTime = this.stopwatchStart;
+        this.timeWindow = 20;
+        this.threshold = 20;
     }
 
-    double lat = 0;
-    if ((wayPointTime == lastWayPointTime) || (lastWayPoint == null))
-      lat = wayPoint.getCoor().lat();
-    else
-      lat = wayPoint.getCoor().lat()
-      *(time - lastWayPointTime)/(wayPointTime - lastWayPointTime)
-      + lastWayPoint.getCoor().lat()
-      *(wayPointTime - time)/(wayPointTime - lastWayPointTime);
-    double lon = 0;
-    if ((wayPointTime == lastWayPointTime) || (lastWayPoint == null))
-      lon = wayPoint.getCoor().lon();
-    else
-      lon = wayPoint.getCoor().lon()
-      *(time - lastWayPointTime)/(wayPointTime - lastWayPointTime)
-      + lastWayPoint.getCoor().lon()
-      *(wayPointTime - time)/(wayPointTime - lastWayPointTime);
+    public GpxTrack getGpxTrack() {
+        return track;
+    }
 
-    return new LatLon(lat, lon);
-  }
+    @Override
+    public int compareTo(TrackReference tr) {
+        String name = (String) track.getAttributes().get("name");
+        String tr_name = (String) tr.track.getAttributes().get("name");
+        if (name != null) {
+            if (tr_name == null)
+                return -1;
+            return name.compareTo(tr_name);
+        }
+        return 1;
+    }
 
-  public void relocateNodes()
-  {
-    for (int i = 0; i < stoplistTM.getNodes().size(); ++i)
-    {
-      Node node = stoplistTM.nodeAt(i);
-      if (node == null)
-    continue;
+    @Override
+    public String toString() {
+        String buf = (String) track.getAttributes().get("name");
+        if (buf == null)
+            return tr("unnamed");
+        return buf;
+    }
 
-      double time = StopImporterDialog.parseTime
-        ((String)stoplistTM.getValueAt(i, 0));
-      LatLon latLon = computeCoor(time);
+    @Override
+    public void tableChanged(TableModelEvent e) {
+        if ((e.getType() == TableModelEvent.UPDATE) && (e.getFirstRow() >= 0)) {
+            if (inEvent)
+                return;
 
-      Node newNode = new Node(node);
-      newNode.setCoor(latLon);
-      Command cmd = new ChangeCommand(node, newNode);
-      if (cmd != null)
-      {
-    Main.main.undoRedo.add(cmd);
-      }
+            double time = StopImporterDialog
+                    .parseTime((String) stoplistTM.getValueAt(e.getFirstRow(), 0));
+            if (time < 0) {
+                stoplistTM.setValueAt(stoplistTM.timeAt(e.getFirstRow()), e.getFirstRow(), 0);
+                JOptionPane.showMessageDialog(null, tr("Can''t parse a time from this string."),
+                        tr("Invalid value"), JOptionPane.ERROR_MESSAGE);
+                return;
+            }
+
+            Main.main.undoRedo.add(new TrackStoplistNameCommand(this, e.getFirstRow()));
+            stoplistTM.setTimeAt(e.getFirstRow(),
+                    (String) stoplistTM.getValueAt(e.getFirstRow(), 0));
+        }
     }
-  }
+
+    public LatLon computeCoor(double time) {
+        double gpsSyncTime = StopImporterDialog.parseTime(this.gpsSyncTime);
+        double dGpsStartTime = StopImporterDialog.parseTime(gpsStartTime);
+        if (gpsSyncTime < dGpsStartTime - 12 * 60 * 60)
+            gpsSyncTime += 24 * 60 * 60;
+        double timeDelta = gpsSyncTime - StopImporterDialog.parseTime(stopwatchStart);
+        time += timeDelta;
+
+        WayPoint wayPoint = null;
+        WayPoint lastWayPoint = null;
+        double wayPointTime = 0;
+        double lastWayPointTime = 0;
+        Iterator<GpxTrackSegment> siter = track.getSegments().iterator();
+        while (siter.hasNext()) {
+            Iterator<WayPoint> witer = siter.next().getWayPoints().iterator();
+            while (witer.hasNext()) {
+                wayPoint = witer.next();
+                String startTime = wayPoint.getString("time");
+                wayPointTime = StopImporterDialog.parseTime(startTime.substring(11, 19));
+                if (startTime.substring(11, 19).compareTo(gpsStartTime.substring(11, 19)) == -1)
+                    wayPointTime += 24 * 60 * 60;
+                if (wayPointTime >= time)
+                    break;
+                lastWayPoint = wayPoint;
+                lastWayPointTime = wayPointTime;
+            }
+            if (wayPointTime >= time)
+                break;
+        }
+
+        double lat = 0;
+        if ((wayPointTime == lastWayPointTime) || (lastWayPoint == null))
+            lat = wayPoint.getCoor().lat();
+        else
+            lat = wayPoint.getCoor().lat() * (time - lastWayPointTime)
+                    / (wayPointTime - lastWayPointTime)
+                    + lastWayPoint.getCoor().lat() * (wayPointTime - time)
+                            / (wayPointTime - lastWayPointTime);
+        double lon = 0;
+        if ((wayPointTime == lastWayPointTime) || (lastWayPoint == null))
+            lon = wayPoint.getCoor().lon();
+        else
+            lon = wayPoint.getCoor().lon() * (time - lastWayPointTime)
+                    / (wayPointTime - lastWayPointTime)
+                    + lastWayPoint.getCoor().lon() * (wayPointTime - time)
+                            / (wayPointTime - lastWayPointTime);
+
+        return new LatLon(lat, lon);
+    }
+
+    public void relocateNodes() {
+        for (int i = 0; i < stoplistTM.getNodes().size(); ++i) {
+            Node node = stoplistTM.nodeAt(i);
+            if (node == null)
+                continue;
+
+            double time = StopImporterDialog.parseTime((String) stoplistTM.getValueAt(i, 0));
+            LatLon latLon = computeCoor(time);
+
+            Node newNode = new Node(node);
+            newNode.setCoor(latLon);
+            Command cmd = new ChangeCommand(node, newNode);
+            if (cmd != null) {
+                Main.main.undoRedo.add(cmd);
+            }
+        }
+    }
 };
Index: /applications/editors/josm/plugins/public_transport/src/public_transport/TrackStoplistAddCommand.java
===================================================================
--- /applications/editors/josm/plugins/public_transport/src/public_transport/TrackStoplistAddCommand.java	(revision 32356)
+++ /applications/editors/josm/plugins/public_transport/src/public_transport/TrackStoplistAddCommand.java	(revision 32357)
@@ -8,38 +8,36 @@
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 
-public class TrackStoplistAddCommand extends Command
-{
-  private int workingLine;
-  private TrackStoplistTableModel stoplistTM = null;
+public class TrackStoplistAddCommand extends Command {
+    private int workingLine;
 
-  public TrackStoplistAddCommand(StopImporterAction controller)
-  {
-    stoplistTM = controller.getCurrentTrack().stoplistTM;
-    workingLine = controller.getDialog().getStoplistTable().getSelectedRow();
-  }
+    private TrackStoplistTableModel stoplistTM = null;
 
-  public boolean executeCommand()
-  {
-    stoplistTM.insertRow(workingLine, "00:00:00");
-    return true;
-  }
+    public TrackStoplistAddCommand(StopImporterAction controller) {
+        stoplistTM = controller.getCurrentTrack().stoplistTM;
+        workingLine = controller.getDialog().getStoplistTable().getSelectedRow();
+    }
 
-  public void undoCommand()
-  {
-    int workingLine = this.workingLine;
-    if (workingLine < 0)
-      workingLine = stoplistTM.getRowCount()-1;
-    stoplistTM.removeRow(workingLine);
-  }
+    @Override
+    public boolean executeCommand() {
+        stoplistTM.insertRow(workingLine, "00:00:00");
+        return true;
+    }
 
-  public void fillModifiedData
-    (Collection< OsmPrimitive > modified, Collection< OsmPrimitive > deleted,
-     Collection< OsmPrimitive > added)
-  {
-  }
+    @Override
+    public void undoCommand() {
+        int workingLine = this.workingLine;
+        if (workingLine < 0)
+            workingLine = stoplistTM.getRowCount() - 1;
+        stoplistTM.removeRow(workingLine);
+    }
 
-  @Override public String getDescriptionText()
-  {
-    return tr("Public Transport: Add track stop");
-  }
-};
+    @Override
+    public void fillModifiedData(Collection<OsmPrimitive> modified,
+            Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
+    }
+
+    @Override
+    public String getDescriptionText() {
+        return tr("Public Transport: Add track stop");
+    }
+}
Index: /applications/editors/josm/plugins/public_transport/src/public_transport/TrackStoplistDeleteCommand.java
===================================================================
--- /applications/editors/josm/plugins/public_transport/src/public_transport/TrackStoplistDeleteCommand.java	(revision 32356)
+++ /applications/editors/josm/plugins/public_transport/src/public_transport/TrackStoplistDeleteCommand.java	(revision 32357)
@@ -11,91 +11,83 @@
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 
-public class TrackStoplistDeleteCommand extends Command
-{
-  private class NodeTimeName
-  {
-    NodeTimeName(Node node, String time, String name, TransText shelter)
-    {
-      this.node = node;
-      this.time = time;
-      this.name = name;
-      this.shelter = shelter;
+public class TrackStoplistDeleteCommand extends Command {
+    private class NodeTimeName {
+        NodeTimeName(Node node, String time, String name, TransText shelter) {
+            this.node = node;
+            this.time = time;
+            this.name = name;
+            this.shelter = shelter;
+        }
+
+        public Node node;
+
+        public String time;
+
+        public String name;
+
+        public TransText shelter;
     }
 
-    public Node node;
-    public String time;
-    public String name;
-    public TransText shelter;
-  };
+    private Vector<Integer> workingLines = null;
 
-  private Vector< Integer > workingLines = null;
-  private Vector< NodeTimeName > nodesForUndo = null;
-  private TrackStoplistTableModel stoplistTM = null;
+    private Vector<NodeTimeName> nodesForUndo = null;
 
-  public TrackStoplistDeleteCommand(StopImporterAction controller)
-  {
-    stoplistTM = controller.getCurrentTrack().stoplistTM;
-    workingLines = new Vector< Integer >();
-    nodesForUndo = new Vector< NodeTimeName >();
+    private TrackStoplistTableModel stoplistTM = null;
 
-    // use selected lines or all lines if no line is selected
-    int[] selectedLines = controller.getDialog().getStoplistTable().getSelectedRows();
-    if (selectedLines.length > 0)
-    {
-      for (int i = 0; i < selectedLines.length; ++i)
-      {
-        workingLines.add(selectedLines[i]);
-      }
+    public TrackStoplistDeleteCommand(StopImporterAction controller) {
+        stoplistTM = controller.getCurrentTrack().stoplistTM;
+        workingLines = new Vector<>();
+        nodesForUndo = new Vector<>();
+
+        // use selected lines or all lines if no line is selected
+        int[] selectedLines = controller.getDialog().getStoplistTable().getSelectedRows();
+        if (selectedLines.length > 0) {
+            for (int i = 0; i < selectedLines.length; ++i) {
+                workingLines.add(selectedLines[i]);
+            }
+        } else {
+            for (int i = 0; i < stoplistTM.getRowCount(); ++i)
+                workingLines.add(new Integer(i));
+        }
     }
-    else
-    {
-      for (int i = 0; i < stoplistTM.getRowCount(); ++i)
-        workingLines.add(new Integer(i));
+
+    @Override
+    public boolean executeCommand() {
+        nodesForUndo.clear();
+        for (int i = workingLines.size() - 1; i >= 0; --i) {
+            int j = workingLines.elementAt(i).intValue();
+            Node node = stoplistTM.nodeAt(j);
+            nodesForUndo.add(new NodeTimeName(node, (String) stoplistTM.getValueAt(j, 0),
+                    (String) stoplistTM.getValueAt(j, 1), (TransText) stoplistTM.getValueAt(j, 2)));
+            stoplistTM.removeRow(j);
+            if (node == null)
+                continue;
+            Main.getLayerManager().getEditDataSet().removePrimitive(node);
+            node.setDeleted(true);
+        }
+        return true;
     }
-  }
 
-  public boolean executeCommand()
-  {
-    nodesForUndo.clear();
-    for (int i = workingLines.size()-1; i >= 0; --i)
-    {
-      int j = workingLines.elementAt(i).intValue();
-      Node node = stoplistTM.nodeAt(j);
-      nodesForUndo.add(new NodeTimeName
-      (node, (String)stoplistTM.getValueAt(j, 0),
-       (String)stoplistTM.getValueAt(j, 1),
-       (TransText)stoplistTM.getValueAt(j, 2)));
-      stoplistTM.removeRow(j);
-      if (node == null)
-        continue;
-      Main.main.getCurrentDataSet().removePrimitive(node);
-      node.setDeleted(true);
+    @Override
+    public void undoCommand() {
+        for (int i = 0; i < workingLines.size(); ++i) {
+            int j = workingLines.elementAt(i).intValue();
+            NodeTimeName ntn = nodesForUndo.elementAt(workingLines.size() - i - 1);
+            stoplistTM.insertRow(j, ntn.node, ntn.time, ntn.name, ntn.shelter);
+            if (ntn.node == null)
+                continue;
+            ntn.node.setDeleted(false);
+            Main.getLayerManager().getEditDataSet().addPrimitive(ntn.node);
+        }
     }
-    return true;
-  }
 
-  public void undoCommand()
-  {
-    for (int i = 0; i < workingLines.size(); ++i)
-    {
-      int j = workingLines.elementAt(i).intValue();
-      NodeTimeName ntn = nodesForUndo.elementAt(workingLines.size() - i - 1);
-      stoplistTM.insertRow(j, ntn.node, ntn.time, ntn.name, ntn.shelter);
-      if (ntn.node == null)
-        continue;
-      ntn.node.setDeleted(false);
-      Main.main.getCurrentDataSet().addPrimitive(ntn.node);
+    @Override
+    public void fillModifiedData(Collection<OsmPrimitive> modified,
+            Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
     }
-  }
 
-  public void fillModifiedData
-    (Collection< OsmPrimitive > modified, Collection< OsmPrimitive > deleted,
-     Collection< OsmPrimitive > added)
-  {
-  }
-
-  @Override public String getDescriptionText()
-  {
-    return tr("Public Transport: Delete track stop");
-  }
+    @Override
+    public String getDescriptionText() {
+        return tr("Public Transport: Delete track stop");
+    }
 };
Index: /applications/editors/josm/plugins/public_transport/src/public_transport/TrackStoplistDetachCommand.java
===================================================================
--- /applications/editors/josm/plugins/public_transport/src/public_transport/TrackStoplistDetachCommand.java	(revision 32356)
+++ /applications/editors/josm/plugins/public_transport/src/public_transport/TrackStoplistDetachCommand.java	(revision 32357)
@@ -10,70 +10,63 @@
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 
-public class TrackStoplistDetachCommand extends Command
-{
-  private Vector< Integer > workingLines = null;
-  private Vector< Node > nodesForUndo = null;
-  private TrackStoplistTableModel stoplistTM = null;
+public class TrackStoplistDetachCommand extends Command {
+    private Vector<Integer> workingLines = null;
 
-  public TrackStoplistDetachCommand(StopImporterAction controller)
-  {
-    stoplistTM = controller.getCurrentTrack().stoplistTM;
-    workingLines = new Vector< Integer >();
-    nodesForUndo = new Vector< Node >();
+    private Vector<Node> nodesForUndo = null;
 
-    // use either selected lines or all lines if no line is selected
-    int[] selectedLines = controller.getDialog().getStoplistTable().getSelectedRows();
-    Vector< Integer > consideredLines = new Vector< Integer >();
-    if (selectedLines.length > 0)
-    {
-      for (int i = 0; i < selectedLines.length; ++i)
-        consideredLines.add(selectedLines[i]);
-    }
-    else
-    {
-      for (int i = 0; i < stoplistTM.getRowCount(); ++i)
-        consideredLines.add(new Integer(i));
+    private TrackStoplistTableModel stoplistTM = null;
+
+    public TrackStoplistDetachCommand(StopImporterAction controller) {
+        stoplistTM = controller.getCurrentTrack().stoplistTM;
+        workingLines = new Vector<>();
+        nodesForUndo = new Vector<>();
+
+        // use either selected lines or all lines if no line is selected
+        int[] selectedLines = controller.getDialog().getStoplistTable().getSelectedRows();
+        Vector<Integer> consideredLines = new Vector<>();
+        if (selectedLines.length > 0) {
+            for (int i = 0; i < selectedLines.length; ++i)
+                consideredLines.add(selectedLines[i]);
+        } else {
+            for (int i = 0; i < stoplistTM.getRowCount(); ++i)
+                consideredLines.add(new Integer(i));
+        }
+
+        // keep only lines where a node can be added
+        for (int i = 0; i < consideredLines.size(); ++i) {
+            if (stoplistTM.nodeAt(consideredLines.elementAt(i)) != null)
+                workingLines.add(consideredLines.elementAt(i));
+        }
     }
 
-    // keep only lines where a node can be added
-    for (int i = 0; i < consideredLines.size(); ++i)
-    {
-      if (stoplistTM.nodeAt(consideredLines.elementAt(i)) != null)
-        workingLines.add(consideredLines.elementAt(i));
+    @Override
+    public boolean executeCommand() {
+        nodesForUndo.clear();
+        for (int i = 0; i < workingLines.size(); ++i) {
+            int j = workingLines.elementAt(i).intValue();
+            Node node = stoplistTM.nodeAt(j);
+            nodesForUndo.add(node);
+            stoplistTM.setNodeAt(j, null);
+        }
+        return true;
     }
-  }
 
-  public boolean executeCommand()
-  {
-    nodesForUndo.clear();
-    for (int i = 0; i < workingLines.size(); ++i)
-    {
-      int j = workingLines.elementAt(i).intValue();
-      Node node = stoplistTM.nodeAt(j);
-      nodesForUndo.add(node);
-      stoplistTM.setNodeAt(j, null);
+    @Override
+    public void undoCommand() {
+        for (int i = 0; i < workingLines.size(); ++i) {
+            int j = workingLines.elementAt(i).intValue();
+            Node node = nodesForUndo.elementAt(i);
+            stoplistTM.setNodeAt(j, node);
+        }
     }
-    return true;
-  }
 
-  public void undoCommand()
-  {
-    for (int i = 0; i < workingLines.size(); ++i)
-    {
-      int j = workingLines.elementAt(i).intValue();
-      Node node = nodesForUndo.elementAt(i);
-      stoplistTM.setNodeAt(j, node);
+    @Override
+    public void fillModifiedData(Collection<OsmPrimitive> modified,
+            Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
     }
-  }
 
-  public void fillModifiedData
-    (Collection< OsmPrimitive > modified, Collection< OsmPrimitive > deleted,
-     Collection< OsmPrimitive > added)
-  {
-  }
-
-  @Override public String getDescriptionText()
-  {
-    return tr("Public Transport: Detach track stop list");
-  }
-};
+    @Override
+    public String getDescriptionText() {
+        return tr("Public Transport: Detach track stop list");
+    }
+}
Index: /applications/editors/josm/plugins/public_transport/src/public_transport/TrackStoplistNameCommand.java
===================================================================
--- /applications/editors/josm/plugins/public_transport/src/public_transport/TrackStoplistNameCommand.java	(revision 32356)
+++ /applications/editors/josm/plugins/public_transport/src/public_transport/TrackStoplistNameCommand.java	(revision 32357)
@@ -12,11 +12,19 @@
 public class TrackStoplistNameCommand extends Command {
     private int workingLine = 0;
+
     private TrackReference trackref = null;
+
     private String oldName = null;
+
     private String name = null;
+
     private String oldTime = null;
+
     private String time = null;
+
     private String oldShelter = null;
+
     private TransText shelter = null;
+
     private LatLon oldLatLon = null;
 
@@ -38,4 +46,5 @@
     }
 
+    @Override
     public boolean executeCommand() {
         Node node = trackref.stoplistTM.nodeAt(workingLine);
@@ -60,4 +69,5 @@
     }
 
+    @Override
     public void undoCommand() {
         Node node = trackref.stoplistTM.nodeAt(workingLine);
@@ -80,6 +90,7 @@
     }
 
-    public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted,
-            Collection<OsmPrimitive> added) {
+    @Override
+    public void fillModifiedData(Collection<OsmPrimitive> modified,
+            Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
     }
 
@@ -88,3 +99,3 @@
         return tr("Public Transport: Edit track stop list");
     }
-};
+}
Index: /applications/editors/josm/plugins/public_transport/src/public_transport/TrackStoplistRelocateCommand.java
===================================================================
--- /applications/editors/josm/plugins/public_transport/src/public_transport/TrackStoplistRelocateCommand.java	(revision 32356)
+++ /applications/editors/josm/plugins/public_transport/src/public_transport/TrackStoplistRelocateCommand.java	(revision 32357)
@@ -9,80 +9,78 @@
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 
-public class TrackStoplistRelocateCommand extends Command
-{
-  private StopImporterAction controller = null;
-  private TrackReference currentTrack = null;
-  private String oldGpsSyncTime = null;
-  private String oldStopwatchStart = null;
-  private String gpsSyncTime = null;
-  private String stopwatchStart = null;
+public class TrackStoplistRelocateCommand extends Command {
+    private StopImporterAction controller = null;
 
-  public TrackStoplistRelocateCommand(StopImporterAction controller)
-  {
-    this.controller = controller;
-    this.currentTrack = controller.getCurrentTrack();
-    this.gpsSyncTime = controller.getDialog().getGpsTimeStart();
-    this.stopwatchStart = controller.getDialog().getStopwatchStart();
-    this.oldGpsSyncTime = currentTrack.gpsSyncTime;
-    this.oldStopwatchStart = currentTrack.stopwatchStart;
-  }
+    private TrackReference currentTrack = null;
 
-  public boolean executeCommand()
-  {
-    currentTrack.gpsSyncTime = gpsSyncTime;
-    currentTrack.stopwatchStart = stopwatchStart;
-    for (int i = 0; i < currentTrack.stoplistTM.getNodes().size(); ++i)
-    {
-      Node node = currentTrack.stoplistTM.nodeAt(i);
-      if (node == null)
-    continue;
+    private String oldGpsSyncTime = null;
 
-      double time = StopImporterDialog.parseTime
-        ((String)currentTrack.stoplistTM.getValueAt(i, 0));
-      node.setCoor(currentTrack.computeCoor(time));
-    }
-    if (currentTrack == controller.getCurrentTrack())
-    {
-      controller.inEvent = true;
-      controller.getDialog().setGpsTimeStart(gpsSyncTime);
-      controller.getDialog().setStopwatchStart(stopwatchStart);
-      controller.inEvent = false;
+    private String oldStopwatchStart = null;
+
+    private String gpsSyncTime = null;
+
+    private String stopwatchStart = null;
+
+    public TrackStoplistRelocateCommand(StopImporterAction controller) {
+        this.controller = controller;
+        this.currentTrack = controller.getCurrentTrack();
+        this.gpsSyncTime = controller.getDialog().getGpsTimeStart();
+        this.stopwatchStart = controller.getDialog().getStopwatchStart();
+        this.oldGpsSyncTime = currentTrack.gpsSyncTime;
+        this.oldStopwatchStart = currentTrack.stopwatchStart;
     }
 
-    return true;
-  }
+    @Override
+    public boolean executeCommand() {
+        currentTrack.gpsSyncTime = gpsSyncTime;
+        currentTrack.stopwatchStart = stopwatchStart;
+        for (int i = 0; i < currentTrack.stoplistTM.getNodes().size(); ++i) {
+            Node node = currentTrack.stoplistTM.nodeAt(i);
+            if (node == null)
+                continue;
 
-  public void undoCommand()
-  {
-    currentTrack.gpsSyncTime = oldGpsSyncTime;
-    currentTrack.stopwatchStart = oldStopwatchStart;
-    for (int i = 0; i < currentTrack.stoplistTM.getNodes().size(); ++i)
-    {
-      Node node = currentTrack.stoplistTM.nodeAt(i);
-      if (node == null)
-    continue;
+            double time = StopImporterDialog
+                    .parseTime((String) currentTrack.stoplistTM.getValueAt(i, 0));
+            node.setCoor(currentTrack.computeCoor(time));
+        }
+        if (currentTrack == controller.getCurrentTrack()) {
+            controller.inEvent = true;
+            controller.getDialog().setGpsTimeStart(gpsSyncTime);
+            controller.getDialog().setStopwatchStart(stopwatchStart);
+            controller.inEvent = false;
+        }
 
-      double time = StopImporterDialog.parseTime
-        ((String)currentTrack.stoplistTM.getValueAt(i, 0));
-      node.setCoor(currentTrack.computeCoor(time));
+        return true;
     }
-    if (currentTrack == controller.getCurrentTrack())
-    {
-      controller.inEvent = true;
-      controller.getDialog().setGpsTimeStart(oldGpsSyncTime);
-      controller.getDialog().setStopwatchStart(oldStopwatchStart);
-      controller.inEvent = false;
+
+    @Override
+    public void undoCommand() {
+        currentTrack.gpsSyncTime = oldGpsSyncTime;
+        currentTrack.stopwatchStart = oldStopwatchStart;
+        for (int i = 0; i < currentTrack.stoplistTM.getNodes().size(); ++i) {
+            Node node = currentTrack.stoplistTM.nodeAt(i);
+            if (node == null)
+                continue;
+
+            double time = StopImporterDialog
+                    .parseTime((String) currentTrack.stoplistTM.getValueAt(i, 0));
+            node.setCoor(currentTrack.computeCoor(time));
+        }
+        if (currentTrack == controller.getCurrentTrack()) {
+            controller.inEvent = true;
+            controller.getDialog().setGpsTimeStart(oldGpsSyncTime);
+            controller.getDialog().setStopwatchStart(oldStopwatchStart);
+            controller.inEvent = false;
+        }
     }
-  }
 
-  public void fillModifiedData
-    (Collection< OsmPrimitive > modified, Collection< OsmPrimitive > deleted,
-     Collection< OsmPrimitive > added)
-  {
-  }
+    @Override
+    public void fillModifiedData(Collection<OsmPrimitive> modified,
+            Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
+    }
 
-  @Override public String getDescriptionText()
-  {
-    return tr("Public Transport: Relocate nodes in track stoplist");
-  }
-};
+    @Override
+    public String getDescriptionText() {
+        return tr("Public Transport: Relocate nodes in track stoplist");
+    }
+}
Index: /applications/editors/josm/plugins/public_transport/src/public_transport/TrackStoplistSortCommand.java
===================================================================
--- /applications/editors/josm/plugins/public_transport/src/public_transport/TrackStoplistSortCommand.java	(revision 32356)
+++ /applications/editors/josm/plugins/public_transport/src/public_transport/TrackStoplistSortCommand.java	(revision 32357)
@@ -12,121 +12,119 @@
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 
-public class TrackStoplistSortCommand extends Command
-{
-  private TrackStoplistTableModel stoplistTM = null;
-  private Vector< Vector< Object > > tableDataModel = null;
-  private Vector< Node > nodes = null;
-  private Vector< String > times = null;
-  private Vector< Integer > workingLines = null;
-  private int insPos;
-  private String stopwatchStart;
+public class TrackStoplistSortCommand extends Command {
+    private TrackStoplistTableModel stoplistTM = null;
 
-  public TrackStoplistSortCommand(StopImporterAction controller)
-  {
-    stoplistTM = controller.getCurrentTrack().stoplistTM;
-    workingLines = new Vector< Integer >();
-    insPos = controller.getDialog().getStoplistTable().getSelectedRow();
-    stopwatchStart = controller.getCurrentTrack().stopwatchStart;
+    private Vector<Vector<Object>> tableDataModel = null;
 
-    // use either selected lines or all lines if no line is selected
-    int[] selectedLines = controller.getDialog().getStoplistTable().getSelectedRows();
-    if (selectedLines.length > 0)
-    {
-      for (int i = 0; i < selectedLines.length; ++i)
-        workingLines.add(selectedLines[i]);
-    }
-    else
-    {
-      for (int i = 0; i < stoplistTM.getRowCount(); ++i)
-        workingLines.add(new Integer(i));
-    }
-  }
+    private Vector<Node> nodes = null;
 
-  @SuppressWarnings("unchecked")
-  public boolean executeCommand()
-  {
-    tableDataModel = (Vector< Vector< Object > >)stoplistTM.getDataVector()
-    .clone();
-    nodes = (Vector< Node >)stoplistTM.getNodes().clone();
-    times = (Vector< String >)stoplistTM.getTimes().clone();
+    private Vector<String> times = null;
 
-    Vector< NodeSortEntry > nodesToSort = new Vector< NodeSortEntry >();
-    for (int i = workingLines.size()-1; i >= 0; --i)
-    {
-      int j = workingLines.elementAt(i).intValue();
-      nodesToSort.add(new NodeSortEntry
-      (stoplistTM.nodeAt(j), (String)stoplistTM.getValueAt(j, 0),
-        (String)stoplistTM.getValueAt(j, 1),
-        (TransText)stoplistTM.getValueAt(j, 2),
-         StopImporterDialog.parseTime(stopwatchStart)));
-      stoplistTM.removeRow(j);
+    private Vector<Integer> workingLines = null;
+
+    private int insPos;
+
+    private String stopwatchStart;
+
+    public TrackStoplistSortCommand(StopImporterAction controller) {
+        stoplistTM = controller.getCurrentTrack().stoplistTM;
+        workingLines = new Vector<>();
+        insPos = controller.getDialog().getStoplistTable().getSelectedRow();
+        stopwatchStart = controller.getCurrentTrack().stopwatchStart;
+
+        // use either selected lines or all lines if no line is selected
+        int[] selectedLines = controller.getDialog().getStoplistTable().getSelectedRows();
+        if (selectedLines.length > 0) {
+            for (int i = 0; i < selectedLines.length; ++i)
+                workingLines.add(selectedLines[i]);
+        } else {
+            for (int i = 0; i < stoplistTM.getRowCount(); ++i)
+                workingLines.add(new Integer(i));
+        }
     }
 
-    Collections.sort(nodesToSort);
+    @Override
+    @SuppressWarnings("unchecked")
+    public boolean executeCommand() {
+        tableDataModel = (Vector<Vector<Object>>) stoplistTM.getDataVector().clone();
+        nodes = (Vector<Node>) stoplistTM.getNodes().clone();
+        times = (Vector<String>) stoplistTM.getTimes().clone();
 
-    int insPos = this.insPos;
-    Iterator< NodeSortEntry > iter = nodesToSort.iterator();
-    while (iter.hasNext())
-    {
-      NodeSortEntry nse = iter.next();
-      stoplistTM.insertRow(insPos, nse.node, nse.time, nse.name, nse.shelter);
-      if (insPos >= 0)
-        ++insPos;
-    }
-    return true;
-  }
+        Vector<NodeSortEntry> nodesToSort = new Vector<>();
+        for (int i = workingLines.size() - 1; i >= 0; --i) {
+            int j = workingLines.elementAt(i).intValue();
+            nodesToSort.add(new NodeSortEntry(stoplistTM.nodeAt(j),
+                    (String) stoplistTM.getValueAt(j, 0), (String) stoplistTM.getValueAt(j, 1),
+                    (TransText) stoplistTM.getValueAt(j, 2),
+                    StopImporterDialog.parseTime(stopwatchStart)));
+            stoplistTM.removeRow(j);
+        }
 
-  public void undoCommand()
-  {
-    stoplistTM.setDataVector(tableDataModel);
-    stoplistTM.setNodes(nodes);
-    stoplistTM.setTimes(times);
-  }
+        Collections.sort(nodesToSort);
 
-  public void fillModifiedData
-    (Collection< OsmPrimitive > modified, Collection< OsmPrimitive > deleted,
-     Collection< OsmPrimitive > added)
-  {
-  }
-
-  @Override public String getDescriptionText()
-  {
-    return tr("Public Transport: sort track stop list");
-  }
-
-  private class NodeSortEntry implements Comparable< NodeSortEntry >
-  {
-    public Node node = null;
-    public String time = null;
-    public String name = null;
-    public TransText shelter = null;
-    public double startTime = 0;
-
-    public NodeSortEntry
-        (Node node, String time, String name, TransText shelter, double startTime)
-    {
-      this.node = node;
-      this.time = time;
-      this.name = name;
-      this.shelter = shelter;
+        int insPos = this.insPos;
+        Iterator<NodeSortEntry> iter = nodesToSort.iterator();
+        while (iter.hasNext()) {
+            NodeSortEntry nse = iter.next();
+            stoplistTM.insertRow(insPos, nse.node, nse.time, nse.name, nse.shelter);
+            if (insPos >= 0)
+                ++insPos;
+        }
+        return true;
     }
 
-    public int compareTo(NodeSortEntry nse)
-    {
-      double time = StopImporterDialog.parseTime(this.time);
-      if (time - startTime > 12*60*60)
-        time -= 24*60*60;
+    @Override
+    public void undoCommand() {
+        stoplistTM.setDataVector(tableDataModel);
+        stoplistTM.setNodes(nodes);
+        stoplistTM.setTimes(times);
+    }
 
-      double nseTime = StopImporterDialog.parseTime(nse.time);
-      if (nseTime - startTime > 12*60*60)
-        nseTime -= 24*60*60;
+    @Override
+    public void fillModifiedData(Collection<OsmPrimitive> modified,
+            Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
+    }
 
-      if (time < nseTime)
-        return -1;
-      else if (time > nseTime)
-        return 1;
-      else
-        return 0;
+    @Override
+    public String getDescriptionText() {
+        return tr("Public Transport: sort track stop list");
     }
-  };
-};
+
+    private class NodeSortEntry implements Comparable<NodeSortEntry> {
+        public Node node = null;
+
+        public String time = null;
+
+        public String name = null;
+
+        public TransText shelter = null;
+
+        public double startTime = 0;
+
+        public NodeSortEntry(Node node, String time, String name, TransText shelter,
+                double startTime) {
+            this.node = node;
+            this.time = time;
+            this.name = name;
+            this.shelter = shelter;
+        }
+
+        @Override
+        public int compareTo(NodeSortEntry nse) {
+            double time = StopImporterDialog.parseTime(this.time);
+            if (time - startTime > 12 * 60 * 60)
+                time -= 24 * 60 * 60;
+
+            double nseTime = StopImporterDialog.parseTime(nse.time);
+            if (nseTime - startTime > 12 * 60 * 60)
+                nseTime -= 24 * 60 * 60;
+
+            if (time < nseTime)
+                return -1;
+            else if (time > nseTime)
+                return 1;
+            else
+                return 0;
+        }
+    }
+}
Index: /applications/editors/josm/plugins/public_transport/src/public_transport/TrackStoplistTableModel.java
===================================================================
--- /applications/editors/josm/plugins/public_transport/src/public_transport/TrackStoplistTableModel.java	(revision 32356)
+++ /applications/editors/josm/plugins/public_transport/src/public_transport/TrackStoplistTableModel.java	(revision 32357)
@@ -9,122 +9,108 @@
 import org.openstreetmap.josm.data.osm.Node;
 
-public class TrackStoplistTableModel extends DefaultTableModel
-{
-  private Vector< Node > nodes = null;
-  private Vector< String > times = null;
-  private static Vector< String > columns = null;
+public class TrackStoplistTableModel extends DefaultTableModel {
+    private Vector<Node> nodes = null;
 
-  public TrackStoplistTableModel(TrackReference tr)
-  {
-    if (columns == null)
-    {
-      columns = new Vector< String >();
-      columns.add(tr("Time"));
-      columns.add(tr("Name"));
-      columns.add(tr("Shelter"));
+    private Vector<String> times = null;
+
+    private static Vector<String> columns = null;
+
+    public TrackStoplistTableModel(TrackReference tr) {
+        if (columns == null) {
+            columns = new Vector<>();
+            columns.add(tr("Time"));
+            columns.add(tr("Name"));
+            columns.add(tr("Shelter"));
+        }
+        nodes = new Vector<>();
+        times = new Vector<>();
+
+        setColumnIdentifiers(columns);
+        addTableModelListener(tr);
     }
-    nodes = new Vector< Node >();
-    times = new Vector< String >();
 
-    setColumnIdentifiers(columns);
-    addTableModelListener(tr);
-  }
+    @Override
+    public boolean isCellEditable(int row, int column) {
+        return true;
+    }
 
-  public boolean isCellEditable(int row, int column) {
-    return true;
-  }
+    @Override
+    public void addRow(Object[] obj) {
+        throw new UnsupportedOperationException();
+    }
 
-  public void addRow(Object[] obj) {
-    throw new UnsupportedOperationException();
-  }
+    @Override
+    public void insertRow(int insPos, Object[] obj) {
+        throw new UnsupportedOperationException();
+    }
 
-  public void insertRow(int insPos, Object[] obj) {
-    throw new UnsupportedOperationException();
-  }
+    public void addRow(String time) {
+        insertRow(-1, time);
+    }
 
-  public void addRow(String time) {
-    insertRow(-1, time);
-  }
+    public void insertRow(int insPos, String time) {
+        insertRow(insPos, null, time, "", new TransText(null));
+    }
 
-  public void insertRow(int insPos, String time)
-  {
-    insertRow(insPos, null, time, "", new TransText(null));
-  }
+    @Override
+    public void removeRow(int pos) {
+        super.removeRow(pos);
+        nodes.removeElementAt(pos);
+        times.removeElementAt(pos);
+    }
 
-  public void removeRow(int pos)
-  {
-    super.removeRow(pos);
-    nodes.removeElementAt(pos);
-    times.removeElementAt(pos);
-  }
+    public Node nodeAt(int i) {
+        return nodes.elementAt(i);
+    }
 
-  public Node nodeAt(int i)
-  {
-    return nodes.elementAt(i);
-  }
+    public void setNodeAt(int i, Node node) {
+        nodes.set(i, node);
+    }
 
-  public void setNodeAt(int i, Node node)
-  {
-    nodes.set(i, node);
-  }
+    public final Vector<Node> getNodes() {
+        return nodes;
+    }
 
-  public final Vector< Node > getNodes()
-  {
-    return nodes;
-  }
+    public void setNodes(Vector<Node> nodes) {
+        this.nodes = nodes;
+    }
 
-  public void setNodes(Vector< Node > nodes)
-  {
-    this.nodes = nodes;
-  }
+    public String timeAt(int i) {
+        return times.elementAt(i);
+    }
 
-  public String timeAt(int i)
-  {
-    return times.elementAt(i);
-  }
+    public void setTimeAt(int i, String time) {
+        times.set(i, time);
+    }
 
-  public void setTimeAt(int i, String time)
-  {
-    times.set(i, time);
-  }
+    public final Vector<String> getTimes() {
+        return times;
+    }
 
-  public final Vector< String > getTimes()
-  {
-    return times;
-  }
+    public void setTimes(Vector<String> times) {
+        this.times = times;
+    }
 
-  public void setTimes(Vector< String > times)
-  {
-    this.times = times;
-  }
+    public void insertRow(int insPos, Node node, String time, String name, TransText shelter) {
+        Object[] buf = { time, name, shelter };
+        if (insPos == -1) {
+            nodes.addElement(node);
+            times.addElement(time);
+            super.addRow(buf);
+        } else {
+            nodes.insertElementAt(node, insPos);
+            times.insertElementAt(time, insPos);
+            super.insertRow(insPos, buf);
+        }
+    }
 
-  public void insertRow
-      (int insPos, Node node, String time, String name, TransText shelter)
-  {
-    Object[] buf = { time, name, shelter };
-    if (insPos == -1)
-    {
-      nodes.addElement(node);
-      times.addElement(time);
-      super.addRow(buf);
+    public void clear() {
+        nodes.clear();
+        times.clear();
+        super.setRowCount(0);
     }
-    else
-    {
-      nodes.insertElementAt(node, insPos);
-      times.insertElementAt(time, insPos);
-      super.insertRow(insPos, buf);
+
+    public void setDataVector(Vector<Vector<Object>> dataVector) {
+        setDataVector(dataVector, columns);
     }
-  }
-
-  public void clear()
-  {
-    nodes.clear();
-    times.clear();
-    super.setRowCount(0);
-  }
-
-  public void setDataVector(Vector< Vector< Object > > dataVector)
-  {
-    setDataVector(dataVector, columns);
-  }
-};
+}
Index: /applications/editors/josm/plugins/public_transport/src/public_transport/TrackSuggestStopsCommand.java
===================================================================
--- /applications/editors/josm/plugins/public_transport/src/public_transport/TrackSuggestStopsCommand.java	(revision 32356)
+++ /applications/editors/josm/plugins/public_transport/src/public_transport/TrackSuggestStopsCommand.java	(revision 32357)
@@ -15,224 +15,219 @@
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 
-public class TrackSuggestStopsCommand extends Command
-{
-  private TrackStoplistTableModel stoplistTM = null;
-  private String type = null;
-  private String stopwatchStart;
-  private String gpsStartTime;
-  private String gpsSyncTime;
-  private double timeWindow;
-  private double threshold;
-  private Collection< GpxTrackSegment > segments = null;
-  private Vector< Vector< Object > > tableDataModel = null;
-  private Vector< Node > nodes = null;
-  private Vector< String > times = null;
-
-  public TrackSuggestStopsCommand(StopImporterAction controller)
-  {
-    if (controller.getCurrentTrack() == null)
-      return;
-    stoplistTM = controller.getCurrentTrack().stoplistTM;
-    type = controller.getDialog().getStoptype();
-    stopwatchStart = controller.getCurrentTrack().stopwatchStart;
-    gpsStartTime = controller.getCurrentTrack().gpsStartTime;
-    gpsSyncTime = controller.getCurrentTrack().gpsSyncTime;
-    timeWindow = controller.getCurrentTrack().timeWindow;
-    threshold = controller.getCurrentTrack().threshold;
-    segments = controller.getCurrentTrack().getGpxTrack().getSegments();
-  }
-
-  @SuppressWarnings("unchecked")
-  public boolean executeCommand()
-  {
-    if (stoplistTM == null)
-      return false;
-    tableDataModel = (Vector< Vector< Object > >)stoplistTM.getDataVector()
-    .clone();
-    nodes = (Vector< Node >)stoplistTM.getNodes().clone();
-    times = (Vector< String >)stoplistTM.getTimes().clone();
-
-    for (int i = 0; i < stoplistTM.getNodes().size(); ++i)
-    {
-      Node node = stoplistTM.nodeAt(i);
-      if (node == null)
-        continue;
-      Main.main.getCurrentDataSet().removePrimitive(node);
-      node.setDeleted(true);
-    }
-    stoplistTM.clear();
-
-    Vector< WayPoint > wayPoints = new Vector< WayPoint >();
-    Iterator< GpxTrackSegment > siter = segments.iterator();
-    while (siter.hasNext())
-    {
-      Iterator< WayPoint > witer = siter.next().getWayPoints().iterator();
-      while (witer.hasNext())
-        wayPoints.add(witer.next());
-    }
-    Vector< Double > wayPointsDist = new Vector< Double >(wayPoints.size());
-
-    int i = 0;
-    double time = -48*60*60;
-    double dGpsStartTime = StopImporterDialog.parseTime(gpsStartTime);
-    while ((i < wayPoints.size()) && (time < dGpsStartTime + timeWindow/2))
-    {
-      if (wayPoints.elementAt(i).getString("time") != null)
-        time = StopImporterDialog.parseTime(wayPoints.elementAt(i)
-            .getString("time").substring(11,19));
-      if (time < dGpsStartTime)
-        time += 24*60*60;
-      wayPointsDist.add(Double.valueOf(Double.POSITIVE_INFINITY));
-      ++i;
-    }
-    while (i < wayPoints.size())
-    {
-      int j = i;
-      double time2 = time;
-      while ((j > 0) && (time - timeWindow/2 < time2))
-      {
-        --j;
-        if (wayPoints.elementAt(j).getString("time") != null)
-          time2 = StopImporterDialog.parseTime(wayPoints.elementAt(j)
-              .getString("time").substring(11,19));
-        if (time2 < dGpsStartTime)
-          time2 += 24*60*60;
-      }
-      int k = i + 1;
-      time2 = time;
-      while ((k < wayPoints.size()) && (time + timeWindow/2 > time2))
-      {
-        if (wayPoints.elementAt(k).getString("time") != null)
-          time2 = StopImporterDialog.parseTime(wayPoints.elementAt(k)
-              .getString("time").substring(11,19));
-        if (time2 < dGpsStartTime)
-          time2 += 24*60*60;
-        ++k;
-      }
-
-      if (j < k)
-      {
-        double dist = 0;
-        LatLon latLonI = wayPoints.elementAt(i).getCoor();
-        for (int l = j; l < k; ++l)
-        {
-          double distL = latLonI.greatCircleDistance(wayPoints.elementAt(l).getCoor());
-          if (distL > dist)
-            dist = distL;
-        }
-        wayPointsDist.add(Double.valueOf(dist));
-      }
-      else
-        wayPointsDist.add(Double.valueOf(Double.POSITIVE_INFINITY));
-
-      if (wayPoints.elementAt(i).getString("time") != null)
-        time = StopImporterDialog.parseTime(wayPoints.elementAt(i)
-            .getString("time").substring(11,19));
-      if (time < dGpsStartTime)
-        time += 24*60*60;
-      ++i;
-    }
-
-    LatLon lastStopCoor = null;
-    for (i = 1; i < wayPoints.size()-1; ++i)
-    {
-      if (wayPointsDist.elementAt(i).doubleValue() >= threshold)
-        continue;
-      if ((wayPointsDist.elementAt(i).compareTo(wayPointsDist.elementAt(i-1)) != -1)
-       || (wayPointsDist.elementAt(i).compareTo(wayPointsDist.elementAt(i+1)) != -1))
-        continue;
-
-      LatLon latLon = wayPoints.elementAt(i).getCoor();
-      if ((lastStopCoor != null) &&  (lastStopCoor.greatCircleDistance(latLon) < threshold))
-        continue;
-
-      if (wayPoints.elementAt(i).getString("time") != null)
-      {
-        time = StopImporterDialog.parseTime(wayPoints.elementAt(i)
-            .getString("time").substring(11,19));
-        double gpsSyncTime = StopImporterDialog.parseTime(this.gpsSyncTime);
-        if (gpsSyncTime < dGpsStartTime - 12*60*60)
-          gpsSyncTime += 24*60*60;
-        double timeDelta = gpsSyncTime - StopImporterDialog.parseTime(stopwatchStart);
-        time -= timeDelta;
-        Node node = StopImporterAction.createNode(latLon, type, "");
-        stoplistTM.insertRow(-1, node, StopImporterAction.timeOf(time), "", new TransText(null));
-      }
-
-      lastStopCoor = latLon;
-    }
-
-    return true;
-  }
-
-  public void undoCommand()
-  {
-    if (stoplistTM == null)
-      return;
-    for (int i = 0; i < stoplistTM.getNodes().size(); ++i)
-    {
-      Node node = stoplistTM.nodeAt(i);
-      if (node == null)
-        continue;
-      Main.main.getCurrentDataSet().removePrimitive(node);
-      node.setDeleted(true);
-    }
-
-    stoplistTM.setDataVector(tableDataModel);
-    stoplistTM.setNodes(nodes);
-    stoplistTM.setTimes(times);
-
-    for (int i = 0; i < stoplistTM.getNodes().size(); ++i)
-    {
-      Node node = stoplistTM.nodeAt(i);
-      if (node == null)
-        continue;
-      node.setDeleted(false);
-      Main.main.getCurrentDataSet().addPrimitive(node);
-    }
-  }
-
-  public void fillModifiedData
-    (Collection< OsmPrimitive > modified, Collection< OsmPrimitive > deleted,
-     Collection< OsmPrimitive > added)
-  {
-  }
-
-  @Override public String getDescriptionText()
-  {
-    return tr("Public Transport: Suggest stops");
-  }
-
-  private class NodeSortEntry implements Comparable< NodeSortEntry >
-  {
-    public Node node = null;
-    public String time = null;
-    public String name = null;
-    public double startTime = 0;
-
-    public NodeSortEntry(Node node, String time, String name, double startTime)
-    {
-      this.node = node;
-      this.time = time;
-      this.name = name;
-    }
-
-    public int compareTo(NodeSortEntry nse)
-    {
-      double time = StopImporterDialog.parseTime(this.time);
-      if (time - startTime > 12*60*60)
-        time -= 24*60*60;
-
-      double nseTime = StopImporterDialog.parseTime(nse.time);
-      if (nseTime - startTime > 12*60*60)
-        nseTime -= 24*60*60;
-
-      if (time < nseTime)
-        return -1;
-      else if (time > nseTime)
-        return 1;
-      else
-        return 0;
-    }
-  };
-};
+public class TrackSuggestStopsCommand extends Command {
+    private TrackStoplistTableModel stoplistTM = null;
+
+    private String type = null;
+
+    private String stopwatchStart;
+
+    private String gpsStartTime;
+
+    private String gpsSyncTime;
+
+    private double timeWindow;
+
+    private double threshold;
+
+    private Collection<GpxTrackSegment> segments = null;
+
+    private Vector<Vector<Object>> tableDataModel = null;
+
+    private Vector<Node> nodes = null;
+
+    private Vector<String> times = null;
+
+    public TrackSuggestStopsCommand(StopImporterAction controller) {
+        if (controller.getCurrentTrack() == null)
+            return;
+        stoplistTM = controller.getCurrentTrack().stoplistTM;
+        type = controller.getDialog().getStoptype();
+        stopwatchStart = controller.getCurrentTrack().stopwatchStart;
+        gpsStartTime = controller.getCurrentTrack().gpsStartTime;
+        gpsSyncTime = controller.getCurrentTrack().gpsSyncTime;
+        timeWindow = controller.getCurrentTrack().timeWindow;
+        threshold = controller.getCurrentTrack().threshold;
+        segments = controller.getCurrentTrack().getGpxTrack().getSegments();
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public boolean executeCommand() {
+        if (stoplistTM == null)
+            return false;
+        tableDataModel = (Vector<Vector<Object>>) stoplistTM.getDataVector().clone();
+        nodes = (Vector<Node>) stoplistTM.getNodes().clone();
+        times = (Vector<String>) stoplistTM.getTimes().clone();
+
+        for (int i = 0; i < stoplistTM.getNodes().size(); ++i) {
+            Node node = stoplistTM.nodeAt(i);
+            if (node == null)
+                continue;
+            Main.getLayerManager().getEditDataSet().removePrimitive(node);
+            node.setDeleted(true);
+        }
+        stoplistTM.clear();
+
+        Vector<WayPoint> wayPoints = new Vector<>();
+        Iterator<GpxTrackSegment> siter = segments.iterator();
+        while (siter.hasNext()) {
+            Iterator<WayPoint> witer = siter.next().getWayPoints().iterator();
+            while (witer.hasNext())
+                wayPoints.add(witer.next());
+        }
+        Vector<Double> wayPointsDist = new Vector<>(wayPoints.size());
+
+        int i = 0;
+        double time = -48 * 60 * 60;
+        double dGpsStartTime = StopImporterDialog.parseTime(gpsStartTime);
+        while ((i < wayPoints.size()) && (time < dGpsStartTime + timeWindow / 2)) {
+            if (wayPoints.elementAt(i).getString("time") != null)
+                time = StopImporterDialog
+                        .parseTime(wayPoints.elementAt(i).getString("time").substring(11, 19));
+            if (time < dGpsStartTime)
+                time += 24 * 60 * 60;
+            wayPointsDist.add(Double.valueOf(Double.POSITIVE_INFINITY));
+            ++i;
+        }
+        while (i < wayPoints.size()) {
+            int j = i;
+            double time2 = time;
+            while ((j > 0) && (time - timeWindow / 2 < time2)) {
+                --j;
+                if (wayPoints.elementAt(j).getString("time") != null)
+                    time2 = StopImporterDialog
+                            .parseTime(wayPoints.elementAt(j).getString("time").substring(11, 19));
+                if (time2 < dGpsStartTime)
+                    time2 += 24 * 60 * 60;
+            }
+            int k = i + 1;
+            time2 = time;
+            while ((k < wayPoints.size()) && (time + timeWindow / 2 > time2)) {
+                if (wayPoints.elementAt(k).getString("time") != null)
+                    time2 = StopImporterDialog
+                            .parseTime(wayPoints.elementAt(k).getString("time").substring(11, 19));
+                if (time2 < dGpsStartTime)
+                    time2 += 24 * 60 * 60;
+                ++k;
+            }
+
+            if (j < k) {
+                double dist = 0;
+                LatLon latLonI = wayPoints.elementAt(i).getCoor();
+                for (int l = j; l < k; ++l) {
+                    double distL = latLonI.greatCircleDistance(wayPoints.elementAt(l).getCoor());
+                    if (distL > dist)
+                        dist = distL;
+                }
+                wayPointsDist.add(Double.valueOf(dist));
+            } else
+                wayPointsDist.add(Double.valueOf(Double.POSITIVE_INFINITY));
+
+            if (wayPoints.elementAt(i).getString("time") != null)
+                time = StopImporterDialog
+                        .parseTime(wayPoints.elementAt(i).getString("time").substring(11, 19));
+            if (time < dGpsStartTime)
+                time += 24 * 60 * 60;
+            ++i;
+        }
+
+        LatLon lastStopCoor = null;
+        for (i = 1; i < wayPoints.size() - 1; ++i) {
+            if (wayPointsDist.elementAt(i).doubleValue() >= threshold)
+                continue;
+            if ((wayPointsDist.elementAt(i).compareTo(wayPointsDist.elementAt(i - 1)) != -1)
+                    || (wayPointsDist.elementAt(i).compareTo(wayPointsDist.elementAt(i + 1)) != -1))
+                continue;
+
+            LatLon latLon = wayPoints.elementAt(i).getCoor();
+            if ((lastStopCoor != null) && (lastStopCoor.greatCircleDistance(latLon) < threshold))
+                continue;
+
+            if (wayPoints.elementAt(i).getString("time") != null) {
+                time = StopImporterDialog
+                        .parseTime(wayPoints.elementAt(i).getString("time").substring(11, 19));
+                double gpsSyncTime = StopImporterDialog.parseTime(this.gpsSyncTime);
+                if (gpsSyncTime < dGpsStartTime - 12 * 60 * 60)
+                    gpsSyncTime += 24 * 60 * 60;
+                double timeDelta = gpsSyncTime - StopImporterDialog.parseTime(stopwatchStart);
+                time -= timeDelta;
+                Node node = StopImporterAction.createNode(latLon, type, "");
+                stoplistTM.insertRow(-1, node, StopImporterAction.timeOf(time), "",
+                        new TransText(null));
+            }
+
+            lastStopCoor = latLon;
+        }
+
+        return true;
+    }
+
+    @Override
+    public void undoCommand() {
+        if (stoplistTM == null)
+            return;
+        for (int i = 0; i < stoplistTM.getNodes().size(); ++i) {
+            Node node = stoplistTM.nodeAt(i);
+            if (node == null)
+                continue;
+            Main.getLayerManager().getEditDataSet().removePrimitive(node);
+            node.setDeleted(true);
+        }
+
+        stoplistTM.setDataVector(tableDataModel);
+        stoplistTM.setNodes(nodes);
+        stoplistTM.setTimes(times);
+
+        for (int i = 0; i < stoplistTM.getNodes().size(); ++i) {
+            Node node = stoplistTM.nodeAt(i);
+            if (node == null)
+                continue;
+            node.setDeleted(false);
+            Main.getLayerManager().getEditDataSet().addPrimitive(node);
+        }
+    }
+
+    @Override
+    public void fillModifiedData(Collection<OsmPrimitive> modified,
+            Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
+    }
+
+    @Override
+    public String getDescriptionText() {
+        return tr("Public Transport: Suggest stops");
+    }
+/*
+    private class NodeSortEntry implements Comparable<NodeSortEntry> {
+        public Node node = null;
+
+        public String time = null;
+
+        public String name = null;
+
+        public double startTime = 0;
+
+        public NodeSortEntry(Node node, String time, String name, double startTime) {
+            this.node = node;
+            this.time = time;
+            this.name = name;
+        }
+
+        @Override
+        public int compareTo(NodeSortEntry nse) {
+            double time = StopImporterDialog.parseTime(this.time);
+            if (time - startTime > 12 * 60 * 60)
+                time -= 24 * 60 * 60;
+
+            double nseTime = StopImporterDialog.parseTime(nse.time);
+            if (nseTime - startTime > 12 * 60 * 60)
+                nseTime -= 24 * 60 * 60;
+
+            if (time < nseTime)
+                return -1;
+            else if (time > nseTime)
+                return 1;
+            else
+                return 0;
+        }
+    }*/
+}
Index: /applications/editors/josm/plugins/public_transport/src/public_transport/TransText.java
===================================================================
--- /applications/editors/josm/plugins/public_transport/src/public_transport/TransText.java	(revision 32356)
+++ /applications/editors/josm/plugins/public_transport/src/public_transport/TransText.java	(revision 32357)
@@ -3,13 +3,13 @@
 import static org.openstreetmap.josm.tools.I18n.tr;
 
-public class TransText
-{
+public class TransText {
     public String text;
-    public TransText(String t)
-    {
+
+    public TransText(String t) {
         text = t;
     }
-    public String toString()
-    {
+
+    @Override
+    public String toString() {
         return text == null ? "" : tr(text);
     }
Index: /applications/editors/josm/plugins/public_transport/src/public_transport/WaypointTableModel.java
===================================================================
--- /applications/editors/josm/plugins/public_transport/src/public_transport/WaypointTableModel.java	(revision 32356)
+++ /applications/editors/josm/plugins/public_transport/src/public_transport/WaypointTableModel.java	(revision 32357)
@@ -14,85 +14,78 @@
 import org.openstreetmap.josm.data.osm.Node;
 
-public class WaypointTableModel extends DefaultTableModel
-      implements TableModelListener
-{
-  private StopImporterAction controller = null;
-  public boolean inEvent = false;
-  public Vector< Node > nodes = new Vector< Node >();
-  public Vector< LatLon > coors = new Vector< LatLon >();
+public class WaypointTableModel extends DefaultTableModel implements TableModelListener {
+    private StopImporterAction controller = null;
 
-  public WaypointTableModel(StopImporterAction controller)
-  {
-    this.controller = controller;
-    addColumn(tr("Time"));
-    addColumn(tr("Stopname"));
-    addColumn(tr("Shelter"));
-    addTableModelListener(this);
-  }
+    public boolean inEvent = false;
 
-  public boolean isCellEditable(int row, int column)
-  {
-    if (column >= 1)
-      return true;
-    return false;
-  }
+    public Vector<Node> nodes = new Vector<>();
 
-  public void addRow(Object[] obj)
-  {
-    throw new UnsupportedOperationException();
-  }
+    public Vector<LatLon> coors = new Vector<>();
 
-  public void insertRow(int insPos, Object[] obj)
-  {
-    throw new UnsupportedOperationException();
-  }
+    public WaypointTableModel(StopImporterAction controller) {
+        this.controller = controller;
+        addColumn(tr("Time"));
+        addColumn(tr("Stopname"));
+        addColumn(tr("Shelter"));
+        addTableModelListener(this);
+    }
 
-  public void addRow(WayPoint wp)
-  {
-    insertRow(-1, wp);
-  }
+    @Override
+    public boolean isCellEditable(int row, int column) {
+        if (column >= 1)
+            return true;
+        return false;
+    }
 
-  public void insertRow(int insPos, WayPoint wp)
-  {
-    String time = wp.getString("time");
-    if (time == null)
-      time = "";
-    String name = wp.getString("name");
-    if (name == null)
-      name = "";
+    @Override
+    public void addRow(Object[] obj) {
+        throw new UnsupportedOperationException();
+    }
 
-    Node node = controller.createNode(wp.getCoor(), name);
+    @Override
+    public void insertRow(int insPos, Object[] obj) {
+        throw new UnsupportedOperationException();
+    }
 
-    Object[] buf = { time, name, new TransText(null) };
-    if (insPos == -1)
-    {
-      nodes.addElement(node);
-      coors.addElement(wp.getCoor());
-      super.addRow(buf);
+    public void addRow(WayPoint wp) {
+        insertRow(-1, wp);
     }
-    else
-    {
-      nodes.insertElementAt(node, insPos);
-      coors.insertElementAt(wp.getCoor(), insPos);
-      super.insertRow(insPos, buf);
+
+    public void insertRow(int insPos, WayPoint wp) {
+        String time = wp.getString("time");
+        if (time == null)
+            time = "";
+        String name = wp.getString("name");
+        if (name == null)
+            name = "";
+
+        Node node = controller.createNode(wp.getCoor(), name);
+
+        Object[] buf = { time, name, new TransText(null) };
+        if (insPos == -1) {
+            nodes.addElement(node);
+            coors.addElement(wp.getCoor());
+            super.addRow(buf);
+        } else {
+            nodes.insertElementAt(node, insPos);
+            coors.insertElementAt(wp.getCoor(), insPos);
+            super.insertRow(insPos, buf);
+        }
     }
-  }
 
-  public void clear()
-  {
-    nodes.clear();
-    super.setRowCount(0);
-  }
+    public void clear() {
+        nodes.clear();
+        super.setRowCount(0);
+    }
 
-  public void tableChanged(TableModelEvent e)
-  {
-    if (e.getType() == TableModelEvent.UPDATE)
-    {
-      if (inEvent)
-        return;
-      Main.main.undoRedo.add(new WaypointsNameCommand
-      (this, e.getFirstRow(), (String)getValueAt(e.getFirstRow(), 1),
-       (TransText)getValueAt(e.getFirstRow(), 2)));
+    @Override
+    public void tableChanged(TableModelEvent e) {
+        if (e.getType() == TableModelEvent.UPDATE) {
+            if (inEvent)
+                return;
+            Main.main.undoRedo.add(new WaypointsNameCommand(this, e.getFirstRow(),
+                    (String) getValueAt(e.getFirstRow(), 1),
+                    (TransText) getValueAt(e.getFirstRow(), 2)));
+        }
     }
-  }
-};
+}
Index: /applications/editors/josm/plugins/public_transport/src/public_transport/WaypointsDetachCommand.java
===================================================================
--- /applications/editors/josm/plugins/public_transport/src/public_transport/WaypointsDetachCommand.java	(revision 32356)
+++ /applications/editors/josm/plugins/public_transport/src/public_transport/WaypointsDetachCommand.java	(revision 32357)
@@ -10,70 +10,63 @@
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 
-public class WaypointsDetachCommand extends Command
-{
-  private Vector< Integer > workingLines = null;
-  private Vector< Node > nodesForUndo = null;
-  private WaypointTableModel waypointTM = null;
+public class WaypointsDetachCommand extends Command {
+    private Vector<Integer> workingLines = null;
 
-  public WaypointsDetachCommand(StopImporterAction controller)
-  {
-    waypointTM = controller.getWaypointTableModel();
-    workingLines = new Vector< Integer >();
-    nodesForUndo = new Vector< Node >();
+    private Vector<Node> nodesForUndo = null;
 
-    // use either selected lines or all lines if no line is selected
-    int[] selectedLines = controller.getDialog().getWaypointsTable().getSelectedRows();
-    Vector< Integer > consideredLines = new Vector< Integer >();
-    if (selectedLines.length > 0)
-    {
-      for (int i = 0; i < selectedLines.length; ++i)
-    consideredLines.add(selectedLines[i]);
-    }
-    else
-    {
-      for (int i = 0; i < waypointTM.getRowCount(); ++i)
-    consideredLines.add(new Integer(i));
+    private WaypointTableModel waypointTM = null;
+
+    public WaypointsDetachCommand(StopImporterAction controller) {
+        waypointTM = controller.getWaypointTableModel();
+        workingLines = new Vector<>();
+        nodesForUndo = new Vector<>();
+
+        // use either selected lines or all lines if no line is selected
+        int[] selectedLines = controller.getDialog().getWaypointsTable().getSelectedRows();
+        Vector<Integer> consideredLines = new Vector<>();
+        if (selectedLines.length > 0) {
+            for (int i = 0; i < selectedLines.length; ++i)
+                consideredLines.add(selectedLines[i]);
+        } else {
+            for (int i = 0; i < waypointTM.getRowCount(); ++i)
+                consideredLines.add(new Integer(i));
+        }
+
+        // keep only lines where a node can be added
+        for (int i = 0; i < consideredLines.size(); ++i) {
+            if (waypointTM.nodes.elementAt(consideredLines.elementAt(i)) != null)
+                workingLines.add(consideredLines.elementAt(i));
+        }
     }
 
-    // keep only lines where a node can be added
-    for (int i = 0; i < consideredLines.size(); ++i)
-    {
-      if (waypointTM.nodes.elementAt(consideredLines.elementAt(i)) != null)
-    workingLines.add(consideredLines.elementAt(i));
+    @Override
+    public boolean executeCommand() {
+        nodesForUndo.clear();
+        for (int i = 0; i < workingLines.size(); ++i) {
+            int j = workingLines.elementAt(i).intValue();
+            Node node = waypointTM.nodes.elementAt(j);
+            nodesForUndo.add(node);
+            waypointTM.nodes.set(j, null);
+        }
+        return true;
     }
-  }
 
-  public boolean executeCommand()
-  {
-    nodesForUndo.clear();
-    for (int i = 0; i < workingLines.size(); ++i)
-    {
-      int j = workingLines.elementAt(i).intValue();
-      Node node = waypointTM.nodes.elementAt(j);
-      nodesForUndo.add(node);
-      waypointTM.nodes.set(j, null);
+    @Override
+    public void undoCommand() {
+        for (int i = 0; i < workingLines.size(); ++i) {
+            int j = workingLines.elementAt(i).intValue();
+            Node node = nodesForUndo.elementAt(i);
+            waypointTM.nodes.set(j, node);
+        }
     }
-    return true;
-  }
 
-  public void undoCommand()
-  {
-    for (int i = 0; i < workingLines.size(); ++i)
-    {
-      int j = workingLines.elementAt(i).intValue();
-      Node node = nodesForUndo.elementAt(i);
-      waypointTM.nodes.set(j, node);
+    @Override
+    public void fillModifiedData(Collection<OsmPrimitive> modified,
+            Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
     }
-  }
 
-  public void fillModifiedData
-    (Collection< OsmPrimitive > modified, Collection< OsmPrimitive > deleted,
-     Collection< OsmPrimitive > added)
-  {
-  }
-
-  @Override public String getDescriptionText()
-  {
-    return tr("Public Transport: Detach waypoints");
-  }
-};
+    @Override
+    public String getDescriptionText() {
+        return tr("Public Transport: Detach waypoints");
+    }
+}
Index: /applications/editors/josm/plugins/public_transport/src/public_transport/WaypointsDisableCommand.java
===================================================================
--- /applications/editors/josm/plugins/public_transport/src/public_transport/WaypointsDisableCommand.java	(revision 32356)
+++ /applications/editors/josm/plugins/public_transport/src/public_transport/WaypointsDisableCommand.java	(revision 32357)
@@ -11,78 +11,71 @@
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 
-public class WaypointsDisableCommand extends Command
-{
-  private Vector< Integer > workingLines = null;
-  private Vector< Node > nodesForUndo = null;
-  private WaypointTableModel waypointTM = null;
+public class WaypointsDisableCommand extends Command {
+    private Vector<Integer> workingLines = null;
 
-  public WaypointsDisableCommand(StopImporterAction controller)
-  {
-    waypointTM = controller.getWaypointTableModel();
-    workingLines = new Vector< Integer >();
-    nodesForUndo = new Vector< Node >();
+    private Vector<Node> nodesForUndo = null;
 
-    // use either selected lines or all lines if no line is selected
-    int[] selectedLines = controller.getDialog().getWaypointsTable().getSelectedRows();
-    Vector< Integer > consideredLines = new Vector< Integer >();
-    if (selectedLines.length > 0)
-    {
-      for (int i = 0; i < selectedLines.length; ++i)
-    consideredLines.add(selectedLines[i]);
-    }
-    else
-    {
-      for (int i = 0; i < waypointTM.getRowCount(); ++i)
-    consideredLines.add(new Integer(i));
+    private WaypointTableModel waypointTM = null;
+
+    public WaypointsDisableCommand(StopImporterAction controller) {
+        waypointTM = controller.getWaypointTableModel();
+        workingLines = new Vector<>();
+        nodesForUndo = new Vector<>();
+
+        // use either selected lines or all lines if no line is selected
+        int[] selectedLines = controller.getDialog().getWaypointsTable().getSelectedRows();
+        Vector<Integer> consideredLines = new Vector<>();
+        if (selectedLines.length > 0) {
+            for (int i = 0; i < selectedLines.length; ++i)
+                consideredLines.add(selectedLines[i]);
+        } else {
+            for (int i = 0; i < waypointTM.getRowCount(); ++i)
+                consideredLines.add(new Integer(i));
+        }
+
+        // keep only lines where a node can be added
+        for (int i = 0; i < consideredLines.size(); ++i) {
+            if (waypointTM.nodes.elementAt(consideredLines.elementAt(i)) != null)
+                workingLines.add(consideredLines.elementAt(i));
+        }
     }
 
-    // keep only lines where a node can be added
-    for (int i = 0; i < consideredLines.size(); ++i)
-    {
-      if (waypointTM.nodes.elementAt(consideredLines.elementAt(i)) != null)
-    workingLines.add(consideredLines.elementAt(i));
+    @Override
+    public boolean executeCommand() {
+        nodesForUndo.clear();
+        for (int i = 0; i < workingLines.size(); ++i) {
+            int j = workingLines.elementAt(i).intValue();
+            Node node = waypointTM.nodes.elementAt(j);
+            nodesForUndo.add(node);
+            if (node == null)
+                continue;
+            waypointTM.nodes.set(j, null);
+            Main.getLayerManager().getEditDataSet().removePrimitive(node);
+            node.setDeleted(true);
+        }
+        return true;
     }
-  }
 
-  public boolean executeCommand()
-  {
-    nodesForUndo.clear();
-    for (int i = 0; i < workingLines.size(); ++i)
-    {
-      int j = workingLines.elementAt(i).intValue();
-      Node node = waypointTM.nodes.elementAt(j);
-      nodesForUndo.add(node);
-      if (node == null)
-    continue;
-      waypointTM.nodes.set(j, null);
-      Main.main.getCurrentDataSet().removePrimitive(node);
-      node.setDeleted(true);
+    @Override
+    public void undoCommand() {
+        for (int i = 0; i < workingLines.size(); ++i) {
+            int j = workingLines.elementAt(i).intValue();
+            Node node = nodesForUndo.elementAt(i);
+            waypointTM.nodes.set(j, node);
+            if (node == null)
+                continue;
+            node.setDeleted(false);
+            Main.getLayerManager().getEditDataSet().addPrimitive(node);
+        }
     }
-    return true;
-  }
 
-  public void undoCommand()
-  {
-    for (int i = 0; i < workingLines.size(); ++i)
-    {
-      int j = workingLines.elementAt(i).intValue();
-      Node node = nodesForUndo.elementAt(i);
-      waypointTM.nodes.set(j, node);
-      if (node == null)
-    continue;
-      node.setDeleted(false);
-      Main.main.getCurrentDataSet().addPrimitive(node);
+    @Override
+    public void fillModifiedData(Collection<OsmPrimitive> modified,
+            Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
     }
-  }
 
-  public void fillModifiedData
-    (Collection< OsmPrimitive > modified, Collection< OsmPrimitive > deleted,
-     Collection< OsmPrimitive > added)
-  {
-  }
-
-  @Override public String getDescriptionText()
-  {
-    return tr("Public Transport: Disable waypoints");
-  }
+    @Override
+    public String getDescriptionText() {
+        return tr("Public Transport: Disable waypoints");
+    }
 };
Index: /applications/editors/josm/plugins/public_transport/src/public_transport/WaypointsEnableCommand.java
===================================================================
--- /applications/editors/josm/plugins/public_transport/src/public_transport/WaypointsEnableCommand.java	(revision 32356)
+++ /applications/editors/josm/plugins/public_transport/src/public_transport/WaypointsEnableCommand.java	(revision 32357)
@@ -11,75 +11,68 @@
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 
-public class WaypointsEnableCommand extends Command
-{
-  private Vector< Integer > workingLines = null;
-  private WaypointTableModel waypointTM = null;
-  private String type = null;
+public class WaypointsEnableCommand extends Command {
+    private Vector<Integer> workingLines = null;
 
-  public WaypointsEnableCommand(StopImporterAction controller)
-  {
-    waypointTM = controller.getWaypointTableModel();
-    type = controller.getDialog().getStoptype();
-    workingLines = new Vector< Integer >();
+    private WaypointTableModel waypointTM = null;
 
-    // use either selected lines or all lines if no line is selected
-    int[] selectedLines = controller.getDialog().getWaypointsTable().getSelectedRows();
-    Vector< Integer > consideredLines = new Vector< Integer >();
-    if (selectedLines.length > 0)
-    {
-      for (int i = 0; i < selectedLines.length; ++i)
-        consideredLines.add(selectedLines[i]);
-    }
-    else
-    {
-      for (int i = 0; i < waypointTM.getRowCount(); ++i)
-        consideredLines.add(new Integer(i));
+    private String type = null;
+
+    public WaypointsEnableCommand(StopImporterAction controller) {
+        waypointTM = controller.getWaypointTableModel();
+        type = controller.getDialog().getStoptype();
+        workingLines = new Vector<>();
+
+        // use either selected lines or all lines if no line is selected
+        int[] selectedLines = controller.getDialog().getWaypointsTable().getSelectedRows();
+        Vector<Integer> consideredLines = new Vector<>();
+        if (selectedLines.length > 0) {
+            for (int i = 0; i < selectedLines.length; ++i)
+                consideredLines.add(selectedLines[i]);
+        } else {
+            for (int i = 0; i < waypointTM.getRowCount(); ++i)
+                consideredLines.add(new Integer(i));
+        }
+
+        // keep only lines where a node can be added
+        for (int i = 0; i < consideredLines.size(); ++i) {
+            if (waypointTM.nodes.elementAt(consideredLines.elementAt(i)) == null)
+                workingLines.add(consideredLines.elementAt(i));
+        }
     }
 
-    // keep only lines where a node can be added
-    for (int i = 0; i < consideredLines.size(); ++i)
-    {
-      if (waypointTM.nodes.elementAt(consideredLines.elementAt(i)) == null)
-        workingLines.add(consideredLines.elementAt(i));
+    @Override
+    public boolean executeCommand() {
+        for (int i = 0; i < workingLines.size(); ++i) {
+            int j = workingLines.elementAt(i).intValue();
+            Node node = StopImporterAction.createNode(waypointTM.coors.elementAt(j), type,
+                    (String) waypointTM.getValueAt(j, 1));
+            TransText shelter = (TransText) waypointTM.getValueAt(j, 2);
+            node.put("shelter", shelter.text);
+            waypointTM.nodes.set(j, node);
+        }
+        return true;
     }
-  }
 
-  public boolean executeCommand()
-  {
-    for (int i = 0; i < workingLines.size(); ++i)
-    {
-      int j = workingLines.elementAt(i).intValue();
-      Node node = StopImporterAction.createNode
-        (waypointTM.coors.elementAt(j), type, (String)waypointTM.getValueAt(j, 1));
-      TransText shelter = (TransText)waypointTM.getValueAt(j, 2);
-      node.put("shelter", shelter.text);
-      waypointTM.nodes.set(j, node);
+    @Override
+    public void undoCommand() {
+        for (int i = 0; i < workingLines.size(); ++i) {
+            int j = workingLines.elementAt(i).intValue();
+            Node node = waypointTM.nodes.elementAt(j);
+            waypointTM.nodes.set(j, null);
+            if (node == null)
+                continue;
+            Main.getLayerManager().getEditDataSet().removePrimitive(node);
+            node.setDeleted(true);
+        }
     }
-    return true;
-  }
 
-  public void undoCommand()
-  {
-    for (int i = 0; i < workingLines.size(); ++i)
-    {
-      int j = workingLines.elementAt(i).intValue();
-      Node node = waypointTM.nodes.elementAt(j);
-      waypointTM.nodes.set(j, null);
-      if (node == null)
-        continue;
-      Main.main.getCurrentDataSet().removePrimitive(node);
-      node.setDeleted(true);
+    @Override
+    public void fillModifiedData(Collection<OsmPrimitive> modified,
+            Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
     }
-  }
 
-  public void fillModifiedData
-    (Collection< OsmPrimitive > modified, Collection< OsmPrimitive > deleted,
-     Collection< OsmPrimitive > added)
-  {
-  }
-
-  @Override public String getDescriptionText()
-  {
-    return tr("Public Transport: Enable waypoints");
-  }
-};
+    @Override
+    public String getDescriptionText() {
+        return tr("Public Transport: Enable waypoints");
+    }
+}
Index: /applications/editors/josm/plugins/public_transport/src/public_transport/WaypointsNameCommand.java
===================================================================
--- /applications/editors/josm/plugins/public_transport/src/public_transport/WaypointsNameCommand.java	(revision 32356)
+++ /applications/editors/josm/plugins/public_transport/src/public_transport/WaypointsNameCommand.java	(revision 32357)
@@ -8,69 +8,68 @@
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 
-public class WaypointsNameCommand extends Command
-{
-  private int workingLine = 0;
-  private WaypointTableModel waypointTM = null;
-  private String oldName = null;
-  private String name = null;
-  private String oldShelter = null;
-  private TransText shelter;
+public class WaypointsNameCommand extends Command {
+    private int workingLine = 0;
 
-  public WaypointsNameCommand
-      (WaypointTableModel waypointTM, int workingLine, String name, TransText shelter)
-  {
-    this.waypointTM = waypointTM;
-    this.workingLine = workingLine;
-    if (waypointTM.nodes.elementAt(workingLine) != null)
-    {
-      oldName = waypointTM.nodes.elementAt(workingLine).get("name");
-      oldShelter = waypointTM.nodes.elementAt(workingLine).get("shelter");
+    private WaypointTableModel waypointTM = null;
+
+    private String oldName = null;
+
+    private String name = null;
+
+    private String oldShelter = null;
+
+    private TransText shelter;
+
+    public WaypointsNameCommand(WaypointTableModel waypointTM, int workingLine, String name,
+            TransText shelter) {
+        this.waypointTM = waypointTM;
+        this.workingLine = workingLine;
+        if (waypointTM.nodes.elementAt(workingLine) != null) {
+            oldName = waypointTM.nodes.elementAt(workingLine).get("name");
+            oldShelter = waypointTM.nodes.elementAt(workingLine).get("shelter");
+        }
+        this.name = name;
+        this.shelter = shelter;
     }
-    this.name = name;
-    this.shelter = shelter;
-  }
 
-  public boolean executeCommand()
-  {
-    if (waypointTM.nodes.elementAt(workingLine) != null)
-    {
-      waypointTM.nodes.elementAt(workingLine).put("name", name);
-      waypointTM.nodes.elementAt(workingLine).put("shelter", shelter.text);
+    @Override
+    public boolean executeCommand() {
+        if (waypointTM.nodes.elementAt(workingLine) != null) {
+            waypointTM.nodes.elementAt(workingLine).put("name", name);
+            waypointTM.nodes.elementAt(workingLine).put("shelter", shelter.text);
+        }
+        waypointTM.inEvent = true;
+        if (name == null)
+            waypointTM.setValueAt("", workingLine, 1);
+        else
+            waypointTM.setValueAt(name, workingLine, 1);
+        waypointTM.setValueAt(shelter, workingLine, 2);
+        waypointTM.inEvent = false;
+        return true;
     }
-    waypointTM.inEvent = true;
-    if (name == null)
-      waypointTM.setValueAt("", workingLine, 1);
-    else
-      waypointTM.setValueAt(name, workingLine, 1);
-    waypointTM.setValueAt(shelter, workingLine, 2);
-    waypointTM.inEvent = false;
-    return true;
-  }
 
-  public void undoCommand()
-  {
-    if (waypointTM.nodes.elementAt(workingLine) != null)
-    {
-      waypointTM.nodes.elementAt(workingLine).put("name", oldName);
-      waypointTM.nodes.elementAt(workingLine).put("shelter", oldShelter);
+    @Override
+    public void undoCommand() {
+        if (waypointTM.nodes.elementAt(workingLine) != null) {
+            waypointTM.nodes.elementAt(workingLine).put("name", oldName);
+            waypointTM.nodes.elementAt(workingLine).put("shelter", oldShelter);
+        }
+        waypointTM.inEvent = true;
+        if (oldName == null)
+            waypointTM.setValueAt("", workingLine, 1);
+        else
+            waypointTM.setValueAt(oldName, workingLine, 1);
+        waypointTM.setValueAt(new TransText(oldShelter), workingLine, 2);
+        waypointTM.inEvent = false;
     }
-    waypointTM.inEvent = true;
-    if (oldName == null)
-      waypointTM.setValueAt("", workingLine, 1);
-    else
-      waypointTM.setValueAt(oldName, workingLine, 1);
-    waypointTM.setValueAt(new TransText(oldShelter), workingLine, 2);
-    waypointTM.inEvent = false;
-  }
 
-  public void fillModifiedData
-    (Collection< OsmPrimitive > modified, Collection< OsmPrimitive > deleted,
-     Collection< OsmPrimitive > added)
-  {
-  }
+    @Override
+    public void fillModifiedData(Collection<OsmPrimitive> modified,
+            Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
+    }
 
-  @Override public String getDescriptionText()
-  {
-    return tr("Public Transport: Edit waypoint name");
-  }
-};
+    @Override
+    public String getDescriptionText() {
+        return tr("Public Transport: Edit waypoint name");
+    }
+}
