From d3679d647d57c2ee7376ddbf6def2d5b23c04307 Mon Sep 17 00:00:00 2001
From: activityworkshop
Date: Sat, 14 Feb 2015 14:38:26 +0100
Subject: [PATCH] Version 2, March 2007
---
tim/prune/App.java | 193 +++++++++++++++++++-
tim/prune/DataSubscriber.java | 10 +-
tim/prune/GpsPruner.java | 5 +-
tim/prune/UpdateMessageBroker.java | 12 +-
tim/prune/data/Altitude.java | 1 +
tim/prune/data/AltitudeRange.java | 10 +
tim/prune/data/Coordinate.java | 22 ++-
tim/prune/data/DataPoint.java | 164 +++++++++++++++--
tim/prune/data/Distance.java | 2 -
tim/prune/data/DoubleRange.java | 10 +
tim/prune/data/FieldList.java | 21 +++
tim/prune/data/IntegerRange.java | 10 +
tim/prune/data/Latitude.java | 5 +-
tim/prune/data/Longitude.java | 5 +-
tim/prune/data/Selection.java | 28 ++-
tim/prune/data/Track.java | 100 +++++++++-
tim/prune/data/TrackInfo.java | 79 ++++++++
tim/prune/gui/AboutScreen.java | 3 +-
tim/prune/gui/DetailsDisplay.java | 133 +++++++++++++-
tim/prune/gui/GenericChart.java | 2 +-
tim/prune/gui/MapChart.java | 39 ++--
tim/prune/gui/MenuManager.java | 105 ++++++-----
tim/prune/lang/prune-texts.properties | 75 +++++++-
tim/prune/lang/prune-texts_de.properties | 85 +++++++--
tim/prune/lang/prune-texts_de_CH.properties | 75 +++++++-
tim/prune/readme.txt | 16 +-
tim/prune/save/FileSaver.java | 88 +++++++--
tim/prune/save/KmlExporter.java | 66 +++++--
tim/prune/undo/UndoDeletePoint.java | 4 +-
29 files changed, 1186 insertions(+), 182 deletions(-)
diff --git a/tim/prune/App.java b/tim/prune/App.java
index a1e6a8b..4ccaed6 100644
--- a/tim/prune/App.java
+++ b/tim/prune/App.java
@@ -1,6 +1,7 @@
package tim.prune;
import java.util.EmptyStackException;
+import java.util.List;
import java.util.Stack;
import javax.swing.JFrame;
@@ -10,18 +11,28 @@ import tim.prune.data.DataPoint;
import tim.prune.data.Field;
import tim.prune.data.Track;
import tim.prune.data.TrackInfo;
+import tim.prune.edit.FieldEditList;
+import tim.prune.edit.PointEditor;
+import tim.prune.edit.PointNameEditor;
import tim.prune.gui.MenuManager;
import tim.prune.gui.UndoManager;
import tim.prune.load.FileLoader;
+import tim.prune.load.JpegLoader;
import tim.prune.save.FileSaver;
import tim.prune.save.KmlExporter;
+import tim.prune.save.PovExporter;
+import tim.prune.threedee.ThreeDException;
+import tim.prune.threedee.ThreeDWindow;
+import tim.prune.threedee.WindowFactory;
import tim.prune.undo.UndoCompress;
import tim.prune.undo.UndoDeleteDuplicates;
import tim.prune.undo.UndoDeletePoint;
import tim.prune.undo.UndoDeleteRange;
+import tim.prune.undo.UndoEditPoint;
import tim.prune.undo.UndoException;
import tim.prune.undo.UndoInsert;
import tim.prune.undo.UndoLoad;
+import tim.prune.undo.UndoLoadPhotos;
import tim.prune.undo.UndoOperation;
import tim.prune.undo.UndoRearrangeWaypoints;
import tim.prune.undo.UndoReverseSection;
@@ -39,6 +50,8 @@ public class App
private int _lastSavePosition = 0;
private MenuManager _menuManager = null;
private FileLoader _fileLoader = null;
+ private JpegLoader _jpegLoader = null;
+ private PovExporter _povExporter = null;
private Stack _undoStack = null;
private UpdateMessageBroker _broker = null;
private boolean _reversePointsConfirmed = false;
@@ -49,8 +62,6 @@ public class App
public static final int REARRANGE_TO_NEAREST = 2;
- // TODO: Make waypoint window to allow list of waypoints, edit names etc
-
/**
* Constructor
* @param inFrame frame object for application
@@ -112,6 +123,17 @@ public class App
}
+ /**
+ * Add a photo or a directory of photos which are already correlated
+ */
+ public void addPhotos()
+ {
+ if (_jpegLoader == null)
+ _jpegLoader = new JpegLoader(this, _frame);
+ _jpegLoader.openFile();
+ }
+
+
/**
* Save the file in the selected format
*/
@@ -148,6 +170,60 @@ public class App
}
+ /**
+ * Export track data as Pov without specifying settings
+ */
+ public void exportPov()
+ {
+ exportPov(false, 0.0, 0.0, 0.0, 0);
+ }
+
+ /**
+ * Export track data as Pov and also specify settings
+ * @param inX X component of unit vector
+ * @param inY Y component of unit vector
+ * @param inZ Z component of unit vector
+ * @param inAltitudeCap altitude cap
+ */
+ public void exportPov(double inX, double inY, double inZ, int inAltitudeCap)
+ {
+ exportPov(true, inX, inY, inZ, inAltitudeCap);
+ }
+
+ /**
+ * Export track data as Pov with optional angle specification
+ * @param inDefineAngles true to define angles, false to ignore
+ * @param inX X component of unit vector
+ * @param inY Y component of unit vector
+ * @param inZ Z component of unit vector
+ */
+ private void exportPov(boolean inDefineSettings, double inX, double inY, double inZ, int inAltitudeCap)
+ {
+ // Check track has data to export
+ if (_track == null || _track.getNumPoints() <= 0)
+ {
+ JOptionPane.showMessageDialog(_frame, I18nManager.getText("error.save.nodata"),
+ I18nManager.getText("error.save.dialogtitle"), JOptionPane.ERROR_MESSAGE);
+ }
+ else
+ {
+ // Make new exporter if necessary
+ if (_povExporter == null)
+ {
+ _povExporter = new PovExporter(this, _frame, _track);
+ }
+ // Specify angles if necessary
+ if (inDefineSettings)
+ {
+ _povExporter.setCameraCoordinates(inX, inY, inZ);
+ _povExporter.setAltitudeCap(inAltitudeCap);
+ }
+ // Initiate export
+ _povExporter.showDialog();
+ }
+ }
+
+
/**
* Exit the application if confirmed
*/
@@ -166,6 +242,62 @@ public class App
}
+ /**
+ * Edit the currently selected point
+ */
+ public void editCurrentPoint()
+ {
+ if (_track != null)
+ {
+ DataPoint currentPoint = _trackInfo.getCurrentPoint();
+ if (currentPoint != null)
+ {
+ // Open point dialog to display details
+ PointEditor editor = new PointEditor(this, _frame);
+ editor.showDialog(_track, currentPoint);
+ }
+ }
+ }
+
+
+ /**
+ * Complete the point edit
+ * @param inEditList list of edits
+ */
+ public void completePointEdit(FieldEditList inEditList, FieldEditList inUndoList)
+ {
+ DataPoint currentPoint = _trackInfo.getCurrentPoint();
+ if (inEditList != null && inEditList.getNumEdits() > 0 && currentPoint != null)
+ {
+ // add information to undo stack
+ UndoOperation undo = new UndoEditPoint(currentPoint, inUndoList);
+ // pass to track for completion
+ if (_track.editPoint(currentPoint, inEditList))
+ {
+ _undoStack.push(undo);
+ }
+ }
+ }
+
+
+ /**
+ * Edit the name of the currently selected (way)point
+ */
+ public void editCurrentPointName()
+ {
+ if (_track != null)
+ {
+ DataPoint currentPoint = _trackInfo.getCurrentPoint();
+ if (currentPoint != null)
+ {
+ // Open point dialog to display details
+ PointNameEditor editor = new PointNameEditor(this, _frame);
+ editor.showDialog(_track, currentPoint);
+ }
+ }
+ }
+
+
/**
* Delete the currently selected point
*/
@@ -359,9 +491,26 @@ public class App
*/
public void show3dWindow()
{
- // TODO: open 3d view window
- JOptionPane.showMessageDialog(_frame, I18nManager.getText("error.function.notimplemented"),
- I18nManager.getText("error.function.notimplemented.title"), JOptionPane.WARNING_MESSAGE);
+ ThreeDWindow window = WindowFactory.getWindow(this, _frame);
+ if (window == null)
+ {
+ JOptionPane.showMessageDialog(_frame, I18nManager.getText("error.function.nojava3d"),
+ I18nManager.getText("error.function.notavailable.title"), JOptionPane.WARNING_MESSAGE);
+ }
+ else
+ {
+ try
+ {
+ // Pass the track object and show the window
+ window.setTrack(_track);
+ window.show();
+ }
+ catch (ThreeDException e)
+ {
+ JOptionPane.showMessageDialog(_frame, I18nManager.getText("error.3d") + ": " + e.getMessage(),
+ I18nManager.getText("error.3d.title"), JOptionPane.ERROR_MESSAGE);
+ }
+ }
}
@@ -428,6 +577,40 @@ public class App
}
+ /**
+ * Accept a list of loaded photos
+ * @param inPhotoList List of Photo objects
+ */
+ public void informPhotosLoaded(List inPhotoList)
+ {
+ if (inPhotoList != null && !inPhotoList.isEmpty())
+ {
+ // TODO: Attempt to restrict loaded photos to current area (if any) ?
+ int numAdded = _trackInfo.addPhotos(inPhotoList);
+ if (numAdded > 0)
+ {
+ _undoStack.add(new UndoLoadPhotos(numAdded));
+ }
+ if (numAdded == 1)
+ {
+ JOptionPane.showMessageDialog(_frame,
+ "" + numAdded + " " + I18nManager.getText("dialog.jpegload.photoadded"),
+ I18nManager.getText("dialog.jpegload.title"), JOptionPane.INFORMATION_MESSAGE);
+ }
+ else
+ {
+ JOptionPane.showMessageDialog(_frame,
+ "" + numAdded + " " + I18nManager.getText("dialog.jpegload.photosadded"),
+ I18nManager.getText("dialog.jpegload.title"), JOptionPane.INFORMATION_MESSAGE);
+ }
+ // TODO: Improve message when photo(s) fail to load (eg already added)
+ _broker.informSubscribers();
+ // update menu
+ _menuManager.informFileLoaded();
+ }
+ }
+
+
/**
* Inform the app that the data has been saved
*/
diff --git a/tim/prune/DataSubscriber.java b/tim/prune/DataSubscriber.java
index ae6c3be..766ed53 100644
--- a/tim/prune/DataSubscriber.java
+++ b/tim/prune/DataSubscriber.java
@@ -6,9 +6,17 @@ package tim.prune;
*/
public interface DataSubscriber
{
+ public static final byte DATA_ADDED_OR_REMOVED = 1;
+ public static final byte DATA_EDITED = 2;
+ public static final byte SELECTION_CHANGED = 4;
+ public static final byte WAYPOINTS_MODIFIED = 8;
+ public static final byte PHOTOS_MODIFIED = 16;
+ public static final byte UNITS_CHANGED = 32;
+ public static final byte ALL = 63;
+
/**
* Inform clients that data has been updated
*/
- public void dataUpdated();
+ public void dataUpdated(byte inUpdateType);
}
diff --git a/tim/prune/GpsPruner.java b/tim/prune/GpsPruner.java
index f76787c..7e9476c 100644
--- a/tim/prune/GpsPruner.java
+++ b/tim/prune/GpsPruner.java
@@ -18,8 +18,9 @@ import tim.prune.gui.ProfileChart;
*/
public class GpsPruner
{
- public static final String VERSION_NUMBER = "1";
- public static final String BUILD_NUMBER = "041";
+ // Version 2, released 29 March 2007, 1 April 2007
+ public static final String VERSION_NUMBER = "2";
+ public static final String BUILD_NUMBER = "056";
private static App APP = null;
diff --git a/tim/prune/UpdateMessageBroker.java b/tim/prune/UpdateMessageBroker.java
index f2dfd2a..417d055 100644
--- a/tim/prune/UpdateMessageBroker.java
+++ b/tim/prune/UpdateMessageBroker.java
@@ -37,12 +37,22 @@ public class UpdateMessageBroker
* the data has been updated
*/
public void informSubscribers()
+ {
+ informSubscribers(DataSubscriber.ALL);
+ }
+
+
+ /**
+ * Send message to all subscribers
+ * @param inChange Change that occurred
+ */
+ public void informSubscribers(byte inChange)
{
for (int i=0; i<_subscribers.length; i++)
{
if (_subscribers[i] != null)
{
- _subscribers[i].dataUpdated();
+ _subscribers[i].dataUpdated(inChange);
}
}
}
diff --git a/tim/prune/data/Altitude.java b/tim/prune/data/Altitude.java
index 73552ae..b55a429 100644
--- a/tim/prune/data/Altitude.java
+++ b/tim/prune/data/Altitude.java
@@ -79,6 +79,7 @@ public class Altitude
*/
public int getValue(int inFormat)
{
+ // TODO: Fix rounding errors here converting between units - return double?
if (inFormat == _format)
return _value;
if (inFormat == FORMAT_METRES)
diff --git a/tim/prune/data/AltitudeRange.java b/tim/prune/data/AltitudeRange.java
index 5b606f4..6c7e5d5 100644
--- a/tim/prune/data/AltitudeRange.java
+++ b/tim/prune/data/AltitudeRange.java
@@ -10,6 +10,16 @@ public class AltitudeRange
private int _format = Altitude.FORMAT_NONE;
+ /**
+ * Clear the altitude range
+ */
+ public void clear()
+ {
+ _range.clear();
+ _format = Altitude.FORMAT_NONE;
+ }
+
+
/**
* Add a value to the range
* @param inValue value to add, only positive values considered
diff --git a/tim/prune/data/Coordinate.java b/tim/prune/data/Coordinate.java
index e297a8d..6d8de61 100644
--- a/tim/prune/data/Coordinate.java
+++ b/tim/prune/data/Coordinate.java
@@ -128,8 +128,9 @@ public abstract class Coordinate
* Constructor
* @param inValue value of coordinate
* @param inFormat format to use
+ * @param inCardinal cardinal
*/
- protected Coordinate(double inValue, int inFormat)
+ protected Coordinate(double inValue, int inFormat, int inCardinal)
{
_asDouble = inValue;
// Calculate degrees, minutes, seconds
@@ -140,10 +141,12 @@ public abstract class Coordinate
_seconds = (int) numSecs;
_fracs = (int) ((numSecs - _seconds) * 10);
// Make a string to display on screen
+ _cardinal = inCardinal;
_originalFormat = FORMAT_NONE;
if (inFormat == FORMAT_NONE) inFormat = FORMAT_DEG_WITHOUT_CARDINAL;
_originalString = output(inFormat);
_originalFormat = inFormat;
+ _valid = true;
}
@@ -193,7 +196,8 @@ public abstract class Coordinate
// format as specified
switch (inFormat)
{
- case FORMAT_DEG_MIN_SEC: {
+ case FORMAT_DEG_MIN_SEC:
+ {
StringBuffer buffer = new StringBuffer();
buffer.append(PRINTABLE_CARDINALS[_cardinal])
.append(threeDigitString(_degrees)).append('°')
@@ -202,11 +206,17 @@ public abstract class Coordinate
.append(_fracs);
answer = buffer.toString(); break;
}
- case FORMAT_DEG_MIN: answer = "" + PRINTABLE_CARDINALS[_cardinal] + threeDigitString(_degrees) + "°"
- + (_minutes + _seconds / 60.0 + _fracs / 600.0); break;
+ case FORMAT_DEG_MIN:
+ {
+ answer = "" + PRINTABLE_CARDINALS[_cardinal] + threeDigitString(_degrees) + "°"
+ + (_minutes + _seconds / 60.0 + _fracs / 600.0); break;
+ }
case FORMAT_DEG:
- case FORMAT_DEG_WITHOUT_CARDINAL: answer = (_asDouble<0.0?"-":"")
- + (_degrees + _minutes / 60.0 + _seconds / 3600.0 + _fracs / 36000.0); break;
+ case FORMAT_DEG_WITHOUT_CARDINAL:
+ {
+ answer = (_asDouble<0.0?"-":"")
+ + (_degrees + _minutes / 60.0 + _seconds / 3600.0 + _fracs / 36000.0); break;
+ }
}
}
return answer;
diff --git a/tim/prune/data/DataPoint.java b/tim/prune/data/DataPoint.java
index 5d66ec5..cd285d6 100644
--- a/tim/prune/data/DataPoint.java
+++ b/tim/prune/data/DataPoint.java
@@ -7,19 +7,19 @@ package tim.prune.data;
*/
public class DataPoint
{
- // Hold these as Strings? Or FieldValue objects?
+ /** Array of Strings holding raw values */
private String[] _fieldValues = null;
- // list of fields
+ /** list of field definitions */
private FieldList _fieldList = null;
- // Special fields for coordinates
+ /** Special fields for coordinates */
private Coordinate _latitude = null, _longitude = null;
private Altitude _altitude;
private Timestamp _timestamp = null;
+ private Photo _photo = null;
+ private String _waypointName = null;
private boolean _pointValid = false;
- // TODO: Make it possible to turn track point into waypoint - may need to alter FieldList
-
/**
* Constructor
* @param inValueArray array of String values
@@ -32,22 +32,32 @@ public class DataPoint
_fieldValues = inValueArray;
// save list of fields
_fieldList = inFieldList;
+ // parse fields into objects
+ parseFields(inAltFormat);
+ }
- // parse fields
+
+ /**
+ * Parse the string values into objects eg Coordinates
+ * @param inAltFormat altitude format
+ */
+ private void parseFields(int inAltFormat)
+ {
_latitude = new Latitude(getFieldValue(Field.LATITUDE));
_longitude = new Longitude(getFieldValue(Field.LONGITUDE));
_altitude = new Altitude(getFieldValue(Field.ALTITUDE), inAltFormat);
_timestamp = new Timestamp(getFieldValue(Field.TIMESTAMP));
+ _waypointName = getFieldValue(Field.WAYPT_NAME);
}
/**
- * Private constructor for artificially generated points (eg interpolated)
+ * Constructor for additional points (eg interpolated, photos)
* @param inLatitude latitude
* @param inLongitude longitude
* @param inAltitude altitude
*/
- private DataPoint(Coordinate inLatitude, Coordinate inLongitude, Altitude inAltitude)
+ public DataPoint(Coordinate inLatitude, Coordinate inLongitude, Altitude inAltitude)
{
// Only these three fields are available
_fieldValues = new String[0];
@@ -83,6 +93,46 @@ public class DataPoint
}
+ /**
+ * Set (or edit) the specified field value
+ * @param inField Field to set
+ * @param inValue value to set
+ */
+ public void setFieldValue(Field inField, String inValue)
+ {
+ // See if this data point already has this field
+ int fieldIndex = _fieldList.getFieldIndex(inField);
+ // Add to field list if necessary
+ if (fieldIndex < 0)
+ {
+ // If value is empty & field doesn't exist then do nothing
+ if (inValue == null || inValue.equals(""))
+ {
+ return;
+ }
+ // value isn't empty so extend field list
+ fieldIndex = _fieldList.extendList(inField);
+ }
+ // Extend array of field values if necessary
+ if (fieldIndex >= _fieldValues.length)
+ {
+ resizeValueArray(fieldIndex);
+ }
+ // Set field value in array
+ _fieldValues[fieldIndex] = inValue;
+ // Change Coordinate, Altitude, Name or Timestamp fields after edit
+ if (_altitude != null)
+ {
+ parseFields(_altitude.getFormat());
+ }
+ else
+ {
+ // use default altitude format of metres
+ parseFields(Altitude.FORMAT_METRES);
+ }
+ }
+
+
public Coordinate getLatitude()
{
return _latitude;
@@ -107,19 +157,22 @@ public class DataPoint
{
return _timestamp;
}
+ public String getWaypointName()
+ {
+ return _waypointName;
+ }
/**
* @return true if point has a waypoint name
*/
public boolean isWaypoint()
{
- String name = getFieldValue(Field.WAYPT_NAME);
- return (name != null && !name.equals(""));
+ return (_waypointName != null && !_waypointName.equals(""));
}
+
/**
- * Compare two DataPoint objects to see if they
- * are duplicates
+ * Compare two DataPoint objects to see if they are duplicates
* @param inOther other object to compare
* @return true if the points are equivalent
*/
@@ -131,26 +184,45 @@ public class DataPoint
{
return false;
}
+ // Make sure photo points aren't specified as duplicates
+ if (_photo != null) return false;
// Compare latitude and longitude
if (!_longitude.equals(inOther._longitude) || !_latitude.equals(inOther._latitude))
{
return false;
}
// Note that conversion from decimal to dms can make non-identical points into duplicates
- // Compare description (if any)
- String name1 = getFieldValue(Field.WAYPT_NAME);
- String name2 = inOther.getFieldValue(Field.WAYPT_NAME);
- if (name1 == null || name1.equals(""))
+ // Compare waypoint name (if any)
+ if (!isWaypoint())
{
- return (name2 == null || name2.equals(""));
+ return !inOther.isWaypoint();
}
else
{
- return (name2 != null && name2.equals(name1));
+ return (inOther._waypointName != null && inOther._waypointName.equals(_waypointName));
}
}
+ /**
+ * Set the photo for this data point
+ * @param inPhoto Photo object
+ */
+ public void setPhoto(Photo inPhoto)
+ {
+ _photo = inPhoto;
+ }
+
+
+ /**
+ * @return associated Photo object
+ */
+ public Photo getPhoto()
+ {
+ return _photo;
+ }
+
+
/**
* @return true if the point is valid
*/
@@ -210,4 +282,60 @@ public class DataPoint
// phew
return answer;
}
+
+
+ /**
+ * Resize the value array
+ * @param inNewIndex new index to allow
+ */
+ private void resizeValueArray(int inNewIndex)
+ {
+ int newSize = inNewIndex + 1;
+ if (newSize > _fieldValues.length)
+ {
+ String[] newArray = new String[newSize];
+ System.arraycopy(_fieldValues, 0, newArray, 0, _fieldValues.length);
+ _fieldValues = newArray;
+ }
+ }
+
+
+ /**
+ * @return a clone object with copied data
+ */
+ public DataPoint clonePoint()
+ {
+ // Copy all values
+ String[] valuesCopy = new String[_fieldValues.length];
+ System.arraycopy(_fieldValues, 0, valuesCopy, 0, _fieldValues.length);
+ // Make new object to hold cloned data
+ DataPoint point = new DataPoint(valuesCopy, _fieldList, _altitude.getFormat());
+ return point;
+ }
+
+
+ /**
+ * Restore the contents from another point
+ * @param inOther point containing contents to copy
+ * @return true if successful
+ */
+ public boolean restoreContents(DataPoint inOther)
+ {
+ if (inOther != null)
+ {
+ // Copy string values across
+ _fieldValues = inOther._fieldValues;
+ if (_altitude != null)
+ {
+ parseFields(_altitude.getFormat());
+ }
+ else
+ {
+ // use default altitude format of metres
+ parseFields(Altitude.FORMAT_METRES);
+ }
+ return true;
+ }
+ return false;
+ }
}
diff --git a/tim/prune/data/Distance.java b/tim/prune/data/Distance.java
index 61afdca..77ab6d4 100644
--- a/tim/prune/data/Distance.java
+++ b/tim/prune/data/Distance.java
@@ -31,6 +31,4 @@ public abstract class Distance
return inAngDist * EARTH_RADIUS_KM;
}
-
-
}
diff --git a/tim/prune/data/DoubleRange.java b/tim/prune/data/DoubleRange.java
index b7d4771..f241d4d 100644
--- a/tim/prune/data/DoubleRange.java
+++ b/tim/prune/data/DoubleRange.java
@@ -10,6 +10,16 @@ public class DoubleRange
private double _min = 0.0, _max = 0.0;
+ /**
+ * Clear for a new calculation
+ */
+ public void clear()
+ {
+ _min = _max = 0.0;
+ _empty = true;
+ }
+
+
/**
* Add a value to the range
* @param inValue value to add
diff --git a/tim/prune/data/FieldList.java b/tim/prune/data/FieldList.java
index 58cf6d5..5e567ea 100644
--- a/tim/prune/data/FieldList.java
+++ b/tim/prune/data/FieldList.java
@@ -135,6 +135,27 @@ public class FieldList
}
+ /**
+ * Extend the field list to include the specified field
+ * @param inField Field to add
+ * @return new index of added Field
+ */
+ public int extendList(Field inField)
+ {
+ // See if field is already in list
+ int currIndex = getFieldIndex(inField);
+ if (currIndex >= 0) return currIndex;
+ // Need to extend - increase array size
+ int oldNumFields = _fieldArray.length;
+ Field[] fields = new Field[oldNumFields + 1];
+ System.arraycopy(_fieldArray, 0, fields, 0, oldNumFields);
+ _fieldArray = fields;
+ // Add new field and return index
+ _fieldArray[oldNumFields] = inField;
+ return oldNumFields;
+ }
+
+
/**
* Convert to String for debug
*/
diff --git a/tim/prune/data/IntegerRange.java b/tim/prune/data/IntegerRange.java
index 61ae34c..b11ba0e 100644
--- a/tim/prune/data/IntegerRange.java
+++ b/tim/prune/data/IntegerRange.java
@@ -9,6 +9,16 @@ public class IntegerRange
private int _min = -1, _max = -1;
+ /**
+ * Clear for a new range calculation
+ */
+ public void clear()
+ {
+ _min = -1;
+ _max = -1;
+ }
+
+
/**
* Add a value to the range
* @param inValue value to add, only positive values considered
diff --git a/tim/prune/data/Latitude.java b/tim/prune/data/Latitude.java
index 6d8bab6..61e8bb2 100644
--- a/tim/prune/data/Latitude.java
+++ b/tim/prune/data/Latitude.java
@@ -20,10 +20,9 @@ public class Latitude extends Coordinate
* @param inValue value of coordinate
* @param inFormat format to use
*/
- protected Latitude(double inValue, int inFormat)
+ public Latitude(double inValue, int inFormat)
{
- super(inValue, inFormat);
- _cardinal = inValue < 0.0 ? SOUTH : NORTH;
+ super(inValue, inFormat, inValue < 0.0 ? SOUTH : NORTH);
}
diff --git a/tim/prune/data/Longitude.java b/tim/prune/data/Longitude.java
index d61adbc..6af5889 100644
--- a/tim/prune/data/Longitude.java
+++ b/tim/prune/data/Longitude.java
@@ -20,10 +20,9 @@ public class Longitude extends Coordinate
* @param inValue value of coordinate
* @param inFormat format to use
*/
- protected Longitude(double inValue, int inFormat)
+ public Longitude(double inValue, int inFormat)
{
- super(inValue, inFormat);
- _cardinal = inValue < 0.0 ? WEST : EAST;
+ super(inValue, inFormat, inValue < 0.0 ? WEST : EAST);
}
diff --git a/tim/prune/data/Selection.java b/tim/prune/data/Selection.java
index c375e82..f09088d 100644
--- a/tim/prune/data/Selection.java
+++ b/tim/prune/data/Selection.java
@@ -383,20 +383,28 @@ public class Selection
*/
private void check()
{
- if (_track != null && _track.getNumPoints() > 0)
+ if (_track != null)
{
- int maxIndex = _track.getNumPoints() - 1;
- if (_currentPoint > maxIndex)
+ if (_track.getNumPoints() > 0)
{
- _currentPoint = maxIndex;
- }
- if (_endIndex > maxIndex)
- {
- _endIndex = maxIndex;
+ int maxIndex = _track.getNumPoints() - 1;
+ if (_currentPoint > maxIndex)
+ {
+ _currentPoint = maxIndex;
+ }
+ if (_endIndex > maxIndex)
+ {
+ _endIndex = maxIndex;
+ }
+ if (_startIndex > maxIndex)
+ {
+ _startIndex = maxIndex;
+ }
}
- if (_startIndex > maxIndex)
+ else
{
- _startIndex = maxIndex;
+ // track is empty, clear selections
+ _currentPoint = _startIndex = _endIndex = -1;
}
}
_broker.informSubscribers();
diff --git a/tim/prune/data/Track.java b/tim/prune/data/Track.java
index 683cd21..e73fa73 100644
--- a/tim/prune/data/Track.java
+++ b/tim/prune/data/Track.java
@@ -1,6 +1,10 @@
package tim.prune.data;
+import java.util.List;
+
import tim.prune.UpdateMessageBroker;
+import tim.prune.edit.FieldEdit;
+import tim.prune.edit.FieldEditList;
/**
@@ -219,6 +223,7 @@ public class Track
*/
public boolean deleteRange(int inStart, int inEnd)
{
+ // TODO: Check for deleting photos?
if (inStart < 0 || inEnd < 0 || inEnd < inStart)
{
// no valid range selected so can't delete
@@ -433,6 +438,7 @@ public class Track
return true;
}
+ // TODO: Need to rearrange photo points too?
/**
* Interpolate extra points between two selected ones
@@ -452,10 +458,26 @@ public class Track
// Make array of points to insert
DataPoint[] insertedPoints = startPoint.interpolate(endPoint, inNumPoints);
-
+
// Insert points into track
- insertRange(insertedPoints, inStartIndex + 1);
- return true;
+ return insertRange(insertedPoints, inStartIndex + 1);
+ }
+
+
+ /**
+ * Append the specified points to the end of the track
+ * @param inPoints DataPoint objects to add
+ */
+ public void appendPoints(DataPoint[] inPoints)
+ {
+ // Insert points into track
+ if (inPoints != null && inPoints.length > 0)
+ {
+ insertRange(inPoints, _numPoints);
+ }
+ // needs to be scaled again to recalc x, y
+ _scaled = false;
+ _broker.informSubscribers();
}
@@ -581,6 +603,49 @@ public class Track
}
+ /**
+ * Collect all the waypoints into the given List
+ * @param inList List to fill with waypoints
+ */
+ public void getWaypoints(List inList)
+ {
+ // clear list
+ inList.clear();
+ // loop over points and copy all waypoints into list
+ for (int i=0; i<=_numPoints-1; i++)
+ {
+ if (_dataPoints[i].isWaypoint())
+ {
+ inList.add(_dataPoints[i]);
+ }
+ }
+ }
+ // TODO: Make similar method to get list of photos
+
+
+ /**
+ * Search for the given Point in the track and return the index
+ * @param inPoint Point to look for
+ * @return index of Point, if any or -1 if not found
+ */
+ public int getPointIndex(DataPoint inPoint)
+ {
+ if (inPoint != null)
+ {
+ // Loop over points in track
+ for (int i=0; i<=_numPoints-1; i++)
+ {
+ if (_dataPoints[i] == inPoint)
+ {
+ return i;
+ }
+ }
+ }
+ // not found
+ return -1;
+ }
+
+
///////// Internal processing methods ////////////////
@@ -604,7 +669,9 @@ public class Track
_longRange.addValue(point.getLongitude().getDouble());
_latRange.addValue(point.getLatitude().getDouble());
if (point.getAltitude().isValid())
+ {
_altitudeRange.addValue(point.getAltitude());
+ }
if (point.isWaypoint())
hasWaypoint = true;
else
@@ -790,4 +857,31 @@ public class Track
_broker.informSubscribers();
return true;
}
+
+
+ /**
+ * Edit the specified point
+ * @param inPoint point to edit
+ * @param inEditList list of edits to make
+ * @return true if successful
+ */
+ public boolean editPoint(DataPoint inPoint, FieldEditList inEditList)
+ {
+ if (inPoint != null && inEditList != null && inEditList.getNumEdits() > 0)
+ {
+ // go through edits one by one
+ int numEdits = inEditList.getNumEdits();
+ for (int i=0; i 0)
+ {
+ DataPoint[] dataPoints = new DataPoint[numPhotosToAdd];
+ int pointNum = 0;
+ // Add each Photo in turn
+ for (int i=0; i").append(I18nManager.getText("dialog.about.summarytext1")).append("
");
descBuffer.append("").append(I18nManager.getText("dialog.about.summarytext2")).append("
");
descBuffer.append("").append(I18nManager.getText("dialog.about.summarytext3")).append("
");
+ descBuffer.append("").append(I18nManager.getText("dialog.about.translatedby")).append("
");
JEditorPane descPane = new JEditorPane("text/html", descBuffer.toString());
descPane.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
descPane.setEditable(false);
descPane.setOpaque(false);
descPane.setAlignmentX(JEditorPane.CENTER_ALIGNMENT);
- // descPane.setBackground(Color.GRAY);
+
mainPanel.add(descPane);
mainPanel.add(new JLabel(" "));
JButton okButton = new JButton(I18nManager.getText("button.ok"));
diff --git a/tim/prune/gui/DetailsDisplay.java b/tim/prune/gui/DetailsDisplay.java
index e9ed747..765b88b 100644
--- a/tim/prune/gui/DetailsDisplay.java
+++ b/tim/prune/gui/DetailsDisplay.java
@@ -17,17 +17,22 @@ import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
+import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
+import javax.swing.JScrollPane;
+import javax.swing.JTabbedPane;
import javax.swing.border.EtchedBorder;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
import tim.prune.App;
+import tim.prune.DataSubscriber;
import tim.prune.I18nManager;
import tim.prune.data.Altitude;
import tim.prune.data.Coordinate;
import tim.prune.data.DataPoint;
import tim.prune.data.Distance;
-import tim.prune.data.Field;
import tim.prune.data.IntegerRange;
import tim.prune.data.Selection;
import tim.prune.data.TrackInfo;
@@ -48,7 +53,7 @@ public class DetailsDisplay extends GenericDisplay
private JLabel _indexLabel = null;
private JLabel _latLabel = null, _longLabel = null;
private JLabel _altLabel = null, _nameLabel = null;
- private JLabel _timeLabel = null;
+ private JLabel _timeLabel = null, _photoFileLabel = null;
// Scroll bar
private JScrollBar _scroller = null;
private boolean _ignoreScrollEvents = false;
@@ -60,6 +65,12 @@ public class DetailsDisplay extends GenericDisplay
private JLabel _rangeLabel = null;
private JLabel _distanceLabel = null, _durationLabel = null;
private JLabel _altRangeLabel = null, _updownLabel = null;
+ // Photos
+ private JList _photoList = null;
+ private PhotoListModel _photoListModel = null;
+ // Waypoints
+ private JList _waypointList = null;
+ private WaypointListModel _waypointListModel = null;
// Units
private JComboBox _unitsDropdown = null;
// Formatter
@@ -113,7 +124,7 @@ public class DetailsDisplay extends GenericDisplay
trackDetailsPanel.add(_trackpointsLabel);
_filenameLabel = new JLabel("");
trackDetailsPanel.add(_filenameLabel);
-
+
// Point details panel
JPanel pointDetailsPanel = new JPanel();
pointDetailsPanel.setLayout(new BoxLayout(pointDetailsPanel, BoxLayout.Y_AXIS));
@@ -133,6 +144,8 @@ public class DetailsDisplay extends GenericDisplay
pointDetailsPanel.add(_altLabel);
_timeLabel = new JLabel("");
pointDetailsPanel.add(_timeLabel);
+ _photoFileLabel = new JLabel("");
+ pointDetailsPanel.add(_photoFileLabel);
_nameLabel = new JLabel("");
pointDetailsPanel.add(_nameLabel);
pointDetailsPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
@@ -214,8 +227,36 @@ public class DetailsDisplay extends GenericDisplay
otherDetailsPanel.add(_updownLabel);
otherDetailsPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
- // add the main panel at the top
- add(mainPanel, BorderLayout.NORTH);
+ // Add tab panel for waypoints / photos
+ JPanel waypointsPanel = new JPanel();
+ waypointsPanel.setLayout(new BoxLayout(waypointsPanel, BoxLayout.Y_AXIS));
+ waypointsPanel.setBorder(BorderFactory.createCompoundBorder(
+ BorderFactory.createEtchedBorder(EtchedBorder.LOWERED), BorderFactory.createEmptyBorder(3, 3, 3, 3))
+ );
+ JTabbedPane tabPane = new JTabbedPane();
+ _waypointListModel = new WaypointListModel(_trackInfo.getTrack());
+ _waypointList = new JList(_waypointListModel);
+ _waypointList.setVisibleRowCount(5);
+ _waypointList.addListSelectionListener(new ListSelectionListener() {
+ public void valueChanged(ListSelectionEvent e)
+ {
+ if (!e.getValueIsAdjusting()) selectWaypoint(_waypointList.getSelectedIndex());
+ }});
+ tabPane.addTab(I18nManager.getText("details.waypointsphotos.waypoints"), new JScrollPane(_waypointList));
+ _photoListModel = new PhotoListModel(_trackInfo.getPhotoList());
+ _photoList = new JList(_photoListModel);
+ _photoList.setVisibleRowCount(5);
+ _photoList.addListSelectionListener(new ListSelectionListener() {
+ public void valueChanged(ListSelectionEvent e)
+ {
+ if (!e.getValueIsAdjusting()) selectPhoto(_photoList.getSelectedIndex());
+ }});
+ // TODO: Re-add photos list after v2
+ // tabPane.addTab(I18nManager.getText("details.waypointsphotos.photos"), new JScrollPane(_photoList));
+ tabPane.setAlignmentX(Component.LEFT_ALIGNMENT);
+ waypointsPanel.add(tabPane);
+ waypointsPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
+
// add the slider, point details, and the other details to the main panel
mainPanel.add(buttonPanel);
mainPanel.add(Box.createVerticalStrut(5));
@@ -226,6 +267,10 @@ public class DetailsDisplay extends GenericDisplay
mainPanel.add(pointDetailsPanel);
mainPanel.add(Box.createVerticalStrut(5));
mainPanel.add(otherDetailsPanel);
+ mainPanel.add(Box.createVerticalStrut(5));
+ mainPanel.add(waypointsPanel);
+ // add the main panel at the top
+ add(mainPanel, BorderLayout.NORTH);
// Add units selection
JPanel lowerPanel = new JPanel();
@@ -236,7 +281,7 @@ public class DetailsDisplay extends GenericDisplay
_unitsDropdown.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
- dataUpdated();
+ dataUpdated(DataSubscriber.UNITS_CHANGED);
}
});
lowerPanel.add(_unitsDropdown);
@@ -257,10 +302,43 @@ public class DetailsDisplay extends GenericDisplay
}
+ /**
+ * Select the specified photo
+ * @param inPhotoIndex index of selected photo
+ */
+ private void selectPhoto(int inPhotoIndex)
+ {
+ if (_photoListModel.getPhoto(inPhotoIndex) != null)
+ {
+ // TODO: Deselect the photo when another point is selected
+ // TODO: show photo thumbnail
+ // select associated point, if any
+ DataPoint point = _photoListModel.getPhoto(inPhotoIndex).getDataPoint();
+ if (point != null)
+ {
+ _trackInfo.selectPoint(point);
+ }
+ }
+ }
+
+
+ /**
+ * Select the specified waypoint
+ * @param inWaypointIndex index of selected waypoint
+ */
+ private void selectWaypoint(int inWaypointIndex)
+ {
+ if (inWaypointIndex >= 0)
+ {
+ _trackInfo.selectPoint(_waypointListModel.getWaypoint(inWaypointIndex));
+ }
+ }
+
+
/**
* Notification that Track has been updated
*/
- public void dataUpdated()
+ public void dataUpdated(byte inUpdateType)
{
// Update track data
if (_track == null || _track.getNumPoints() <= 0)
@@ -297,6 +375,7 @@ public class DetailsDisplay extends GenericDisplay
_longLabel.setText("");
_altLabel.setText("");
_timeLabel.setText("");
+ _photoFileLabel.setText("");
_nameLabel.setText("");
}
else
@@ -314,7 +393,14 @@ public class DetailsDisplay extends GenericDisplay
_timeLabel.setText(LABEL_POINT_TIMESTAMP + currentPoint.getTimestamp().getText());
else
_timeLabel.setText("");
- String name = currentPoint.getFieldValue(Field.WAYPT_NAME);
+ if (currentPoint.getPhoto() != null && currentPoint.getPhoto().getFile() != null)
+ {
+ _photoFileLabel.setText(I18nManager.getText("details.photofile") + ": "
+ + currentPoint.getPhoto().getFile().getName());
+ }
+ else
+ _photoFileLabel.setText("");
+ String name = currentPoint.getWaypointName();
if (name != null && !name.equals(""))
{
_nameLabel.setText(LABEL_POINT_WAYPOINTNAME + name);
@@ -389,6 +475,37 @@ public class DetailsDisplay extends GenericDisplay
_updownLabel.setText("");
}
}
+ // update waypoints and photos if necessary
+ if ((inUpdateType |
+ (DataSubscriber.DATA_ADDED_OR_REMOVED | DataSubscriber.DATA_EDITED | DataSubscriber.WAYPOINTS_MODIFIED)) > 0)
+ {
+ _waypointListModel.fireChanged();
+ }
+ if ((inUpdateType |
+ (DataSubscriber.DATA_ADDED_OR_REMOVED | DataSubscriber.DATA_EDITED | DataSubscriber.PHOTOS_MODIFIED)) > 0)
+ {
+ _photoListModel.fireChanged();
+ }
+ // Deselect selected waypoint if selected point has since changed
+ if (_waypointList.getSelectedIndex() >= 0)
+ {
+ if (_trackInfo.getCurrentPoint() == null
+ || !_waypointListModel.getWaypoint(_waypointList.getSelectedIndex()).equals(_trackInfo.getCurrentPoint()))
+ {
+ // point is selected in list but different from current point - deselect
+ _waypointList.clearSelection();
+ }
+ }
+ // Do the same for the photos
+ if (_photoList.getSelectedIndex() >= 0)
+ {
+ if (_trackInfo.getCurrentPoint() == null
+ || !_photoListModel.getPhoto(_photoList.getSelectedIndex()).getDataPoint().equals(_trackInfo.getCurrentPoint()))
+ {
+ // photo is selected in list but different from current point - deselect
+ _photoList.clearSelection();
+ }
+ }
}
diff --git a/tim/prune/gui/GenericChart.java b/tim/prune/gui/GenericChart.java
index 081c823..916c738 100644
--- a/tim/prune/gui/GenericChart.java
+++ b/tim/prune/gui/GenericChart.java
@@ -71,7 +71,7 @@ public abstract class GenericChart extends GenericDisplay implements MouseListen
/**
* Method to inform map that data has changed
*/
- public void dataUpdated()
+ public void dataUpdated(byte inUpdateType)
{
repaint();
}
diff --git a/tim/prune/gui/MapChart.java b/tim/prune/gui/MapChart.java
index 13b1b7d..1236f13 100644
--- a/tim/prune/gui/MapChart.java
+++ b/tim/prune/gui/MapChart.java
@@ -19,9 +19,9 @@ import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import tim.prune.App;
+import tim.prune.DataSubscriber;
import tim.prune.I18nManager;
import tim.prune.data.DataPoint;
-import tim.prune.data.Field;
import tim.prune.data.TrackInfo;
@@ -83,16 +83,16 @@ public class MapChart extends GenericChart implements MouseWheelListener, KeyLis
/**
* Override track updating to refresh image
*/
- public void dataUpdated()
+ public void dataUpdated(byte inUpdateType)
{
- // Check if number of points has changed or Track
- // object has a different signature
- if (_track.getNumPoints() != _numPoints)
+ // Check if number of points has changed or data has been edited
+ if (_track.getNumPoints() != _numPoints || (inUpdateType & DATA_EDITED) > 0)
{
_image = null;
+ _lastSelectedPoint = -1;
_numPoints = _track.getNumPoints();
}
- super.dataUpdated();
+ super.dataUpdated(inUpdateType);
}
@@ -126,25 +126,25 @@ public class MapChart extends GenericChart implements MouseWheelListener, KeyLis
// Autopan is enabled and a point is selected - work out x and y to see if it's within range
x = width/2 + (int) ((_track.getX(selectedPoint) - _offsetX) / _scale * _zoomScale);
y = height/2 - (int) ((_track.getY(selectedPoint) - _offsetY) / _scale * _zoomScale);
- if (x < BORDER_WIDTH)
+ if (x <= BORDER_WIDTH)
{
// autopan left
_offsetX -= (width / 4 - x) * _scale / _zoomScale;
_image = null;
}
- else if (x > (width - BORDER_WIDTH))
+ else if (x >= (width - BORDER_WIDTH))
{
// autopan right
_offsetX += (x - width * 3/4) * _scale / _zoomScale;
_image = null;
}
- if (y < BORDER_WIDTH)
+ if (y <= BORDER_WIDTH)
{
// autopan up
_offsetY += (height / 4 - y) * _scale / _zoomScale;
_image = null;
}
- else if (y > (height - BORDER_WIDTH))
+ else if (y >= (height - BORDER_WIDTH))
{
// autopan down
_offsetY -= (y - height * 3/4) * _scale / _zoomScale;
@@ -197,6 +197,7 @@ public class MapChart extends GenericChart implements MouseWheelListener, KeyLis
}
}
+ // Draw rectangle for dragging zoom area
if (_zoomDragging)
{
g.setColor(COLOR_CROSSHAIRS);
@@ -205,6 +206,9 @@ public class MapChart extends GenericChart implements MouseWheelListener, KeyLis
g.drawLine(_zoomDragToX, _zoomDragFromY, _zoomDragToX, _zoomDragToY);
g.drawLine(_zoomDragFromX, _zoomDragToY, _zoomDragToX, _zoomDragToY);
}
+
+ // Attempt to grab keyboard focus if possible
+ this.requestFocus();
}
@@ -245,7 +249,7 @@ public class MapChart extends GenericChart implements MouseWheelListener, KeyLis
for (int i=0; iyZoom?yZoom:xZoom);
+ // deselect point if selected (to stop autopan)
+ _trackInfo.getSelection().selectPoint(-1);
// Pan first to ensure pan occurs with correct scale
panMap(yPan, xPan);
// Then zoom in and request repaint
@@ -513,7 +520,11 @@ public class MapChart extends GenericChart implements MouseWheelListener, KeyLis
panMap(upwardsPan, rightwardsPan);
// Check for delete key to delete current point
if (code == KeyEvent.VK_DELETE && _trackInfo.getSelection().getCurrentPointIndex() >= 0)
+ {
_app.deleteCurrentPoint();
+ // reset last selected point to trigger autopan
+ _lastSelectedPoint = -1;
+ }
}
}
diff --git a/tim/prune/gui/MenuManager.java b/tim/prune/gui/MenuManager.java
index 665142e..64a66d8 100644
--- a/tim/prune/gui/MenuManager.java
+++ b/tim/prune/gui/MenuManager.java
@@ -31,9 +31,12 @@ public class MenuManager implements DataSubscriber
// Menu items which need enabling/disabling
JMenuItem _saveItem = null;
- JMenuItem _exportItem = null;
+ JMenuItem _exportKmlItem = null;
+ JMenuItem _exportPovItem = null;
JMenuItem _undoItem = null;
JMenuItem _clearUndoItem = null;
+ JMenuItem _editPointItem = null;
+ JMenuItem _editWaypointNameItem = null;
JMenuItem _deletePointItem = null;
JMenuItem _deleteRangeItem = null;
JMenuItem _deleteDuplicatesItem = null;
@@ -71,6 +74,7 @@ public class MenuManager implements DataSubscriber
{
JMenuBar menubar = new JMenuBar();
JMenu fileMenu = new JMenu(I18nManager.getText("menu.file"));
+ // Open file
JMenuItem openMenuItem = new JMenuItem(I18nManager.getText("menu.file.open"));
openMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_DOWN_MASK));
openMenuItem.addActionListener(new ActionListener() {
@@ -80,6 +84,17 @@ public class MenuManager implements DataSubscriber
}
});
fileMenu.add(openMenuItem);
+ // Add photos
+ JMenuItem addPhotosMenuItem = new JMenuItem(I18nManager.getText("menu.file.addphotos"));
+ addPhotosMenuItem.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e)
+ {
+ _app.addPhotos();
+ }
+ });
+ // TODO: Re-add add photos menu item after v2
+ // fileMenu.add(addPhotosMenuItem);
+ // Save
_saveItem = new JMenuItem(I18nManager.getText("menu.file.save"), KeyEvent.VK_S);
_saveItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
@@ -90,15 +105,24 @@ public class MenuManager implements DataSubscriber
_saveItem.setEnabled(false);
fileMenu.add(_saveItem);
// Export
- _exportItem = new JMenuItem(I18nManager.getText("menu.file.export"));
- _exportItem.addActionListener(new ActionListener() {
+ _exportKmlItem = new JMenuItem(I18nManager.getText("menu.file.exportkml"));
+ _exportKmlItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
_app.exportKml();
}
});
- _exportItem.setEnabled(false);
- fileMenu.add(_exportItem);
+ _exportKmlItem.setEnabled(false);
+ fileMenu.add(_exportKmlItem);
+ _exportPovItem = new JMenuItem(I18nManager.getText("menu.file.exportpov"));
+ _exportPovItem.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e)
+ {
+ _app.exportPov();
+ }
+ });
+ _exportPovItem.setEnabled(false);
+ fileMenu.add(_exportPovItem);
fileMenu.addSeparator();
JMenuItem exitMenuItem = new JMenuItem(I18nManager.getText("menu.file.exit"));
exitMenuItem.addActionListener(new ActionListener() {
@@ -130,6 +154,24 @@ public class MenuManager implements DataSubscriber
_clearUndoItem.setEnabled(false);
editMenu.add(_clearUndoItem);
editMenu.addSeparator();
+ _editPointItem = new JMenuItem(I18nManager.getText("menu.edit.editpoint"));
+ _editPointItem.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e)
+ {
+ _app.editCurrentPoint();
+ }
+ });
+ _editPointItem.setEnabled(false);
+ editMenu.add(_editPointItem);
+ _editWaypointNameItem = new JMenuItem(I18nManager.getText("menu.edit.editwaypointname"));
+ _editWaypointNameItem.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e)
+ {
+ _app.editCurrentPointName();
+ }
+ });
+ _editWaypointNameItem.setEnabled(false);
+ editMenu.add(_editWaypointNameItem);
_deletePointItem = new JMenuItem(I18nManager.getText("menu.edit.deletepoint"));
_deletePointItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
@@ -240,21 +282,18 @@ public class MenuManager implements DataSubscriber
selectMenu.add(_selectNoneItem);
menubar.add(selectMenu);
- // Add 3d menu if available
- if (isJava3dEnabled())
- {
- JMenu threeDMenu = new JMenu(I18nManager.getText("menu.3d"));
- _show3dItem = new JMenuItem(I18nManager.getText("menu.3d.show3d"));
- _show3dItem.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e)
- {
- _app.show3dWindow();
- }
- });
- _show3dItem.setEnabled(false);
- threeDMenu.add(_show3dItem);
- menubar.add(threeDMenu);
- }
+ // Add 3d menu (whether java3d available or not)
+ JMenu threeDMenu = new JMenu(I18nManager.getText("menu.3d"));
+ _show3dItem = new JMenuItem(I18nManager.getText("menu.3d.show3d"));
+ _show3dItem.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e)
+ {
+ _app.show3dWindow();
+ }
+ });
+ _show3dItem.setEnabled(false);
+ threeDMenu.add(_show3dItem);
+ menubar.add(threeDMenu);
// Help menu for About
JMenu helpMenu = new JMenu(I18nManager.getText("menu.help"));
@@ -285,34 +324,16 @@ public class MenuManager implements DataSubscriber
}
- /**
- * @return true if 3d capability is installed
- */
- private static boolean isJava3dEnabled()
- {
- boolean has3d = false;
- try
- {
- Class universeClass = Class.forName("com.sun.j3d.utils.universe.SimpleUniverse");
- has3d = true;
- }
- catch (ClassNotFoundException e)
- {
- // no java3d classes available
- }
- return has3d;
- }
-
-
/**
* @see tim.prune.DataSubscriber#dataUpdated(tim.prune.data.Track)
*/
- public void dataUpdated()
+ public void dataUpdated(byte inUpdateType)
{
boolean hasData = (_track != null && _track.getNumPoints() > 0);
// set functions which require data
_saveItem.setEnabled(hasData);
- _exportItem.setEnabled(hasData);
+ _exportKmlItem.setEnabled(hasData);
+ _exportPovItem.setEnabled(hasData);
_deleteDuplicatesItem.setEnabled(hasData);
_compressItem.setEnabled(hasData);
_rearrangeMenu.setEnabled(hasData && _track.hasMixedData());
@@ -326,6 +347,8 @@ public class MenuManager implements DataSubscriber
_clearUndoItem.setEnabled(hasUndo);
// is there a current point?
boolean hasPoint = (hasData && _selection.getCurrentPointIndex() >= 0);
+ _editPointItem.setEnabled(hasPoint);
+ _editWaypointNameItem.setEnabled(hasPoint);
_deletePointItem.setEnabled(hasPoint);
// is there a current range?
boolean hasRange = (hasData && _selection.hasRangeSelected());
diff --git a/tim/prune/lang/prune-texts.properties b/tim/prune/lang/prune-texts.properties
index 01f9dad..ff55656 100644
--- a/tim/prune/lang/prune-texts.properties
+++ b/tim/prune/lang/prune-texts.properties
@@ -4,12 +4,16 @@
# Menu entries
menu.file=File
menu.file.open=Open
+menu.file.addphotos=Add Photos
menu.file.save=Save
-menu.file.export=Export KML
+menu.file.exportkml=Export KML
+menu.file.exportpov=Export POV
menu.file.exit=Exit
menu.edit=Edit
menu.edit.undo=Undo
menu.edit.clearundo=Clear undo list
+menu.edit.editpoint=Edit point
+menu.edit.editwaypointname=Edit waypoint name
menu.edit.deletepoint=Delete point
menu.edit.deleterange=Delete range
menu.edit.deleteduplicates=Delete duplicates
@@ -34,7 +38,7 @@ menu.map.zoomfull=Zoom to full scale
menu.map.autopan=Autopan
# Dialogs
-dialog.exit.confirm.title=Exit prune
+dialog.exit.confirm.title=Exit Prune
dialog.exit.confirm.text=Your data is not saved. Are you sure you want to exit?
dialog.openappend.title=Append to existing data
dialog.openappend.text=Append this data to the data already loaded?
@@ -64,19 +68,37 @@ dialog.openoptions.deliminfo.fields=fields
dialog.openoptions.deliminfo.norecords=No records
dialog.openoptions.tabledesc=Extract of file
dialog.openoptions.altitudeunits=Altitude units
+dialog.jpegload.subdirectories=Include subdirectories
+dialog.jpegload.progress.title=Loading photos
+dialog.jpegload.progress=Please wait while the photos are searched
+dialog.jpegload.title=Loaded photos
+dialog.jpegload.photoadded=photo was added
+dialog.jpegload.photosadded=photos were added
dialog.saveoptions.title=Save file
dialog.save.fieldstosave=Fields to save
dialog.save.table.field=Field
dialog.save.table.hasdata=Has data
dialog.save.table.save=Save
+dialog.save.headerrow=Output header row
dialog.save.coordinateunits=Coordinate units
dialog.save.units.original=Original
dialog.save.altitudeunits=Altitude units
dialog.save.oktitle=File saved
dialog.save.ok1=Successfully saved
dialog.save.ok2=points to file
+dialog.save.overwrite.title=File already exists
+dialog.save.overwrite.text=This file already exists. Are you sure you want to overwrite the file?
dialog.exportkml.title=Export KML
dialog.exportkml.text=Please enter a short description for the data
+dialog.exportkml.filetype=KML files
+dialog.exportpov.title=Export POV
+dialog.exportpov.text=Please enter the parameters for the POV export
+dialog.exportpov.font=Font
+dialog.exportpov.camerax=Camera X
+dialog.exportpov.cameray=Camera Y
+dialog.exportpov.cameraz=Camera Z
+dialog.exportpov.filetype=POV files
+dialog.exportpov.warningtracksize=This track has a large number of points, which Java3D might not be able to display.\nAre you sure you want to continue?
dialog.confirmreversetrack.title=Confirm reversal
dialog.confirmreversetrack.text=This track contains timestamp information, which will be out of sequence after a reversal.\nAre you sure you want to reverse this section?
dialog.interpolate.title=Interpolate points
@@ -90,12 +112,29 @@ dialog.undo.none.title=Cannot undo
dialog.undo.none.text=No operations to undo!
dialog.clearundo.title=Clear undo list
dialog.clearundo.text=Are you sure you want to clear the undo list?\nAll undo information will be lost!
-dialog.about.title=About
+dialog.pointedit.title=Edit point
+dialog.pointedit.text=Select each field to edit and use the 'Edit' button to change the value
+dialog.pointedit.table.field=Field
+dialog.pointedit.table.value=Value
+dialog.pointedit.table.changed=Changed
+dialog.pointedit.changevalue.text=Enter the new value for this field
+dialog.pointedit.changevalue.title=Edit field
+dialog.pointnameedit.title=Edit waypoint name
+dialog.pointnameedit.name=Waypoint name
+dialog.pointnameedit.uppercase=UPPER case
+dialog.pointnameedit.lowercase=lower case
+dialog.pointnameedit.sentencecase=Sentence case
+dialog.about.title=About Prune
dialog.about.version=Version
dialog.about.build=Build
dialog.about.summarytext1=Prune is a program for loading, displaying and editing data from GPS receivers.
dialog.about.summarytext2=It is released under the Gnu GPL for free, open, worldwide use and enhancement.
Copying, redistribution and modification are permitted and encouraged
according to the conditions in the included license.txt
file.
dialog.about.summarytext3=Please see http://activityworkshop.net/
for more information and user guides.
+dialog.about.translatedby=English text by activityworkshop.
+
+# 3d window
+dialog.3d.title=Prune Three-d view
+dialog.3d.altitudecap=Minimum altitude range
# Buttons
button.ok=OK
@@ -103,13 +142,17 @@ button.back=Back
button.next=Next
button.finish=Finish
button.cancel=Cancel
+button.overwrite=Overwrite
button.moveup=Move up
button.movedown=Move down
-button.startrange=Set range start
-button.endrange=Set range end
+button.startrange=Set start
+button.endrange=Set end
button.deletepoint=Delete point
button.deleterange=Delete range
+button.edit=Edit
button.exit=Exit
+button.close=Close
+button.continue=Continue
# Display components
display.nodata=No data loaded
@@ -123,6 +166,7 @@ details.pointdetails=Point details
details.index.selected=Index
details.index.of=of
details.nopointselection=No point selected
+details.photofile=Photo file
details.norangeselection=No range selected
details.rangedetails=Range details
details.range.selected=Selected
@@ -135,6 +179,8 @@ display.range.time.secs=s
display.range.time.mins=m
display.range.time.hours=h
display.range.time.days=d
+details.waypointsphotos.waypoints=Waypoints
+details.waypointsphotos.photos=Photos
# Field names
fieldname.latitude=Latitude
@@ -162,8 +208,16 @@ units.degminsec=Deg-min-sec
units.degmin=Deg-min
units.deg=Degrees
+# Cardinals for 3d plots
+cardinal.n=N
+cardinal.s=S
+cardinal.e=E
+cardinal.w=W
+
# Undo operations
undo.load=load data
+undo.loadphotos=load photos
+undo.editpoint=edit point
undo.deletepoint=delete point
undo.deleterange=delete range
undo.compress=compress track
@@ -175,13 +229,20 @@ undo.rearrangewaypoints=rearrange waypoints
# Error messages
error.save.dialogtitle=Error saving data
error.save.nodata=No data to save
-error.save.fileexists=File already exists. Just to be safe this program won't overwrite it.
error.save.failed=Failed to save the data to file:
error.load.dialogtitle=Error loading data
error.load.noread=Cannot read file
+error.jpegload.dialogtitle=Error loading photos
+error.jpegload.nofilesfound=No files found
+error.jpegload.nojpegsfound=No jpeg files found
+error.jpegload.noexiffound=No EXIF information found
+error.jpegload.nogpsfound=No GPS information found
error.undofailed.title=Undo failed
error.undofailed.text=Failed to undo operation
error.function.noop.title=Function had no effect
error.rearrange.noop=Rearranging waypoints had no effect
-error.function.notimplemented.title=Function not available
error.function.notimplemented=Sorry, this function has not yet been implemented.
+error.function.notavailable.title=Function not available
+error.function.nojava3d=This function requires the Java3d library,\navailable from Sun.com or Blackdown.org.
+error.3d.title=Error in 3d display
+error.3d=An error occurred with the 3d display
diff --git a/tim/prune/lang/prune-texts_de.properties b/tim/prune/lang/prune-texts_de.properties
index 2acf4d1..98fc57c 100644
--- a/tim/prune/lang/prune-texts_de.properties
+++ b/tim/prune/lang/prune-texts_de.properties
@@ -4,12 +4,16 @@
# Menu entries
menu.file=Datei
menu.file.open=Öffnen
+menu.file.addphotos=Fotos laden
menu.file.save=Speichern
-menu.file.export=KML exportieren
+menu.file.exportkml=KML exportieren
+menu.file.exportpov=POV exportieren
menu.file.exit=Beenden
menu.edit=Bearbeiten
menu.edit.undo=Undo
menu.edit.clearundo=Undo-Liste löschen
+menu.edit.editpoint=Punkt bearbeiten
+menu.edit.editwaypointname=Waypoint Name bearbeiten
menu.edit.deletepoint=Punkt löschen
menu.edit.deleterange=Spanne löschen
menu.edit.deleteduplicates=Duplikate löschen
@@ -49,7 +53,7 @@ dialog.compresstrack.single.text=Punkt wurde entfernt
dialog.compresstrack.multi.text=Punkte wurden entfernt
dialog.compresstrack.nonefound=Keine Punkte konnten entfernt werden
dialog.openoptions.title=Öffnen Optionen
-dialog.openoptions.filesnippet=Extrakt vom File
+dialog.openoptions.filesnippet=Extrakt von der Datei
dialog.load.table.field=Feld
dialog.load.table.datatype=Daten Typ
dialog.load.table.description=Beschreibung
@@ -62,21 +66,39 @@ dialog.delimiter.other=Andere
dialog.openoptions.deliminfo.records=Rekords, mit
dialog.openoptions.deliminfo.fields=Feldern
dialog.openoptions.deliminfo.norecords=Keine Rekords
-dialog.openoptions.tabledesc=Extrakt vom File
+dialog.openoptions.tabledesc=Extrakt von der Datei
dialog.openoptions.altitudeunits=Höhe Maßeinheiten
-dialog.saveoptions.title=File speichern
+dialog.jpegload.subdirectories=Subordnern auch durchsuchen
+dialog.jpegload.progress.title=Fotos werden geladen
+dialog.jpegload.progress=Bitte warten während die Fotos durchgesucht werden
+dialog.jpegload.title=Fotos geladen
+dialog.jpegload.photoadded=Foto wurde geladen
+dialog.jpegload.photosadded=Fotos wurden geladen
+dialog.saveoptions.title=Datei speichern
dialog.save.fieldstosave=Felder zu speichern
dialog.save.table.field=Feld
dialog.save.table.hasdata=Hat Daten
dialog.save.table.save=Speichern
+dialog.save.headerrow=Titel Zeile speichern
dialog.save.coordinateunits=Koordinaten Maßeinheiten
dialog.save.units.original=Original
dialog.save.altitudeunits=Höhe Maßeinheiten
-dialog.save.oktitle=File gespeichert
+dialog.save.oktitle=Datei gespeichert
dialog.save.ok1=Es wurden
dialog.save.ok2=Punkte gespeichert nach
+dialog.save.overwrite.title=Datei existiert
+dialog.save.overwrite.text=Diese Datei existiert schon. Sind Sie sicher, Sie wollen die Datei überschreiben?
dialog.exportkml.title=KML exportieren
dialog.exportkml.text=Kurze Beschreibung von den Daten
+dialog.exportkml.filetype=KML Dateien
+dialog.exportpov.title=POV exportieren
+dialog.exportpov.text=Geben Sie die Parameter ein für das POV Export
+dialog.exportpov.font=Font
+dialog.exportpov.camerax=Kamera X
+dialog.exportpov.cameray=Kamera Y
+dialog.exportpov.cameraz=Kamera Z
+dialog.exportpov.filetype=POV Dateien
+dialog.exportpov.warningtracksize=Dieser Track hat sehr viele Punkte, die Java3D vielleicht nicht bearbeiten kann.\nSind Sie sicher, Sie wollen fortsetzen?
dialog.confirmreversetrack.title=Umkehrung bestätigen
dialog.confirmreversetrack.text=Diese Daten enthalten Zeitstempel Informationen, die bei einer Umkehrung ausser Reihenfolge erscheinen würden.\nSind Sie sicher, Sie wollen diese Spanne umkehren?
dialog.interpolate.title=Punkte interpolieren
@@ -90,12 +112,29 @@ dialog.undo.none.title=Undo nicht m
dialog.undo.none.text=Keine Operationen können rückgängig gemacht werden.
dialog.clearundo.title=Undo-Liste löschen
dialog.clearundo.text=Sind Sie sicher, Sie wollen die Undo-Liste löschen?\nAlle Undo Information wird veloren gehen!
-dialog.about.title=Über
+dialog.pointedit.title=Punkt bearbeiten
+dialog.pointedit.text=Wählen Sie jeden Feld aus zu bearbeiten, und mit dem 'Bearbeiten' Knopf den Wert ändern
+dialog.pointedit.table.field=Feld
+dialog.pointedit.table.value=Wert
+dialog.pointedit.table.changed=Geändert
+dialog.pointedit.changevalue.text=Geben Sie den neuen Wert für dieses Feld ein
+dialog.pointedit.changevalue.title=Feld bearbeiten
+dialog.pointnameedit.title=Waypoint Name bearbeiten
+dialog.pointnameedit.name=Waypoint Name
+dialog.pointnameedit.uppercase=GROSS geschrieben
+dialog.pointnameedit.lowercase=klein geschrieben
+dialog.pointnameedit.sentencecase=Gemischt geschrieben
+dialog.about.title=Über Prune
dialog.about.version=Version
dialog.about.build=Build
dialog.about.summarytext1=Prune ist ein Programm für das Laden, Darstellen und Editieren von Daten von GPS Geräten.
-dialog.about.summarytext2=Es ist unter den Gnu GPL zur Verfügung gestellt, für frei, gratis und offen Gebrauch und Weiterentwicklung.
Kopieren, Weiterverbreitung und Veränderungen sind erlaubt und willkommen
unter die Bedingungen im enthaltenen license.txt
File.
+dialog.about.summarytext2=Es ist unter den Gnu GPL zur Verfügung gestellt, für frei, gratis und offen Gebrauch und Weiterentwicklung.
Kopieren, Weiterverbreitung und Veränderungen sind erlaubt und willkommen
unter die Bedingungen in der enthaltenen license.txt
Datei.
dialog.about.summarytext3=Bitte sehen Sie http://activityworkshop.net/
für weitere Information und Benutzeranleitungen.
+dialog.about.translatedby=Deutsche Übersetzung von activityworkshop.
+
+# 3d window
+dialog.3d.title=Prune Drei-D Ansicht
+dialog.3d.altitudecap=Minimum Höhenskala
# Buttons
button.ok=OK
@@ -103,13 +142,17 @@ button.back=Zur
button.next=Vorwärts
button.finish=Fertig
button.cancel=Abbrechen
+button.overwrite=Überschreiben
button.moveup=Aufwärts moven
button.movedown=Abwärts moven
button.startrange=Start setzen
button.endrange=Stopp setzen
button.deletepoint=Punkt löschen
button.deleterange=Spanne löschen
+button.edit=Bearbeiten
button.exit=Beenden
+button.close=Schließen
+button.continue=Fortsetzen
# Display components
display.nodata=Keine Daten geladen
@@ -123,6 +166,7 @@ details.pointdetails=Details vom Punkt
details.index.selected=Index
details.index.of=von
details.nopointselection=Nichts selektiert
+details.photofile=Foto Datei
details.norangeselection=Nichts selektiert
details.rangedetails=Details von Spanne
details.range.selected=Selektiert
@@ -135,6 +179,8 @@ display.range.time.secs=S
display.range.time.mins=M
display.range.time.hours=Std
display.range.time.days=T
+details.waypointsphotos.waypoints=Waypoints
+details.waypointsphotos.photos=Fotos
# Field names
fieldname.latitude=Breitengrad
@@ -162,12 +208,20 @@ units.degminsec=Grad-Min-Sek
units.degmin=Grad-Min
units.deg=Grad
+# Cardinals for 3d plots
+cardinal.n=N
+cardinal.s=S
+cardinal.e=O
+cardinal.w=W
+
# Undo operations
undo.load=Daten laden
+undo.loadphotos=Fotos laden
+undo.editpoint=Punkt bearbeiten
undo.deletepoint=Punkt löschen
undo.deleterange=Spanne löschen
undo.compress=Track komprimieren
-undo.insert=Punkte dazufügen
+undo.insert=Punkte hinzufügen
undo.deleteduplicates=Duplikaten löschen
undo.reverse=Spanne umdrehen
undo.rearrangewaypoints=Waypoints reorganisieren
@@ -175,13 +229,20 @@ undo.rearrangewaypoints=Waypoints reorganisieren
# Error messages
error.save.dialogtitle=Fehler beim Speichern
error.save.nodata=Keine Daten wurden geladen
-error.save.fileexists=File existiert schon. Um sicher zu sein, wird dieses Programm den File nicht überschreiben.
-error.save.failed=Speichern vom File fehlgeschlagen :
+error.save.failed=Speichern von der Datei fehlgeschlagen :
error.load.dialogtitle=Fehler beim Laden
-error.load.noread=File konnte nicht gelesen werden
+error.load.noread=Datei konnte nicht gelesen werden
+error.jpegload.dialogtitle=Fehler beim Laden von Fotos
+error.jpegload.nofilesfound=Keine Dateien gefunden
+error.jpegload.nojpegsfound=Keine Jpeg Dateien gefunden
+error.jpegload.noexiffound=Keine EXIF Information gefunden
+error.jpegload.nogpsfound=Keine GPS Information gefunden
error.undofailed.title=Undo fehlgeschlagen
error.undofailed.text=Operation konnte nicht rückgängig gemacht werden
error.function.noop.title=Funktion hat nichts gemacht
error.rearrange.noop=Waypoints Reorganisieren hatte keinen Effekt
-error.function.notimplemented.title=Funktion nicht verfügbar
error.function.notimplemented=Sorry, diese Funktion wurde noch nicht implementiert.
+error.function.notavailable.title=Funktion nicht verfügbar
+error.function.nojava3d=Diese Funktion braucht den Java3d Library,\nvon Sun.com oder Blackdown.org erhältlich.
+error.3d.title=Fehler mit 3d Darstellung
+error.3d=Ein Fehler ist mit der 3d Darstellung aufgetreten
diff --git a/tim/prune/lang/prune-texts_de_CH.properties b/tim/prune/lang/prune-texts_de_CH.properties
index dd7bc9f..e48b3b7 100644
--- a/tim/prune/lang/prune-texts_de_CH.properties
+++ b/tim/prune/lang/prune-texts_de_CH.properties
@@ -4,18 +4,22 @@
# Menu entries
menu.file=Datei
menu.file.open=Öffne
+menu.file.addphotos=Fötelis innätue
menu.file.save=Speichere
-menu.file.export=KML exportiere
+menu.file.exportkml=KML exportiere
+menu.file.exportpov=POV exportiere
menu.file.exit=Beände
menu.edit=Editiere
menu.edit.undo=Undo
menu.edit.clearundo=Undo-Liste lösche
+menu.edit.editpoint=Punkt editiere
+menu.edit.editwaypointname=Waypoint Name editiere
menu.edit.deletepoint=Punkt lösche
menu.edit.deleterange=Spanne lösche
menu.edit.deleteduplicates=Doppeldate lösche
menu.edit.compress=Date komprimiere
menu.edit.interpolate=Interpoliere
-menu.edit.reverse=Spanne umkehre
+menu.edit.reverse=Spanne umdrähie
menu.edit.rearrange=Waypoints reorganisiere
menu.edit.rearrange.start=Alli zum Aafang
menu.edit.rearrange.end=Alli zum Ände
@@ -63,20 +67,38 @@ dialog.openoptions.deliminfo.records=Rekords, mit
dialog.openoptions.deliminfo.fields=Fäldere
dialog.openoptions.deliminfo.norecords=Kei Rekords
dialog.openoptions.tabledesc=Extrakt vom File
-dialog.openoptions.altitudeunits=Höchi Massiiheite
+dialog.openoptions.altitudeunits=Höchi Masseiheite
+dialog.jpegload.subdirectories=Subordnern au
+dialog.jpegload.progress.title=Fötelis lade
+dialog.jpegload.progress=Bitte warte während die Fötolis durägsucht werde
+dialog.jpegload.title=Fötelis glade worde
+dialog.jpegload.photoadded=Föteli isch glade worde
+dialog.jpegload.photosadded=Fötelis sin glade worde
dialog.saveoptions.title=File speichere
dialog.save.fieldstosave=Fälder zu speichere
dialog.save.table.field=Fäld
dialog.save.table.hasdata=Het Date
dialog.save.table.save=Speichere
+dialog.save.headerrow=Titel Ziile speichere
dialog.save.coordinateunits=Koordinate Massiiheite
dialog.save.units.original=Original
dialog.save.altitudeunits=Höchi Massiiheite
dialog.save.oktitle=File gespeichert worde
dialog.save.ok1=Es isch
dialog.save.ok2=Punkte gespeichert worde na
+dialog.save.overwrite.title=s'File existiert scho
+dialog.save.overwrite.text=s'File existiert scho. Sind Sie sicher, Sie wend s'File überschriibe?
dialog.exportkml.title=KML exportiere
dialog.exportkml.text=Kurze Beschriibig von den Date
+dialog.exportkml.filetype=KML Dateie
+dialog.exportpov.title=POV exportiere
+dialog.exportpov.text=Gäbet Sie die Parameter ii fürs POV Export
+dialog.exportpov.font=Font
+dialog.exportpov.camerax=Kamera X
+dialog.exportpov.cameray=Kamera Y
+dialog.exportpov.cameraz=Kamera Z
+dialog.exportpov.filetype=POV Dateie
+dialog.exportpov.warningtracksize=Dieser Track hät sehr viele Punkte, die Java3D villiicht nöd chann bearbeite.\nSind Sie sicher, Sie wend trotzdem fortsetze?
dialog.confirmreversetrack.title=Umdrehig bestätige
dialog.confirmreversetrack.text=Diese Daten enthalte Ziitstämpel Informatione, die bei dr Umkehrig usser Reihefolge erschiene würdi.\nSind Sie sicher, Sie wend diese Spanne umkehre?
dialog.interpolate.title=Punkte interpoliere
@@ -90,12 +112,29 @@ dialog.undo.none.title=Undo n
dialog.undo.none.text=Keini Operatione könne rückgängig gmacht werde.
dialog.clearundo.title=Undo-Liste lösche
dialog.clearundo.text=Sind Sie sicher, Sie wend die Undo-Liste lösche?\nAlle Undo Infos werdet verlore gah!
-dialog.about.title=Über
+dialog.pointedit.title=Punkt editiere
+dialog.pointedit.text=Wählet Sie jäden Fäld uus zu editiere, und mitem 'Editiere' Chnopf den Wert ändere
+dialog.pointedit.table.field=Fäld
+dialog.pointedit.table.value=Wert
+dialog.pointedit.table.changed=Geändert
+dialog.pointedit.changevalue.text=Gebet Sie den neuen Wert für diesen Fäld ina
+dialog.pointedit.changevalue.title=Fäld editiere
+dialog.pointnameedit.title=Waypoint Name editiere
+dialog.pointnameedit.name=Waypoint Name
+dialog.pointnameedit.uppercase=GROSS gschriebe
+dialog.pointnameedit.lowercase=chli gschriebe
+dialog.pointnameedit.sentencecase=Gmischt gschriebe
+dialog.about.title=Über Prune
dialog.about.version=Version
dialog.about.build=Build
dialog.about.summarytext1=Prune isch n Programm fürs Lade, Darstelle und Editiere vo Date von GPS Geräte.
dialog.about.summarytext2=Es isch unter den Gnu GPL zur Verfüegig gstellt,für frei, gratis und offen Gebruuch und Wiiterentwicklig.
Kopiere, Wiiterverbreitig und Veränderige sin erlaubt und willkommen
unter die Bedingunge im enthaltene license.txt
File.
dialog.about.summarytext3=Bitte lueg na http://activityworkshop.net/
für wiitere Information und Benutzeraaleitige.
+dialog.about.translatedby=Schwiizerdüütschi Übersetzig vo activityworkshop.
+
+# 3d window
+dialog.3d.title=Prune Drüü-d aasicht
+dialog.3d.altitudecap=Minimum Höhenskala
# Buttons
button.ok=OK
@@ -103,13 +142,17 @@ button.back=Zrugg
button.next=Nöchste
button.finish=Fertig
button.cancel=Abbräche
+button.overwrite=Überschriibe
button.moveup=Uufwärts move
button.movedown=Abwärts move
button.startrange=Start setze
button.endrange=Stopp setze
button.deletepoint=Punkt lösche
button.deleterange=Spanne lösche
+button.edit=Editiere
button.exit=Beände
+button.close=Schliesse
+button.continue=Fortsetze
# Display components
display.nodata=Kei Date glade worde
@@ -123,6 +166,7 @@ details.pointdetails=Details vom Punkt
details.index.selected=Index
details.index.of=vo
details.nopointselection=Nüüt selektiert
+details.photofile=Föteli Datei
details.norangeselection=Nüüt selektiert
details.rangedetails=Details vo dr Spanne
details.range.selected=Selektiert
@@ -135,6 +179,8 @@ display.range.time.secs=S
display.range.time.mins=M
display.range.time.hours=Std
display.range.time.days=T
+details.waypointsphotos.waypoints=Waypoints
+details.waypointsphotos.photos=Fötelis
# Field names
fieldname.latitude=Breitegrad
@@ -162,8 +208,16 @@ units.degminsec=Grad-Min-Sek
units.degmin=Grad-Min
units.deg=Grad
+# Cardinals for 3d plots
+cardinal.n=N
+cardinal.s=S
+cardinal.e=O
+cardinal.w=W
+
# Undo operations
undo.load=Date lade
+undo.loadphotos=Fötelis lade
+undo.editpoint=Punkt editiere
undo.deletepoint=Punkt lösche
undo.deleterange=Spanne lösche
undo.compress=Track komprimiere
@@ -175,13 +229,20 @@ undo.rearrangewaypoints=Waypoints reorganisiere
# Error messages
error.save.dialogtitle=Fehler bim Speichere
error.save.nodata=Kei Date zum speichere
-error.save.fileexists=File existiert scho. Um sicher z'sii, wird s'Programm s'File nöd überschriibe.
error.save.failed=Speichere vom File fehlgschlage :
error.load.dialogtitle=Fehler bim Lade
error.load.noread=File cha nöd glase werde
-error.undofailed.title=Undo isch fehlgschlage
+error.jpegload.dialogtitle=Fehler bim Lade von Fötelis
+error.jpegload.nofilesfound=Kei Dateie gfunde
+error.jpegload.nojpegsfound=Kei Jpegs gfunde
+error.jpegload.noexiffound=Kei EXIF Information gfunde
+error.jpegload.nogpsfound=Kei GPS Information gfunde
+error.undofailed.title=Undo isch fehlgschlage worde
error.undofailed.text=Operation kann nöd rückgängig gmacht werde
error.function.noop.title=Funktion hät gar nüüt gmacht
error.rearrange.noop=Waypoints Reorganisiere hät kein Effäkt gha
-error.function.notimplemented.title=Funktion nöd verfüegbar
error.function.notimplemented=Sorry, d'Funktion isch nonig implementiert worde.
+error.function.notavailable.title=Funktion nöd verfüegbar
+error.function.nojava3d=Sorry, d'Funktion brucht d Java3d Library,\nvo Sun.com odr Blackdown.org erhältlech.
+error.3d.title=Fähler mitm 3d Darstellig
+error.3d=N Fähler isch mitm 3d Darstellig ufgtrete
diff --git a/tim/prune/readme.txt b/tim/prune/readme.txt
index fc788d2..4437095 100644
--- a/tim/prune/readme.txt
+++ b/tim/prune/readme.txt
@@ -1,4 +1,4 @@
-Prune version 1
+Prune version 2
===============
Prune is an application for viewing, editing and managing coordinate data from GPS systems.
@@ -14,8 +14,8 @@ losses incurred through use of the program, however caused.
Running
=======
-To run Prune from the jar file, simply call it from a Command Prompt or shell:
- java -jar prune_1.jar
+To run Prune from the jar file, simply call it from a command prompt or shell:
+ java -jar prune_02.jar
If the jar file is saved in a different directory, you will need to include the path.
Depending on your system settings, you may be able to click or double-click on the jar file
@@ -23,6 +23,16 @@ in a file manager window to execute it. A shortcut, menu item, desktop icon or
can of course be made should you wish.
+Updates since version 1
+=======================
+
+The following features were added since version 1:
+ - Display of data in 3d view using Java3D library
+ - Export of 3d model to POV format for rendering by povray
+ - Point edit dialog, waypoint name edit dialog
+ - Waypoint list
+
+
Further information and updates
===============================
diff --git a/tim/prune/save/FileSaver.java b/tim/prune/save/FileSaver.java
index b1ea368..f5f92bc 100644
--- a/tim/prune/save/FileSaver.java
+++ b/tim/prune/save/FileSaver.java
@@ -17,6 +17,7 @@ import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
+import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
@@ -56,6 +57,7 @@ public class FileSaver
private JButton _moveUpButton = null, _moveDownButton = null;
private JRadioButton[] _delimiterRadios = null;
private JTextField _otherDelimiterText = null;
+ private JCheckBox _headerRowCheckbox = null;
private JRadioButton[] _coordUnitsRadios = null;
private JRadioButton[] _altitudeUnitsRadios = null;
private static final int[] FORMAT_COORDS = {Coordinate.FORMAT_NONE, Coordinate.FORMAT_DEG_MIN_SEC,
@@ -214,6 +216,12 @@ public class FileSaver
}
delimsPanel.add(otherPanel);
firstCard.add(delimsPanel);
+
+ // header checkbox
+ firstCard.add(Box.createRigidArea(new Dimension(0,10)));
+ _headerRowCheckbox = new JCheckBox(I18nManager.getText("dialog.save.headerrow"));
+ firstCard.add(_headerRowCheckbox);
+
_cards.add(firstCard, "card1");
JPanel secondCard = new JPanel();
@@ -260,6 +268,7 @@ public class FileSaver
}
altUnitsPanel.setAlignmentX(JPanel.LEFT_ALIGNMENT);
secondCardHolder.add(altUnitsPanel);
+ // TODO: selection of format of timestamps
secondCard.add(secondCardHolder, BorderLayout.NORTH);
_cards.add(secondCard, "card2");
@@ -270,10 +279,10 @@ public class FileSaver
_backButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
- CardLayout cl = (CardLayout)(_cards.getLayout());
- cl.previous(_cards);
- _backButton.setEnabled(false);
- _nextButton.setEnabled(true);
+ CardLayout cl = (CardLayout)(_cards.getLayout());
+ cl.previous(_cards);
+ _backButton.setEnabled(false);
+ _nextButton.setEnabled(true);
}
});
_backButton.setEnabled(false);
@@ -283,10 +292,10 @@ public class FileSaver
_nextButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
- CardLayout cl = (CardLayout)(_cards.getLayout());
- cl.next(_cards);
- _backButton.setEnabled(true);
- _nextButton.setEnabled(false);
+ CardLayout cl = (CardLayout)(_cards.getLayout());
+ cl.next(_cards);
+ _backButton.setEnabled(true);
+ _nextButton.setEnabled(false);
}
});
buttonPanel.add(_nextButton);
@@ -336,11 +345,20 @@ public class FileSaver
coordFormat = FORMAT_COORDS[i];
int altitudeFormat = Altitude.FORMAT_NONE;
for (int i=0; i<_altitudeUnitsRadios.length; i++)
+ {
if (_altitudeUnitsRadios[i].isSelected())
+ {
altitudeFormat = FORMAT_ALTS[i];
-
- // Check if file exists, don't overwrite any files for v1!
- if (!saveFile.exists())
+ }
+ }
+
+ // Check if file exists, and confirm overwrite if necessary
+ Object[] buttonTexts = {I18nManager.getText("button.overwrite"), I18nManager.getText("button.cancel")};
+ if (!saveFile.exists() || JOptionPane.showOptionDialog(_parentFrame,
+ I18nManager.getText("dialog.save.overwrite.text"),
+ I18nManager.getText("dialog.save.overwrite.title"), JOptionPane.YES_NO_OPTION,
+ JOptionPane.WARNING_MESSAGE, null, buttonTexts, buttonTexts[1])
+ == JOptionPane.YES_OPTION)
{
try
{
@@ -350,14 +368,39 @@ public class FileSaver
char delimiter = getDelimiter();
FieldInfo info = null;
Field field = null;
+
StringBuffer buffer = null;
- // For now, just spit out to console
- int numPoints = _track.getNumPoints();
int numFields = _model.getRowCount();
+ boolean firstField = true;
+ // Write header row if required
+ if (_headerRowCheckbox.isSelected())
+ {
+ buffer = new StringBuffer();
+ for (int f=0; f\n\n\n");
writer.write("\t");
writer.write(inDescription);
@@ -127,6 +131,7 @@ public class KmlExporter
DataPoint point = null;
boolean hasTrackpoints = false;
// Loop over waypoints
+ boolean writtenPhotoHeader = false;
int numPoints = _track.getNumPoints();
for (i=0; ihttp://maps.google.com/mapfiles/kml/pal4/icon46.png");
+ writtenPhotoHeader = true;
+ }
+ exportPhotoPoint(point, writer);
+ }
else
{
hasTrackpoints = true;
@@ -160,12 +174,16 @@ public class KmlExporter
writer.close();
JOptionPane.showMessageDialog(_parentFrame, I18nManager.getText("dialog.save.ok1")
+ " " + numPoints + " " + I18nManager.getText("dialog.save.ok2")
- + inFile.getAbsolutePath(),
+ + " " + inFile.getAbsolutePath(),
I18nManager.getText("dialog.save.oktitle"), JOptionPane.INFORMATION_MESSAGE);
return true;
}
catch (IOException ioe)
{
+ try {
+ if (writer != null) writer.close();
+ }
+ catch (IOException ioe2) {}
JOptionPane.showMessageDialog(_parentFrame, I18nManager.getText("error.save.failed") + ioe.getMessage(),
I18nManager.getText("error.save.dialogtitle"), JOptionPane.ERROR_MESSAGE);
}
@@ -177,12 +195,34 @@ public class KmlExporter
* Export the specified waypoint into the file
* @param inPoint waypoint to export
* @param inWriter writer object
+ * @throws IOException on write failure
*/
private void exportWaypoint(DataPoint inPoint, Writer inWriter) throws IOException
{
inWriter.write("\t\n\t\t");
- inWriter.write(inPoint.getFieldValue(Field.WAYPT_NAME).trim());
+ inWriter.write(inPoint.getWaypointName().trim());
+ inWriter.write("\n");
+ inWriter.write("\t\t\n\t\t\t");
+ inWriter.write(inPoint.getLongitude().output(Coordinate.FORMAT_DEG_WITHOUT_CARDINAL));
+ inWriter.write(',');
+ inWriter.write(inPoint.getLatitude().output(Coordinate.FORMAT_DEG_WITHOUT_CARDINAL));
+ inWriter.write(",0\n\t\t\n\t\n");
+ }
+
+
+ /**
+ * Export the specified photo into the file
+ * @param inPoint data point including photo
+ * @param inWriter writer object
+ * @throws IOException on write failure
+ */
+ private void exportPhotoPoint(DataPoint inPoint, Writer inWriter) throws IOException
+ {
+ // TODO: Export photos to KML too - for photos need kmz!
+ inWriter.write("\t\n\t\t");
+ inWriter.write(inPoint.getPhoto().getFile().getName());
inWriter.write("\n");
+ inWriter.write("#camera_icon\n");
inWriter.write("\t\t\n\t\t\t");
inWriter.write(inPoint.getLongitude().output(Coordinate.FORMAT_DEG_WITHOUT_CARDINAL));
inWriter.write(',');
diff --git a/tim/prune/undo/UndoDeletePoint.java b/tim/prune/undo/UndoDeletePoint.java
index ebc4d89..4cc09b4 100644
--- a/tim/prune/undo/UndoDeletePoint.java
+++ b/tim/prune/undo/UndoDeletePoint.java
@@ -2,7 +2,6 @@ package tim.prune.undo;
import tim.prune.I18nManager;
import tim.prune.data.DataPoint;
-import tim.prune.data.Field;
import tim.prune.data.TrackInfo;
/**
@@ -32,7 +31,7 @@ public class UndoDeletePoint implements UndoOperation
public String getDescription()
{
String desc = I18nManager.getText("undo.deletepoint");
- String pointName = _point.getFieldValue(Field.WAYPT_NAME);
+ String pointName = _point.getWaypointName();
if (pointName != null && !pointName.equals(""))
desc = desc + " " + pointName;
return desc;
@@ -50,5 +49,6 @@ public class UndoDeletePoint implements UndoOperation
{
throw new UndoException(getDescription());
}
+ // TODO: Reinsert photo into list if necessary
}
}
\ No newline at end of file
--
2.43.0