From: activityworkshop Date: Sat, 14 Feb 2015 13:38:26 +0000 (+0100) Subject: Version 2, March 2007 X-Git-Tag: v19.2~38 X-Git-Url: http://gitweb.fperrin.net/?p=GpsPrune.git;a=commitdiff_plain;h=d3679d647d57c2ee7376ddbf6def2d5b23c04307 Version 2, March 2007 --- 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