X-Git-Url: http://gitweb.fperrin.net/?a=blobdiff_plain;f=tim%2Fprune%2Fsave%2FGpxExporter.java;h=8203593b0d6d72387293df350e1366a8ddf097ae;hb=3745d70b1427bb8ac1a085e47cbdc566936784e1;hp=019cc438bdbf96003595e7c7ebe7d84654839d11;hpb=1ee49ae3c8ef3aa2e63eadd458531e5f8bd4f92c;p=GpsPrune.git diff --git a/tim/prune/save/GpxExporter.java b/tim/prune/save/GpxExporter.java index 019cc43..8203593 100644 --- a/tim/prune/save/GpxExporter.java +++ b/tim/prune/save/GpxExporter.java @@ -6,11 +6,14 @@ import java.awt.FlowLayout; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Writer; +import java.nio.charset.Charset; import javax.swing.BorderFactory; import javax.swing.Box; @@ -38,6 +41,8 @@ import tim.prune.data.Field; import tim.prune.data.Timestamp; import tim.prune.data.TrackInfo; import tim.prune.load.GenericFileFilter; +import tim.prune.save.xml.GpxCacherList; + /** * Class to export track information @@ -127,6 +132,14 @@ public class GpxExporter extends GenericFunction implements Runnable mainPanel.add(checkPanel); dialogPanel.add(mainPanel, BorderLayout.CENTER); + // close dialog if escape pressed + _nameField.addKeyListener(new KeyAdapter() { + public void keyReleased(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { + _dialog.dispose(); + } + } + }); // button panel at bottom JPanel buttonPanel = new JPanel(); buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT)); @@ -142,8 +155,7 @@ public class GpxExporter extends GenericFunction implements Runnable buttonPanel.add(okButton); JButton cancelButton = new JButton(I18nManager.getText("button.cancel")); cancelButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) - { + public void actionPerformed(ActionEvent e) { _dialog.dispose(); } }); @@ -288,8 +300,9 @@ public class GpxExporter extends GenericFunction implements Runnable // Instantiate source file cachers in case we want to copy output GpxCacherList gpxCachers = null; if (inUseCopy) gpxCachers = new GpxCacherList(inInfo.getFileInfo()); - // Write or copy header - inWriter.write(getHeaderString(gpxCachers)); + // Write or copy headers + inWriter.write(getXmlHeaderString(inWriter)); + inWriter.write(getGpxHeaderString(gpxCachers)); // Name field String trackName = "PruneTrack"; if (inName != null && !inName.equals("")) @@ -301,12 +314,7 @@ public class GpxExporter extends GenericFunction implements Runnable } // Description field inWriter.write("\t"); - if (inDesc != null && !inDesc.equals("")) { - inWriter.write(inDesc); - } - else { - inWriter.write("Export from Prune"); - } + inWriter.write((inDesc != null && !inDesc.equals(""))?inDesc:"Export from Prune"); inWriter.write("\n"); int i = 0; @@ -334,7 +342,7 @@ public class GpxExporter extends GenericFunction implements Runnable if (point.isWaypoint()) { if (exportWaypoints) { - String pointSource = (inUseCopy?gpxCachers.getSourceString(point):null); + String pointSource = (inUseCopy?getPointSource(gpxCachers, point):null); if (pointSource != null) { inWriter.write(pointSource); inWriter.write('\n'); @@ -404,7 +412,7 @@ public class GpxExporter extends GenericFunction implements Runnable if ((point.getPhoto()==null && inExportTrackpoints) || (point.getPhoto()!=null && inExportPhotos)) { // get the source from the point (if any) - String pointSource = (inCachers!=null?inCachers.getSourceString(point):null); + String pointSource = getPointSource(inCachers, point); boolean writePoint = (pointSource != null && pointSource.toLowerCase().startsWith(inPointTag)) || (pointSource == null && !inOnlyCopies); if (writePoint) @@ -430,12 +438,83 @@ public class GpxExporter extends GenericFunction implements Runnable return numSaved; } + + /** + * Get the point source for the specified point + * @param inCachers list of GPX cachers to ask for source + * @param inPoint point object + * @return xml source if available, or null otherwise + */ + private static String getPointSource(GpxCacherList inCachers, DataPoint inPoint) + { + if (inCachers == null || inPoint == null) {return null;} + String source = inCachers.getSourceString(inPoint); + if (source == null || !inPoint.isModified()) {return source;} + // Point has been modified - maybe it's possible to modify the source + source = replaceGpxTags(source, "lat=\"", "\"", inPoint.getLatitude().output(Coordinate.FORMAT_DECIMAL_FORCE_POINT)); + source = replaceGpxTags(source, "lon=\"", "\"", inPoint.getLongitude().output(Coordinate.FORMAT_DECIMAL_FORCE_POINT)); + source = replaceGpxTags(source, "", "", inPoint.getAltitude().getStringValue(Altitude.Format.METRES)); + source = replaceGpxTags(source, "", inPoint.getTimestamp().getText(Timestamp.FORMAT_ISO_8601)); + if (inPoint.isWaypoint()) {source = replaceGpxTags(source, "", "", inPoint.getWaypointName());} // only for waypoints + return source; + } + + /** + * Replace the given value into the given XML string + * @param inSource source XML for point + * @param inStartTag start tag for field + * @param inEndTag end tag for field + * @param inValue value to replace between start tag and end tag + * @return modified String, or null if not possible + */ + private static String replaceGpxTags(String inSource, String inStartTag, String inEndTag, String inValue) + { + if (inSource == null) {return null;} + // Look for start and end tags within source + final int startPos = inSource.indexOf(inStartTag); + final int endPos = inSource.indexOf(inEndTag, startPos+inStartTag.length()); + if (startPos > 0 && endPos > 0) + { + String origValue = inSource.substring(startPos + inStartTag.length(), endPos); + if (inValue != null && origValue.equals(inValue)) { + // Value unchanged + return inSource; + } + else if (inValue == null || inValue.equals("")) { + // Need to delete value + return inSource.substring(0, startPos) + inSource.substring(endPos + inEndTag.length()); + } + else { + // Need to replace value + return inSource.substring(0, startPos+inStartTag.length()) + inValue + inSource.substring(endPos); + } + } + // Value not found for this field in original source + if (inValue == null || inValue.equals("")) {return inSource;} + return null; + } + + /** + * Get the header string for the xml document including encoding + * @param inWriter writer object + * @return header string defining encoding + */ + private static String getXmlHeaderString(OutputStreamWriter inWriter) + { + String encoding = inWriter.getEncoding(); + try { + encoding = Charset.forName(encoding).name(); + } + catch (Exception e) {} // ignore failure to find encoding + return "\n"; + } + /** - * Get the header string for the gpx + * Get the header string for the gpx tag * @param inCachers cacher list to ask for headers, if available * @return header string from cachers or as default */ - private static String getHeaderString(GpxCacherList inCachers) + private static String getGpxHeaderString(GpxCacherList inCachers) { String gpxHeader = null; if (inCachers != null) {gpxHeader = inCachers.getFirstHeader();} @@ -447,7 +526,7 @@ public class GpxExporter extends GenericFunction implements Runnable + " xmlns=\"http://www.topografix.com/GPX/1/0\"" + " xsi:schemaLocation=\"http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd\">\n"; } - return "\n" + gpxHeader + "\n"; + return gpxHeader + "\n"; } /**