[josm-plugins] 136/369: Imported Upstream version 0.0.svn21666
Bas Couwenberg
sebastic at xs4all.nl
Sat Oct 18 12:03:35 UTC 2014
This is an automated email from the git hooks/post-receive script.
sebastic-guest pushed a commit to branch master
in repository josm-plugins.
commit 375f232adc72d7d1c46429aa04c934d1896e6cdb
Author: David Paleino <dapal at debian.org>
Date: Sat Jun 12 13:13:11 2010 +0200
Imported Upstream version 0.0.svn21666
---
cadastre-fr/src/cadastre_fr/CacheControl.java | 32 +-
cadastre-fr/src/cadastre_fr/CadastreInterface.java | 17 +-
cadastre-fr/src/cadastre_fr/CadastrePlugin.java | 2 +
.../src/cadastre_fr/CadastrePreferenceSetting.java | 4 +-
.../src/cadastre_fr/DownloadWMSPlanImage.java | 3 +-
.../src/cadastre_fr/MenuActionGrabPlanImage.java | 124 +-
.../src/cadastre_fr/MenuActionNewLocation.java | 45 +-
cadastre-fr/src/cadastre_fr/WMSLayer.java | 10 +
.../plugin/colorscheme/ColorSchemePreference.java | 14 +-
editgpx/.settings/org.eclipse.jdt.ui.prefs | 54 +
.../josm/plugins/editgpx/EditGpxLayer.java | 115 +-
.../josm/plugins/editgpx/EditGpxMode.java | 279 ++--
.../josm/plugins/editgpx/EditGpxPlugin.java | 116 +-
.../josm/plugins/editgpx/GPXLayerImportAction.java | 191 ++-
.../josm/plugins/editgpx/data/EditGpxData.java | 62 +
.../josm/plugins/editgpx/data/EditGpxTrack.java | 57 +
.../plugins/editgpx/data/EditGpxTrackSegment.java | 44 +
.../josm/plugins/editgpx/data/EditGpxWayPoint.java | 39 +
livegps/src/livegps/LiveGpsAcquirer.java | 293 ++--
livegps/src/org/json/JSONArray.java | 918 ++++++++++++
livegps/src/org/json/JSONException.java | 31 +
livegps/src/org/json/JSONObject.java | 1584 ++++++++++++++++++++
livegps/src/org/json/JSONString.java | 18 +
livegps/src/org/json/JSONTokener.java | 435 ++++++
.../plugins/measurement/MeasurementDialog.java | 67 +-
.../josm/plugins/slippymap/SlippyMapLayer.java | 18 +-
svn-info.xml | 8 +-
wmsplugin/sources.cfg | 2 +-
wmsplugin/src/wmsplugin/WMSLayer.java | 2 +-
wmsplugin/webkit-image-gtk.c | 45 +-
30 files changed, 3971 insertions(+), 658 deletions(-)
diff --git a/cadastre-fr/src/cadastre_fr/CacheControl.java b/cadastre-fr/src/cadastre_fr/CacheControl.java
index 24223fe..84ca7f9 100644
--- a/cadastre-fr/src/cadastre_fr/CacheControl.java
+++ b/cadastre-fr/src/cadastre_fr/CacheControl.java
@@ -72,22 +72,24 @@ public class CacheControl implements Runnable {
}
private void checkDirSize(File path) {
- long size = 0;
- long oldestFileDate = Long.MAX_VALUE;
- int oldestFile = 0;
- File[] files = path.listFiles();
- for (int i = 0; i < files.length; i++) {
- size += files[i].length();
- if (files[i].lastModified() < oldestFileDate) {
- oldestFile = i;
- oldestFileDate = files[i].lastModified();
+ if (cacheSize != 0) {
+ long size = 0;
+ long oldestFileDate = Long.MAX_VALUE;
+ int oldestFile = 0;
+ File[] files = path.listFiles();
+ for (int i = 0; i < files.length; i++) {
+ size += files[i].length();
+ if (files[i].lastModified() < oldestFileDate) {
+ oldestFile = i;
+ oldestFileDate = files[i].lastModified();
+ }
+ }
+ if (size > (long)cacheSize*1024*1024) {
+ System.out.println("Delete oldest file \""+ files[oldestFile].getName()
+ + "\" in cache dir to stay under the limit of " + cacheSize + " MB.");
+ files[oldestFile].delete();
+ checkDirSize(path);
}
- }
- if (size > cacheSize*1024*1024) {
- System.out.println("Delete oldest file \""+ files[oldestFile].getName()
- + "\" in cache dir to stay under the limit of " + cacheSize + " MB.");
- files[oldestFile].delete();
- checkDirSize(path);
}
}
diff --git a/cadastre-fr/src/cadastre_fr/CadastreInterface.java b/cadastre-fr/src/cadastre_fr/CadastreInterface.java
index d48c1db..58484fd 100644
--- a/cadastre-fr/src/cadastre_fr/CadastreInterface.java
+++ b/cadastre-fr/src/cadastre_fr/CadastreInterface.java
@@ -151,6 +151,7 @@ public class CadastreInterface {
public void resetInterfaceRefIfNewLayer(String newWMSLayerName) {
if (!newWMSLayerName.equals(lastWMSLayerName)) {
interfaceRef = null;
+ cookie = null; // new since WMS server requires that we come back to the main form
}
}
@@ -174,7 +175,15 @@ public class CadastreInterface {
if (listOfCommunes.size() > 1) {
// commune unknown, prompt the list of communes from
// server and try with codeCommune
- wmsLayer.setCodeCommune(selectCommuneDialog());
+ String selected = selectMunicipalityDialog(wmsLayer);
+ if (selected != null) {
+ String newCodeCommune = selected.substring(1, selected.indexOf(">")-2);
+ String newLocation = selected.substring(selected.indexOf(">")+1, selected.lastIndexOf(" - "));
+ wmsLayer.setCodeCommune(newCodeCommune);
+ wmsLayer.setLocation(newLocation);
+ Main.pref.put("cadastrewms.codeCommune", newCodeCommune);
+ Main.pref.put("cadastrewms.location", newLocation);
+ }
checkLayerDuplicates(wmsLayer);
interfaceRef = postForm(wmsLayer, wmsLayer.getCodeCommune());
}
@@ -257,6 +266,7 @@ public class CadastreInterface {
content += "&codeCommune=" + codeCommune;
}
content += "&codeDepartement=";
+ content += wmsLayer.getDepartement();
content += "&nbResultatParPage=10";
content += "&x=0&y=0";
searchFormURL = new URL(baseURL + "/scpc/rechercherPlan.do");
@@ -379,7 +389,7 @@ public class CadastreInterface {
}
}
- private String selectCommuneDialog() {
+ private String selectMunicipalityDialog(WMSLayer wmsLayer) {
JPanel p = new JPanel(new GridBagLayout());
String[] communeList = new String[listOfCommunes.size() + 1];
communeList[0] = tr("Choose from...");
@@ -399,8 +409,7 @@ public class CadastreInterface {
// till here
if (!Integer.valueOf(JOptionPane.OK_OPTION).equals(pane.getValue()))
return null;
- String result = listOfCommunes.elementAt(inputCommuneList.getSelectedIndex()-1);
- return result.substring(1, result.indexOf(">")-2);
+ return listOfCommunes.elementAt(inputCommuneList.getSelectedIndex()-1);
}
private int selectFeuilleDialog() {
diff --git a/cadastre-fr/src/cadastre_fr/CadastrePlugin.java b/cadastre-fr/src/cadastre_fr/CadastrePlugin.java
index 6d338fb..68bf39a 100644
--- a/cadastre-fr/src/cadastre_fr/CadastrePlugin.java
+++ b/cadastre-fr/src/cadastre_fr/CadastrePlugin.java
@@ -112,6 +112,8 @@ import org.openstreetmap.josm.data.projection.*;
* - download cancellation improved
* - last deployment for Java1.5 compatibility
* 2.0 xx-xxx-xxxx - update projection for "La Reunion" departement to RGR92, UTM40S.
+ * - add 'departement' as option in the municipality selection
+ * - fixed bug in cache directory size control (and disabled by default)
*/
public class CadastrePlugin extends Plugin {
static String VERSION = "2.0";
diff --git a/cadastre-fr/src/cadastre_fr/CadastrePreferenceSetting.java b/cadastre-fr/src/cadastre_fr/CadastrePreferenceSetting.java
index 01a60d6..ca4c30b 100644
--- a/cadastre-fr/src/cadastre_fr/CadastrePreferenceSetting.java
+++ b/cadastre-fr/src/cadastre_fr/CadastrePreferenceSetting.java
@@ -56,7 +56,7 @@ public class CadastrePreferenceSetting implements PreferenceSetting {
private JRadioButton crosspiece4 = new JRadioButton("100m");
- private JCheckBox autoFirstLayer = new JCheckBox(tr("Automaticly select first WMS layer when grabing if multiple layers exist."));
+ private JCheckBox autoFirstLayer = new JCheckBox(tr("Select first WMS layer in list."));
private JRadioButton grabRes1 = new JRadioButton("high");
@@ -79,7 +79,7 @@ public class CadastrePreferenceSetting implements PreferenceSetting {
private JCheckBox enableCache = new JCheckBox(tr("Enable automatic caching."));
- static final int DEFAULT_CACHE_SIZE = 500;
+ static final int DEFAULT_CACHE_SIZE = 0; // disabled by default
JLabel jLabelCacheSize = new JLabel(tr("Max. cache size (in MB)"));
private JTextField cacheSize = new JTextField(20);
diff --git a/cadastre-fr/src/cadastre_fr/DownloadWMSPlanImage.java b/cadastre-fr/src/cadastre_fr/DownloadWMSPlanImage.java
index 648eb15..c31c982 100644
--- a/cadastre-fr/src/cadastre_fr/DownloadWMSPlanImage.java
+++ b/cadastre-fr/src/cadastre_fr/DownloadWMSPlanImage.java
@@ -19,7 +19,7 @@ public class DownloadWMSPlanImage {
private Future<Task> task = null;
private WMSLayer wmsLayer;
private Bounds bounds;
- private boolean dontGeoreference = false;
+ private static boolean dontGeoreference = false;
private static String errorMessage;
private class Task extends PleaseWaitRunnable {
@@ -106,6 +106,7 @@ public class DownloadWMSPlanImage {
public void download(WMSLayer wmsLayer) {
MapView mv = Main.map.mapView;
Bounds bounds = new Bounds(mv.getLatLon(0, mv.getHeight()), mv.getLatLon(mv.getWidth(), 0));
+ dontGeoreference = false;
//Main.worker.execute(new DownloadWMSPlanImage(wmsLayer, bounds));
Task t = new Task(wmsLayer, bounds);
diff --git a/cadastre-fr/src/cadastre_fr/MenuActionGrabPlanImage.java b/cadastre-fr/src/cadastre_fr/MenuActionGrabPlanImage.java
index 447f4fb..96b79a1 100644
--- a/cadastre-fr/src/cadastre_fr/MenuActionGrabPlanImage.java
+++ b/cadastre-fr/src/cadastre_fr/MenuActionGrabPlanImage.java
@@ -44,6 +44,7 @@ public class MenuActionGrabPlanImage extends JosmAction implements Runnable, Mou
private EastNorth georefpoint1;
private EastNorth georefpoint2;
private boolean ignoreMouseClick = false;
+ private boolean clickOnTheMap = false;
/**
* The time which needs to pass between two clicks during georeferencing, in milliseconds
@@ -62,7 +63,10 @@ public class MenuActionGrabPlanImage extends JosmAction implements Runnable, Mou
public void actionInterrupted() {
actionCompleted();
- wmsLayer = null;
+ if (wmsLayer != null) {
+ Main.map.mapView.removeLayer(wmsLayer);
+ wmsLayer = null;
+ }
}
@Override
@@ -99,7 +103,12 @@ public class MenuActionGrabPlanImage extends JosmAction implements Runnable, Mou
public void run() {
// wait until plan image is fully loaded and joined into one single image
boolean loadedFromCache = downloadWMSPlanImage.waitFinished();
- if (wmsLayer.images.size() == 1 && !loadedFromCache) {
+ if (loadedFromCache) {
+ Main.map.repaint();
+ } else if (wmsLayer.images.size() == 0) {
+ // action cancelled or image loaded from cache (and already georeferenced)
+ actionInterrupted();
+ } else {
int reply = JOptionPane.CANCEL_OPTION;
if (wmsLayer.isAlreadyGeoreferenced()) {
reply = JOptionPane.showConfirmDialog(null,
@@ -118,8 +127,7 @@ public class MenuActionGrabPlanImage extends JosmAction implements Runnable, Mou
else
startGeoreferencing();
}
- } else // action cancelled or image loaded from cache (and already georeferenced)
- Main.map.repaint();
+ }
}
public void mouseClicked(MouseEvent e) {
@@ -132,31 +140,36 @@ public class MenuActionGrabPlanImage extends JosmAction implements Runnable, Mou
if (e.getButton() != MouseEvent.BUTTON1)
return;
if (ignoreMouseClick) return; // In case we are currently just allowing zooming to read lambert coordinates
- countMouseClicked++;
EastNorth ea = Main.proj.latlon2eastNorth(Main.map.mapView.getLatLon(e.getX(), e.getY()));
System.out.println("clic:"+countMouseClicked+" ,"+ea+", mode:"+mode);
- // ignore clicks outside the image
- if (ea.east() < wmsLayer.images.get(0).min.east() || ea.east() > wmsLayer.images.get(0).max.east()
- || ea.north() < wmsLayer.images.get(0).min.north() || ea.north() > wmsLayer.images.get(0).max.north())
- return;
- if (mode == cGetCorners) {
- if (countMouseClicked == 1) {
- ea1 = ea;
- continueCropping();
- }
- if (countMouseClicked == 2) {
- wmsLayer.cropImage(ea1, ea);
- Main.map.mapView.repaint();
- startGeoreferencing();
- }
- } else if (mode == cGetLambertCrosspieces) {
- if (countMouseClicked == 1) {
- ea1 = ea;
- inputLambertPosition(); // This will automatically asks for second point and continue the georeferencing
- }
- if (countMouseClicked == 2) {
- ea2 = ea;
- inputLambertPosition(); // This will automatically ends the georeferencing
+ if (clickOnTheMap) {
+ clickOnTheMap = false;
+ handleNewCoordinates(ea.east(), ea.north());
+ } else {
+ countMouseClicked++;
+ // ignore clicks outside the image
+ if (ea.east() < wmsLayer.images.get(0).min.east() || ea.east() > wmsLayer.images.get(0).max.east()
+ || ea.north() < wmsLayer.images.get(0).min.north() || ea.north() > wmsLayer.images.get(0).max.north())
+ return;
+ if (mode == cGetCorners) {
+ if (countMouseClicked == 1) {
+ ea1 = ea;
+ continueCropping();
+ }
+ if (countMouseClicked == 2) {
+ wmsLayer.cropImage(ea1, ea);
+ Main.map.mapView.repaint();
+ startGeoreferencing();
+ }
+ } else if (mode == cGetLambertCrosspieces) {
+ if (countMouseClicked == 1) {
+ ea1 = ea;
+ inputLambertPosition(); // This will automatically asks for second point and continue the georeferencing
+ }
+ if (countMouseClicked == 2) {
+ ea2 = ea;
+ inputLambertPosition(); // This will automatically ends the georeferencing
+ }
}
}
}
@@ -248,6 +261,8 @@ public class MenuActionGrabPlanImage extends JosmAction implements Runnable, Mou
wmsLayer.saveNewCache();
Main.map.mapView.repaint();
actionCompleted();
+ clickOnTheMap = false;
+ ignoreMouseClick = false;
}
/**
@@ -261,14 +276,14 @@ public class MenuActionGrabPlanImage extends JosmAction implements Runnable, Mou
"or just retry "+action+" ?"), "",
JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE,
null, options, options[0]);
+ countMouseClicked = 0;
if (selectedValue == 0) { // "Cancel"
// remove layer
Main.map.mapView.removeLayer(wmsLayer);
wmsLayer = null;
Main.map.mapView.removeMouseListener(this);
- return false;
- } else
- countMouseClicked = 0;
+ return false;
+ }
return true;
}
@@ -288,9 +303,12 @@ public class MenuActionGrabPlanImage extends JosmAction implements Runnable, Mou
p.add(inputEast, GBC.eol().fill(GBC.HORIZONTAL).insets(10, 5, 0, 5));
p.add(labelNorth, GBC.std().insets(0, 0, 10, 0));
p.add(inputNorth, GBC.eol().fill(GBC.HORIZONTAL).insets(10, 5, 0, 5));
+ final Object[] options = {tr("OK"),
+ tr("Cancel"),
+ tr("I use the mouse")};
final JOptionPane pane = new JOptionPane(p,
- JOptionPane.INFORMATION_MESSAGE, JOptionPane.OK_CANCEL_OPTION,
- null);
+ JOptionPane.INFORMATION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION,
+ null, options, options[0]);
String number;
if (countMouseClicked == 1)
number = "first";
@@ -307,25 +325,27 @@ public class MenuActionGrabPlanImage extends JosmAction implements Runnable, Mou
public void propertyChange(PropertyChangeEvent evt) {
if (JOptionPane.VALUE_PROPERTY.equals(evt.getPropertyName())) {
ignoreMouseClick = false;
- if (!Integer.valueOf(JOptionPane.OK_OPTION).equals(
- pane.getValue())) {
+ // Cancel
+ if (pane.getValue().equals(options[1])) {
if (canceledOrRestartCurrAction("georeferencing"))
startGeoreferencing();
}
- if (inputEast.getText().length() != 0
- && inputNorth.getText().length() != 0) {
- try {
- double e = Double.parseDouble(inputEast.getText());
- double n = Double.parseDouble(inputNorth.getText());
- if (countMouseClicked == 1) {
- georefpoint1 = new EastNorth(e, n);
- continueGeoreferencing();
- } else {
- georefpoint2 = new EastNorth(e, n);
- endGeoreferencing();
+ // Click on the map
+ if (pane.getValue().equals(options[2])) {
+ clickOnTheMap = true;
+ } else {
+ // OK (coordinates manually entered)
+ clickOnTheMap = false;
+ if (inputEast.getText().length() != 0
+ && inputNorth.getText().length() != 0) {
+ double e, n;
+ try {
+ e = Double.parseDouble(inputEast.getText());
+ n = Double.parseDouble(inputNorth.getText());
+ } catch (NumberFormatException ex) {
+ return;
}
- } catch (NumberFormatException e) {
- return;
+ handleNewCoordinates(e, n);
}
}
}
@@ -333,6 +353,16 @@ public class MenuActionGrabPlanImage extends JosmAction implements Runnable, Mou
});
}
+ private void handleNewCoordinates(double e, double n) {
+ if (countMouseClicked == 1) {
+ georefpoint1 = new EastNorth(e, n);
+ continueGeoreferencing();
+ } else {
+ georefpoint2 = new EastNorth(e, n);
+ endGeoreferencing();
+ }
+ }
+
/**
* Use point org1 as anchor for scale, then move org1 to dst1, then rotate org2 on dst2
* around org1/dst1 anchor
diff --git a/cadastre-fr/src/cadastre_fr/MenuActionNewLocation.java b/cadastre-fr/src/cadastre_fr/MenuActionNewLocation.java
index 9ddc3f1..f740da3 100644
--- a/cadastre-fr/src/cadastre_fr/MenuActionNewLocation.java
+++ b/cadastre-fr/src/cadastre_fr/MenuActionNewLocation.java
@@ -7,6 +7,7 @@ import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
+import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
@@ -23,6 +24,31 @@ import org.openstreetmap.josm.tools.GBC;
public class MenuActionNewLocation extends JosmAction {
private static final long serialVersionUID = 1L;
+
+ private static final String departements[] = {
+ "", tr("(optional)"),
+ "001", "01 - Ain", "002", "02 - Aisne", "003", "03 - Allier", "004", "04 - Alpes de Haute-Provence", "005", "05 - Hautes-Alpes",
+ "006", "06 - Alpes-Maritimes", "007", "07 - Ard\u00eache", "008", "08 - Ardennes", "009", "09 - Ari\u00e8ge", "010", "10 - Aube",
+ "011", "11 - Aude", "012", "12 - Aveyron", "013", "13 - Bouches-du-Rh\u00f4ne", "014", "14 - Calvados", "015", "15 - Cantal",
+ "016", "16 - Charente", "017", "17 - Charente-Maritime", "018", "18 - Cher", "019", "19 - Corr\u00e8ze",
+ "02A", "2A - Corse-du-Sud", "02B", "2B - Haute-Corse",
+ "021", "21 - C\u00f4te-d'Or", "022", "22 - C\u00f4tes d'Armor", "023", "23 - Creuse", "024", "24 - Dordogne", "025", "25 - Doubs",
+ "026", "26 - Dr\u00f4me", "027", "27 - Eure", "028", "28 - Eure-et-Loir", "029", "29 - Finist\u00e8re", "030", "30 - Gard",
+ "031", "31 - Haute-Garonne", "032", "32 - Gers", "033", "33 - Gironde", "034", "34 - H\u00e9rault", "035", "35 - Ille-et-Vilaine",
+ "036", "36 - Indre", "037", "37 - Indre-et-Loire", "038", "38 - Is\u00e8re", "039", "39 - Jura", "040", "40 - Landes",
+ "041", "41 - Loir-et-Cher", "042", "42 - Loire", "043", "43 - Haute-Loire", "044", "44 - Loire-Atlantique", "045", "45 - Loiret",
+ "046", "46 - Lot", "047", "47 - Lot-et-Garonne", "048", "48 - Loz\u00e8re", "049", "49 - Maine-et-Loire", "050", "50 - Manche",
+ "051", "51 - Marne", "052", "52 - Haute-Marne", "053", "53 - Mayenne", "054", "54 - Meurthe-et-Moselle", "055", "55 - Meuse",
+ "056", "56 - Morbihan", "057", "57 - Moselle", "058", "58 - Ni\u00e8vre", "059", "59 - Nord", "060", "60 - Oise",
+ "061", "61 - Orne", "062", "62 - Pas-de-Calais", "063", "63 - Puy-de-D\u00f4me", "064", "64 - Pyr\u00e9n\u00e9es-Atlantiques", "065", "65 - Hautes-Pyr\u00e9n\u00e9es",
+ "066", "66 - Pyr\u00e9n\u00e9es-Orientales", "067", "67 - Bas-Rhin", "068", "68 - Haut-Rhin", "069", "69 - Rh\u00f4ne", "070", "70 - Haute-Sa\u00f4ne",
+ "071", "71 - Sa\u00f4ne-et-Loire", "072", "72 - Sarthe", "073", "73 - Savoie", "074", "74 - Haute-Savoie", "075", "75 - Paris",
+ "076", "76 - Seine-Maritime", "077", "77 - Seine-et-Marne", "078", "78 - Yvelines", "079", "79 - Deux-S\u00e8vres", "080", "80 - Somme",
+ "081", "81 - Tarn", "082", "82 - Tarn-et-Garonne", "083", "83 - Var", "084", "84 - Vaucluse", "085", "85 - Vend\u00e9e",
+ "086", "86 - Vienne", "087", "87 - Haute-Vienne", "088", "88 - Vosges", "089", "89 - Yonne", "090", "90 - Territoire de Belfort",
+ "091", "91 - Essonne", "092", "92 - Hauts-de-Seine", "093", "93 - Seine-Saint-Denis", "094", "94 - Val-de-Marne", "095", "95 - Val-d'Oise",
+ "971", "971 - Guadeloupe", "972", "972 - Martinique", "973", "973 - Guyane", "974", "974 - R\u00e9union"
+ };
public MenuActionNewLocation() {
super(tr("Change location"), "cadastre_small", tr("Set a new location for the next request"), null, false);
@@ -45,10 +71,22 @@ public class MenuActionNewLocation extends JosmAction {
final JTextField inputTown = new JTextField( Main.pref.get("cadastrewms.location") );
inputTown.setToolTipText(tr("<html>Enter the town,village or city name.<br>"
+ "Use the syntax and punctuation known by www.cadastre.gouv.fr .</html>"));
-
+ JLabel labelDepartement = new JLabel(tr("Departement"));
+ final JComboBox inputDepartement = new JComboBox();
+ for (int i=1; i<departements.length; i+=2) {
+ inputDepartement.addItem(departements[i]);
+ }
+ inputDepartement.setToolTipText(tr("<html>Departement number (optional)</html>"));
+ if (!Main.pref.get("cadastrewms.codeDepartement").equals("")) {
+ for (int i=0; i < departements.length; i=i+2)
+ if (departements[i].equals(Main.pref.get("cadastrewms.codeDepartement")))
+ inputDepartement.setSelectedIndex(i/2);
+ }
p.add(labelSectionNewLocation, GBC.eol());
p.add(labelLocation, GBC.std().insets(10, 0, 0, 0));
p.add(inputTown, GBC.eol().fill(GBC.HORIZONTAL).insets(5, 0, 0, 5));
+ p.add(labelDepartement, GBC.std().insets(10, 0, 0, 0));
+ p.add(inputDepartement, GBC.eol().fill(GBC.HORIZONTAL).insets(5, 0, 0, 5));
JOptionPane pane = new JOptionPane(p, JOptionPane.INFORMATION_MESSAGE, JOptionPane.OK_CANCEL_OPTION, null) {
private static final long serialVersionUID = 1L;
@@ -65,12 +103,14 @@ public class MenuActionNewLocation extends JosmAction {
WMSLayer wmsLayer = null;
if (!inputTown.getText().equals("")) {
location = inputTown.getText().toUpperCase();
+ codeDepartement = departements[inputDepartement.getSelectedIndex()*2];
changeInterface = true;
Main.pref.put("cadastrewms.location", location);
Main.pref.put("cadastrewms.codeCommune", codeCommune);
+ Main.pref.put("cadastrewms.codeDepartement", codeDepartement);
if (Main.map != null) {
for (Layer l : Main.map.mapView.getAllLayers()) {
- if (l instanceof WMSLayer && l.getName().equalsIgnoreCase(location + codeDepartement)) {
+ if (l instanceof WMSLayer && l.getName().equalsIgnoreCase(location)) {
return null;
}
}
@@ -84,6 +124,7 @@ public class MenuActionNewLocation extends JosmAction {
else if (Main.proj instanceof UTM_France_DOM)
zone = ((UTM_France_DOM)Main.proj).getCurrentGeodesic();
wmsLayer = new WMSLayer(location, codeCommune, zone);
+ wmsLayer.setDepartement(codeDepartement);
CadastrePlugin.addWMSLayer(wmsLayer);
System.out.println("Add new layer with Location:" + inputTown.getText());
} else if (existingLayers != null && existingLayers.size() > 0 && Main.map.mapView.getActiveLayer() instanceof WMSLayer) {
diff --git a/cadastre-fr/src/cadastre_fr/WMSLayer.java b/cadastre-fr/src/cadastre_fr/WMSLayer.java
index d9127e9..b6bebaf 100644
--- a/cadastre-fr/src/cadastre_fr/WMSLayer.java
+++ b/cadastre-fr/src/cadastre_fr/WMSLayer.java
@@ -68,6 +68,8 @@ public class WMSLayer extends Layer implements ImageObserver {
private CacheControl cacheControl = null;
private String location = "";
+
+ private String departement = "";
private String codeCommune = "";
@@ -378,6 +380,14 @@ public class WMSLayer extends Layer implements ImageObserver {
setName(rebuildName());
}
+ public String getDepartement() {
+ return departement;
+ }
+
+ public void setDepartement(String departement) {
+ this.departement = departement;
+ }
+
public String getCodeCommune() {
return codeCommune;
}
diff --git a/colorscheme/src/at/dallermassl/josm/plugin/colorscheme/ColorSchemePreference.java b/colorscheme/src/at/dallermassl/josm/plugin/colorscheme/ColorSchemePreference.java
index bcb784d..0a2c493 100644
--- a/colorscheme/src/at/dallermassl/josm/plugin/colorscheme/ColorSchemePreference.java
+++ b/colorscheme/src/at/dallermassl/josm/plugin/colorscheme/ColorSchemePreference.java
@@ -16,6 +16,7 @@ import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
+import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
@@ -52,6 +53,9 @@ public class ColorSchemePreference implements PreferenceSetting {
* @see org.openstreetmap.josm.gui.preferences.PreferenceSetting#addGui(org.openstreetmap.josm.gui.preferences.PreferenceDialog)
*/
public void addGui(final PreferenceTabbedPane gui) {
+ JPanel panel = new JPanel(new GridBagLayout());
+ panel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+
Map<String, String> colorMap = Main.pref.getAllPrefix(PREF_KEY_COLOR_PREFIX);
colorKeys = new ArrayList<String>(colorMap.keySet());
Collections.sort(colorKeys);
@@ -109,14 +113,18 @@ public class ColorSchemePreference implements PreferenceSetting {
addScheme.setToolTipText(tr("Use the current colors as a new color scheme."));
deleteScheme.setToolTipText(tr("Delete the selected scheme from the list."));
- gui.map.add(new JLabel(tr("Color Schemes")), GBC.eol().insets(0,5,0,0));
- gui.map.add(new JScrollPane(schemesList), GBC.eol().fill(GBC.BOTH));
+ panel.add(new JLabel(tr("Color Schemes")), GBC.eol().insets(0,5,0,0));
+ panel.add(new JScrollPane(schemesList), GBC.eol().fill(GBC.BOTH));
JPanel buttonPanel = new JPanel(new GridBagLayout());
- gui.map.add(buttonPanel, GBC.eol().fill(GBC.HORIZONTAL));
+ panel.add(buttonPanel, GBC.eol().fill(GBC.HORIZONTAL));
buttonPanel.add(Box.createHorizontalGlue(), GBC.std().fill(GBC.HORIZONTAL));
buttonPanel.add(useScheme, GBC.std().insets(0,5,5,0));
buttonPanel.add(addScheme, GBC.std().insets(0,5,5,0));
buttonPanel.add(deleteScheme, GBC.std().insets(0,5,5,0));
+
+ JScrollPane scrollpane = new JScrollPane(panel);
+ scrollpane.setBorder(BorderFactory.createEmptyBorder( 0, 0, 0, 0 ));
+ gui.displaycontent.addTab(tr("Color Schemes"), scrollpane);
}
/**
diff --git a/editgpx/.settings/org.eclipse.jdt.ui.prefs b/editgpx/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..4a3398d
--- /dev/null
+++ b/editgpx/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,54 @@
+#Tue May 25 21:33:38 CEST 2010
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=true
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=false
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=false
+sp_cleanup.always_use_this_for_non_static_method_access=false
+sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.correct_indentation=true
+sp_cleanup.format_source_code=false
+sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.make_local_variable_final=false
+sp_cleanup.make_parameters_final=false
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.organize_imports=true
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_casts=true
+sp_cleanup.remove_unnecessary_nls_tags=false
+sp_cleanup.remove_unused_imports=false
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.use_blocks=false
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_parentheses_in_expressions=false
+sp_cleanup.use_this_for_non_static_field_access=false
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+sp_cleanup.use_this_for_non_static_method_access=false
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
diff --git a/editgpx/src/org/openstreetmap/josm/plugins/editgpx/EditGpxLayer.java b/editgpx/src/org/openstreetmap/josm/plugins/editgpx/EditGpxLayer.java
index 4d4f56f..6f49c7c 100644
--- a/editgpx/src/org/openstreetmap/josm/plugins/editgpx/EditGpxLayer.java
+++ b/editgpx/src/org/openstreetmap/josm/plugins/editgpx/EditGpxLayer.java
@@ -11,14 +11,6 @@ import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
import javax.swing.AbstractAction;
import javax.swing.Icon;
@@ -29,31 +21,29 @@ import javax.swing.JSeparator;
import org.openstreetmap.josm.Main;
import org.openstreetmap.josm.data.Bounds;
import org.openstreetmap.josm.data.gpx.GpxData;
-import org.openstreetmap.josm.data.gpx.ImmutableGpxTrack;
-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.Way;
import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
import org.openstreetmap.josm.gui.MapView;
import org.openstreetmap.josm.gui.dialogs.LayerListDialog;
import org.openstreetmap.josm.gui.dialogs.LayerListPopup;
import org.openstreetmap.josm.gui.layer.GpxLayer;
import org.openstreetmap.josm.gui.layer.Layer;
-import org.openstreetmap.josm.tools.DateUtils;
+import org.openstreetmap.josm.plugins.editgpx.data.EditGpxData;
+import org.openstreetmap.josm.plugins.editgpx.data.EditGpxTrack;
+import org.openstreetmap.josm.plugins.editgpx.data.EditGpxTrackSegment;
+import org.openstreetmap.josm.plugins.editgpx.data.EditGpxWayPoint;
import org.openstreetmap.josm.tools.ImageProvider;
public class EditGpxLayer extends Layer {
private static Icon icon = new ImageIcon(Toolkit.getDefaultToolkit().createImage(EditGpxPlugin.class.getResource("/images/editgpx_layer.png")));
- private DataSet dataSet;
+ public final EditGpxData data;
private GPXLayerImportAction layerImport;
- public EditGpxLayer(String str, DataSet ds) {
+ public EditGpxLayer(String str, EditGpxData gpxData) {
super(str);
- dataSet = ds;
- layerImport = new GPXLayerImportAction(dataSet);
+ data = gpxData;
+ layerImport = new GPXLayerImportAction(data);
}
/**
@@ -62,7 +52,7 @@ public class EditGpxLayer extends Layer {
*/
public void initializeImport() {
try {
- if(dataSet.getNodes().isEmpty() ) {
+ if(data.isEmpty()) {
layerImport.activateImport();
}
} catch (Exception e) {
@@ -116,10 +106,14 @@ public class EditGpxLayer extends Layer {
//don't iterate through dataSet whiling making changes
synchronized(layerImport.importing) {
- for(Node n: dataSet.getNodes()) {
- if (!n.isDeleted()) {
- Point pnt = Main.map.mapView.getPoint(n.getEastNorth());
- g.drawOval(pnt.x - 2, pnt.y - 2, 4, 4);
+ for (EditGpxTrack track: data.getTracks()) {
+ for (EditGpxTrackSegment segment: track.getSegments()) {
+ for (EditGpxWayPoint wayPoint: segment.getWayPoints()) {
+ if (!wayPoint.isDeleted()) {
+ Point pnt = Main.map.mapView.getPoint(wayPoint.getCoor().getEastNorth());
+ g.drawOval(pnt.x - 2, pnt.y - 2, 4, 4);
+ }
+ }
}
}
}
@@ -144,76 +138,7 @@ public class EditGpxLayer extends Layer {
* @return GPXData
*/
private GpxData toGpxData(boolean anonTime) {
- GpxData gpxData = new GpxData();
- HashSet<Node> doneNodes = new HashSet<Node>();
- //add all ways
- for (Way w : dataSet.getWays()) {
- if (w.isIncomplete() || w.isDeleted()) continue;
- List<Collection<WayPoint>> segments = new ArrayList<Collection<WayPoint>>();
-
- List<WayPoint> trkseg = null;
- for (Node n : w.getNodes()) {
- if (n.isIncomplete() || n.isDeleted()) {
- trkseg = null;
- continue;
- }
-
- Date tstamp = n.getTimestamp();
-
- if (trkseg == null) {
- trkseg = new ArrayList<WayPoint>();
- segments.add(trkseg);
- }
- doneNodes.add(n);
-
- WayPoint wpt = new WayPoint(n.getCoor());
- if (anonTime) {
- wpt.attr.put("time", "1970-01-01T00:00:00Z");
- } else {
- wpt.attr.put("time", DateUtils.fromDate(tstamp));
- }
- wpt.setTime();
-
- trkseg.add(wpt);
- }
-
- // Do not create empty segments
- for (Iterator<Collection<WayPoint>> segIt = segments.iterator(); segIt.hasNext(); ) {
- if (segIt.next().isEmpty()) {
- segIt.remove();
- }
- }
-
- Map<String, Object> trkAttributes = new HashMap<String, Object>();
- if (w.get("name") != null) {
- trkAttributes.put("name", w.get("name"));
- }
- if (!segments.isEmpty()) {
- gpxData.tracks.add(new ImmutableGpxTrack(segments, trkAttributes));
- }
-
- }
-
- // add nodes as waypoints
- for (Node n : dataSet.getNodes()) {
- if (n.isIncomplete() || n.isDeleted() || doneNodes.contains(n)) continue;
-
- Date tstamp = n.getTimestamp();
-
- WayPoint wpt = new WayPoint(n.getCoor());
- if (anonTime) {
- wpt.attr.put("time", "1970-01-01T00:00:00Z");
- } else {
- wpt.attr.put("time", DateUtils.fromDate(tstamp));
- }
- wpt.setTime();
-
- if (n.getKeys() != null && n.keySet().contains("name")) {
- wpt.attr.put("name", n.get("name"));
- }
- gpxData.waypoints.add(wpt);
- }
- return gpxData;
+ return data.createGpxData();
}
//context item "Convert to GPX layer"
@@ -224,6 +149,8 @@ public class EditGpxLayer extends Layer {
public void actionPerformed(ActionEvent e) {
Main.main.addLayer(new GpxLayer(toGpxData(false), tr("Converted from: {0}", getName())));
Main.main.removeLayer(EditGpxLayer.this);
+ if(Main.map.mapMode instanceof EditGpxMode)
+ Main.map.selectSelectTool(false);
}
}
@@ -235,6 +162,8 @@ public class EditGpxLayer extends Layer {
public void actionPerformed(ActionEvent e) {
Main.main.addLayer(new GpxLayer(toGpxData(true), tr("Converted from: {0}", getName())));
Main.main.removeLayer(EditGpxLayer.this);
+ if(Main.map.mapMode instanceof EditGpxMode)
+ Main.map.selectSelectTool(false);
}
}
}
diff --git a/editgpx/src/org/openstreetmap/josm/plugins/editgpx/EditGpxMode.java b/editgpx/src/org/openstreetmap/josm/plugins/editgpx/EditGpxMode.java
index ae17cb9..42a8058 100644
--- a/editgpx/src/org/openstreetmap/josm/plugins/editgpx/EditGpxMode.java
+++ b/editgpx/src/org/openstreetmap/josm/plugins/editgpx/EditGpxMode.java
@@ -3,6 +3,8 @@
*/
package org.openstreetmap.josm.plugins.editgpx;
+import static org.openstreetmap.josm.tools.I18n.tr;
+
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Graphics;
@@ -10,126 +12,169 @@ import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
+import java.util.List;
import org.openstreetmap.josm.Main;
import org.openstreetmap.josm.actions.mapmode.MapMode;
-import org.openstreetmap.josm.data.osm.DataSet;
-import org.openstreetmap.josm.data.osm.Node;
import org.openstreetmap.josm.gui.MapFrame;
+import org.openstreetmap.josm.gui.MapView;
+import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
+import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.plugins.editgpx.data.EditGpxData;
+import org.openstreetmap.josm.plugins.editgpx.data.EditGpxTrack;
+import org.openstreetmap.josm.plugins.editgpx.data.EditGpxTrackSegment;
+import org.openstreetmap.josm.plugins.editgpx.data.EditGpxWayPoint;
+
+
+public class EditGpxMode extends MapMode implements LayerChangeListener {
+
+ private static final long serialVersionUID = 7940589057093872411L;
+ Point pointPressed;
+ MapFrame mapFrame;
+ Rectangle oldRect;
+ MapFrame frame;
+ EditGpxLayer currentEditLayer;
+
+ public EditGpxMode(MapFrame mapFrame, String name, String desc) {
+ super(name, "editgpx_mode.png", desc, mapFrame, Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
+ }
+
+ @Override public void enterMode() {
+ super.enterMode();
+ Main.map.mapView.addMouseListener(this);
+ Main.map.mapView.addMouseMotionListener(this);
+ MapView.addLayerChangeListener(this);
+ updateLayer();
+ }
+
+ @Override public void exitMode() {
+ super.exitMode();
+ Main.map.mapView.removeMouseListener(this);
+ Main.map.mapView.removeMouseMotionListener(this);
+ }
+
+
+ @Override public void mousePressed(MouseEvent e) {
+ pointPressed = new Point(e.getPoint());
+ }
+
+
+ @Override public void mouseDragged(MouseEvent e) {
+ if ( (e.getModifiersEx() & InputEvent.BUTTON1_DOWN_MASK) == InputEvent.BUTTON1_DOWN_MASK) {
+ //if button1 is hold, draw the rectangle.
+ paintRect(pointPressed, e.getPoint());
+ }
+ }
+
+ @Override public void mouseReleased(MouseEvent e) {
+ if (e.getButton() != MouseEvent.BUTTON1) {
+ return;
+ }
+
+ Point pointReleased = e.getPoint();
+
+ Rectangle r = createRect(pointReleased, pointPressed);
+
+ //go through nodes and mark the ones in the selection rect as deleted
+ if (currentEditLayer != null) {
+ for (EditGpxTrack track: currentEditLayer.data.getTracks()) {
+ for (EditGpxTrackSegment segment: track.getSegments()) {
+ for (EditGpxWayPoint wayPoint: segment.getWayPoints()) {
+ Point p = Main.map.mapView.getPoint(wayPoint.getCoor().getEastNorth());
+ if (r.contains(p)) {
+ wayPoint.setDeleted(true);
+ }
+ }
+ }
+ }
+ }
+ oldRect = null;
+ Main.map.mapView.repaint();
+
+ }
+
+ /**
+ * create rectangle out of two given corners
+ */
+ public Rectangle createRect(Point p1, Point p2) {
+ int x,y,w,h;
+ if (p1.x == p2.x && p1.y == p2.y) {
+ //if p1 and p2 same points draw a small rectangle around them
+ x = p1.x -1;
+ y = p1.y -1;
+ w = 3;
+ h = 3;
+ } else {
+ if (p1.x < p2.x){
+ x = p1.x;
+ w = p2.x-p1.x;
+ } else {
+ x = p2.x;
+ w = p1.x-p2.x;
+ }
+ if (p1.y < p2.y) {
+ y = p1.y;
+ h = p2.y-p1.y;
+ } else {
+ y = p2.y;
+ h = p1.y-p2.y;
+ }
+ }
+ return new Rectangle(x,y,w,h);
+ }
+
+ /**
+ * Draw a selection rectangle on screen.
+ */
+ private void paintRect(Point p1, Point p2) {
+ Graphics g = frame.getGraphics();//Main.map.mapView.getGraphics();
+
+ Rectangle r = oldRect;
+ if (r != null) {
+ //overwrite old rct
+ g.setXORMode(Color.BLACK);
+ g.setColor(Color.WHITE);
+ g.drawRect(r.x,r.y,r.width,r.height);
+ }
+
+ g.setXORMode(Color.BLACK);
+ g.setColor(Color.WHITE);
+ r = createRect(p1,p2);
+ g.drawRect(r.x,r.y,r.width,r.height);
+ oldRect = r;
+ }
+
+
+ public void setFrame(MapFrame mapFrame) {
+ frame = mapFrame;
+ }
+
+ /**
+ * create new layer, add listeners and try importing gpx data.
+ */
+ private void updateLayer() {
+
+ List<EditGpxLayer> layers = Main.map.mapView.getLayersOfType(EditGpxLayer.class);
+ currentEditLayer = layers.isEmpty()?null:layers.get(0);
+
+ if(currentEditLayer == null) {
+ currentEditLayer = new EditGpxLayer(tr("EditGpx"), new EditGpxData());
+ Main.main.addLayer(currentEditLayer);
+ currentEditLayer.initializeImport();
+ }
+ Main.map.mapView.repaint();
+ }
+
+ public void activeLayerChange(Layer oldLayer, Layer newLayer) { }
+
+ public void layerAdded(Layer newLayer) { }
+
+ public void layerRemoved(Layer oldLayer) {
+ if (oldLayer instanceof EditGpxLayer) {
+ currentEditLayer = null;
+ if(Main.map.mapMode instanceof EditGpxMode)
+ Main.map.selectSelectTool(false);
+ }
+ }
-
-public class EditGpxMode extends MapMode {
-
- private static final long serialVersionUID = 7940589057093872411L;
- Point pointPressed;
- DataSet dataSet;
- MapFrame mapFrame;
- Rectangle oldRect;
- MapFrame frame;
-
- public EditGpxMode(MapFrame mapFrame, String name, String desc, DataSet ds) {
- super(name, "editgpx_mode.png", desc, mapFrame, Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
- dataSet = ds;
- }
-
- @Override public void enterMode() {
- super.enterMode();
- Main.map.mapView.addMouseListener(this);
- Main.map.mapView.addMouseMotionListener(this);
- }
-
- @Override public void exitMode() {
- super.exitMode();
- Main.map.mapView.removeMouseListener(this);
- Main.map.mapView.removeMouseMotionListener(this);
- }
-
-
- @Override public void mousePressed(MouseEvent e) {
- pointPressed = new Point(e.getPoint());
- }
-
-
- @Override public void mouseDragged(MouseEvent e) {
- if ( (e.getModifiersEx() & InputEvent.BUTTON1_DOWN_MASK) == InputEvent.BUTTON1_DOWN_MASK) {
- //if button1 is hold, draw the rectangle.
- paintRect(pointPressed, e.getPoint());
- }
- }
-
- @Override public void mouseReleased(MouseEvent e) {
- if (e.getButton() != MouseEvent.BUTTON1) {
- return;
- } else {
- Point pointReleased = e.getPoint();
-
- Rectangle r = createRect(pointReleased, pointPressed);
-
- //go through nodes and mark the ones in the selection rect as deleted
- for (Node n: dataSet.getNodes()) {
- Point p = Main.map.mapView.getPoint(n);
- if (r.contains(p)) {
- n.setDeleted(true);
- }
- }
- oldRect = null;
- Main.map.mapView.repaint();
- }
- }
-
- /**
- * create rectangle out of two given corners
- */
- public Rectangle createRect(Point p1, Point p2) {
- int x,y,w,h;
- if (p1.x == p2.x && p1.y == p2.y) {
- //if p1 and p2 same points draw a small rectangle around them
- x = p1.x -1;
- y = p1.y -1;
- w = 3;
- h = 3;
- } else {
- if (p1.x < p2.x){
- x = p1.x;
- w = p2.x-p1.x;
- } else {
- x = p2.x;
- w = p1.x-p2.x;
- }
- if (p1.y < p2.y) {
- y = p1.y;
- h = p2.y-p1.y;
- } else {
- y = p2.y;
- h = p1.y-p2.y;
- }
- }
- return new Rectangle(x,y,w,h);
- }
-
- /**
- * Draw a selection rectangle on screen.
- */
- private void paintRect(Point p1, Point p2) {
- Graphics g = frame.getGraphics();//Main.map.mapView.getGraphics();
-
- Rectangle r = oldRect;
- if (r != null) {
- //overwrite old rct
- g.setXORMode(Color.BLACK);
- g.setColor(Color.WHITE);
- g.drawRect(r.x,r.y,r.width,r.height);
- }
-
- g.setXORMode(Color.BLACK);
- g.setColor(Color.WHITE);
- r = createRect(p1,p2);
- g.drawRect(r.x,r.y,r.width,r.height);
- oldRect = r;
- }
-
-
- public void setFrame(MapFrame mapFrame) {
- frame = mapFrame;
- }
}
diff --git a/editgpx/src/org/openstreetmap/josm/plugins/editgpx/EditGpxPlugin.java b/editgpx/src/org/openstreetmap/josm/plugins/editgpx/EditGpxPlugin.java
index 5345966..6699953 100644
--- a/editgpx/src/org/openstreetmap/josm/plugins/editgpx/EditGpxPlugin.java
+++ b/editgpx/src/org/openstreetmap/josm/plugins/editgpx/EditGpxPlugin.java
@@ -3,24 +3,18 @@
*/
package org.openstreetmap.josm.plugins.editgpx;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
+import static org.openstreetmap.josm.tools.I18n.tr;
+
import java.net.URL;
import javax.swing.ImageIcon;
import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.data.osm.DataSet;
import org.openstreetmap.josm.gui.IconToggleButton;
import org.openstreetmap.josm.gui.MapFrame;
-import org.openstreetmap.josm.gui.MapView;
-import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
-import org.openstreetmap.josm.gui.layer.Layer;
import org.openstreetmap.josm.plugins.Plugin;
import org.openstreetmap.josm.plugins.PluginInformation;
-import static org.openstreetmap.josm.tools.I18n.tr;
-
/**
* Provides an editable GPX layer. Editable layer here means the deletion of points is supported.
* This plugin can be used to prepare tracks for upload to OSM eg. delete uninteresting parts
@@ -37,82 +31,32 @@ import static org.openstreetmap.josm.tools.I18n.tr;
*/
public class EditGpxPlugin extends Plugin {
- private IconToggleButton btn;
- private EditGpxMode mode;
- protected static EditGpxLayer eGpxLayer;
- protected static DataSet dataSet;
- public static boolean active = false;
-
- public EditGpxPlugin(PluginInformation info) {
- super(info);
- dataSet = new DataSet();
- mode = new EditGpxMode(Main.map, "editgpx", tr("edit gpx tracks"), dataSet);
-
- btn = new IconToggleButton(mode);
- btn.setVisible(true);
- }
-
- /**
- * initialize button. if button is pressed create new layer.
- */
- @Override
- public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) {
- if(oldFrame == null && newFrame != null) {
- mode.setFrame(newFrame);
-
- if(Main.map != null)
- Main.map.addMapMode(btn);
-
- active = btn.isSelected();
-
- btn.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- active = btn.isSelected();
- if (active) {
- Main.worker.execute(new Runnable() {
- public void run() {
- updateLayer();
- }
- });
- }
- }
- });
- }
- }
-
- /**
- * create new layer, add listeners and try importing gpx data.
- */
- private void updateLayer() {
- if(eGpxLayer == null) {
- eGpxLayer = new EditGpxLayer(tr("EditGpx"), dataSet);
- Main.main.addLayer(eGpxLayer);
- MapView.addLayerChangeListener(new LayerChangeListener(){
-
- public void activeLayerChange(final Layer oldLayer, final Layer newLayer) {
- if(newLayer instanceof EditGpxLayer)
- EditGpxPlugin.eGpxLayer = (EditGpxLayer)newLayer;
- }
-
- public void layerAdded(final Layer newLayer) {
- }
-
- public void layerRemoved(final Layer oldLayer) {
- if(oldLayer == eGpxLayer) {
- eGpxLayer = null;
- //dataSet = new DataSet();
- MapView.removeLayerChangeListener(this);
- }
- }
- });
-
- eGpxLayer.initializeImport();
- }
- Main.map.mapView.repaint();
- }
-
- public static ImageIcon loadIcon(String name) {
- URL url = EditGpxPlugin.class.getResource("/images/editgpx.png");
- return new ImageIcon(url);
- }
+ private IconToggleButton btn;
+ private EditGpxMode mode;
+
+ public EditGpxPlugin(PluginInformation info) {
+ super(info);
+ mode = new EditGpxMode(Main.map, "editgpx", tr("edit gpx tracks"));
+
+ btn = new IconToggleButton(mode);
+ btn.setVisible(true);
+ }
+
+ /**
+ * initialize button. if button is pressed create new layer.
+ */
+ @Override
+ public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) {
+ if(oldFrame == null && newFrame != null) {
+ mode.setFrame(newFrame);
+
+ if(Main.map != null)
+ Main.map.addMapMode(btn);
+ }
+ }
+
+ public static ImageIcon loadIcon(String name) {
+ URL url = EditGpxPlugin.class.getResource("/images/editgpx.png");
+ return new ImageIcon(url);
+ }
}
diff --git a/editgpx/src/org/openstreetmap/josm/plugins/editgpx/GPXLayerImportAction.java b/editgpx/src/org/openstreetmap/josm/plugins/editgpx/GPXLayerImportAction.java
index 654ebda..65d23d5 100644
--- a/editgpx/src/org/openstreetmap/josm/plugins/editgpx/GPXLayerImportAction.java
+++ b/editgpx/src/org/openstreetmap/josm/plugins/editgpx/GPXLayerImportAction.java
@@ -24,15 +24,9 @@ import javax.swing.JList;
import javax.swing.JOptionPane;
import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.data.gpx.GpxTrack;
-import org.openstreetmap.josm.data.gpx.GpxTrackSegment;
-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.Way;
import org.openstreetmap.josm.gui.layer.GpxLayer;
import org.openstreetmap.josm.gui.layer.Layer;
-import org.openstreetmap.josm.tools.DateUtils;
+import org.openstreetmap.josm.plugins.editgpx.data.EditGpxData;
import org.openstreetmap.josm.tools.ImageProvider;
/**
@@ -43,102 +37,89 @@ import org.openstreetmap.josm.tools.ImageProvider;
class GPXLayerImportAction extends AbstractAction {
- private static final long serialVersionUID = 5794897888911798168L;
- private DataSet dataSet;
- public Object importing = new Object(); //used for synchronization
-
- public GPXLayerImportAction(DataSet ds) {
- //TODO what is icon at the end?
- super(tr("Import path from GPX layer"), ImageProvider.get("dialogs", "edit"));
- this.dataSet = ds;
- }
-
- /**
- * shows a list of GPX layers. if user selects one the data from this layer is
- * imported.
- */
- public void activateImport() {
- Box panel = Box.createVerticalBox();
- DefaultListModel dModel= new DefaultListModel();
-
- final JList layerList = new JList(dModel);
- Collection<Layer> data = Main.map.mapView.getAllLayers();
- Layer lastLayer = null;
- int layerCnt = 0;
-
- for (Layer l : data){
- if(l instanceof GpxLayer){
- dModel.addElement(l);
- lastLayer = l;
- layerCnt++;
- }
- }
- if(layerCnt == 1){
- layerList.setSelectedValue(lastLayer, true);
- }
- if(layerCnt > 0){
- layerList.setCellRenderer(new DefaultListCellRenderer(){
- @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
- Layer layer = (Layer)value;
- JLabel label = (JLabel)super.getListCellRendererComponent(list,
- layer.getName(), index, isSelected, cellHasFocus);
- Icon icon = layer.getIcon();
- label.setIcon(icon);
- label.setToolTipText(layer.getToolTipText());
- return label;
- }
- });
-
- JCheckBox dropFirst = new JCheckBox(tr("Drop existing path"));
-
- panel.add(layerList);
- panel.add(dropFirst);
-
- final JOptionPane optionPane = new JOptionPane(panel, JOptionPane.QUESTION_MESSAGE, JOptionPane.OK_CANCEL_OPTION){
- @Override public void selectInitialValue() {
- layerList.requestFocusInWindow();
- }
- };
- final JDialog dlg = optionPane.createDialog(Main.parent, tr("Import path from GPX layer"));
- dlg.setVisible(true);
-
- Object answer = optionPane.getValue();
- if (answer == null || answer == JOptionPane.UNINITIALIZED_VALUE ||
- (answer instanceof Integer && (Integer)answer != JOptionPane.OK_OPTION)) {
- return;
- }
-
- GpxLayer gpx = (GpxLayer)layerList.getSelectedValue();
-
- synchronized(importing) {
- for (GpxTrack trk : gpx.data.tracks) {
- for (GpxTrackSegment segment : trk.getSegments()) {
- Way w = new Way();
- for (WayPoint p : segment.getWayPoints()) {
- Node n = new Node(p.getCoor());
- String timestr = p.getString("time");
- if(timestr != null)
- n.setTimestamp(DateUtils.fromString(timestr));
- dataSet.addPrimitive(n);
- w.addNode(n); //TODO what to do with these while deletion
- }
- dataSet.addPrimitive(w);
- }
- }
- }
- Main.map.mapView.repaint();
-
- } else {
- // no gps layer
- JOptionPane.showMessageDialog(Main.parent,tr("No GPX data layer found."));
- }
- }
-
- /**
- * called when pressing "Import.." from context menu of EditGpx layer
- *
- */
- public void actionPerformed(ActionEvent arg0) {
- activateImport();
- }
+ private static final long serialVersionUID = 5794897888911798168L;
+ private EditGpxData data;
+ public Object importing = new Object(); //used for synchronization
+
+ public GPXLayerImportAction(EditGpxData data) {
+ //TODO what is icon at the end?
+ super(tr("Import path from GPX layer"), ImageProvider.get("dialogs", "edit"));
+ this.data = data;
+ }
+
+ /**
+ * shows a list of GPX layers. if user selects one the data from this layer is
+ * imported.
+ */
+ public void activateImport() {
+ Box panel = Box.createVerticalBox();
+ DefaultListModel dModel= new DefaultListModel();
+
+ final JList layerList = new JList(dModel);
+ Collection<Layer> data = Main.map.mapView.getAllLayers();
+ Layer lastLayer = null;
+ int layerCnt = 0;
+
+ for (Layer l : data){
+ if(l instanceof GpxLayer){
+ dModel.addElement(l);
+ lastLayer = l;
+ layerCnt++;
+ }
+ }
+ if(layerCnt == 1){
+ layerList.setSelectedValue(lastLayer, true);
+ }
+ if(layerCnt > 0){
+ layerList.setCellRenderer(new DefaultListCellRenderer(){
+ @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
+ Layer layer = (Layer)value;
+ JLabel label = (JLabel)super.getListCellRendererComponent(list,
+ layer.getName(), index, isSelected, cellHasFocus);
+ Icon icon = layer.getIcon();
+ label.setIcon(icon);
+ label.setToolTipText(layer.getToolTipText());
+ return label;
+ }
+ });
+
+ JCheckBox dropFirst = new JCheckBox(tr("Drop existing path"));
+
+ panel.add(layerList);
+ panel.add(dropFirst);
+
+ final JOptionPane optionPane = new JOptionPane(panel, JOptionPane.QUESTION_MESSAGE, JOptionPane.OK_CANCEL_OPTION){
+ @Override public void selectInitialValue() {
+ layerList.requestFocusInWindow();
+ }
+ };
+ final JDialog dlg = optionPane.createDialog(Main.parent, tr("Import path from GPX layer"));
+ dlg.setVisible(true);
+
+ Object answer = optionPane.getValue();
+ if (answer == null || answer == JOptionPane.UNINITIALIZED_VALUE ||
+ (answer instanceof Integer && (Integer)answer != JOptionPane.OK_OPTION)) {
+ return;
+ }
+
+ GpxLayer gpx = (GpxLayer)layerList.getSelectedValue();
+
+ synchronized(importing) {
+ this.data.load(gpx.data, dropFirst.isSelected());
+ }
+ Main.map.mapView.repaint();
+
+ } else {
+ // no gps layer
+ JOptionPane.showMessageDialog(Main.parent,tr("No GPX data layer found."));
+ }
+ }
+
+ /**
+ * called when pressing "Import.." from context menu of EditGpx layer
+ *
+ */
+ public void actionPerformed(ActionEvent arg0) {
+ activateImport();
+ }
}
diff --git a/editgpx/src/org/openstreetmap/josm/plugins/editgpx/data/EditGpxData.java b/editgpx/src/org/openstreetmap/josm/plugins/editgpx/data/EditGpxData.java
new file mode 100644
index 0000000..2e4a394
--- /dev/null
+++ b/editgpx/src/org/openstreetmap/josm/plugins/editgpx/data/EditGpxData.java
@@ -0,0 +1,62 @@
+package org.openstreetmap.josm.plugins.editgpx.data;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.openstreetmap.josm.data.gpx.GpxData;
+import org.openstreetmap.josm.data.gpx.GpxRoute;
+import org.openstreetmap.josm.data.gpx.GpxTrack;
+import org.openstreetmap.josm.data.gpx.WayPoint;
+
+public class EditGpxData {
+
+ private final List<EditGpxTrack> tracks = new ArrayList<EditGpxTrack>();
+ // Only copy of routes and waypoints to preserve all info when converting back to gpx track
+ private final List<GpxRoute> routes = new ArrayList<GpxRoute>();
+ private final List<WayPoint> waypoints = new ArrayList<WayPoint>();
+
+ public void load(GpxData data, boolean drop) {
+ if(drop)
+ tracks.clear();
+ for (GpxTrack track: data.tracks) {
+ tracks.add(new EditGpxTrack(track));
+ }
+ routes.clear();
+ routes.addAll(data.routes);
+ waypoints.clear();
+ waypoints.addAll(data.waypoints);
+ }
+
+ public boolean isEmpty() {
+ for (EditGpxTrack track: tracks) {
+ for (EditGpxTrackSegment segment: track.getSegments()) {
+ if (!segment.getWayPoints().isEmpty()) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ public List<EditGpxTrack> getTracks() {
+ return tracks;
+ }
+
+ public GpxData createGpxData() {
+ GpxData result = new GpxData();
+
+ for (EditGpxTrack track: tracks) {
+ if (!track.isDeleted()) {
+ GpxTrack newTrack = track.createGpxTrack();
+ if (!newTrack.getSegments().isEmpty()) {
+ result.tracks.add(newTrack);
+ }
+ }
+ }
+
+ result.routes.addAll(routes);
+ result.waypoints.addAll(waypoints);
+ return result;
+ }
+
+}
diff --git a/editgpx/src/org/openstreetmap/josm/plugins/editgpx/data/EditGpxTrack.java b/editgpx/src/org/openstreetmap/josm/plugins/editgpx/data/EditGpxTrack.java
new file mode 100644
index 0000000..9cf5a91
--- /dev/null
+++ b/editgpx/src/org/openstreetmap/josm/plugins/editgpx/data/EditGpxTrack.java
@@ -0,0 +1,57 @@
+package org.openstreetmap.josm.plugins.editgpx.data;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.openstreetmap.josm.data.gpx.GpxTrack;
+import org.openstreetmap.josm.data.gpx.GpxTrackSegment;
+import org.openstreetmap.josm.data.gpx.ImmutableGpxTrack;
+import org.openstreetmap.josm.data.gpx.WayPoint;
+
+public class EditGpxTrack {
+
+ private final List<EditGpxTrackSegment> segments = new ArrayList<EditGpxTrackSegment>();
+ private final Map<String, Object> attributes = new HashMap<String, Object>();
+ private boolean isDeleted;
+
+ public EditGpxTrack(GpxTrack track) {
+ attributes.putAll(track.getAttributes());
+ for (GpxTrackSegment segment: track.getSegments()) {
+ segments.add(new EditGpxTrackSegment(segment));
+ }
+ }
+
+ public List<EditGpxTrackSegment> getSegments() {
+ return segments;
+ }
+ public Map<String, Object> getAttributes() {
+ return attributes;
+ }
+
+ public GpxTrack createGpxTrack() {
+
+ Collection<Collection<WayPoint>> wayPoints = new ArrayList<Collection<WayPoint>>();
+
+ for (EditGpxTrackSegment segment: segments) {
+ if (!segment.isDeleted()) {
+ List<WayPoint> points = segment.getNonDeletedWaypoints();
+ if (!points.isEmpty()) {
+ wayPoints.add(points);
+ }
+ }
+ }
+
+ return new ImmutableGpxTrack(wayPoints, attributes);
+ }
+
+ public void setDeleted(boolean isDeleted) {
+ this.isDeleted = isDeleted;
+ }
+
+ public boolean isDeleted() {
+ return isDeleted;
+ }
+}
diff --git a/editgpx/src/org/openstreetmap/josm/plugins/editgpx/data/EditGpxTrackSegment.java b/editgpx/src/org/openstreetmap/josm/plugins/editgpx/data/EditGpxTrackSegment.java
new file mode 100644
index 0000000..f11f8b4
--- /dev/null
+++ b/editgpx/src/org/openstreetmap/josm/plugins/editgpx/data/EditGpxTrackSegment.java
@@ -0,0 +1,44 @@
+package org.openstreetmap.josm.plugins.editgpx.data;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.openstreetmap.josm.data.gpx.GpxTrackSegment;
+import org.openstreetmap.josm.data.gpx.WayPoint;
+
+public class EditGpxTrackSegment {
+
+ private final List<EditGpxWayPoint> wayPoints = new ArrayList<EditGpxWayPoint>();
+ private boolean deleted;
+
+ public EditGpxTrackSegment(GpxTrackSegment segment) {
+ for (WayPoint wayPoint: segment.getWayPoints()) {
+ wayPoints.add(new EditGpxWayPoint(wayPoint));
+ }
+ }
+
+ public List<EditGpxWayPoint> getWayPoints() {
+ return wayPoints;
+ }
+
+ public List<WayPoint> getNonDeletedWaypoints() {
+ List<WayPoint> result = new ArrayList<WayPoint>();
+
+ for (EditGpxWayPoint wp: wayPoints) {
+ if (!wp.isDeleted()) {
+ result.add(wp.createWayPoint());
+ }
+ }
+
+ return result;
+ }
+
+ public void setDeleted(boolean deleted) {
+ this.deleted = deleted;
+ }
+
+ public boolean isDeleted() {
+ return deleted;
+ }
+
+}
diff --git a/editgpx/src/org/openstreetmap/josm/plugins/editgpx/data/EditGpxWayPoint.java b/editgpx/src/org/openstreetmap/josm/plugins/editgpx/data/EditGpxWayPoint.java
new file mode 100644
index 0000000..f0a5a42
--- /dev/null
+++ b/editgpx/src/org/openstreetmap/josm/plugins/editgpx/data/EditGpxWayPoint.java
@@ -0,0 +1,39 @@
+package org.openstreetmap.josm.plugins.editgpx.data;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.openstreetmap.josm.data.coor.CachedLatLon;
+import org.openstreetmap.josm.data.gpx.WayPoint;
+
+public class EditGpxWayPoint {
+ private final double time;
+ private final CachedLatLon coor;
+ private boolean deleted;
+ private Map<String, Object> attributes;
+
+ public EditGpxWayPoint(WayPoint wayPoint) {
+ this.time = wayPoint.time;
+ this.coor = new CachedLatLon(wayPoint.getCoor());
+ this.attributes = new HashMap<String, Object>(wayPoint.attr);
+ }
+
+ public WayPoint createWayPoint() {
+ WayPoint result = new WayPoint(getCoor());
+ result.time = time;
+ result.attr = attributes;
+ return result;
+ }
+
+ public void setDeleted(boolean deleted) {
+ this.deleted = deleted;
+ }
+
+ public boolean isDeleted() {
+ return deleted;
+ }
+
+ public CachedLatLon getCoor() {
+ return coor;
+ }
+}
diff --git a/livegps/src/livegps/LiveGpsAcquirer.java b/livegps/src/livegps/LiveGpsAcquirer.java
index fc8c048..c4542aa 100644
--- a/livegps/src/livegps/LiveGpsAcquirer.java
+++ b/livegps/src/livegps/LiveGpsAcquirer.java
@@ -2,6 +2,8 @@ package livegps;
import static org.openstreetmap.josm.tools.I18n.tr;
+import java.lang.Float;
+
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.BufferedReader;
@@ -15,13 +17,19 @@ import java.util.List;
import org.openstreetmap.josm.Main;
import org.openstreetmap.josm.data.coor.LatLon;
+import org.json.JSONObject;
+import org.json.JSONException;
+
public class LiveGpsAcquirer implements Runnable {
- Socket gpsdSocket;
- BufferedReader gpsdReader;
- boolean connected = false;
- String gpsdHost;
- int gpsdPort;
- boolean shutdownFlag = false;
+ private String gpsdHost;
+ private int gpsdPort;
+
+ private Socket gpsdSocket;
+ private BufferedReader gpsdReader;
+ private boolean connected = false;
+ private boolean shutdownFlag = false;
+ private boolean JSONProtocol = true;
+
private final List<PropertyChangeListener> propertyChangeListener = new ArrayList<PropertyChangeListener>();
private PropertyChangeEvent lastStatusEvent;
private PropertyChangeEvent lastDataEvent;
@@ -111,124 +119,37 @@ public class LiveGpsAcquirer implements Runnable {
shutdownFlag = false;
while (!shutdownFlag) {
- double lat = 0;
- double lon = 0;
- float speed = 0;
- float course = 0;
- boolean haveFix = false;
try {
- if (!connected) {
- System.out.println("LiveGps tries to connect to gpsd");
- fireGpsStatusChangeEvent(
- LiveGpsStatus.GpsStatus.CONNECTING,
- tr("Connecting"));
- InetAddress[] addrs = InetAddress.getAllByName(gpsdHost);
- for (int i = 0; i < addrs.length && gpsdSocket == null; i++) {
- try {
- gpsdSocket = new Socket(addrs[i], gpsdPort);
- break;
- } catch (Exception e) {
- System.out
- .println("LiveGps: Could not open connection to gpsd: "
- + e);
- gpsdSocket = null;
- }
- }
-
- if (gpsdSocket != null) {
- gpsdReader = new BufferedReader(new InputStreamReader(
- gpsdSocket.getInputStream()));
- gpsdSocket.getOutputStream().write(
- new byte[] { 'w', 13, 10 });
- fireGpsStatusChangeEvent(
- LiveGpsStatus.GpsStatus.CONNECTING,
- tr("Connecting"));
- connected = true;
- System.out.println("LiveGps: Connected to gpsd");
- }
- }
+ if (!connected)
+ connect();
if (connected) {
+ String line;
+
// <FIXXME date="23.06.2007" author="cdaller">
// TODO this read is blocking if gps is connected but has no
// fix, so gpsd does not send positions
- String line = gpsdReader.readLine();
+ line = gpsdReader.readLine();
// </FIXXME>
if (line == null)
break;
- String words[] = line.split(",");
- if ((words.length == 0) || (!words[0].equals("GPSD"))) {
- // unexpected response.
+ if (JSONProtocol == true)
+ gpsData = ParseJSON(line);
+ else
+ gpsData = ParseOld(line);
+
+ if (gpsData == null)
continue;
- }
-
- for (int i = 1; i < words.length; i++) {
-
- if ((words[i].length() < 2)
- || (words[i].charAt(1) != '=')) {
- // unexpected response.
- continue;
- }
-
- char what = words[i].charAt(0);
- String value = words[i].substring(2);
- oldGpsData = gpsData;
- gpsData = new LiveGpsData();
- switch (what) {
- case 'O':
- // full report, tab delimited.
- String[] status = value.split("\\s+");
- if (status.length >= 5) {
- lat = Double.parseDouble(status[3]);
- lon = Double.parseDouble(status[4]);
- try {
- speed = Float.parseFloat(status[9]);
- course = Float.parseFloat(status[8]);
- // view.setSpeed(speed);
- // view.setCourse(course);
- } catch (NumberFormatException nex) {
- }
- haveFix = true;
- }
- break;
- case 'P':
- // position report, tab delimited.
- String[] pos = value.split("\\s+");
- if (pos.length >= 2) {
- lat = Double.parseDouble(pos[0]);
- lon = Double.parseDouble(pos[1]);
- speed = Float.NaN;
- course = Float.NaN;
- haveFix = true;
- }
- break;
- default:
- // not interested
- }
- fireGpsStatusChangeEvent(
- LiveGpsStatus.GpsStatus.CONNECTED,
- tr("Connected"));
- gpsData.setFix(haveFix);
- if (haveFix) {
- // view.setCurrentPosition(lat, lon);
- gpsData.setLatLon(new LatLon(lat, lon));
- gpsData.setSpeed(speed);
- gpsData.setCourse(course);
- fireGpsDataChangeEvent(oldGpsData, gpsData);
- }
- }
+
+ fireGpsDataChangeEvent(oldGpsData, gpsData);
+ oldGpsData = gpsData;
} else {
- // not connected:
- fireGpsStatusChangeEvent(
- LiveGpsStatus.GpsStatus.DISCONNECTED,
- tr("Not connected"));
+ fireGpsStatusChangeEvent(LiveGpsStatus.GpsStatus.DISCONNECTED, tr("Not connected"));
try {
Thread.sleep(1000);
- } catch (InterruptedException ignore) {
- }
- ;
+ } catch (InterruptedException ignore) {}
}
} catch (IOException iox) {
connected = false;
@@ -241,11 +162,8 @@ public class LiveGpsAcquirer implements Runnable {
tr("Connection Failed"));
try {
Thread.sleep(1000);
- } catch (InterruptedException ignore) {
- }
- ;
+ } catch (InterruptedException ignore) {} ;
// send warning to layer
-
}
}
@@ -257,8 +175,7 @@ public class LiveGpsAcquirer implements Runnable {
gpsdSocket = null;
System.out.println("LiveGps: Disconnected from gpsd");
} catch (Exception e) {
- System.out
- .println("LiveGps: Unable to close socket; reconnection may not be possible");
+ System.out.println("LiveGps: Unable to close socket; reconnection may not be possible");
}
}
}
@@ -267,4 +184,150 @@ public class LiveGpsAcquirer implements Runnable {
shutdownFlag = true;
}
+ private void connect() throws IOException {
+ JSONObject greeting;
+ String line, type, release;
+
+ System.out.println("LiveGps: trying to connect to gpsd at " + gpsdHost + ":" + gpsdPort);
+ fireGpsStatusChangeEvent( LiveGpsStatus.GpsStatus.CONNECTING, tr("Connecting"));
+
+ InetAddress[] addrs = InetAddress.getAllByName(gpsdHost);
+ for (int i = 0; i < addrs.length && gpsdSocket == null; i++) {
+ try {
+ gpsdSocket = new Socket(addrs[i], gpsdPort);
+ break;
+ } catch (Exception e) {
+ System.out.println("LiveGps: Could not open connection to gpsd: " + e);
+ gpsdSocket = null;
+ }
+ }
+
+ if (gpsdSocket == null)
+ return;
+
+ fireGpsStatusChangeEvent(LiveGpsStatus.GpsStatus.CONNECTING, tr("Connecting"));
+
+ /*
+ * First emit the "w" symbol. The older version will activate, the newer one will ignore it.
+ */
+ gpsdSocket.getOutputStream().write(new byte[] { 'w', 13, 10 });
+
+ gpsdReader = new BufferedReader(new InputStreamReader(gpsdSocket.getInputStream()));
+ line = gpsdReader.readLine();
+ if (line == null)
+ return;
+
+ try {
+ greeting = new JSONObject(line);
+ type = greeting.getString("class");
+ if (type.equals("VERSION")) {
+ release = greeting.getString("release");
+ System.out.println("LiveGps: Connected to gpsd " + release);
+ } else
+ System.out.println("LiveGps: Unexpected JSON in gpsd greeting: " + line);
+ } catch (JSONException jex) {
+ if (line.startsWith("GPSD,")) {
+ connected = true;
+ JSONProtocol = false;
+ System.out.println("LiveGps: Connected to old gpsd protocol version.");
+ fireGpsStatusChangeEvent(LiveGpsStatus.GpsStatus.CONNECTED, tr("Connected"));
+ }
+ }
+
+ if (JSONProtocol == true) {
+ JSONObject Watch = new JSONObject();
+ try {
+ Watch.put("enable", true);
+ Watch.put("json", true);
+ } catch (JSONException je) {};
+
+ String Request = "?WATCH=" + Watch.toString() + ";\n";
+ gpsdSocket.getOutputStream().write(Request.getBytes());
+
+ connected = true;
+ fireGpsStatusChangeEvent(LiveGpsStatus.GpsStatus.CONNECTED, tr("Connected"));
+ }
+ }
+
+ private LiveGpsData ParseJSON(String line) {
+ JSONObject report;
+ String type;
+ double lat = 0;
+ double lon = 0;
+ float speed = 0;
+ float course = 0;
+
+ try {
+ report = new JSONObject(line);
+ type = report.getString("class");
+ } catch (JSONException jex) {
+ System.out.println("LiveGps: line read from gpsd is not a JSON object:" + line);
+ return null;
+ }
+ if (!type.equals("TPV"))
+ return null;
+
+ try {
+ lat = report.getDouble("lat");
+ lon = report.getDouble("lon");
+ speed = (new Float(report.getDouble("speed"))).floatValue();
+ course = (new Float(report.getDouble("track"))).floatValue();
+
+ return new LiveGpsData(lat, lon, course, speed, true);
+ } catch (JSONException je) {}
+
+ return null;
+ }
+
+ private LiveGpsData ParseOld(String line) {
+ String words[];
+ double lat = 0;
+ double lon = 0;
+ float speed = 0;
+ float course = 0;
+
+ words = line.split(",");
+ if ((words.length == 0) || (!words[0].equals("GPSD")))
+ return null;
+
+ for (int i = 1; i < words.length; i++) {
+ if ((words[i].length() < 2) || (words[i].charAt(1) != '=')) {
+ // unexpected response.
+ continue;
+ }
+
+ char what = words[i].charAt(0);
+ String value = words[i].substring(2);
+ switch (what) {
+ case 'O':
+ // full report, tab delimited.
+ String[] status = value.split("\\s+");
+ if (status.length >= 5) {
+ lat = Double.parseDouble(status[3]);
+ lon = Double.parseDouble(status[4]);
+ try {
+ speed = Float.parseFloat(status[9]);
+ course = Float.parseFloat(status[8]);
+ } catch (NumberFormatException nex) {}
+ return new LiveGpsData(lat, lon, course, speed, true);
+ }
+ break;
+ case 'P':
+ // position report, tab delimited.
+ String[] pos = value.split("\\s+");
+ if (pos.length >= 2) {
+ lat = Double.parseDouble(pos[0]);
+ lon = Double.parseDouble(pos[1]);
+ speed = Float.NaN;
+ course = Float.NaN;
+ return new LiveGpsData(lat, lon, course, speed, true);
+ }
+ break;
+ default:
+ // not interested
+ }
+ }
+
+ return null;
+ }
}
diff --git a/livegps/src/org/json/JSONArray.java b/livegps/src/org/json/JSONArray.java
new file mode 100644
index 0000000..5cc6f71
--- /dev/null
+++ b/livegps/src/org/json/JSONArray.java
@@ -0,0 +1,918 @@
+package org.json;
+
+/*
+Copyright (c) 2002 JSON.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+The Software shall be used for Good, not Evil.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+import java.io.IOException;
+import java.io.Writer;
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * A JSONArray is an ordered sequence of values. Its external text form is a
+ * string wrapped in square brackets with commas separating the values. The
+ * internal form is an object having <code>get</code> and <code>opt</code>
+ * methods for accessing the values by index, and <code>put</code> methods for
+ * adding or replacing values. The values can be any of these types:
+ * <code>Boolean</code>, <code>JSONArray</code>, <code>JSONObject</code>,
+ * <code>Number</code>, <code>String</code>, or the
+ * <code>JSONObject.NULL object</code>.
+ * <p>
+ * The constructor can convert a JSON text into a Java object. The
+ * <code>toString</code> method converts to JSON text.
+ * <p>
+ * A <code>get</code> method returns a value if one can be found, and throws an
+ * exception if one cannot be found. An <code>opt</code> method returns a
+ * default value instead of throwing an exception, and so is useful for
+ * obtaining optional values.
+ * <p>
+ * The generic <code>get()</code> and <code>opt()</code> methods return an
+ * object which you can cast or query for type. There are also typed
+ * <code>get</code> and <code>opt</code> methods that do type checking and type
+ * coercion for you.
+ * <p>
+ * The texts produced by the <code>toString</code> methods strictly conform to
+ * JSON syntax rules. The constructors are more forgiving in the texts they will
+ * accept:
+ * <ul>
+ * <li>An extra <code>,</code> <small>(comma)</small> may appear just
+ * before the closing bracket.</li>
+ * <li>The <code>null</code> value will be inserted when there
+ * is <code>,</code> <small>(comma)</small> elision.</li>
+ * <li>Strings may be quoted with <code>'</code> <small>(single
+ * quote)</small>.</li>
+ * <li>Strings do not need to be quoted at all if they do not begin with a quote
+ * or single quote, and if they do not contain leading or trailing spaces,
+ * and if they do not contain any of these characters:
+ * <code>{ } [ ] / \ : , = ; #</code> and if they do not look like numbers
+ * and if they are not the reserved words <code>true</code>,
+ * <code>false</code>, or <code>null</code>.</li>
+ * <li>Values can be separated by <code>;</code> <small>(semicolon)</small> as
+ * well as by <code>,</code> <small>(comma)</small>.</li>
+ * <li>Numbers may have the
+ * <code>0x-</code> <small>(hex)</small> prefix.</li>
+ * </ul>
+
+ * @author JSON.org
+ * @version 2009-04-14
+ */
+public class JSONArray {
+
+
+ /**
+ * The arrayList where the JSONArray's properties are kept.
+ */
+ private ArrayList myArrayList;
+
+
+ /**
+ * Construct an empty JSONArray.
+ */
+ public JSONArray() {
+ this.myArrayList = new ArrayList();
+ }
+
+ /**
+ * Construct a JSONArray from a JSONTokener.
+ * @param x A JSONTokener
+ * @throws JSONException If there is a syntax error.
+ */
+ public JSONArray(JSONTokener x) throws JSONException {
+ this();
+ char c = x.nextClean();
+ char q;
+ if (c == '[') {
+ q = ']';
+ } else if (c == '(') {
+ q = ')';
+ } else {
+ throw x.syntaxError("A JSONArray text must start with '['");
+ }
+ if (x.nextClean() == ']') {
+ return;
+ }
+ x.back();
+ for (;;) {
+ if (x.nextClean() == ',') {
+ x.back();
+ this.myArrayList.add(null);
+ } else {
+ x.back();
+ this.myArrayList.add(x.nextValue());
+ }
+ c = x.nextClean();
+ switch (c) {
+ case ';':
+ case ',':
+ if (x.nextClean() == ']') {
+ return;
+ }
+ x.back();
+ break;
+ case ']':
+ case ')':
+ if (q != c) {
+ throw x.syntaxError("Expected a '" + new Character(q) + "'");
+ }
+ return;
+ default:
+ throw x.syntaxError("Expected a ',' or ']'");
+ }
+ }
+ }
+
+
+ /**
+ * Construct a JSONArray from a source JSON text.
+ * @param source A string that begins with
+ * <code>[</code> <small>(left bracket)</small>
+ * and ends with <code>]</code> <small>(right bracket)</small>.
+ * @throws JSONException If there is a syntax error.
+ */
+ public JSONArray(String source) throws JSONException {
+ this(new JSONTokener(source));
+ }
+
+
+ /**
+ * Construct a JSONArray from a Collection.
+ * @param collection A Collection.
+ */
+ public JSONArray(Collection collection) {
+ this.myArrayList = new ArrayList();
+ if (collection != null) {
+ Iterator iter = collection.iterator();
+ while (iter.hasNext()) {
+ Object o = iter.next();
+ this.myArrayList.add(JSONObject.wrap(o));
+ }
+ }
+ }
+
+
+ /**
+ * Construct a JSONArray from an array
+ * @throws JSONException If not an array.
+ */
+ public JSONArray(Object array) throws JSONException {
+ this();
+ if (array.getClass().isArray()) {
+ int length = Array.getLength(array);
+ for (int i = 0; i < length; i += 1) {
+ this.put(JSONObject.wrap(Array.get(array, i)));
+ }
+ } else {
+ throw new JSONException(
+"JSONArray initial value should be a string or collection or array.");
+ }
+ }
+
+
+ /**
+ * Get the object value associated with an index.
+ * @param index
+ * The index must be between 0 and length() - 1.
+ * @return An object value.
+ * @throws JSONException If there is no value for the index.
+ */
+ public Object get(int index) throws JSONException {
+ Object o = opt(index);
+ if (o == null) {
+ throw new JSONException("JSONArray[" + index + "] not found.");
+ }
+ return o;
+ }
+
+
+ /**
+ * Get the boolean value associated with an index.
+ * The string values "true" and "false" are converted to boolean.
+ *
+ * @param index The index must be between 0 and length() - 1.
+ * @return The truth.
+ * @throws JSONException If there is no value for the index or if the
+ * value is not convertable to boolean.
+ */
+ public boolean getBoolean(int index) throws JSONException {
+ Object o = get(index);
+ if (o.equals(Boolean.FALSE) ||
+ (o instanceof String &&
+ ((String)o).equalsIgnoreCase("false"))) {
+ return false;
+ } else if (o.equals(Boolean.TRUE) ||
+ (o instanceof String &&
+ ((String)o).equalsIgnoreCase("true"))) {
+ return true;
+ }
+ throw new JSONException("JSONArray[" + index + "] is not a Boolean.");
+ }
+
+
+ /**
+ * Get the double value associated with an index.
+ *
+ * @param index The index must be between 0 and length() - 1.
+ * @return The value.
+ * @throws JSONException If the key is not found or if the value cannot
+ * be converted to a number.
+ */
+ public double getDouble(int index) throws JSONException {
+ Object o = get(index);
+ try {
+ return o instanceof Number ?
+ ((Number)o).doubleValue() :
+ Double.valueOf((String)o).doubleValue();
+ } catch (Exception e) {
+ throw new JSONException("JSONArray[" + index +
+ "] is not a number.");
+ }
+ }
+
+
+ /**
+ * Get the int value associated with an index.
+ *
+ * @param index The index must be between 0 and length() - 1.
+ * @return The value.
+ * @throws JSONException If the key is not found or if the value cannot
+ * be converted to a number.
+ * if the value cannot be converted to a number.
+ */
+ public int getInt(int index) throws JSONException {
+ Object o = get(index);
+ return o instanceof Number ?
+ ((Number)o).intValue() : (int)getDouble(index);
+ }
+
+
+ /**
+ * Get the JSONArray associated with an index.
+ * @param index The index must be between 0 and length() - 1.
+ * @return A JSONArray value.
+ * @throws JSONException If there is no value for the index. or if the
+ * value is not a JSONArray
+ */
+ public JSONArray getJSONArray(int index) throws JSONException {
+ Object o = get(index);
+ if (o instanceof JSONArray) {
+ return (JSONArray)o;
+ }
+ throw new JSONException("JSONArray[" + index +
+ "] is not a JSONArray.");
+ }
+
+
+ /**
+ * Get the JSONObject associated with an index.
+ * @param index subscript
+ * @return A JSONObject value.
+ * @throws JSONException If there is no value for the index or if the
+ * value is not a JSONObject
+ */
+ public JSONObject getJSONObject(int index) throws JSONException {
+ Object o = get(index);
+ if (o instanceof JSONObject) {
+ return (JSONObject)o;
+ }
+ throw new JSONException("JSONArray[" + index +
+ "] is not a JSONObject.");
+ }
+
+
+ /**
+ * Get the long value associated with an index.
+ *
+ * @param index The index must be between 0 and length() - 1.
+ * @return The value.
+ * @throws JSONException If the key is not found or if the value cannot
+ * be converted to a number.
+ */
+ public long getLong(int index) throws JSONException {
+ Object o = get(index);
+ return o instanceof Number ?
+ ((Number)o).longValue() : (long)getDouble(index);
+ }
+
+
+ /**
+ * Get the string associated with an index.
+ * @param index The index must be between 0 and length() - 1.
+ * @return A string value.
+ * @throws JSONException If there is no value for the index.
+ */
+ public String getString(int index) throws JSONException {
+ return get(index).toString();
+ }
+
+
+ /**
+ * Determine if the value is null.
+ * @param index The index must be between 0 and length() - 1.
+ * @return true if the value at the index is null, or if there is no value.
+ */
+ public boolean isNull(int index) {
+ return JSONObject.NULL.equals(opt(index));
+ }
+
+
+ /**
+ * Make a string from the contents of this JSONArray. The
+ * <code>separator</code> string is inserted between each element.
+ * Warning: This method assumes that the data structure is acyclical.
+ * @param separator A string that will be inserted between the elements.
+ * @return a string.
+ * @throws JSONException If the array contains an invalid number.
+ */
+ public String join(String separator) throws JSONException {
+ int len = length();
+ StringBuffer sb = new StringBuffer();
+
+ for (int i = 0; i < len; i += 1) {
+ if (i > 0) {
+ sb.append(separator);
+ }
+ sb.append(JSONObject.valueToString(this.myArrayList.get(i)));
+ }
+ return sb.toString();
+ }
+
+
+ /**
+ * Get the number of elements in the JSONArray, included nulls.
+ *
+ * @return The length (or size).
+ */
+ public int length() {
+ return this.myArrayList.size();
+ }
+
+
+ /**
+ * Get the optional object value associated with an index.
+ * @param index The index must be between 0 and length() - 1.
+ * @return An object value, or null if there is no
+ * object at that index.
+ */
+ public Object opt(int index) {
+ return (index < 0 || index >= length()) ?
+ null : this.myArrayList.get(index);
+ }
+
+
+ /**
+ * Get the optional boolean value associated with an index.
+ * It returns false if there is no value at that index,
+ * or if the value is not Boolean.TRUE or the String "true".
+ *
+ * @param index The index must be between 0 and length() - 1.
+ * @return The truth.
+ */
+ public boolean optBoolean(int index) {
+ return optBoolean(index, false);
+ }
+
+
+ /**
+ * Get the optional boolean value associated with an index.
+ * It returns the defaultValue if there is no value at that index or if
+ * it is not a Boolean or the String "true" or "false" (case insensitive).
+ *
+ * @param index The index must be between 0 and length() - 1.
+ * @param defaultValue A boolean default.
+ * @return The truth.
+ */
+ public boolean optBoolean(int index, boolean defaultValue) {
+ try {
+ return getBoolean(index);
+ } catch (Exception e) {
+ return defaultValue;
+ }
+ }
+
+
+ /**
+ * Get the optional double value associated with an index.
+ * NaN is returned if there is no value for the index,
+ * or if the value is not a number and cannot be converted to a number.
+ *
+ * @param index The index must be between 0 and length() - 1.
+ * @return The value.
+ */
+ public double optDouble(int index) {
+ return optDouble(index, Double.NaN);
+ }
+
+
+ /**
+ * Get the optional double value associated with an index.
+ * The defaultValue is returned if there is no value for the index,
+ * or if the value is not a number and cannot be converted to a number.
+ *
+ * @param index subscript
+ * @param defaultValue The default value.
+ * @return The value.
+ */
+ public double optDouble(int index, double defaultValue) {
+ try {
+ return getDouble(index);
+ } catch (Exception e) {
+ return defaultValue;
+ }
+ }
+
+
+ /**
+ * Get the optional int value associated with an index.
+ * Zero is returned if there is no value for the index,
+ * or if the value is not a number and cannot be converted to a number.
+ *
+ * @param index The index must be between 0 and length() - 1.
+ * @return The value.
+ */
+ public int optInt(int index) {
+ return optInt(index, 0);
+ }
+
+
+ /**
+ * Get the optional int value associated with an index.
+ * The defaultValue is returned if there is no value for the index,
+ * or if the value is not a number and cannot be converted to a number.
+ * @param index The index must be between 0 and length() - 1.
+ * @param defaultValue The default value.
+ * @return The value.
+ */
+ public int optInt(int index, int defaultValue) {
+ try {
+ return getInt(index);
+ } catch (Exception e) {
+ return defaultValue;
+ }
+ }
+
+
+ /**
+ * Get the optional JSONArray associated with an index.
+ * @param index subscript
+ * @return A JSONArray value, or null if the index has no value,
+ * or if the value is not a JSONArray.
+ */
+ public JSONArray optJSONArray(int index) {
+ Object o = opt(index);
+ return o instanceof JSONArray ? (JSONArray)o : null;
+ }
+
+
+ /**
+ * Get the optional JSONObject associated with an index.
+ * Null is returned if the key is not found, or null if the index has
+ * no value, or if the value is not a JSONObject.
+ *
+ * @param index The index must be between 0 and length() - 1.
+ * @return A JSONObject value.
+ */
+ public JSONObject optJSONObject(int index) {
+ Object o = opt(index);
+ return o instanceof JSONObject ? (JSONObject)o : null;
+ }
+
+
+ /**
+ * Get the optional long value associated with an index.
+ * Zero is returned if there is no value for the index,
+ * or if the value is not a number and cannot be converted to a number.
+ *
+ * @param index The index must be between 0 and length() - 1.
+ * @return The value.
+ */
+ public long optLong(int index) {
+ return optLong(index, 0);
+ }
+
+
+ /**
+ * Get the optional long value associated with an index.
+ * The defaultValue is returned if there is no value for the index,
+ * or if the value is not a number and cannot be converted to a number.
+ * @param index The index must be between 0 and length() - 1.
+ * @param defaultValue The default value.
+ * @return The value.
+ */
+ public long optLong(int index, long defaultValue) {
+ try {
+ return getLong(index);
+ } catch (Exception e) {
+ return defaultValue;
+ }
+ }
+
+
+ /**
+ * Get the optional string value associated with an index. It returns an
+ * empty string if there is no value at that index. If the value
+ * is not a string and is not null, then it is coverted to a string.
+ *
+ * @param index The index must be between 0 and length() - 1.
+ * @return A String value.
+ */
+ public String optString(int index) {
+ return optString(index, "");
+ }
+
+
+ /**
+ * Get the optional string associated with an index.
+ * The defaultValue is returned if the key is not found.
+ *
+ * @param index The index must be between 0 and length() - 1.
+ * @param defaultValue The default value.
+ * @return A String value.
+ */
+ public String optString(int index, String defaultValue) {
+ Object o = opt(index);
+ return o != null ? o.toString() : defaultValue;
+ }
+
+
+ /**
+ * Append a boolean value. This increases the array's length by one.
+ *
+ * @param value A boolean value.
+ * @return this.
+ */
+ public JSONArray put(boolean value) {
+ put(value ? Boolean.TRUE : Boolean.FALSE);
+ return this;
+ }
+
+
+ /**
+ * Put a value in the JSONArray, where the value will be a
+ * JSONArray which is produced from a Collection.
+ * @param value A Collection value.
+ * @return this.
+ */
+ public JSONArray put(Collection value) {
+ put(new JSONArray(value));
+ return this;
+ }
+
+
+ /**
+ * Append a double value. This increases the array's length by one.
+ *
+ * @param value A double value.
+ * @throws JSONException if the value is not finite.
+ * @return this.
+ */
+ public JSONArray put(double value) throws JSONException {
+ Double d = new Double(value);
+ JSONObject.testValidity(d);
+ put(d);
+ return this;
+ }
+
+
+ /**
+ * Append an int value. This increases the array's length by one.
+ *
+ * @param value An int value.
+ * @return this.
+ */
+ public JSONArray put(int value) {
+ put(new Integer(value));
+ return this;
+ }
+
+
+ /**
+ * Append an long value. This increases the array's length by one.
+ *
+ * @param value A long value.
+ * @return this.
+ */
+ public JSONArray put(long value) {
+ put(new Long(value));
+ return this;
+ }
+
+
+ /**
+ * Put a value in the JSONArray, where the value will be a
+ * JSONObject which is produced from a Map.
+ * @param value A Map value.
+ * @return this.
+ */
+ public JSONArray put(Map value) {
+ put(new JSONObject(value));
+ return this;
+ }
+
+
+ /**
+ * Append an object value. This increases the array's length by one.
+ * @param value An object value. The value should be a
+ * Boolean, Double, Integer, JSONArray, JSONObject, Long, or String, or the
+ * JSONObject.NULL object.
+ * @return this.
+ */
+ public JSONArray put(Object value) {
+ this.myArrayList.add(value);
+ return this;
+ }
+
+
+ /**
+ * Put or replace a boolean value in the JSONArray. If the index is greater
+ * than the length of the JSONArray, then null elements will be added as
+ * necessary to pad it out.
+ * @param index The subscript.
+ * @param value A boolean value.
+ * @return this.
+ * @throws JSONException If the index is negative.
+ */
+ public JSONArray put(int index, boolean value) throws JSONException {
+ put(index, value ? Boolean.TRUE : Boolean.FALSE);
+ return this;
+ }
+
+
+ /**
+ * Put a value in the JSONArray, where the value will be a
+ * JSONArray which is produced from a Collection.
+ * @param index The subscript.
+ * @param value A Collection value.
+ * @return this.
+ * @throws JSONException If the index is negative or if the value is
+ * not finite.
+ */
+ public JSONArray put(int index, Collection value) throws JSONException {
+ put(index, new JSONArray(value));
+ return this;
+ }
+
+
+ /**
+ * Put or replace a double value. If the index is greater than the length of
+ * the JSONArray, then null elements will be added as necessary to pad
+ * it out.
+ * @param index The subscript.
+ * @param value A double value.
+ * @return this.
+ * @throws JSONException If the index is negative or if the value is
+ * not finite.
+ */
+ public JSONArray put(int index, double value) throws JSONException {
+ put(index, new Double(value));
+ return this;
+ }
+
+
+ /**
+ * Put or replace an int value. If the index is greater than the length of
+ * the JSONArray, then null elements will be added as necessary to pad
+ * it out.
+ * @param index The subscript.
+ * @param value An int value.
+ * @return this.
+ * @throws JSONException If the index is negative.
+ */
+ public JSONArray put(int index, int value) throws JSONException {
+ put(index, new Integer(value));
+ return this;
+ }
+
+
+ /**
+ * Put or replace a long value. If the index is greater than the length of
+ * the JSONArray, then null elements will be added as necessary to pad
+ * it out.
+ * @param index The subscript.
+ * @param value A long value.
+ * @return this.
+ * @throws JSONException If the index is negative.
+ */
+ public JSONArray put(int index, long value) throws JSONException {
+ put(index, new Long(value));
+ return this;
+ }
+
+
+ /**
+ * Put a value in the JSONArray, where the value will be a
+ * JSONObject which is produced from a Map.
+ * @param index The subscript.
+ * @param value The Map value.
+ * @return this.
+ * @throws JSONException If the index is negative or if the the value is
+ * an invalid number.
+ */
+ public JSONArray put(int index, Map value) throws JSONException {
+ put(index, new JSONObject(value));
+ return this;
+ }
+
+
+ /**
+ * Put or replace an object value in the JSONArray. If the index is greater
+ * than the length of the JSONArray, then null elements will be added as
+ * necessary to pad it out.
+ * @param index The subscript.
+ * @param value The value to put into the array. The value should be a
+ * Boolean, Double, Integer, JSONArray, JSONObject, Long, or String, or the
+ * JSONObject.NULL object.
+ * @return this.
+ * @throws JSONException If the index is negative or if the the value is
+ * an invalid number.
+ */
+ public JSONArray put(int index, Object value) throws JSONException {
+ JSONObject.testValidity(value);
+ if (index < 0) {
+ throw new JSONException("JSONArray[" + index + "] not found.");
+ }
+ if (index < length()) {
+ this.myArrayList.set(index, value);
+ } else {
+ while (index != length()) {
+ put(JSONObject.NULL);
+ }
+ put(value);
+ }
+ return this;
+ }
+
+
+ /**
+ * Remove an index and close the hole.
+ * @param index The index of the element to be removed.
+ * @return The value that was associated with the index,
+ * or null if there was no value.
+ */
+ public Object remove(int index) {
+ Object o = opt(index);
+ this.myArrayList.remove(index);
+ return o;
+ }
+
+
+ /**
+ * Produce a JSONObject by combining a JSONArray of names with the values
+ * of this JSONArray.
+ * @param names A JSONArray containing a list of key strings. These will be
+ * paired with the values.
+ * @return A JSONObject, or null if there are no names or if this JSONArray
+ * has no values.
+ * @throws JSONException If any of the names are null.
+ */
+ public JSONObject toJSONObject(JSONArray names) throws JSONException {
+ if (names == null || names.length() == 0 || length() == 0) {
+ return null;
+ }
+ JSONObject jo = new JSONObject();
+ for (int i = 0; i < names.length(); i += 1) {
+ jo.put(names.getString(i), this.opt(i));
+ }
+ return jo;
+ }
+
+
+ /**
+ * Make a JSON text of this JSONArray. For compactness, no
+ * unnecessary whitespace is added. If it is not possible to produce a
+ * syntactically correct JSON text then null will be returned instead. This
+ * could occur if the array contains an invalid number.
+ * <p>
+ * Warning: This method assumes that the data structure is acyclical.
+ *
+ * @return a printable, displayable, transmittable
+ * representation of the array.
+ */
+ public String toString() {
+ try {
+ return '[' + join(",") + ']';
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+
+ /**
+ * Make a prettyprinted JSON text of this JSONArray.
+ * Warning: This method assumes that the data structure is acyclical.
+ * @param indentFactor The number of spaces to add to each level of
+ * indentation.
+ * @return a printable, displayable, transmittable
+ * representation of the object, beginning
+ * with <code>[</code> <small>(left bracket)</small> and ending
+ * with <code>]</code> <small>(right bracket)</small>.
+ * @throws JSONException
+ */
+ public String toString(int indentFactor) throws JSONException {
+ return toString(indentFactor, 0);
+ }
+
+
+ /**
+ * Make a prettyprinted JSON text of this JSONArray.
+ * Warning: This method assumes that the data structure is acyclical.
+ * @param indentFactor The number of spaces to add to each level of
+ * indentation.
+ * @param indent The indention of the top level.
+ * @return a printable, displayable, transmittable
+ * representation of the array.
+ * @throws JSONException
+ */
+ String toString(int indentFactor, int indent) throws JSONException {
+ int len = length();
+ if (len == 0) {
+ return "[]";
+ }
+ int i;
+ StringBuffer sb = new StringBuffer("[");
+ if (len == 1) {
+ sb.append(JSONObject.valueToString(this.myArrayList.get(0),
+ indentFactor, indent));
+ } else {
+ int newindent = indent + indentFactor;
+ sb.append('\n');
+ for (i = 0; i < len; i += 1) {
+ if (i > 0) {
+ sb.append(",\n");
+ }
+ for (int j = 0; j < newindent; j += 1) {
+ sb.append(' ');
+ }
+ sb.append(JSONObject.valueToString(this.myArrayList.get(i),
+ indentFactor, newindent));
+ }
+ sb.append('\n');
+ for (i = 0; i < indent; i += 1) {
+ sb.append(' ');
+ }
+ }
+ sb.append(']');
+ return sb.toString();
+ }
+
+
+ /**
+ * Write the contents of the JSONArray as JSON text to a writer.
+ * For compactness, no whitespace is added.
+ * <p>
+ * Warning: This method assumes that the data structure is acyclical.
+ *
+ * @return The writer.
+ * @throws JSONException
+ */
+ public Writer write(Writer writer) throws JSONException {
+ try {
+ boolean b = false;
+ int len = length();
+
+ writer.write('[');
+
+ for (int i = 0; i < len; i += 1) {
+ if (b) {
+ writer.write(',');
+ }
+ Object v = this.myArrayList.get(i);
+ if (v instanceof JSONObject) {
+ ((JSONObject)v).write(writer);
+ } else if (v instanceof JSONArray) {
+ ((JSONArray)v).write(writer);
+ } else {
+ writer.write(JSONObject.valueToString(v));
+ }
+ b = true;
+ }
+ writer.write(']');
+ return writer;
+ } catch (IOException e) {
+ throw new JSONException(e);
+ }
+ }
+}
\ No newline at end of file
diff --git a/livegps/src/org/json/JSONException.java b/livegps/src/org/json/JSONException.java
new file mode 100644
index 0000000..45e3b8d
--- /dev/null
+++ b/livegps/src/org/json/JSONException.java
@@ -0,0 +1,31 @@
+package org.json;
+
+/**
+ * The JSONException is thrown by the JSON.org classes when things are amiss.
+ * @author JSON.org
+ * @version 2008-09-18
+ */
+public class JSONException extends Exception {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 0;
+ private Throwable cause;
+
+ /**
+ * Constructs a JSONException with an explanatory message.
+ * @param message Detail about the reason for the exception.
+ */
+ public JSONException(String message) {
+ super(message);
+ }
+
+ public JSONException(Throwable t) {
+ super(t.getMessage());
+ this.cause = t;
+ }
+
+ public Throwable getCause() {
+ return this.cause;
+ }
+}
diff --git a/livegps/src/org/json/JSONObject.java b/livegps/src/org/json/JSONObject.java
new file mode 100644
index 0000000..e34a752
--- /dev/null
+++ b/livegps/src/org/json/JSONObject.java
@@ -0,0 +1,1584 @@
+package org.json;
+
+/*
+Copyright (c) 2002 JSON.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+The Software shall be used for Good, not Evil.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+import java.io.IOException;
+import java.io.Writer;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.TreeSet;
+
+/**
+ * A JSONObject is an unordered collection of name/value pairs. Its
+ * external form is a string wrapped in curly braces with colons between the
+ * names and values, and commas between the values and names. The internal form
+ * is an object having <code>get</code> and <code>opt</code> methods for
+ * accessing the values by name, and <code>put</code> methods for adding or
+ * replacing values by name. The values can be any of these types:
+ * <code>Boolean</code>, <code>JSONArray</code>, <code>JSONObject</code>,
+ * <code>Number</code>, <code>String</code>, or the <code>JSONObject.NULL</code>
+ * object. A JSONObject constructor can be used to convert an external form
+ * JSON text into an internal form whose values can be retrieved with the
+ * <code>get</code> and <code>opt</code> methods, or to convert values into a
+ * JSON text using the <code>put</code> and <code>toString</code> methods.
+ * A <code>get</code> method returns a value if one can be found, and throws an
+ * exception if one cannot be found. An <code>opt</code> method returns a
+ * default value instead of throwing an exception, and so is useful for
+ * obtaining optional values.
+ * <p>
+ * The generic <code>get()</code> and <code>opt()</code> methods return an
+ * object, which you can cast or query for type. There are also typed
+ * <code>get</code> and <code>opt</code> methods that do type checking and type
+ * coercion for you.
+ * <p>
+ * The <code>put</code> methods adds values to an object. For example, <pre>
+ * myString = new JSONObject().put("JSON", "Hello, World!").toString();</pre>
+ * produces the string <code>{"JSON": "Hello, World"}</code>.
+ * <p>
+ * The texts produced by the <code>toString</code> methods strictly conform to
+ * the JSON syntax rules.
+ * The constructors are more forgiving in the texts they will accept:
+ * <ul>
+ * <li>An extra <code>,</code> <small>(comma)</small> may appear just
+ * before the closing brace.</li>
+ * <li>Strings may be quoted with <code>'</code> <small>(single
+ * quote)</small>.</li>
+ * <li>Strings do not need to be quoted at all if they do not begin with a quote
+ * or single quote, and if they do not contain leading or trailing spaces,
+ * and if they do not contain any of these characters:
+ * <code>{ } [ ] / \ : , = ; #</code> and if they do not look like numbers
+ * and if they are not the reserved words <code>true</code>,
+ * <code>false</code>, or <code>null</code>.</li>
+ * <li>Keys can be followed by <code>=</code> or <code>=></code> as well as
+ * by <code>:</code>.</li>
+ * <li>Values can be followed by <code>;</code> <small>(semicolon)</small> as
+ * well as by <code>,</code> <small>(comma)</small>.</li>
+ * <li>Numbers may have the <code>0x-</code> <small>(hex)</small> prefix.</li>
+ * </ul>
+ * @author JSON.org
+ * @version 2010-05-17
+ */
+public class JSONObject {
+
+ /**
+ * JSONObject.NULL is equivalent to the value that JavaScript calls null,
+ * whilst Java's null is equivalent to the value that JavaScript calls
+ * undefined.
+ */
+ private static final class Null {
+
+ /**
+ * There is only intended to be a single instance of the NULL object,
+ * so the clone method returns itself.
+ * @return NULL.
+ */
+ protected final Object clone() {
+ return this;
+ }
+
+
+ /**
+ * A Null object is equal to the null value and to itself.
+ * @param object An object to test for nullness.
+ * @return true if the object parameter is the JSONObject.NULL object
+ * or null.
+ */
+ public boolean equals(Object object) {
+ return object == null || object == this;
+ }
+
+
+ /**
+ * Get the "null" string value.
+ * @return The string "null".
+ */
+ public String toString() {
+ return "null";
+ }
+ }
+
+
+ /**
+ * The map where the JSONObject's properties are kept.
+ */
+ private Map map;
+
+
+ /**
+ * It is sometimes more convenient and less ambiguous to have a
+ * <code>NULL</code> object than to use Java's <code>null</code> value.
+ * <code>JSONObject.NULL.equals(null)</code> returns <code>true</code>.
+ * <code>JSONObject.NULL.toString()</code> returns <code>"null"</code>.
+ */
+ public static final Object NULL = new Null();
+
+
+ /**
+ * Construct an empty JSONObject.
+ */
+ public JSONObject() {
+ this.map = new HashMap();
+ }
+
+
+ /**
+ * Construct a JSONObject from a subset of another JSONObject.
+ * An array of strings is used to identify the keys that should be copied.
+ * Missing keys are ignored.
+ * @param jo A JSONObject.
+ * @param names An array of strings.
+ * @throws JSONException
+ * @exception JSONException If a value is a non-finite number or if a name is duplicated.
+ */
+ public JSONObject(JSONObject jo, String[] names) {
+ this();
+ for (int i = 0; i < names.length; i += 1) {
+ try {
+ putOnce(names[i], jo.opt(names[i]));
+ } catch (Exception ignore) {
+ }
+ }
+ }
+
+
+ /**
+ * Construct a JSONObject from a JSONTokener.
+ * @param x A JSONTokener object containing the source string.
+ * @throws JSONException If there is a syntax error in the source string
+ * or a duplicated key.
+ */
+ public JSONObject(JSONTokener x) throws JSONException {
+ this();
+ char c;
+ String key;
+
+ if (x.nextClean() != '{') {
+ throw x.syntaxError("A JSONObject text must begin with '{'");
+ }
+ for (;;) {
+ c = x.nextClean();
+ switch (c) {
+ case 0:
+ throw x.syntaxError("A JSONObject text must end with '}'");
+ case '}':
+ return;
+ default:
+ x.back();
+ key = x.nextValue().toString();
+ }
+
+ /*
+ * The key is followed by ':'. We will also tolerate '=' or '=>'.
+ */
+
+ c = x.nextClean();
+ if (c == '=') {
+ if (x.next() != '>') {
+ x.back();
+ }
+ } else if (c != ':') {
+ throw x.syntaxError("Expected a ':' after a key");
+ }
+ putOnce(key, x.nextValue());
+
+ /*
+ * Pairs are separated by ','. We will also tolerate ';'.
+ */
+
+ switch (x.nextClean()) {
+ case ';':
+ case ',':
+ if (x.nextClean() == '}') {
+ return;
+ }
+ x.back();
+ break;
+ case '}':
+ return;
+ default:
+ throw x.syntaxError("Expected a ',' or '}'");
+ }
+ }
+ }
+
+
+ /**
+ * Construct a JSONObject from a Map.
+ *
+ * @param map A map object that can be used to initialize the contents of
+ * the JSONObject.
+ * @throws JSONException
+ */
+ public JSONObject(Map map) {
+ this.map = new HashMap();
+ if (map != null) {
+ Iterator i = map.entrySet().iterator();
+ while (i.hasNext()) {
+ Map.Entry e = (Map.Entry)i.next();
+ this.map.put(e.getKey(), wrap(e.getValue()));
+ }
+ }
+ }
+
+
+ /**
+ * Construct a JSONObject from an Object using bean getters.
+ * It reflects on all of the public methods of the object.
+ * For each of the methods with no parameters and a name starting
+ * with <code>"get"</code> or <code>"is"</code> followed by an uppercase letter,
+ * the method is invoked, and a key and the value returned from the getter method
+ * are put into the new JSONObject.
+ *
+ * The key is formed by removing the <code>"get"</code> or <code>"is"</code> prefix.
+ * If the second remaining character is not upper case, then the first
+ * character is converted to lower case.
+ *
+ * For example, if an object has a method named <code>"getName"</code>, and
+ * if the result of calling <code>object.getName()</code> is <code>"Larry Fine"</code>,
+ * then the JSONObject will contain <code>"name": "Larry Fine"</code>.
+ *
+ * @param bean An object that has getter methods that should be used
+ * to make a JSONObject.
+ */
+ public JSONObject(Object bean) {
+ this();
+ populateMap(bean);
+ }
+
+
+ /**
+ * Construct a JSONObject from an Object, using reflection to find the
+ * public members. The resulting JSONObject's keys will be the strings
+ * from the names array, and the values will be the field values associated
+ * with those keys in the object. If a key is not found or not visible,
+ * then it will not be copied into the new JSONObject.
+ * @param object An object that has fields that should be used to make a
+ * JSONObject.
+ * @param names An array of strings, the names of the fields to be obtained
+ * from the object.
+ */
+ public JSONObject(Object object, String names[]) {
+ this();
+ Class c = object.getClass();
+ for (int i = 0; i < names.length; i += 1) {
+ String name = names[i];
+ try {
+ putOpt(name, c.getField(name).get(object));
+ } catch (Exception ignore) {
+ }
+ }
+ }
+
+
+ /**
+ * Construct a JSONObject from a source JSON text string.
+ * This is the most commonly used JSONObject constructor.
+ * @param source A string beginning
+ * with <code>{</code> <small>(left brace)</small> and ending
+ * with <code>}</code> <small>(right brace)</small>.
+ * @exception JSONException If there is a syntax error in the source
+ * string or a duplicated key.
+ */
+ public JSONObject(String source) throws JSONException {
+ this(new JSONTokener(source));
+ }
+
+
+ /**
+ * Accumulate values under a key. It is similar to the put method except
+ * that if there is already an object stored under the key then a
+ * JSONArray is stored under the key to hold all of the accumulated values.
+ * If there is already a JSONArray, then the new value is appended to it.
+ * In contrast, the put method replaces the previous value.
+ * @param key A key string.
+ * @param value An object to be accumulated under the key.
+ * @return this.
+ * @throws JSONException If the value is an invalid number
+ * or if the key is null.
+ */
+ public JSONObject accumulate(String key, Object value)
+ throws JSONException {
+ testValidity(value);
+ Object o = opt(key);
+ if (o == null) {
+ put(key, value instanceof JSONArray ?
+ new JSONArray().put(value) :
+ value);
+ } else if (o instanceof JSONArray) {
+ ((JSONArray)o).put(value);
+ } else {
+ put(key, new JSONArray().put(o).put(value));
+ }
+ return this;
+ }
+
+
+ /**
+ * Append values to the array under a key. If the key does not exist in the
+ * JSONObject, then the key is put in the JSONObject with its value being a
+ * JSONArray containing the value parameter. If the key was already
+ * associated with a JSONArray, then the value parameter is appended to it.
+ * @param key A key string.
+ * @param value An object to be accumulated under the key.
+ * @return this.
+ * @throws JSONException If the key is null or if the current value
+ * associated with the key is not a JSONArray.
+ */
+ public JSONObject append(String key, Object value) throws JSONException {
+ testValidity(value);
+ Object o = opt(key);
+ if (o == null) {
+ put(key, new JSONArray().put(value));
+ } else if (o instanceof JSONArray) {
+ put(key, ((JSONArray)o).put(value));
+ } else {
+ throw new JSONException("JSONObject[" + key +
+ "] is not a JSONArray.");
+ }
+ return this;
+ }
+
+
+ /**
+ * Produce a string from a double. The string "null" will be returned if
+ * the number is not finite.
+ * @param d A double.
+ * @return A String.
+ */
+ static public String doubleToString(double d) {
+ if (Double.isInfinite(d) || Double.isNaN(d)) {
+ return "null";
+ }
+
+// Shave off trailing zeros and decimal point, if possible.
+
+ String s = Double.toString(d);
+ if (s.indexOf('.') > 0 && s.indexOf('e') < 0 && s.indexOf('E') < 0) {
+ while (s.endsWith("0")) {
+ s = s.substring(0, s.length() - 1);
+ }
+ if (s.endsWith(".")) {
+ s = s.substring(0, s.length() - 1);
+ }
+ }
+ return s;
+ }
+
+
+ /**
+ * Get the value object associated with a key.
+ *
+ * @param key A key string.
+ * @return The object associated with the key.
+ * @throws JSONException if the key is not found.
+ */
+ public Object get(String key) throws JSONException {
+ Object o = opt(key);
+ if (o == null) {
+ throw new JSONException("JSONObject[" + quote(key) +
+ "] not found.");
+ }
+ return o;
+ }
+
+
+ /**
+ * Get the boolean value associated with a key.
+ *
+ * @param key A key string.
+ * @return The truth.
+ * @throws JSONException
+ * if the value is not a Boolean or the String "true" or "false".
+ */
+ public boolean getBoolean(String key) throws JSONException {
+ Object o = get(key);
+ if (o.equals(Boolean.FALSE) ||
+ (o instanceof String &&
+ ((String)o).equalsIgnoreCase("false"))) {
+ return false;
+ } else if (o.equals(Boolean.TRUE) ||
+ (o instanceof String &&
+ ((String)o).equalsIgnoreCase("true"))) {
+ return true;
+ }
+ throw new JSONException("JSONObject[" + quote(key) +
+ "] is not a Boolean.");
+ }
+
+
+ /**
+ * Get the double value associated with a key.
+ * @param key A key string.
+ * @return The numeric value.
+ * @throws JSONException if the key is not found or
+ * if the value is not a Number object and cannot be converted to a number.
+ */
+ public double getDouble(String key) throws JSONException {
+ Object o = get(key);
+ try {
+ return o instanceof Number ?
+ ((Number)o).doubleValue() :
+ Double.valueOf((String)o).doubleValue();
+ } catch (Exception e) {
+ throw new JSONException("JSONObject[" + quote(key) +
+ "] is not a number.");
+ }
+ }
+
+
+ /**
+ * Get the int value associated with a key.
+ *
+ * @param key A key string.
+ * @return The integer value.
+ * @throws JSONException if the key is not found or if the value cannot
+ * be converted to an integer.
+ */
+ public int getInt(String key) throws JSONException {
+ Object o = get(key);
+ try {
+ return o instanceof Number ?
+ ((Number)o).intValue() :
+ Integer.parseInt((String)o);
+ } catch (Exception e) {
+ throw new JSONException("JSONObject[" + quote(key) +
+ "] is not an int.");
+ }
+ }
+
+
+ /**
+ * Get the JSONArray value associated with a key.
+ *
+ * @param key A key string.
+ * @return A JSONArray which is the value.
+ * @throws JSONException if the key is not found or
+ * if the value is not a JSONArray.
+ */
+ public JSONArray getJSONArray(String key) throws JSONException {
+ Object o = get(key);
+ if (o instanceof JSONArray) {
+ return (JSONArray)o;
+ }
+ throw new JSONException("JSONObject[" + quote(key) +
+ "] is not a JSONArray.");
+ }
+
+
+ /**
+ * Get the JSONObject value associated with a key.
+ *
+ * @param key A key string.
+ * @return A JSONObject which is the value.
+ * @throws JSONException if the key is not found or
+ * if the value is not a JSONObject.
+ */
+ public JSONObject getJSONObject(String key) throws JSONException {
+ Object o = get(key);
+ if (o instanceof JSONObject) {
+ return (JSONObject)o;
+ }
+ throw new JSONException("JSONObject[" + quote(key) +
+ "] is not a JSONObject.");
+ }
+
+
+ /**
+ * Get the long value associated with a key.
+ *
+ * @param key A key string.
+ * @return The long value.
+ * @throws JSONException if the key is not found or if the value cannot
+ * be converted to a long.
+ */
+ public long getLong(String key) throws JSONException {
+ Object o = get(key);
+ try {
+ return o instanceof Number ?
+ ((Number)o).longValue() :
+ Long.parseLong((String)o);
+ } catch (Exception e) {
+ throw new JSONException("JSONObject[" + quote(key) +
+ "] is not a long.");
+ }
+ }
+
+
+ /**
+ * Get an array of field names from a JSONObject.
+ *
+ * @return An array of field names, or null if there are no names.
+ */
+ public static String[] getNames(JSONObject jo) {
+ int length = jo.length();
+ if (length == 0) {
+ return null;
+ }
+ Iterator i = jo.keys();
+ String[] names = new String[length];
+ int j = 0;
+ while (i.hasNext()) {
+ names[j] = (String)i.next();
+ j += 1;
+ }
+ return names;
+ }
+
+
+ /**
+ * Get an array of field names from an Object.
+ *
+ * @return An array of field names, or null if there are no names.
+ */
+ public static String[] getNames(Object object) {
+ if (object == null) {
+ return null;
+ }
+ Class klass = object.getClass();
+ Field[] fields = klass.getFields();
+ int length = fields.length;
+ if (length == 0) {
+ return null;
+ }
+ String[] names = new String[length];
+ for (int i = 0; i < length; i += 1) {
+ names[i] = fields[i].getName();
+ }
+ return names;
+ }
+
+
+ /**
+ * Get the string associated with a key.
+ *
+ * @param key A key string.
+ * @return A string which is the value.
+ * @throws JSONException if the key is not found.
+ */
+ public String getString(String key) throws JSONException {
+ return get(key).toString();
+ }
+
+
+ /**
+ * Determine if the JSONObject contains a specific key.
+ * @param key A key string.
+ * @return true if the key exists in the JSONObject.
+ */
+ public boolean has(String key) {
+ return this.map.containsKey(key);
+ }
+
+
+ /**
+ * Increment a property of a JSONObject. If there is no such property,
+ * create one with a value of 1. If there is such a property, and if
+ * it is an Integer, Long, Double, or Float, then add one to it.
+ * @param key A key string.
+ * @return this.
+ * @throws JSONException If there is already a property with this name
+ * that is not an Integer, Long, Double, or Float.
+ */
+ public JSONObject increment(String key) throws JSONException {
+ Object value = opt(key);
+ if (value == null) {
+ put(key, 1);
+ } else {
+ if (value instanceof Integer) {
+ put(key, ((Integer)value).intValue() + 1);
+ } else if (value instanceof Long) {
+ put(key, ((Long)value).longValue() + 1);
+ } else if (value instanceof Double) {
+ put(key, ((Double)value).doubleValue() + 1);
+ } else if (value instanceof Float) {
+ put(key, ((Float)value).floatValue() + 1);
+ } else {
+ throw new JSONException("Unable to increment [" + key + "].");
+ }
+ }
+ return this;
+ }
+
+
+ /**
+ * Determine if the value associated with the key is null or if there is
+ * no value.
+ * @param key A key string.
+ * @return true if there is no value associated with the key or if
+ * the value is the JSONObject.NULL object.
+ */
+ public boolean isNull(String key) {
+ return JSONObject.NULL.equals(opt(key));
+ }
+
+
+ /**
+ * Get an enumeration of the keys of the JSONObject.
+ *
+ * @return An iterator of the keys.
+ */
+ public Iterator keys() {
+ return this.map.keySet().iterator();
+ }
+
+
+ /**
+ * Get the number of keys stored in the JSONObject.
+ *
+ * @return The number of keys in the JSONObject.
+ */
+ public int length() {
+ return this.map.size();
+ }
+
+
+ /**
+ * Produce a JSONArray containing the names of the elements of this
+ * JSONObject.
+ * @return A JSONArray containing the key strings, or null if the JSONObject
+ * is empty.
+ */
+ public JSONArray names() {
+ JSONArray ja = new JSONArray();
+ Iterator keys = keys();
+ while (keys.hasNext()) {
+ ja.put(keys.next());
+ }
+ return ja.length() == 0 ? null : ja;
+ }
+
+ /**
+ * Produce a string from a Number.
+ * @param n A Number
+ * @return A String.
+ * @throws JSONException If n is a non-finite number.
+ */
+ static public String numberToString(Number n)
+ throws JSONException {
+ if (n == null) {
+ throw new JSONException("Null pointer");
+ }
+ testValidity(n);
+
+// Shave off trailing zeros and decimal point, if possible.
+
+ String s = n.toString();
+ if (s.indexOf('.') > 0 && s.indexOf('e') < 0 && s.indexOf('E') < 0) {
+ while (s.endsWith("0")) {
+ s = s.substring(0, s.length() - 1);
+ }
+ if (s.endsWith(".")) {
+ s = s.substring(0, s.length() - 1);
+ }
+ }
+ return s;
+ }
+
+
+ /**
+ * Get an optional value associated with a key.
+ * @param key A key string.
+ * @return An object which is the value, or null if there is no value.
+ */
+ public Object opt(String key) {
+ return key == null ? null : this.map.get(key);
+ }
+
+
+ /**
+ * Get an optional boolean associated with a key.
+ * It returns false if there is no such key, or if the value is not
+ * Boolean.TRUE or the String "true".
+ *
+ * @param key A key string.
+ * @return The truth.
+ */
+ public boolean optBoolean(String key) {
+ return optBoolean(key, false);
+ }
+
+
+ /**
+ * Get an optional boolean associated with a key.
+ * It returns the defaultValue if there is no such key, or if it is not
+ * a Boolean or the String "true" or "false" (case insensitive).
+ *
+ * @param key A key string.
+ * @param defaultValue The default.
+ * @return The truth.
+ */
+ public boolean optBoolean(String key, boolean defaultValue) {
+ try {
+ return getBoolean(key);
+ } catch (Exception e) {
+ return defaultValue;
+ }
+ }
+
+
+ /**
+ * Get an optional double associated with a key,
+ * or NaN if there is no such key or if its value is not a number.
+ * If the value is a string, an attempt will be made to evaluate it as
+ * a number.
+ *
+ * @param key A string which is the key.
+ * @return An object which is the value.
+ */
+ public double optDouble(String key) {
+ return optDouble(key, Double.NaN);
+ }
+
+
+ /**
+ * Get an optional double associated with a key, or the
+ * defaultValue if there is no such key or if its value is not a number.
+ * If the value is a string, an attempt will be made to evaluate it as
+ * a number.
+ *
+ * @param key A key string.
+ * @param defaultValue The default.
+ * @return An object which is the value.
+ */
+ public double optDouble(String key, double defaultValue) {
+ try {
+ Object o = opt(key);
+ return o instanceof Number ? ((Number)o).doubleValue() :
+ new Double((String)o).doubleValue();
+ } catch (Exception e) {
+ return defaultValue;
+ }
+ }
+
+
+ /**
+ * Get an optional int value associated with a key,
+ * or zero if there is no such key or if the value is not a number.
+ * If the value is a string, an attempt will be made to evaluate it as
+ * a number.
+ *
+ * @param key A key string.
+ * @return An object which is the value.
+ */
+ public int optInt(String key) {
+ return optInt(key, 0);
+ }
+
+
+ /**
+ * Get an optional int value associated with a key,
+ * or the default if there is no such key or if the value is not a number.
+ * If the value is a string, an attempt will be made to evaluate it as
+ * a number.
+ *
+ * @param key A key string.
+ * @param defaultValue The default.
+ * @return An object which is the value.
+ */
+ public int optInt(String key, int defaultValue) {
+ try {
+ return getInt(key);
+ } catch (Exception e) {
+ return defaultValue;
+ }
+ }
+
+
+ /**
+ * Get an optional JSONArray associated with a key.
+ * It returns null if there is no such key, or if its value is not a
+ * JSONArray.
+ *
+ * @param key A key string.
+ * @return A JSONArray which is the value.
+ */
+ public JSONArray optJSONArray(String key) {
+ Object o = opt(key);
+ return o instanceof JSONArray ? (JSONArray)o : null;
+ }
+
+
+ /**
+ * Get an optional JSONObject associated with a key.
+ * It returns null if there is no such key, or if its value is not a
+ * JSONObject.
+ *
+ * @param key A key string.
+ * @return A JSONObject which is the value.
+ */
+ public JSONObject optJSONObject(String key) {
+ Object o = opt(key);
+ return o instanceof JSONObject ? (JSONObject)o : null;
+ }
+
+
+ /**
+ * Get an optional long value associated with a key,
+ * or zero if there is no such key or if the value is not a number.
+ * If the value is a string, an attempt will be made to evaluate it as
+ * a number.
+ *
+ * @param key A key string.
+ * @return An object which is the value.
+ */
+ public long optLong(String key) {
+ return optLong(key, 0);
+ }
+
+
+ /**
+ * Get an optional long value associated with a key,
+ * or the default if there is no such key or if the value is not a number.
+ * If the value is a string, an attempt will be made to evaluate it as
+ * a number.
+ *
+ * @param key A key string.
+ * @param defaultValue The default.
+ * @return An object which is the value.
+ */
+ public long optLong(String key, long defaultValue) {
+ try {
+ return getLong(key);
+ } catch (Exception e) {
+ return defaultValue;
+ }
+ }
+
+
+ /**
+ * Get an optional string associated with a key.
+ * It returns an empty string if there is no such key. If the value is not
+ * a string and is not null, then it is coverted to a string.
+ *
+ * @param key A key string.
+ * @return A string which is the value.
+ */
+ public String optString(String key) {
+ return optString(key, "");
+ }
+
+
+ /**
+ * Get an optional string associated with a key.
+ * It returns the defaultValue if there is no such key.
+ *
+ * @param key A key string.
+ * @param defaultValue The default.
+ * @return A string which is the value.
+ */
+ public String optString(String key, String defaultValue) {
+ Object o = opt(key);
+ return o != null ? o.toString() : defaultValue;
+ }
+
+
+ private void populateMap(Object bean) {
+ Class klass = bean.getClass();
+
+// If klass is a System class then set includeSuperClass to false.
+
+ boolean includeSuperClass = klass.getClassLoader() != null;
+
+ Method[] methods = (includeSuperClass) ?
+ klass.getMethods() : klass.getDeclaredMethods();
+ for (int i = 0; i < methods.length; i += 1) {
+ try {
+ Method method = methods[i];
+ if (Modifier.isPublic(method.getModifiers())) {
+ String name = method.getName();
+ String key = "";
+ if (name.startsWith("get")) {
+ if (name.equals("getClass") ||
+ name.equals("getDeclaringClass")) {
+ key = "";
+ } else {
+ key = name.substring(3);
+ }
+ } else if (name.startsWith("is")) {
+ key = name.substring(2);
+ }
+ if (key.length() > 0 &&
+ Character.isUpperCase(key.charAt(0)) &&
+ method.getParameterTypes().length == 0) {
+ if (key.length() == 1) {
+ key = key.toLowerCase();
+ } else if (!Character.isUpperCase(key.charAt(1))) {
+ key = key.substring(0, 1).toLowerCase() +
+ key.substring(1);
+ }
+
+ Object result = method.invoke(bean, (Object[])null);
+
+ map.put(key, wrap(result));
+ }
+ }
+ } catch (Exception ignore) {
+ }
+ }
+ }
+
+
+ /**
+ * Put a key/boolean pair in the JSONObject.
+ *
+ * @param key A key string.
+ * @param value A boolean which is the value.
+ * @return this.
+ * @throws JSONException If the key is null.
+ */
+ public JSONObject put(String key, boolean value) throws JSONException {
+ put(key, value ? Boolean.TRUE : Boolean.FALSE);
+ return this;
+ }
+
+
+ /**
+ * Put a key/value pair in the JSONObject, where the value will be a
+ * JSONArray which is produced from a Collection.
+ * @param key A key string.
+ * @param value A Collection value.
+ * @return this.
+ * @throws JSONException
+ */
+ public JSONObject put(String key, Collection value) throws JSONException {
+ put(key, new JSONArray(value));
+ return this;
+ }
+
+
+ /**
+ * Put a key/double pair in the JSONObject.
+ *
+ * @param key A key string.
+ * @param value A double which is the value.
+ * @return this.
+ * @throws JSONException If the key is null or if the number is invalid.
+ */
+ public JSONObject put(String key, double value) throws JSONException {
+ put(key, new Double(value));
+ return this;
+ }
+
+
+ /**
+ * Put a key/int pair in the JSONObject.
+ *
+ * @param key A key string.
+ * @param value An int which is the value.
+ * @return this.
+ * @throws JSONException If the key is null.
+ */
+ public JSONObject put(String key, int value) throws JSONException {
+ put(key, new Integer(value));
+ return this;
+ }
+
+
+ /**
+ * Put a key/long pair in the JSONObject.
+ *
+ * @param key A key string.
+ * @param value A long which is the value.
+ * @return this.
+ * @throws JSONException If the key is null.
+ */
+ public JSONObject put(String key, long value) throws JSONException {
+ put(key, new Long(value));
+ return this;
+ }
+
+
+ /**
+ * Put a key/value pair in the JSONObject, where the value will be a
+ * JSONObject which is produced from a Map.
+ * @param key A key string.
+ * @param value A Map value.
+ * @return this.
+ * @throws JSONException
+ */
+ public JSONObject put(String key, Map value) throws JSONException {
+ put(key, new JSONObject(value));
+ return this;
+ }
+
+
+ /**
+ * Put a key/value pair in the JSONObject. If the value is null,
+ * then the key will be removed from the JSONObject if it is present.
+ * @param key A key string.
+ * @param value An object which is the value. It should be of one of these
+ * types: Boolean, Double, Integer, JSONArray, JSONObject, Long, String,
+ * or the JSONObject.NULL object.
+ * @return this.
+ * @throws JSONException If the value is non-finite number
+ * or if the key is null.
+ */
+ public JSONObject put(String key, Object value) throws JSONException {
+ if (key == null) {
+ throw new JSONException("Null key.");
+ }
+ if (value != null) {
+ testValidity(value);
+ this.map.put(key, value);
+ } else {
+ remove(key);
+ }
+ return this;
+ }
+
+
+ /**
+ * Put a key/value pair in the JSONObject, but only if the key and the
+ * value are both non-null, and only if there is not already a member
+ * with that name.
+ * @param key
+ * @param value
+ * @return his.
+ * @throws JSONException if the key is a duplicate
+ */
+ public JSONObject putOnce(String key, Object value) throws JSONException {
+ if (key != null && value != null) {
+ if (opt(key) != null) {
+ throw new JSONException("Duplicate key \"" + key + "\"");
+ }
+ put(key, value);
+ }
+ return this;
+ }
+
+
+ /**
+ * Put a key/value pair in the JSONObject, but only if the
+ * key and the value are both non-null.
+ * @param key A key string.
+ * @param value An object which is the value. It should be of one of these
+ * types: Boolean, Double, Integer, JSONArray, JSONObject, Long, String,
+ * or the JSONObject.NULL object.
+ * @return this.
+ * @throws JSONException If the value is a non-finite number.
+ */
+ public JSONObject putOpt(String key, Object value) throws JSONException {
+ if (key != null && value != null) {
+ put(key, value);
+ }
+ return this;
+ }
+
+
+ /**
+ * Produce a string in double quotes with backslash sequences in all the
+ * right places. A backslash will be inserted within </, allowing JSON
+ * text to be delivered in HTML. In JSON text, a string cannot contain a
+ * control character or an unescaped quote or backslash.
+ * @param string A String
+ * @return A String correctly formatted for insertion in a JSON text.
+ */
+ public static String quote(String string) {
+ if (string == null || string.length() == 0) {
+ return "\"\"";
+ }
+
+ char b;
+ char c = 0;
+ int i;
+ int len = string.length();
+ StringBuffer sb = new StringBuffer(len + 4);
+ String t;
+
+ sb.append('"');
+ for (i = 0; i < len; i += 1) {
+ b = c;
+ c = string.charAt(i);
+ switch (c) {
+ case '\\':
+ case '"':
+ sb.append('\\');
+ sb.append(c);
+ break;
+ case '/':
+ if (b == '<') {
+ sb.append('\\');
+ }
+ sb.append(c);
+ break;
+ case '\b':
+ sb.append("\\b");
+ break;
+ case '\t':
+ sb.append("\\t");
+ break;
+ case '\n':
+ sb.append("\\n");
+ break;
+ case '\f':
+ sb.append("\\f");
+ break;
+ case '\r':
+ sb.append("\\r");
+ break;
+ default:
+ if (c < ' ' || (c >= '\u0080' && c < '\u00a0') ||
+ (c >= '\u2000' && c < '\u2100')) {
+ t = "000" + Integer.toHexString(c);
+ sb.append("\\u" + t.substring(t.length() - 4));
+ } else {
+ sb.append(c);
+ }
+ }
+ }
+ sb.append('"');
+ return sb.toString();
+ }
+
+ /**
+ * Remove a name and its value, if present.
+ * @param key The name to be removed.
+ * @return The value that was associated with the name,
+ * or null if there was no value.
+ */
+ public Object remove(String key) {
+ return this.map.remove(key);
+ }
+
+ /**
+ * Get an enumeration of the keys of the JSONObject.
+ * The keys will be sorted alphabetically.
+ *
+ * @return An iterator of the keys.
+ */
+ public Iterator sortedKeys() {
+ return new TreeSet(this.map.keySet()).iterator();
+ }
+
+ /**
+ * Try to convert a string into a number, boolean, or null. If the string
+ * can't be converted, return the string.
+ * @param s A String.
+ * @return A simple JSON value.
+ */
+ static public Object stringToValue(String s) {
+ if (s.equals("")) {
+ return s;
+ }
+ if (s.equalsIgnoreCase("true")) {
+ return Boolean.TRUE;
+ }
+ if (s.equalsIgnoreCase("false")) {
+ return Boolean.FALSE;
+ }
+ if (s.equalsIgnoreCase("null")) {
+ return JSONObject.NULL;
+ }
+
+ /*
+ * If it might be a number, try converting it.
+ * We support the non-standard 0x- convention.
+ * If a number cannot be produced, then the value will just
+ * be a string. Note that the 0x-, plus, and implied string
+ * conventions are non-standard. A JSON parser may accept
+ * non-JSON forms as long as it accepts all correct JSON forms.
+ */
+
+ char b = s.charAt(0);
+ if ((b >= '0' && b <= '9') || b == '.' || b == '-' || b == '+') {
+ if (b == '0' && s.length() > 2 &&
+ (s.charAt(1) == 'x' || s.charAt(1) == 'X')) {
+ try {
+ return new Integer(Integer.parseInt(s.substring(2), 16));
+ } catch (Exception ignore) {
+ }
+ }
+ try {
+ if (s.indexOf('.') > -1 ||
+ s.indexOf('e') > -1 || s.indexOf('E') > -1) {
+ return Double.valueOf(s);
+ } else {
+ Long myLong = new Long(s);
+ if (myLong.longValue() == myLong.intValue()) {
+ return new Integer(myLong.intValue());
+ } else {
+ return myLong;
+ }
+ }
+ } catch (Exception ignore) {
+ }
+ }
+ return s;
+ }
+
+
+ /**
+ * Throw an exception if the object is an NaN or infinite number.
+ * @param o The object to test.
+ * @throws JSONException If o is a non-finite number.
+ */
+ static void testValidity(Object o) throws JSONException {
+ if (o != null) {
+ if (o instanceof Double) {
+ if (((Double)o).isInfinite() || ((Double)o).isNaN()) {
+ throw new JSONException(
+ "JSON does not allow non-finite numbers.");
+ }
+ } else if (o instanceof Float) {
+ if (((Float)o).isInfinite() || ((Float)o).isNaN()) {
+ throw new JSONException(
+ "JSON does not allow non-finite numbers.");
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Produce a JSONArray containing the values of the members of this
+ * JSONObject.
+ * @param names A JSONArray containing a list of key strings. This
+ * determines the sequence of the values in the result.
+ * @return A JSONArray of values.
+ * @throws JSONException If any of the values are non-finite numbers.
+ */
+ public JSONArray toJSONArray(JSONArray names) throws JSONException {
+ if (names == null || names.length() == 0) {
+ return null;
+ }
+ JSONArray ja = new JSONArray();
+ for (int i = 0; i < names.length(); i += 1) {
+ ja.put(this.opt(names.getString(i)));
+ }
+ return ja;
+ }
+
+ /**
+ * Make a JSON text of this JSONObject. For compactness, no whitespace
+ * is added. If this would not result in a syntactically correct JSON text,
+ * then null will be returned instead.
+ * <p>
+ * Warning: This method assumes that the data structure is acyclical.
+ *
+ * @return a printable, displayable, portable, transmittable
+ * representation of the object, beginning
+ * with <code>{</code> <small>(left brace)</small> and ending
+ * with <code>}</code> <small>(right brace)</small>.
+ */
+ public String toString() {
+ try {
+ Iterator keys = keys();
+ StringBuffer sb = new StringBuffer("{");
+
+ while (keys.hasNext()) {
+ if (sb.length() > 1) {
+ sb.append(',');
+ }
+ Object o = keys.next();
+ sb.append(quote(o.toString()));
+ sb.append(':');
+ sb.append(valueToString(this.map.get(o)));
+ }
+ sb.append('}');
+ return sb.toString();
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+
+ /**
+ * Make a prettyprinted JSON text of this JSONObject.
+ * <p>
+ * Warning: This method assumes that the data structure is acyclical.
+ * @param indentFactor The number of spaces to add to each level of
+ * indentation.
+ * @return a printable, displayable, portable, transmittable
+ * representation of the object, beginning
+ * with <code>{</code> <small>(left brace)</small> and ending
+ * with <code>}</code> <small>(right brace)</small>.
+ * @throws JSONException If the object contains an invalid number.
+ */
+ public String toString(int indentFactor) throws JSONException {
+ return toString(indentFactor, 0);
+ }
+
+
+ /**
+ * Make a prettyprinted JSON text of this JSONObject.
+ * <p>
+ * Warning: This method assumes that the data structure is acyclical.
+ * @param indentFactor The number of spaces to add to each level of
+ * indentation.
+ * @param indent The indentation of the top level.
+ * @return a printable, displayable, transmittable
+ * representation of the object, beginning
+ * with <code>{</code> <small>(left brace)</small> and ending
+ * with <code>}</code> <small>(right brace)</small>.
+ * @throws JSONException If the object contains an invalid number.
+ */
+ String toString(int indentFactor, int indent) throws JSONException {
+ int j;
+ int n = length();
+ if (n == 0) {
+ return "{}";
+ }
+ Iterator keys = sortedKeys();
+ StringBuffer sb = new StringBuffer("{");
+ int newindent = indent + indentFactor;
+ Object o;
+ if (n == 1) {
+ o = keys.next();
+ sb.append(quote(o.toString()));
+ sb.append(": ");
+ sb.append(valueToString(this.map.get(o), indentFactor,
+ indent));
+ } else {
+ while (keys.hasNext()) {
+ o = keys.next();
+ if (sb.length() > 1) {
+ sb.append(",\n");
+ } else {
+ sb.append('\n');
+ }
+ for (j = 0; j < newindent; j += 1) {
+ sb.append(' ');
+ }
+ sb.append(quote(o.toString()));
+ sb.append(": ");
+ sb.append(valueToString(this.map.get(o), indentFactor,
+ newindent));
+ }
+ if (sb.length() > 1) {
+ sb.append('\n');
+ for (j = 0; j < indent; j += 1) {
+ sb.append(' ');
+ }
+ }
+ }
+ sb.append('}');
+ return sb.toString();
+ }
+
+
+ /**
+ * Make a JSON text of an Object value. If the object has an
+ * value.toJSONString() method, then that method will be used to produce
+ * the JSON text. The method is required to produce a strictly
+ * conforming text. If the object does not contain a toJSONString
+ * method (which is the most common case), then a text will be
+ * produced by other means. If the value is an array or Collection,
+ * then a JSONArray will be made from it and its toJSONString method
+ * will be called. If the value is a MAP, then a JSONObject will be made
+ * from it and its toJSONString method will be called. Otherwise, the
+ * value's toString method will be called, and the result will be quoted.
+ *
+ * <p>
+ * Warning: This method assumes that the data structure is acyclical.
+ * @param value The value to be serialized.
+ * @return a printable, displayable, transmittable
+ * representation of the object, beginning
+ * with <code>{</code> <small>(left brace)</small> and ending
+ * with <code>}</code> <small>(right brace)</small>.
+ * @throws JSONException If the value is or contains an invalid number.
+ */
+ static String valueToString(Object value) throws JSONException {
+ if (value == null || value.equals(null)) {
+ return "null";
+ }
+ if (value instanceof JSONString) {
+ Object o;
+ try {
+ o = ((JSONString)value).toJSONString();
+ } catch (Exception e) {
+ throw new JSONException(e);
+ }
+ if (o instanceof String) {
+ return (String)o;
+ }
+ throw new JSONException("Bad value from toJSONString: " + o);
+ }
+ if (value instanceof Number) {
+ return numberToString((Number) value);
+ }
+ if (value instanceof Boolean || value instanceof JSONObject ||
+ value instanceof JSONArray) {
+ return value.toString();
+ }
+ if (value instanceof Map) {
+ return new JSONObject((Map)value).toString();
+ }
+ if (value instanceof Collection) {
+ return new JSONArray((Collection)value).toString();
+ }
+ if (value.getClass().isArray()) {
+ return new JSONArray(value).toString();
+ }
+ return quote(value.toString());
+ }
+
+
+ /**
+ * Make a prettyprinted JSON text of an object value.
+ * <p>
+ * Warning: This method assumes that the data structure is acyclical.
+ * @param value The value to be serialized.
+ * @param indentFactor The number of spaces to add to each level of
+ * indentation.
+ * @param indent The indentation of the top level.
+ * @return a printable, displayable, transmittable
+ * representation of the object, beginning
+ * with <code>{</code> <small>(left brace)</small> and ending
+ * with <code>}</code> <small>(right brace)</small>.
+ * @throws JSONException If the object contains an invalid number.
+ */
+ static String valueToString(Object value, int indentFactor, int indent)
+ throws JSONException {
+ if (value == null || value.equals(null)) {
+ return "null";
+ }
+ try {
+ if (value instanceof JSONString) {
+ Object o = ((JSONString)value).toJSONString();
+ if (o instanceof String) {
+ return (String)o;
+ }
+ }
+ } catch (Exception ignore) {
+ }
+ if (value instanceof Number) {
+ return numberToString((Number) value);
+ }
+ if (value instanceof Boolean) {
+ return value.toString();
+ }
+ if (value instanceof JSONObject) {
+ return ((JSONObject)value).toString(indentFactor, indent);
+ }
+ if (value instanceof JSONArray) {
+ return ((JSONArray)value).toString(indentFactor, indent);
+ }
+ if (value instanceof Map) {
+ return new JSONObject((Map)value).toString(indentFactor, indent);
+ }
+ if (value instanceof Collection) {
+ return new JSONArray((Collection)value).toString(indentFactor, indent);
+ }
+ if (value.getClass().isArray()) {
+ return new JSONArray(value).toString(indentFactor, indent);
+ }
+ return quote(value.toString());
+ }
+
+
+ /**
+ * Wrap an object, if necessary. If the object is null, return the NULL
+ * object. If it is an array or collection, wrap it in a JSONArray. If
+ * it is a map, wrap it in a JSONObject. If it is a standard property
+ * (Double, String, et al) then it is already wrapped. Otherwise, if it
+ * comes from one of the java packages, turn it into a string. And if
+ * it doesn't, try to wrap it in a JSONObject. If the wrapping fails,
+ * then null is returned.
+ *
+ * @param object The object to wrap
+ * @return The wrapped value
+ */
+ static Object wrap(Object object) {
+ try {
+ if (object == null) {
+ return NULL;
+ }
+ if (object instanceof JSONObject || object instanceof JSONArray ||
+ NULL.equals(object) || object instanceof JSONString ||
+ object instanceof Byte || object instanceof Character ||
+ object instanceof Short || object instanceof Integer ||
+ object instanceof Long || object instanceof Boolean ||
+ object instanceof Float || object instanceof Double ||
+ object instanceof String) {
+ return object;
+ }
+
+ if (object instanceof Collection) {
+ return new JSONArray((Collection)object);
+ }
+ if (object.getClass().isArray()) {
+ return new JSONArray(object);
+ }
+ if (object instanceof Map) {
+ return new JSONObject((Map)object);
+ }
+ Package objectPackage = object.getClass().getPackage();
+ String objectPackageName = ( objectPackage != null ? objectPackage.getName() : "" );
+ if (objectPackageName.startsWith("java.") ||
+ objectPackageName.startsWith("javax.") ||
+ object.getClass().getClassLoader() == null) {
+ return object.toString();
+ }
+ return new JSONObject(object);
+ } catch(Exception exception) {
+ return null;
+ }
+ }
+
+
+ /**
+ * Write the contents of the JSONObject as JSON text to a writer.
+ * For compactness, no whitespace is added.
+ * <p>
+ * Warning: This method assumes that the data structure is acyclical.
+ *
+ * @return The writer.
+ * @throws JSONException
+ */
+ public Writer write(Writer writer) throws JSONException {
+ try {
+ boolean b = false;
+ Iterator keys = keys();
+ writer.write('{');
+
+ while (keys.hasNext()) {
+ if (b) {
+ writer.write(',');
+ }
+ Object k = keys.next();
+ writer.write(quote(k.toString()));
+ writer.write(':');
+ Object v = this.map.get(k);
+ if (v instanceof JSONObject) {
+ ((JSONObject)v).write(writer);
+ } else if (v instanceof JSONArray) {
+ ((JSONArray)v).write(writer);
+ } else {
+ writer.write(valueToString(v));
+ }
+ b = true;
+ }
+ writer.write('}');
+ return writer;
+ } catch (IOException exception) {
+ throw new JSONException(exception);
+ }
+ }
+}
\ No newline at end of file
diff --git a/livegps/src/org/json/JSONString.java b/livegps/src/org/json/JSONString.java
new file mode 100644
index 0000000..17f4384
--- /dev/null
+++ b/livegps/src/org/json/JSONString.java
@@ -0,0 +1,18 @@
+package org.json;
+/**
+ * The <code>JSONString</code> interface allows a <code>toJSONString()</code>
+ * method so that a class can change the behavior of
+ * <code>JSONObject.toString()</code>, <code>JSONArray.toString()</code>,
+ * and <code>JSONWriter.value(</code>Object<code>)</code>. The
+ * <code>toJSONString</code> method will be used instead of the default behavior
+ * of using the Object's <code>toString()</code> method and quoting the result.
+ */
+public interface JSONString {
+ /**
+ * The <code>toJSONString</code> method allows a class to produce its own JSON
+ * serialization.
+ *
+ * @return A strictly syntactically correct JSON text.
+ */
+ public String toJSONString();
+}
diff --git a/livegps/src/org/json/JSONTokener.java b/livegps/src/org/json/JSONTokener.java
new file mode 100644
index 0000000..fe52f31
--- /dev/null
+++ b/livegps/src/org/json/JSONTokener.java
@@ -0,0 +1,435 @@
+package org.json;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+
+/*
+Copyright (c) 2002 JSON.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+The Software shall be used for Good, not Evil.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+/**
+ * A JSONTokener takes a source string and extracts characters and tokens from
+ * it. It is used by the JSONObject and JSONArray constructors to parse
+ * JSON source strings.
+ * @author JSON.org
+ * @version 2010-02-02
+ */
+public class JSONTokener {
+
+ private int character;
+ private boolean eof;
+ private int index;
+ private int line;
+ private char previous;
+ private Reader reader;
+ private boolean usePrevious;
+
+
+ /**
+ * Construct a JSONTokener from a reader.
+ *
+ * @param reader A reader.
+ */
+ public JSONTokener(Reader reader) {
+ this.reader = reader.markSupported() ?
+ reader : new BufferedReader(reader);
+ this.eof = false;
+ this.usePrevious = false;
+ this.previous = 0;
+ this.index = 0;
+ this.character = 1;
+ this.line = 1;
+ }
+
+
+ /**
+ * Construct a JSONTokener from a string.
+ *
+ * @param s A source string.
+ */
+ public JSONTokener(String s) {
+ this(new StringReader(s));
+ }
+
+
+ /**
+ * Back up one character. This provides a sort of lookahead capability,
+ * so that you can test for a digit or letter before attempting to parse
+ * the next number or identifier.
+ */
+ public void back() throws JSONException {
+ if (usePrevious || index <= 0) {
+ throw new JSONException("Stepping back two steps is not supported");
+ }
+ this.index -= 1;
+ this.character -= 1;
+ this.usePrevious = true;
+ this.eof = false;
+ }
+
+
+ /**
+ * Get the hex value of a character (base16).
+ * @param c A character between '0' and '9' or between 'A' and 'F' or
+ * between 'a' and 'f'.
+ * @return An int between 0 and 15, or -1 if c was not a hex digit.
+ */
+ public static int dehexchar(char c) {
+ if (c >= '0' && c <= '9') {
+ return c - '0';
+ }
+ if (c >= 'A' && c <= 'F') {
+ return c - ('A' - 10);
+ }
+ if (c >= 'a' && c <= 'f') {
+ return c - ('a' - 10);
+ }
+ return -1;
+ }
+
+ public boolean end() {
+ return eof && !usePrevious;
+ }
+
+
+ /**
+ * Determine if the source string still contains characters that next()
+ * can consume.
+ * @return true if not yet at the end of the source.
+ */
+ public boolean more() throws JSONException {
+ next();
+ if (end()) {
+ return false;
+ }
+ back();
+ return true;
+ }
+
+
+ /**
+ * Get the next character in the source string.
+ *
+ * @return The next character, or 0 if past the end of the source string.
+ */
+ public char next() throws JSONException {
+ int c;
+ if (this.usePrevious) {
+ this.usePrevious = false;
+ c = this.previous;
+ } else {
+ try {
+ c = this.reader.read();
+ } catch (IOException exception) {
+ throw new JSONException(exception);
+ }
+
+ if (c <= 0) { // End of stream
+ this.eof = true;
+ c = 0;
+ }
+ }
+ this.index += 1;
+ if (this.previous == '\r') {
+ this.line += 1;
+ this.character = c == '\n' ? 0 : 1;
+ } else if (c == '\n') {
+ this.line += 1;
+ this.character = 0;
+ } else {
+ this.character += 1;
+ }
+ this.previous = (char) c;
+ return this.previous;
+ }
+
+
+ /**
+ * Consume the next character, and check that it matches a specified
+ * character.
+ * @param c The character to match.
+ * @return The character.
+ * @throws JSONException if the character does not match.
+ */
+ public char next(char c) throws JSONException {
+ char n = next();
+ if (n != c) {
+ throw syntaxError("Expected '" + c + "' and instead saw '" +
+ n + "'");
+ }
+ return n;
+ }
+
+
+ /**
+ * Get the next n characters.
+ *
+ * @param n The number of characters to take.
+ * @return A string of n characters.
+ * @throws JSONException
+ * Substring bounds error if there are not
+ * n characters remaining in the source string.
+ */
+ public String next(int n) throws JSONException {
+ if (n == 0) {
+ return "";
+ }
+
+ char[] buffer = new char[n];
+ int pos = 0;
+
+ while (pos < n) {
+ buffer[pos] = next();
+ if (end()) {
+ throw syntaxError("Substring bounds error");
+ }
+ pos += 1;
+ }
+ return new String(buffer);
+ }
+
+
+ /**
+ * Get the next char in the string, skipping whitespace.
+ * @throws JSONException
+ * @return A character, or 0 if there are no more characters.
+ */
+ public char nextClean() throws JSONException {
+ for (;;) {
+ char c = next();
+ if (c == 0 || c > ' ') {
+ return c;
+ }
+ }
+ }
+
+
+ /**
+ * Return the characters up to the next close quote character.
+ * Backslash processing is done. The formal JSON format does not
+ * allow strings in single quotes, but an implementation is allowed to
+ * accept them.
+ * @param quote The quoting character, either
+ * <code>"</code> <small>(double quote)</small> or
+ * <code>'</code> <small>(single quote)</small>.
+ * @return A String.
+ * @throws JSONException Unterminated string.
+ */
+ public String nextString(char quote) throws JSONException {
+ char c;
+ StringBuffer sb = new StringBuffer();
+ for (;;) {
+ c = next();
+ switch (c) {
+ case 0:
+ case '\n':
+ case '\r':
+ throw syntaxError("Unterminated string");
+ case '\\':
+ c = next();
+ switch (c) {
+ case 'b':
+ sb.append('\b');
+ break;
+ case 't':
+ sb.append('\t');
+ break;
+ case 'n':
+ sb.append('\n');
+ break;
+ case 'f':
+ sb.append('\f');
+ break;
+ case 'r':
+ sb.append('\r');
+ break;
+ case 'u':
+ sb.append((char)Integer.parseInt(next(4), 16));
+ break;
+ case '"':
+ case '\'':
+ case '\\':
+ case '/':
+ sb.append(c);
+ break;
+ default:
+ throw syntaxError("Illegal escape.");
+ }
+ break;
+ default:
+ if (c == quote) {
+ return sb.toString();
+ }
+ sb.append(c);
+ }
+ }
+ }
+
+
+ /**
+ * Get the text up but not including the specified character or the
+ * end of line, whichever comes first.
+ * @param d A delimiter character.
+ * @return A string.
+ */
+ public String nextTo(char d) throws JSONException {
+ StringBuffer sb = new StringBuffer();
+ for (;;) {
+ char c = next();
+ if (c == d || c == 0 || c == '\n' || c == '\r') {
+ if (c != 0) {
+ back();
+ }
+ return sb.toString().trim();
+ }
+ sb.append(c);
+ }
+ }
+
+
+ /**
+ * Get the text up but not including one of the specified delimiter
+ * characters or the end of line, whichever comes first.
+ * @param delimiters A set of delimiter characters.
+ * @return A string, trimmed.
+ */
+ public String nextTo(String delimiters) throws JSONException {
+ char c;
+ StringBuffer sb = new StringBuffer();
+ for (;;) {
+ c = next();
+ if (delimiters.indexOf(c) >= 0 || c == 0 ||
+ c == '\n' || c == '\r') {
+ if (c != 0) {
+ back();
+ }
+ return sb.toString().trim();
+ }
+ sb.append(c);
+ }
+ }
+
+
+ /**
+ * Get the next value. The value can be a Boolean, Double, Integer,
+ * JSONArray, JSONObject, Long, or String, or the JSONObject.NULL object.
+ * @throws JSONException If syntax error.
+ *
+ * @return An object.
+ */
+ public Object nextValue() throws JSONException {
+ char c = nextClean();
+ String s;
+
+ switch (c) {
+ case '"':
+ case '\'':
+ return nextString(c);
+ case '{':
+ back();
+ return new JSONObject(this);
+ case '[':
+ case '(':
+ back();
+ return new JSONArray(this);
+ }
+
+ /*
+ * Handle unquoted text. This could be the values true, false, or
+ * null, or it can be a number. An implementation (such as this one)
+ * is allowed to also accept non-standard forms.
+ *
+ * Accumulate characters until we reach the end of the text or a
+ * formatting character.
+ */
+
+ StringBuffer sb = new StringBuffer();
+ while (c >= ' ' && ",:]}/\\\"[{;=#".indexOf(c) < 0) {
+ sb.append(c);
+ c = next();
+ }
+ back();
+
+ s = sb.toString().trim();
+ if (s.equals("")) {
+ throw syntaxError("Missing value");
+ }
+ return JSONObject.stringToValue(s);
+ }
+
+
+ /**
+ * Skip characters until the next character is the requested character.
+ * If the requested character is not found, no characters are skipped.
+ * @param to A character to skip to.
+ * @return The requested character, or zero if the requested character
+ * is not found.
+ */
+ public char skipTo(char to) throws JSONException {
+ char c;
+ try {
+ int startIndex = this.index;
+ int startCharacter = this.character;
+ int startLine = this.line;
+ reader.mark(Integer.MAX_VALUE);
+ do {
+ c = next();
+ if (c == 0) {
+ reader.reset();
+ this.index = startIndex;
+ this.character = startCharacter;
+ this.line = startLine;
+ return c;
+ }
+ } while (c != to);
+ } catch (IOException exc) {
+ throw new JSONException(exc);
+ }
+
+ back();
+ return c;
+ }
+
+
+ /**
+ * Make a JSONException to signal a syntax error.
+ *
+ * @param message The error message.
+ * @return A JSONException object, suitable for throwing
+ */
+ public JSONException syntaxError(String message) {
+ return new JSONException(message + toString());
+ }
+
+
+ /**
+ * Make a printable string of this JSONTokener.
+ *
+ * @return " at {index} [character {character} line {line}]"
+ */
+ public String toString() {
+ return " at " + index + " [character " + this.character + " line " + this.line + "]";
+ }
+}
\ No newline at end of file
diff --git a/measurement/src/org/openstreetmap/josm/plugins/measurement/MeasurementDialog.java b/measurement/src/org/openstreetmap/josm/plugins/measurement/MeasurementDialog.java
index 3bb7a1a..288d4ee 100644
--- a/measurement/src/org/openstreetmap/josm/plugins/measurement/MeasurementDialog.java
+++ b/measurement/src/org/openstreetmap/josm/plugins/measurement/MeasurementDialog.java
@@ -102,44 +102,42 @@ public class MeasurementDialog extends ToggleDialog implements ActionListener
this.setPreferredSize(new Dimension(0, 92));
final MeasurementDialog dlg = this;
- //TODO: is this enough?
-
- DataSet.selListeners.add(new SelectionChangedListener(){
+ DataSet.selListeners.add(new SelectionChangedListener() {
public void selectionChanged(Collection<? extends OsmPrimitive> arg0) {
double length = 0.0;
double segAngle = 0.0;
- double area = 0.0;
- Node lastNode = null;
- for(OsmPrimitive p:arg0){
- // ignore incomplete nodes
- if(p instanceof Node && !((Node)p).isIncomplete()){
- Node n =(Node)p;
- if(lastNode == null){
- lastNode = n;
- }else{
- length += MeasurementLayer.calcDistance(lastNode.getCoor(), n.getCoor());
- segAngle = MeasurementLayer.angleBetween(lastNode.getCoor(), n.getCoor());
- lastNode = n;
- }
- } else if(p instanceof Way){
- Way w = (Way)p;
- Node lastN = null;
- for(Node n: w.getNodes()){
- if(lastN != null){
- length += MeasurementLayer.calcDistance(lastN.getCoor(), n.getCoor());
- //http://local.wasp.uwa.edu.au/~pbourke/geometry/polyarea/
- area += (MeasurementLayer.calcX(n.getCoor()) * MeasurementLayer.calcY(lastN.getCoor()))
- - (MeasurementLayer.calcY(n.getCoor()) * MeasurementLayer.calcX(lastN.getCoor()));
- }
- lastN = n;
- }
- if (lastN != null && lastN == w.getNodes().iterator().next()){
- area = Math.abs(area / 2);
- }else{
- area = 0;
- }
- }
+ double area = 0.0;
+ Node lastNode = null;
+ for(OsmPrimitive p:arg0) {
+ // ignore incomplete nodes
+ if(p instanceof Node && !((Node)p).isIncomplete()) {
+ Node n =(Node)p;
+ if(lastNode == null) {
+ lastNode = n;
+ } else {
+ length += MeasurementLayer.calcDistance(lastNode.getCoor(), n.getCoor());
+ segAngle = MeasurementLayer.angleBetween(lastNode.getCoor(), n.getCoor());
+ lastNode = n;
+ }
+ } else if(p instanceof Way) {
+ Way w = (Way)p;
+ Node lastN = null;
+ for(Node n: w.getNodes()) {
+ if(lastN != null) {
+ length += MeasurementLayer.calcDistance(lastN.getCoor(), n.getCoor());
+ //http://local.wasp.uwa.edu.au/~pbourke/geometry/polyarea/
+ area += (MeasurementLayer.calcX(n.getCoor()) * MeasurementLayer.calcY(lastN.getCoor()))
+ - (MeasurementLayer.calcY(n.getCoor()) * MeasurementLayer.calcX(lastN.getCoor()));
+ segAngle = MeasurementLayer.angleBetween(lastN.getCoor(), n.getCoor());
+ }
+ lastN = n;
+ }
+ if (lastN != null && lastN == w.getNodes().iterator().next())
+ area = Math.abs(area / 2);
+ else
+ area = 0;
+ }
}
dlg.selectLengthLabel.setText(new DecimalFormat("#0.00").format(length) + " m");
@@ -163,5 +161,4 @@ public class MeasurementDialog extends ToggleDialog implements ActionListener
public void resetValues(){
MeasurementPlugin.getCurrentLayer().reset();
}
-
}
diff --git a/slippymap/src/org/openstreetmap/josm/plugins/slippymap/SlippyMapLayer.java b/slippymap/src/org/openstreetmap/josm/plugins/slippymap/SlippyMapLayer.java
index bbd0fd6..fc59189 100644
--- a/slippymap/src/org/openstreetmap/josm/plugins/slippymap/SlippyMapLayer.java
+++ b/slippymap/src/org/openstreetmap/josm/plugins/slippymap/SlippyMapLayer.java
@@ -89,7 +89,7 @@ public class SlippyMapLayer extends Layer implements PreferenceChangedListener,
if (debug)
out("clearing tile storage");
tileCache = new MemoryTileCache();
- tileCache.setCacheSize(2000);
+ tileCache.setCacheSize(200);
}
/**
@@ -801,8 +801,11 @@ public class SlippyMapLayer extends Layer implements PreferenceChangedListener,
}
}
+ boolean az_disable = false;
boolean autoZoomEnabled()
{
+ if (az_disable)
+ return false;
return autoZoomPopup.isSelected();
}
/**
@@ -851,8 +854,21 @@ public class SlippyMapLayer extends Layer implements PreferenceChangedListener,
if (debug)
out("too zoomed in, (" + ts.tilesSpanned()
+ "), increasing zoom from " + currentZoomLevel);
+ // This is a hack. ts.tooSmall() is proabably a bad thing, and this works
+ // around it. If we have a very small window, the tileSet may be well
+ // less than 1 real tile wide, but that's expected. But, this sees the
+ // tile set as too small and zooms in. The code below that checks for
+ // pixel stretching disagrees and tries to zoom out. Both calls recurse,
+ // hillarity ensues, and the stack overflows.
+ //
+ // This really needs to get fixed properly. We probably shouldn't even
+ // have the tooSmall() check on tileSets. But, this also helps the zoom
+ // converge to the correct place much faster.
+ boolean tmp = az_disable;
+ az_disable = true;
if (increaseZoomLevel())
this.paint(oldg, mv, bounds);
+ az_disable = tmp;
return;
}
}
diff --git a/svn-info.xml b/svn-info.xml
index 5fb6705..1d5a2a8 100644
--- a/svn-info.xml
+++ b/svn-info.xml
@@ -3,16 +3,16 @@
<entry
kind="dir"
path="plugins"
- revision="21271">
+ revision="21666">
<url>http://svn.openstreetmap.org/applications/editors/josm/plugins</url>
<repository>
<root>http://svn.openstreetmap.org</root>
<uuid>b9d5c4c9-76e1-0310-9c85-f3177eceb1e4</uuid>
</repository>
<commit
- revision="21258">
-<author>guardian</author>
-<date>2010-05-13T11:33:01.904594Z</date>
+ revision="21666">
+<author>bastik</author>
+<date>2010-06-12T07:13:56.296435Z</date>
</commit>
</entry>
</info>
diff --git a/wmsplugin/sources.cfg b/wmsplugin/sources.cfg
index e832913..89837de 100644
--- a/wmsplugin/sources.cfg
+++ b/wmsplugin/sources.cfg
@@ -44,7 +44,7 @@ false;MLIT Japan (ORTHO03);http://orthophoto.mlit.go.jp:8888/wms/service/wmsRast
#
# only for Italy
false;Lodi - Italy;http://sit.provincia.lodi.it/mapserver/mapserv.exe?map=ortofoto_wgs84.map&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&SRS=EPSG:4326&LAYERS=Terraitaly%20Ortofoto%202007&STYLES=%2C%2C&FORMAT=image/png&TRANSPARENT=TRUE&
-false;Sicily - Italy;http://88.53.214.52/arcgis/services/OrtofotoATA_20072008_f33/MapServer/WMSServer?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&CRS=CRS:84&LAYERS=0&STYLES=default&FORMAT=image/jpeg&
+false;Sicily - Italy;http://88.53.214.52/arcgis/services/WGS84_F33/OrtofotoATA_20072008_f33/MapServer/WMSServer?LAYERS=0&REQUEST=GetMap&VERSION=1.1.1&FORMAT=image%2Fpng&STYLES=&
#
#
# URLS must be designed to append arguments directly behind. So the URLS should either end with '?' or '&'
diff --git a/wmsplugin/src/wmsplugin/WMSLayer.java b/wmsplugin/src/wmsplugin/WMSLayer.java
index b691ad7..cd6fe54 100644
--- a/wmsplugin/src/wmsplugin/WMSLayer.java
+++ b/wmsplugin/src/wmsplugin/WMSLayer.java
@@ -471,7 +471,7 @@ public class WMSLayer extends Layer {
baseName = getName();
}
Main.pref.put("wmsplugin.url."+ i +".url",baseURL );
- Main.pref.put("wmsplugin.url."+String.valueOf(i)+".name", baseName + "#PPD=" + getPPD() );
+ Main.pref.put("wmsplugin.url."+String.valueOf(i)+".name", baseName + "#PPD=" + pixelPerDegree );
WMSPlugin.refreshMenu();
}
}
diff --git a/wmsplugin/webkit-image-gtk.c b/wmsplugin/webkit-image-gtk.c
index af81e5d..cbefbe0 100644
--- a/wmsplugin/webkit-image-gtk.c
+++ b/wmsplugin/webkit-image-gtk.c
@@ -1,37 +1,36 @@
/* There is no licence for this, I don't care what you do with it */
-#include <stdio.h>
#include <stdlib.h>
+#include <unistd.h>
+#include <gio/gunixoutputstream.h>
#include <webkit/webkit.h>
#define WIDTH 2000
/* compile with:
-gcc -o webkit-image-gtk webkit-image-gtk.c `pkg-config --cflags --libs webkit-1.0`
-*/
+ * gcc -o webkit-image-gtk webkit-image-gtk.c `pkg-config --cflags --libs webkit-1.0 gio-unix-2.0`
+ * Requires GTK+ 2.20 and WebKitGtk+ 1.1.1
+ */
static void
-on_finished (WebKitWebView *view, WebKitWebFrame *frame)
+on_finished (WebKitWebView *view,
+ WebKitWebFrame *frame,
+ GtkOffscreenWindow *window)
{
- GdkPixmap *pixmap;
- GdkColormap *cmap;
GdkPixbuf *pixbuf;
- gchar *buffer;
- gsize size;
+ GOutputStream *stream;
- pixmap = gtk_widget_get_snapshot (GTK_WIDGET (view), NULL);
- cmap = gdk_colormap_get_system ();
- pixbuf = gdk_pixbuf_get_from_drawable (NULL, GDK_DRAWABLE (pixmap), cmap,
- 0, 0, 0, 0, WIDTH, WIDTH);
+ pixbuf = gtk_offscreen_window_get_pixbuf (window);
- gdk_pixbuf_save_to_buffer (pixbuf, &buffer, &size, "png", NULL, NULL);
-
- fwrite (buffer, 1, size, stdout);
+ stream = g_unix_output_stream_new (STDOUT_FILENO, TRUE);
+ gdk_pixbuf_save_to_stream (pixbuf, stream, "png", NULL, NULL, NULL);
exit (1);
}
-int main (int argc, char **argv)
+int
+main (int argc,
+ char **argv)
{
GtkWidget *window;
GtkWidget *view;
@@ -41,23 +40,17 @@ int main (int argc, char **argv)
gtk_init (&argc, &argv);
- window = gtk_window_new (GTK_WINDOW_POPUP);
-
- /* Check if compositing window manager is running, needs one for now */
- if (gtk_widget_is_composited (window))
- gtk_window_set_opacity (GTK_WINDOW (window), 0.0);
- else
- g_error ("This requires a compositing window manager for now");
+ window = gtk_offscreen_window_new ();
view = webkit_web_view_new ();
- webkit_web_view_open (WEBKIT_WEB_VIEW (view), argv[1]);
+ webkit_web_view_load_uri (WEBKIT_WEB_VIEW (view), argv[1]);
gtk_widget_set_size_request (view, WIDTH, WIDTH);
gtk_container_add (GTK_CONTAINER (window), view);
gtk_widget_show_all (window);
- g_signal_connect (G_OBJECT (view), "load-finished",
- G_CALLBACK (on_finished), NULL);
+ g_signal_connect (view, "load-finished",
+ G_CALLBACK (on_finished), window);
gtk_main ();
return 0;
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/josm-plugins.git
More information about the Pkg-grass-devel
mailing list