Index: /applications/editors/josm/plugins/lakewalker/README
===================================================================
--- /applications/editors/josm/plugins/lakewalker/README	(revision 4094)
+++ /applications/editors/josm/plugins/lakewalker/README	(revision 4095)
@@ -1,8 +1,9 @@
 A JOSM plugin to interface to Darryl Shpak's Lakewalker module
 
- - On-screen feedback to Lakewalker progress
+ - On-screen feedback to Lakewalker progress with cancel
  - Tag ways appropriately
  - limit ways to length
  - Access all lakewalker options via preferences and via ctrl-click pop-up dialog
  - Manage Landsat image cache from Prefs screen
+ - Read data in thread
  - ...
Index: /applications/editors/josm/plugins/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/Configurer.java
===================================================================
--- /applications/editors/josm/plugins/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/Configurer.java	(revision 4095)
+++ /applications/editors/josm/plugins/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/Configurer.java	(revision 4095)
@@ -0,0 +1,145 @@
+/*
+ * $Id: Configurer.java 2175 2007-06-04 04:19:59 +0000 (Mon, 04 Jun 2007) rodneykinney $
+ *
+ * Copyright (c) 2000-2003 by Rodney Kinney
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License (LGPL) as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, copies are available 
+ * at http://www.opensource.org.
+ */
+package org.openstreetmap.josm.plugins.lakewalker;
+
+import java.beans.PropertyChangeListener;
+
+/**
+ * A property editor class.  Wraps an Object value and provides
+ * methods for saving and restoring the Object from a String.  Also
+ * includes a {@link java.awt.Component} that can be placed into a
+ * property editing window, allowing the user to change the value
+ * interactively.
+ * */
+public abstract class Configurer {
+// FIXME: maybe parameterize this so that value can have the right type
+// in subclasses?
+  public static final String NAME_PROPERTY = "Configurer.name";
+  //    public static final String VALUE_PROPERTY = "value";
+
+  /** A String the uniquely identifies this property */
+  protected String key;
+  /** A String that provides a short description of the property to the user */
+  protected String name;
+  /** The value */
+  protected Object value;
+  protected java.beans.PropertyChangeSupport changeSupport;
+  /** When noUpdate is true, setting the value programmatically will not
+   * result in an update of the GUI Component */
+  protected boolean noUpdate = false;
+  /** When frozen is true, setting the value programmatically will not
+   * result in a PropertyChangeEvent being fired */
+  protected boolean frozen = false;
+
+  public Configurer(String key, String name) {
+    this(key, name, null);
+  }
+
+  public Configurer(String key, String name, Object val) {
+    this.key = key;
+    this.name = name;
+    changeSupport = new java.beans.PropertyChangeSupport(this);
+    setValue(val);
+  }
+
+  /**
+   * Unique identifier
+   */
+  public String getKey() {
+    return key;
+  }
+
+  /**
+   * Plain English description of the Object
+   */
+  public String getName() {
+    return name;
+  }
+
+  public void setName(String s) {
+    String oldName = name;
+    name = s;
+    if (!frozen) {
+      changeSupport.firePropertyChange(NAME_PROPERTY, oldName, name);
+    }
+  }
+
+  /**
+   * The Object value
+   * May be null if the Object has not been initialized
+   */
+  public Object getValue() {
+    return value;
+  }
+
+  /**
+   * @return a String representation of the Object value
+   */
+  public abstract String getValueString();
+
+  /**
+   * Set the Object value
+   */
+  public void setValue(Object o) {
+    Object oldValue = getValue();
+    value = o;
+    if (!frozen) {
+      changeSupport.firePropertyChange(key, oldValue, value);
+    }
+  }
+
+  /**
+   * If true, then don't fire PropertyChangeEvents when the value is reset
+   */
+  public void setFrozen(boolean val) {
+    frozen = val;
+  }
+
+  public boolean isFrozen() {
+    return frozen;
+  }
+
+  /**
+   * Fire a PropertyChangeEvent as if the value had been set from null
+   */
+  public void fireUpdate() {
+    changeSupport.firePropertyChange(key, null, value);
+  }
+
+  /**
+   * Set the Object value from a String
+   */
+  public abstract void setValue(String s);
+
+  /**
+   * GUI interface for setting the option in an editing window
+   */
+  public abstract java.awt.Component getControls();
+
+  /**
+   * Add a listener to be notified when the Object state changes
+   */
+  public void addPropertyChangeListener(java.beans.PropertyChangeListener l) {
+    changeSupport.addPropertyChangeListener(l);
+  }
+  
+  public void removePropertyChangeListener(PropertyChangeListener l) {
+    changeSupport.removePropertyChangeListener(l);
+  }
+}
Index: /applications/editors/josm/plugins/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/DoubleConfigurer.java
===================================================================
--- /applications/editors/josm/plugins/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/DoubleConfigurer.java	(revision 4095)
+++ /applications/editors/josm/plugins/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/DoubleConfigurer.java	(revision 4095)
@@ -0,0 +1,57 @@
+/*
+ * $Id: DoubleConfigurer.java 5 2003-10-02 15:11:38 +0000 (Thu, 02 Oct 2003) rodneykinney $
+ *
+ * Copyright (c) 2000-2003 by Rodney Kinney
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License (LGPL) as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, copies are available 
+ * at http://www.opensource.org.
+ */
+package org.openstreetmap.josm.plugins.lakewalker;
+
+/**
+ * A Configurer for Double values
+ */
+public class DoubleConfigurer extends StringConfigurer {
+
+  public DoubleConfigurer() {
+    super();
+  }
+
+  public DoubleConfigurer(String key, String name) {
+    this(key, name, new Double(0));
+  }
+
+  public DoubleConfigurer(String key, String name, Double val) {
+    super(key, name, val == null ? null : val.toString());
+  }
+
+  public void setValue(String s) {
+    Double d = null;
+    try {
+      d = Double.valueOf(s);
+    }
+    catch (NumberFormatException e) {
+      d = null;
+    }
+    if (d != null) {
+      setValue(d);
+    }
+    if (!noUpdate && nameField != null) {
+      nameField.setText(d.toString());
+    }
+  }
+
+  public String getValueString() {
+    return value == null ? null : value.toString();
+  }
+}
Index: /applications/editors/josm/plugins/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/IntConfigurer.java
===================================================================
--- /applications/editors/josm/plugins/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/IntConfigurer.java	(revision 4095)
+++ /applications/editors/josm/plugins/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/IntConfigurer.java	(revision 4095)
@@ -0,0 +1,73 @@
+/*
+ * $Id: IntConfigurer.java 874 2006-03-15 14:20:56 +0000 (Wed, 15 Mar 2006) rodneykinney $
+ *
+ * Copyright (c) 2000-2003 by Rodney Kinney
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License (LGPL) as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, copies are available
+ * at http://www.opensource.org.
+ */
+package org.openstreetmap.josm.plugins.lakewalker;
+
+/**
+ * A Configurer for Integer values
+ */
+public class IntConfigurer extends StringConfigurer {
+  
+  public IntConfigurer() {
+    super();
+  }
+  
+  public IntConfigurer(String key, String name) {
+    this(key, name, new Integer(0));
+  }
+
+  public IntConfigurer(String key, String name, Integer val) {
+    super(key, name);
+    if (val != null) {
+      setValue(val);
+    }
+  }
+
+  public void setValue(String s) {
+    Integer i = null;
+    try {
+      i = Integer.valueOf(s);
+    }
+    catch (NumberFormatException e) {
+      i = null;
+    }
+    if (i != null) {
+      setValue(i);
+    }
+  }
+  
+  public int getIntValue(int defaultValue) {
+    if (getValue() instanceof Integer) {
+      return ((Integer)getValue()).intValue();
+    }
+    else {
+      return defaultValue;
+    }
+  }
+
+  public void setValue(Object o) {
+    if (!noUpdate && nameField != null && o != null) {
+      nameField.setText(o.toString());
+    }
+    super.setValue(o);
+  }
+
+  public String getValueString() {
+    return value == null ? null : value.toString();
+  }
+}
Index: /applications/editors/josm/plugins/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/LakewalkerAction.java
===================================================================
--- /applications/editors/josm/plugins/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/LakewalkerAction.java	(revision 4094)
+++ /applications/editors/josm/plugins/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/LakewalkerAction.java	(revision 4095)
@@ -12,4 +12,5 @@
 import java.io.File;
 import java.io.InputStreamReader;
+import java.nio.channels.ClosedByInterruptException;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -18,4 +19,5 @@
 
 import javax.swing.JOptionPane;
+import javax.swing.ProgressMonitor;
 
 import org.openstreetmap.josm.Main;
@@ -29,5 +31,7 @@
 import org.openstreetmap.josm.data.osm.Segment;
 import org.openstreetmap.josm.data.osm.Way;
+import org.openstreetmap.josm.gui.PleaseWaitRunnable;
 import org.openstreetmap.josm.tools.ImageProvider;
+import org.xml.sax.SAXException;
 
 /**
@@ -42,5 +46,5 @@
   protected Cursor oldCursor;
   protected List<Node> selectedNodes;
-
+  
   public LakewalkerAction(String name) {
     super(name, "lakewalker-sml", tr("Lake Walker."), KeyEvent.VK_L, KeyEvent.CTRL_MASK
@@ -48,4 +52,5 @@
     this.name = name;
     setEnabled(true);
+
   }
 
@@ -53,10 +58,10 @@
 
     Main.map.mapView.setCursor(oldCursor);
-    
+
     if (Main.map == null) {
       JOptionPane.showMessageDialog(Main.parent, tr("No data loaded."));
       return;
     }
-    
+
     selectedNodes = new ArrayList<Node>();
     for (OsmPrimitive osm : Main.ds.getSelected()) {
@@ -76,109 +81,72 @@
     }
   }
-  
+
   protected void lakewalk(Point clickPoint) {
-   LatLon pos = Main.map.mapView.getLatLon(clickPoint.x, clickPoint.y);
-   String line;
-   
-   File working_dir = new File (Main.pref.getPreferencesDir(), "plugins");
-   working_dir = new File(working_dir, "Lakewalker");
-   String target = Main.pref.get(LakewalkerPlugin.PREF_PYTHON) + " lakewalker.py";
-   LatLon topLeft = Main.map.mapView.getLatLon(0, 0);
-   LatLon botRight = Main.map.mapView.getLatLon(Main.map.mapView.getWidth(), Main.map.mapView.getHeight());
-   
-   target += " --lat=" + pos.lat();
-   target += " --lon=" + pos.lon();
-   target += " --left=" + topLeft.lon();
-   target += " --right=" + botRight.lon();
-   target += " --top=" + topLeft.lat();
-   target += " --bottom=" + botRight.lat();
-   target += " --josm";
-   
-   Collection<Command> commands = new LinkedList<Command>();
-   Way way = new Way();
-   Node lastNode = null;
-   Node firstNode = null;
-   
-   try
-   {
-    Runtime rt = Runtime.getRuntime();
-    System.out.println("dir: "+working_dir+", target: "+target);
-    Process p = rt.exec(target, null, working_dir);
-    System.out.println("Just Run");
-    BufferedReader input =
-     
-      new BufferedReader
- 
-      (new InputStreamReader(p.getInputStream()));
-    BufferedReader err = new BufferedReader(new InputStreamReader (p.getErrorStream())) ;
+    LatLon pos = Main.map.mapView.getLatLon(clickPoint.x, clickPoint.y);
+
+    /*
+     * Collect options
+     */
+    File working_dir = new File(Main.pref.getPreferencesDir(), "plugins");
+    working_dir = new File(working_dir, "Lakewalker");
+    String target = Main.pref.get(LakewalkerPreferences.PREF_PYTHON) + " lakewalker.py";
+    LatLon topLeft = Main.map.mapView.getLatLon(0, 0);
+    LatLon botRight = Main.map.mapView.getLatLon(Main.map.mapView.getWidth(), Main.map.mapView
+        .getHeight());
+
+    /*
+     * Build command line
+     */
+    target += " --lat=" + pos.lat();
+    target += " --lon=" + pos.lon();
+    target += " --left=" + topLeft.lon();
+    target += " --right=" + botRight.lon();
+    target += " --top=" + topLeft.lat();
+    target += " --bottom=" + botRight.lat();
+    target += " --maxnodes=" + Main.pref.get(LakewalkerPreferences.PREF_MAX_NODES, "50000");
+    target += " --threshold=" + Main.pref.get(LakewalkerPreferences.PREF_THRESHOLD, "35");
+    target += " --josm";
+
+
     
-    /*
-     * Lakewalker will output data it stdout. Each line has a code
-     * in character 1 indicating the type of data on the line:
-     * 
-     * m text - Status message
-     * l name [size] - Access landsat image name. size is returned if it needs to be downloaded.
-     * e text - Error message
-     * s nnn - Start node data stream, nnn seperate tracings to follow
-     * t nnn - Start tracing, nnn nodes to follow
-     * x [o] - End of Tracing. o indicates do not connect last node to first
-     * n lat lon [o] - Node. o indicates it is an open node (not connected to the previous node)
-     * z - End of data stream
-     */
-    while ((line = input.readLine()) != null) {
-      System.out.println(line);
-      char option = line.charAt(0);
-      switch(option) {
-      case 'n':
-          String[] tokens = line.split(" ");
-          try {
-            LatLon ll = new LatLon(Double.parseDouble(tokens[1]), Double.parseDouble(tokens[2]));
-            Node n = new Node(ll);
-            commands.add(new AddCommand(n));
-            if (lastNode != null) {
-              Segment s = new Segment(lastNode, n);
-              commands.add(new AddCommand(s));
-              way.segments.add(s);
-            }
-            else {
-              firstNode = n;
-            }
-            lastNode = n;
-          }
-          catch (Exception ex) {
+
+
+    try {
+      /*
+       * Start the Lakewalker
+       */
+      Runtime rt = Runtime.getRuntime();
+      System.out.println("dir: " + working_dir + ", target: " + target);
+      Process p = rt.exec(target, null, working_dir);
+      final BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
+      
+      /*
+       * Start a thread to read the output
+       */
+      final LakewalkerReader reader = new LakewalkerReader();
+      
+      PleaseWaitRunnable lakewalkerTask = new PleaseWaitRunnable(tr("Tracing")){
+        @Override protected void realRun() throws SAXException {
+          reader.read(input);
+        }
+        @Override protected void finish() {
           
-          }
-          break;
+        }
+        @Override protected void cancel() {
+          reader.cancel();
           
-      case 'x':
-          Segment s = new Segment(lastNode, firstNode);
-          commands.add(new AddCommand(s));
-          way.segments.add(s);
-          commands.add(new AddCommand(way));
-          break;
-      }
-      
-     }
-    
-    while ((line = err.readLine()) != null) {
-       System.out.println(line);
-     }
- 
-    input.close();
-    p.destroy();
-
-   }
-   catch (Exception ex) {
-     System.out.println("Exception caught: "+ex.getMessage());
-   }
-   
-   if (!commands.isEmpty()) {
-     Main.main.undoRedo.add(new SequenceCommand(tr("Lakewalker trace"), commands));
-     Main.ds.setSelected(way);
-   }
-  }
-  
+        }
+      };
+      Main.worker.execute(lakewalkerTask); 
+    }
+    catch (Exception ex) {
+      System.out.println("Exception caught: " + ex.getMessage());
+    }
+
+
+  }
+
   protected void lakewalk(List nodes) {
-    
+
   }
 
@@ -189,8 +157,8 @@
   }
 
-  public void mouseEntered(MouseEvent e) {  
-  }
-
-  public void mouseExited(MouseEvent e) {  
+  public void mouseEntered(MouseEvent e) {
+  }
+
+  public void mouseExited(MouseEvent e) {
   }
 
@@ -200,68 +168,69 @@
   public void mouseReleased(MouseEvent e) {
   }
-  
-//  class DuplicateDialog extends JDialog {
-//    private static final long serialVersionUID = 1L;
-//    protected Box mainPanel;
-//    protected IntConfigurer offset;
-//    protected boolean cancelled;
-//    protected String right;
-//    protected String left;
-//    protected JComboBox moveCombo;
-//
-//    public DuplicateDialog(String title) {
-//      super();
-//      this.setTitle(title);
-//      this.setModal(true);
-//      initComponents();
-//    }
-//
-//    protected void initComponents() {
-//      mainPanel = Box.createVerticalBox();
-//      offset = new IntConfigurer("", tr("Offset (metres):  "), new Integer(15));
-//      mainPanel.add(offset.getControls());
-//      getContentPane().add(mainPanel);
-//
-//      right = tr("right/down");
-//      left = tr("left/up");
-//      Box movePanel = Box.createHorizontalBox();
-//      movePanel.add(new JLabel(tr("Create new segments to the ")));
-//      moveCombo = new JComboBox(new String[] {right, left});
-//      movePanel.add(moveCombo);
-//      movePanel.add(new JLabel(tr(" of existing segments.")));
-//      mainPanel.add(movePanel);
-//
-//      Box buttonPanel = Box.createHorizontalBox();
-//      JButton okButton = new JButton(tr("Ok"));
-//      okButton.addActionListener(new ActionListener() {
-//        public void actionPerformed(ActionEvent e) {
-//          cancelled = false;
-//          setVisible(false);
-//
-//        }
-//      });
-//      JButton canButton = new JButton(tr("Cancel"));
-//      canButton.addActionListener(new ActionListener() {
-//        public void actionPerformed(ActionEvent e) {
-//          cancelled = true;
-//          setVisible(false);
-//        }
-//      });
-//      buttonPanel.add(okButton);
-//      buttonPanel.add(canButton);
-//      mainPanel.add(buttonPanel);
-//
-//      pack();
-//    }
-//
-//    protected int getOffset() {
-//      int off = offset.getIntValue(15);
-//      return right.equals(moveCombo.getSelectedItem()) ? off : -off;
-//    }
-//
-//    protected boolean isCancelled() {
-//      return cancelled;
-//    }
-//
-//  }
+
+
+  // class DuplicateDialog extends JDialog {
+  // private static final long serialVersionUID = 1L;
+  // protected Box mainPanel;
+  // protected IntConfigurer offset;
+  // protected boolean cancelled;
+  // protected String right;
+  // protected String left;
+  // protected JComboBox moveCombo;
+  //
+  // public DuplicateDialog(String title) {
+  // super();
+  // this.setTitle(title);
+  // this.setModal(true);
+  // initComponents();
+  // }
+  //
+  // protected void initComponents() {
+  // mainPanel = Box.createVerticalBox();
+  // offset = new IntConfigurer("", tr("Offset (metres): "), new Integer(15));
+  // mainPanel.add(offset.getControls());
+  // getContentPane().add(mainPanel);
+  //
+  // right = tr("right/down");
+  // left = tr("left/up");
+  // Box movePanel = Box.createHorizontalBox();
+  // movePanel.add(new JLabel(tr("Create new segments to the ")));
+  // moveCombo = new JComboBox(new String[] {right, left});
+  // movePanel.add(moveCombo);
+  // movePanel.add(new JLabel(tr(" of existing segments.")));
+  // mainPanel.add(movePanel);
+  //
+  // Box buttonPanel = Box.createHorizontalBox();
+  // JButton okButton = new JButton(tr("Ok"));
+  // okButton.addActionListener(new ActionListener() {
+  // public void actionPerformed(ActionEvent e) {
+  // cancelled = false;
+  // setVisible(false);
+  //
+  // }
+  // });
+  // JButton canButton = new JButton(tr("Cancel"));
+  // canButton.addActionListener(new ActionListener() {
+  // public void actionPerformed(ActionEvent e) {
+  // cancelled = true;
+  // setVisible(false);
+  // }
+  // });
+  // buttonPanel.add(okButton);
+  // buttonPanel.add(canButton);
+  // mainPanel.add(buttonPanel);
+  //
+  // pack();
+  // }
+  //
+  // protected int getOffset() {
+  // int off = offset.getIntValue(15);
+  // return right.equals(moveCombo.getSelectedItem()) ? off : -off;
+  // }
+  //
+  // protected boolean isCancelled() {
+  // return cancelled;
+  // }
+  //
+  // }
 }
Index: /applications/editors/josm/plugins/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/LakewalkerPlugin.java
===================================================================
--- /applications/editors/josm/plugins/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/LakewalkerPlugin.java	(revision 4094)
+++ /applications/editors/josm/plugins/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/LakewalkerPlugin.java	(revision 4095)
@@ -17,6 +17,5 @@
 public class LakewalkerPlugin extends Plugin {
 
-  public static final String VERSION = "0.2";
-  public static final String PREF_PYTHON = "lakewalker.python";
+  public static final String VERSION = "0.3";
   
   protected String name;
@@ -47,5 +46,5 @@
   public PreferenceSetting getPreferenceSetting() 
   {
-    return new LakewalkerPreferenceSetting();
+    return new LakewalkerPreferences();
   }
 
Index: plications/editors/josm/plugins/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/LakewalkerPreferenceSetting.java
===================================================================
--- /applications/editors/josm/plugins/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/LakewalkerPreferenceSetting.java	(revision 4094)
+++ 	(revision )
@@ -1,32 +1,0 @@
-package org.openstreetmap.josm.plugins.lakewalker;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-import javax.swing.JTextField;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.gui.preferences.PreferenceDialog;
-import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
-import org.openstreetmap.josm.tools.GBC;
-import org.openstreetmap.josm.tools.I18n;
-public class LakewalkerPreferenceSetting implements PreferenceSetting {
-
-  protected JTextField python = new JTextField(10);
-  
-  public void addGui(PreferenceDialog gui) {
-    python.setToolTipText(tr("<html>Path to python executable.</html>"));
-    String description = tr("An interlude to the Lakewalker Python module to trace water bodies on Landsat imagery.<br><br>Version: {0}", LakewalkerPlugin.VERSION);
-    JPanel prefPanel = gui.createPreferenceTab("lakewalker.png", I18n.tr("Lakewalker Plugin Preferences"), description);
-    prefPanel.add(new JLabel(tr("Python executable")), GBC.std().insets(10,5,5,0));
-    prefPanel.add(python, GBC.eol().insets(0,5,0,0).fill(GBC.HORIZONTAL));
-    
-  }
-
-  public void ok() {
-    Main.pref.put(LakewalkerPlugin.PREF_PYTHON, python.getText());
-    
-  }
-  
-}
Index: /applications/editors/josm/plugins/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/LakewalkerPreferences.java
===================================================================
--- /applications/editors/josm/plugins/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/LakewalkerPreferences.java	(revision 4095)
+++ /applications/editors/josm/plugins/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/LakewalkerPreferences.java	(revision 4095)
@@ -0,0 +1,56 @@
+package org.openstreetmap.josm.plugins.lakewalker;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.gui.preferences.PreferenceDialog;
+import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
+import org.openstreetmap.josm.tools.GBC;
+import org.openstreetmap.josm.tools.I18n;
+public class LakewalkerPreferences implements PreferenceSetting {
+
+  public static final String PREF_PYTHON = "lakewalker.python";
+  public static final String PREF_MAX_SEG = "lakewalker.max_segs_in_way";
+  public static final String PREF_MAX_NODES = "lakewalker.max_nodes";
+  public static final String PREF_THRESHOLD = "lakewalker.threshold";
+  
+  protected JTextField python = new JTextField(10);
+  protected IntConfigurer maxSegs = new IntConfigurer();
+  protected IntConfigurer maxNodes = new IntConfigurer();
+  protected IntConfigurer threshold = new IntConfigurer();
+  
+  public void addGui(PreferenceDialog gui) {
+    python.setToolTipText(tr("Path to python executable."));
+    maxSegs.setToolTipText(tr("Maximum number of segments per way."));
+    maxNodes.setToolTipText(tr("Maximum number of nodes to trace."));
+    maxNodes.setToolTipText(tr("Gray threshold."));
+    String description = tr("An interlude to the Lakewalker Python module to trace water bodies on Landsat imagery.<br><br>Version: {0}", LakewalkerPlugin.VERSION);
+    
+    JPanel prefPanel = gui.createPreferenceTab("lakewalker.png", I18n.tr("Lakewalker Plugin Preferences"), description);
+    prefPanel.add(new JLabel(tr("Python executable")), GBC.std().insets(10,5,5,0));
+    prefPanel.add(python, GBC.eol().insets(0,5,0,0).fill(GBC.HORIZONTAL));
+    prefPanel.add(new JLabel(tr("Maximum number of segments per way")), GBC.std().insets(10,5,5,0));
+    prefPanel.add(maxSegs.getControls(), GBC.eol().insets(0,5,0,0).fill(GBC.HORIZONTAL));
+    prefPanel.add(new JLabel(tr("Maximum number of nodes to trace")), GBC.std().insets(10,5,5,0));
+    prefPanel.add(maxNodes.getControls(), GBC.eol().insets(0,5,0,0).fill(GBC.HORIZONTAL));
+    prefPanel.add(new JLabel(tr("Maximum gray value to count as water")), GBC.std().insets(10,5,5,0));
+    prefPanel.add(threshold.getControls(), GBC.eol().insets(0,5,0,0).fill(GBC.HORIZONTAL));
+       
+    python.setText(Main.pref.get(PREF_PYTHON, "python.exe"));
+    maxSegs.setValue(Main.pref.get(PREF_MAX_SEG, "250"));
+    maxNodes.setValue(Main.pref.get(PREF_MAX_NODES, "50000"));
+    threshold.setValue(Main.pref.get(PREF_THRESHOLD, "35"));
+  }
+
+  public void ok() {
+    Main.pref.put(PREF_PYTHON, python.getText());
+    Main.pref.put(PREF_MAX_SEG, maxSegs.getValueString());    
+    Main.pref.put(PREF_MAX_NODES, maxNodes.getValueString());
+    Main.pref.put(PREF_THRESHOLD, threshold.getValueString());
+  }
+  
+}
Index: /applications/editors/josm/plugins/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/LakewalkerReader.java
===================================================================
--- /applications/editors/josm/plugins/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/LakewalkerReader.java	(revision 4095)
+++ /applications/editors/josm/plugins/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/LakewalkerReader.java	(revision 4095)
@@ -0,0 +1,116 @@
+/* LakewalkerReader.java
+ * 
+ * Read and process data from a Lakwalker python module
+ * 
+ */
+package org.openstreetmap.josm.plugins.lakewalker;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.io.BufferedReader;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedList;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.command.AddCommand;
+import org.openstreetmap.josm.command.Command;
+import org.openstreetmap.josm.command.SequenceCommand;
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.Segment;
+import org.openstreetmap.josm.data.osm.Way;
+
+public class LakewalkerReader {
+  
+  protected Collection<Command> commands = new LinkedList<Command>();
+  protected Collection<Way> ways = new ArrayList<Way>();
+  protected boolean cancel;
+  
+  /*
+   * Read the data
+   */
+  public void read(BufferedReader input) {
+    /*
+     * Lakewalker will output data it stdout. Each line has a code in
+     * character 1 indicating the type of data on the line:
+     * 
+     * m text - Status message l name [size] - Access landsat image name. size
+     * is returned if it needs to be downloaded. e text - Error message s nnn -
+     * Start node data stream, nnn seperate tracings to follow t nnn - Start
+     * tracing, nnn nodes to follow x [o] - End of Tracing. o indicates do not
+     * connect last node to first n lat lon [o] - Node. o indicates it is an
+     * open node (not connected to the previous node) z - End of data stream
+     */
+
+    Way way = new Way();
+    Node lastNode = null;
+    Node firstNode = null;
+    String line;
+    Main.pleaseWaitDlg.currentAction.setText("Initializing");
+    Main.pleaseWaitDlg.repaint();
+
+    try {
+      while ((line = input.readLine()) != null) {
+        if (cancel) {
+          return;
+        }
+        System.out.println(line);
+        char option = line.charAt(0);
+        switch (option) {
+        case 'n':
+          String[] tokens = line.split(" ");
+          try {
+            LatLon ll = new LatLon(Double.parseDouble(tokens[1]), Double.parseDouble(tokens[2]));
+            Node n = new Node(ll);
+            commands.add(new AddCommand(n));
+            if (lastNode != null) {
+              Segment s = new Segment(lastNode, n);
+              commands.add(new AddCommand(s));
+              way.segments.add(s);
+            }
+            else {
+              firstNode = n;
+            }
+            lastNode = n;
+          }
+          catch (Exception ex) {
+
+          }
+          break;
+
+        case 's':
+          Main.pleaseWaitDlg.currentAction.setText(line.substring(2));
+          Main.pleaseWaitDlg.repaint();
+          break;
+          
+        case 'x':
+          Segment s = new Segment(lastNode, firstNode);
+          commands.add(new AddCommand(s));
+          way.segments.add(s);
+          commands.add(new AddCommand(way));
+          break;
+        }
+      } 
+      input.close();
+    }
+
+    catch (Exception ex) {
+    }
+    
+    if (!commands.isEmpty()) {
+      Main.main.undoRedo.add(new SequenceCommand(tr("Lakewalker trace"), commands));
+      Main.ds.setSelected(ways);
+    }
+
+
+  }
+  
+  /*
+   * User has hit the cancel button
+   */
+  public void cancel() {
+    cancel = true;
+  }
+  
+}
Index: /applications/editors/josm/plugins/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/StringConfigurer.java
===================================================================
--- /applications/editors/josm/plugins/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/StringConfigurer.java	(revision 4095)
+++ /applications/editors/josm/plugins/lakewalker/src/org/openstreetmap/josm/plugins/lakewalker/StringConfigurer.java	(revision 4095)
@@ -0,0 +1,81 @@
+/*
+ * $Id: StringConfigurer.java 2073 2007-05-10 14:34:31 +0000 (Thu, 10 May 2007) rodneykinney $
+ *
+ * Copyright (c) 2000-2003 by Rodney Kinney
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License (LGPL) as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, copies are available 
+ * at http://www.opensource.org.
+ */
+package org.openstreetmap.josm.plugins.lakewalker;
+
+import javax.swing.BoxLayout;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+
+/**
+ * A Configurer for String values
+ */
+public class StringConfigurer extends Configurer {
+  protected JPanel p;
+  protected JTextField nameField = new JTextField(12);
+
+  public StringConfigurer() {
+    this(null, "");
+  }
+  
+  public StringConfigurer(String key, String name) {
+    this(key, name, "");
+  }
+
+  public StringConfigurer(String key, String name, String val) {
+    super(key, name, val);
+  }
+
+  public String getValueString() {
+    return (String) value;
+  }
+
+  public void setValue(String s) {
+    if (!noUpdate && nameField != null) {
+      nameField.setText(s);
+    }
+    setValue((Object) s);
+  }
+
+  public void setToolTipText(String s) {
+    nameField.setToolTipText(s);
+  }
+  
+  public java.awt.Component getControls() {
+    if (p == null) {
+      p = new JPanel();
+      p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));
+      p.add(new JLabel(getName()));
+      nameField.setMaximumSize
+        (new java.awt.Dimension(nameField.getMaximumSize().width,
+                                nameField.getPreferredSize().height));
+      nameField.setText(getValueString());
+      p.add(nameField);
+      nameField.addKeyListener(new java.awt.event.KeyAdapter() {
+        public void keyReleased(java.awt.event.KeyEvent evt) {
+          noUpdate = true;
+          setValue(nameField.getText());
+          noUpdate = false;
+        }
+      });
+    }
+    return p;
+  }
+
+}
