]> gitweb.fperrin.net Git - GpsPrune.git/commitdiff
Merge branch 'srtm-multi-sources' into fp-integration v19.2.fp3
authorFrédéric Perrin <fred@fperrin.net>
Sun, 1 Dec 2019 21:37:03 +0000 (21:37 +0000)
committerFrédéric Perrin <fred@fperrin.net>
Sun, 1 Dec 2019 21:37:03 +0000 (21:37 +0000)
21 files changed:
.gitignore [new file with mode: 0644]
buildtools/build.sh [changed mode: 0644->0755]
src/tim/prune/App.java
src/tim/prune/FunctionLibrary.java
src/tim/prune/data/DataPoint.java
src/tim/prune/data/FileInfo.java
src/tim/prune/data/Track.java
src/tim/prune/function/RemoveAltitudes.java [new file with mode: 0644]
src/tim/prune/function/edit/PointEditor.java
src/tim/prune/function/edit/PointNameEditor.java
src/tim/prune/gui/DisplayUtils.java
src/tim/prune/gui/MenuManager.java
src/tim/prune/gui/SelectorDisplay.java
src/tim/prune/gui/Viewport.java
src/tim/prune/gui/map/MapCanvas.java
src/tim/prune/gui/map/MapPosition.java
src/tim/prune/gui/map/MapSource.java
src/tim/prune/gui/map/MapTileManager.java
src/tim/prune/gui/map/OsmMapSource.java
src/tim/prune/lang/prune-texts_en.properties
src/tim/prune/undo/UndoRemoveAltitudes.java [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..8e9e794
--- /dev/null
@@ -0,0 +1,2 @@
+*.class
+*.jar
old mode 100644 (file)
new mode 100755 (executable)
index b38e2ce..c7fcf3d
@@ -1,3 +1,4 @@
+set -e
 # Build script
 # Version number
 PRUNENAME=gpsprune_19.2
index 3a778588ab815a7f30c4b396e4de9d2c266836da..317064d39984acb566cee90940236c52c32fd58f 100644 (file)
@@ -51,6 +51,7 @@ public class App
 {
        // Instance variables
        private JFrame _frame = null;
+       private String _titlePrefix = null;
        private Track _track = null;
        private TrackInfo _trackInfo = null;
        private int _lastSavePosition = 0;
@@ -79,6 +80,7 @@ public class App
        public App(JFrame inFrame)
        {
                _frame = inFrame;
+               _titlePrefix = _frame.getTitle();
                _undoStack = new UndoStack();
                _track = new Track();
                _trackInfo = new TrackInfo(_track);
@@ -454,6 +456,22 @@ public class App
        }
 
 
+       /**
+        * Remove altitudes from selected points
+        */
+       public void removeAltitudes(int selStart, int selEnd)
+       {
+               UndoRemoveAltitudes undo = new UndoRemoveAltitudes(_trackInfo, selStart, selEnd);
+               if (_trackInfo.getTrack().removeAltitudes(selStart, selEnd))
+               {
+                       _undoStack.add(undo);
+                       _trackInfo.getSelection().markInvalid();
+                       UpdateMessageBroker.informSubscribers(DataSubscriber.DATA_EDITED);
+                       UpdateMessageBroker.informSubscribers(I18nManager.getText("confirm.removealtitudes"));
+               }
+       }
+
+
        /**
         * Merge the track segments within the current selection
         */
@@ -759,6 +777,10 @@ public class App
                        + " '" + inSourceInfo.getName() + "'");
                // update menu
                _menuManager.informFileLoaded();
+               // recentre viewport on new file data
+               _viewport.recentreViewport();
+               // update main window title
+               updateTitle();
                // Remove busy lock
                _busyLoading = false;
                // load next file if there's a queue
@@ -1001,4 +1023,16 @@ public class App
        public void setCurrentMode(AppMode inMode) {
                _appMode = inMode;
        }
+
+       /** Update main window title **/
+       public void updateTitle() {
+               ArrayList<String> filenames = _trackInfo.getFileInfo().getFilenames();
+               if (filenames.size() > 0) {
+                       _frame.setTitle(_titlePrefix + ": " + String.join(", ", filenames));
+               }
+               else
+               {
+                       _frame.setTitle(_titlePrefix);
+               }
+       }
 }
index ea78e9a175e0ba7b7f3d4edb6e95ac23c854bd78..4be286e479d036a8b37cabe8223f495872a2f361 100644 (file)
@@ -28,6 +28,7 @@ import tim.prune.function.PhotoPopupFunction;
 import tim.prune.function.PlayAudioFunction;
 import tim.prune.function.RearrangePhotosFunction;
 import tim.prune.function.RearrangeWaypointsFunction;
+import tim.prune.function.RemoveAltitudes;
 import tim.prune.function.RemoveAudioFunction;
 import tim.prune.function.RemovePhotoFunction;
 import tim.prune.function.RotatePhoto;
@@ -109,6 +110,7 @@ public abstract class FunctionLibrary
        public static GenericFunction FUNCTION_DOWNLOAD_OSM = null;
        public static GenericFunction FUNCTION_ADD_TIME_OFFSET  = null;
        public static GenericFunction FUNCTION_ADD_ALTITUDE_OFFSET  = null;
+       public static GenericFunction FUNCTION_REMOVE_ALTITUDES = null;
        public static GenericFunction FUNCTION_CONVERT_NAMES_TO_TIMES  = null;
        public static GenericFunction FUNCTION_DELETE_FIELD_VALUES  = null;
        public static GenericFunction FUNCTION_PASTE_COORDINATES = null;
@@ -189,6 +191,7 @@ public abstract class FunctionLibrary
                FUNCTION_DOWNLOAD_OSM = new DownloadOsmFunction(inApp);
                FUNCTION_ADD_TIME_OFFSET = new AddTimeOffset(inApp);
                FUNCTION_ADD_ALTITUDE_OFFSET = new AddAltitudeOffset(inApp);
+               FUNCTION_REMOVE_ALTITUDES = new RemoveAltitudes(inApp);
                FUNCTION_CONVERT_NAMES_TO_TIMES = new ConvertNamesToTimes(inApp);
                FUNCTION_DELETE_FIELD_VALUES = new DeleteFieldValues(inApp);
                FUNCTION_PASTE_COORDINATES = new PasteCoordinates(inApp);
index 84f4800bcd2c0a0d546da8a83a87868810bf3a54..01e9975786139a1736653d68dd1fd747109b3788 100644 (file)
@@ -354,6 +354,16 @@ public class DataPoint
                }
        }
 
+       /**
+        * Remove altitude from point
+        */
+       public void removeAltitude()
+       {
+               _altitude = Altitude.NONE;
+               _fieldValues[_fieldList.getFieldIndex(Field.ALTITUDE)] = _altitude.getStringValue(null);
+               setModified(false);
+       }
+
        /**
         * Reset the altitude to the previous value (by an undo)
         * @param inClone altitude object cloned from earlier
index 41900cb8736df60d668238306079256bf2dca175..7eaac8f307d1bcde51f68a3bf662cd6879adeab2 100644 (file)
@@ -74,6 +74,19 @@ public class FileInfo
                return "";
        }
 
+       /**
+        * @return The source names
+        */
+       public ArrayList<String> getFilenames()
+       {
+               ArrayList<String> filenames = new ArrayList<String>();
+               for (SourceInfo source : _sources)
+               {
+                       filenames.add(source.getName());
+               }
+               return filenames;
+       }
+
        /**
         * @param inIndex index number, starting from zero
         * @return source info object
index f45854a0e3d47a1fd5fc0ee6924732b3294decc0..ef099d4c171d1651bfd627a3beb71bd271943a15 100644 (file)
@@ -377,6 +377,31 @@ public class Track
        }
 
 
+       /**
+        * Remove altitudes from the specified range
+        * @param inStart start of range
+        * @param inEnd end of range
+        */
+       public boolean removeAltitudes(int inStart, int inEnd)
+       {
+               // sanity check
+               if (inStart < 0 || inEnd < 0 || inStart >= inEnd || inEnd >= _numPoints) {
+                       return false;
+               }
+
+               boolean anyRemoved = false;
+               for (int i=inStart; i<=inEnd; i++)
+               {
+                       DataPoint p = _dataPoints[i];
+                       if (p != null && p.hasAltitude())
+                       {
+                               p.removeAltitude();
+                               anyRemoved = true;
+                       }
+               }
+               return anyRemoved;
+       }
+
        /**
         * Interleave all waypoints by each nearest track point
         * @return true if successful, false if no change
diff --git a/src/tim/prune/function/RemoveAltitudes.java b/src/tim/prune/function/RemoveAltitudes.java
new file mode 100644 (file)
index 0000000..1c8b05c
--- /dev/null
@@ -0,0 +1,60 @@
+package tim.prune.function;
+
+import java.awt.BorderLayout;
+import java.awt.FlowLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseAdapter;
+
+import javax.swing.BorderFactory;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+
+import tim.prune.App;
+import tim.prune.GenericFunction;
+import tim.prune.I18nManager;
+import tim.prune.config.Config;
+import tim.prune.data.Field;
+import tim.prune.data.Unit;
+import tim.prune.data.UnitSetLibrary;
+
+/**
+ * Class to provide the function to add remove the altitude from points in a
+ * track range
+ */
+public class RemoveAltitudes extends GenericFunction
+{
+       /**
+        * Constructor
+        * @param inApp application object for callback
+        */
+       public RemoveAltitudes(App inApp)
+       {
+               super(inApp);
+       }
+
+       /** Get the name key */
+       public String getNameKey() {
+               return "function.removealtitudes";
+       }
+
+       /**
+        * Begin the function
+        */
+       public void begin()
+       {
+               int selStart = _app.getTrackInfo().getSelection().getStart();
+               int selEnd = _app.getTrackInfo().getSelection().getEnd();
+               if (!_app.getTrackInfo().getTrack().hasData(Field.ALTITUDE, selStart, selEnd))
+               {
+                       _app.showErrorMessage(getNameKey(), "dialog.addaltitude.noaltitudes");
+                       return;
+               }
+               _app.removeAltitudes(selStart, selEnd);
+       }
+}
index c66201b8d6f48ebcdf56105daa126077d0b85486..546a65e57e4cec6cf19be1ba0c477d598a7aeb4d 100644 (file)
@@ -307,10 +307,23 @@ public class PointEditor
                        if (_model.getChanged(i))
                        {
                                Field field = fieldList.getField(i);
+                               if (field == field.WAYPT_NAME) {
+                                       if (wasNameAdded(_model.getValue(i))) {
+                                               _app.createPoint(_point.clonePoint());
+                                       }
+                               }
                                editList.addEdit(new FieldEdit(field, _model.getValue(i)));
                                undoList.addEdit(new FieldEdit(field, _point.getFieldValue(field)));
                        }
                }
                _app.completePointEdit(editList, undoList);
        }
+
+       private boolean wasNameAdded(String newName)
+       {
+               String prevName = _point.getWaypointName();
+               boolean prevNull = (prevName == null || prevName.equals(""));
+               boolean newNull = (newName == null || newName.equals(""));
+               return (prevNull && !newNull);
+       }
 }
index 53e1f834b962fa8a098a9fc9345934dbdac3003f..ca5771d45fe9886c2717127b8e80ef257a47dc8e 100644 (file)
@@ -206,7 +206,14 @@ public class PointNameEditor extends GenericFunction
                // Check whether name has really changed
                if (hasNameChanged())
                {
-                       // Make lists for edit and undo, and add the changed field
+                       // If a new name has been added, changing the point
+                       // from trackpoint to waypoint, duplicate it
+                       if (wasNameAdded())
+                       {
+                               _app.createPoint(_point.clonePoint());
+                       }
+
+                       // make lists for edit and undo, and add the changed field
                        FieldEditList editList = new FieldEditList();
                        FieldEditList undoList = new FieldEditList();
                        editList.addEdit(new FieldEdit(Field.WAYPT_NAME, _nameField.getText().trim()));
@@ -231,4 +238,17 @@ public class PointNameEditor extends GenericFunction
                        || (!prevNull && newNull)
                        || (!prevNull && !newNull && !prevName.equals(newName));
        }
+
+       /**
+        * Check whether a new name has been added
+        * @return true if it has indeed
+        */
+       private boolean wasNameAdded()
+       {
+               String prevName = _point.getWaypointName();
+               String newName = _nameField.getText().trim();
+               boolean prevNull = (prevName == null || prevName.equals(""));
+               boolean newNull = (newName == null || newName.equals(""));
+               return (prevNull && !newNull);
+       }
 }
index 25640d8e5072bfc2e70acfc3e26c7de208a494e3..2300296760fa1febfeb8f2dc59d393ca35bb639a 100644 (file)
@@ -36,7 +36,8 @@ public abstract class DisplayUtils
                if (inNumSecs < 86400L) return "" + (inNumSecs / 60 / 60) + I18nManager.getText("display.range.time.hours")
                        + " " + ((inNumSecs / 60) % 60) + I18nManager.getText("display.range.time.mins");
                if (inNumSecs < 432000L) return "" + (inNumSecs / 86400L) + I18nManager.getText("display.range.time.days")
-                       + " " + (inNumSecs / 60 / 60) % 24 + I18nManager.getText("display.range.time.hours");
+                       + " " + (inNumSecs / 60 / 60) % 24 + I18nManager.getText("display.range.time.hours")
+                       + " " + ((inNumSecs / 60) % 60) + I18nManager.getText("display.range.time.mins");
                if (inNumSecs < 86400000L) return "" + (inNumSecs / 86400L) + I18nManager.getText("display.range.time.days");
                return "big";
        }
index b24c7184998a67c7d04f5cf8f8260c269002d6c9..bd0d37813d40c8d9259707999a7285bafddec348 100644 (file)
@@ -80,6 +80,7 @@ public class MenuManager implements DataSubscriber
        private JMenuItem _reverseItem = null;
        private JMenuItem _addTimeOffsetItem = null;
        private JMenuItem _addAltitudeOffsetItem = null;
+       private JMenuItem _removeAltitudesItem = null;
        private JMenuItem _mergeSegmentsItem = null;
        private JMenuItem _rearrangeWaypointsItem = null;
        private JMenuItem _splitSegmentsItem = null;
@@ -435,6 +436,8 @@ public class MenuManager implements DataSubscriber
                rangeMenu.add(_addTimeOffsetItem);
                _addAltitudeOffsetItem = makeMenuItem(FunctionLibrary.FUNCTION_ADD_ALTITUDE_OFFSET, false);
                rangeMenu.add(_addAltitudeOffsetItem);
+               _removeAltitudesItem = makeMenuItem(FunctionLibrary.FUNCTION_REMOVE_ALTITUDES, false);
+               rangeMenu.add(_removeAltitudesItem);
                _mergeSegmentsItem = new JMenuItem(I18nManager.getText("menu.range.mergetracksegments"));
                _mergeSegmentsItem.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e) {
@@ -968,6 +971,7 @@ public class MenuManager implements DataSubscriber
                _reverseItem.setEnabled(hasRange);
                _addTimeOffsetItem.setEnabled(hasRange);
                _addAltitudeOffsetItem.setEnabled(hasRange);
+               _removeAltitudesItem.setEnabled(hasRange);
                _convertNamesToTimesItem.setEnabled(hasRange && _track.hasWaypoints());
                _deleteFieldValuesItem.setEnabled(hasRange);
                _fullRangeDetailsItem.setEnabled(hasRange);
index fa6630dc5b71400bd4f7202fb688f9a911cc3f6f..9dfc24f42394ad624d925589a2acd344411c12a0 100644 (file)
@@ -228,8 +228,9 @@ public class SelectorDisplay extends GenericDisplay
                        else if (numFiles > 1)
                        {
                                final String labelText = I18nManager.getText("details.track.numfiles") + ": " + numFiles;
+                               final String filenameString = String.join(", ", _trackInfo.getFileInfo().getFilenames());
                                _filenameLabel.setText(labelText);
-                               _filenameLabel.setToolTipText(labelText);
+                               _filenameLabel.setToolTipText(filenameString);
                        }
                        else
                        {
index 25eba2fb1847306d41aed63021c7cbe3e4ed2cf0..aec78a61f7703e3f3f97807c5347a04a91743708 100644 (file)
@@ -40,4 +40,12 @@ public class Viewport
                double maxLon = MapUtils.getLongitudeFromX(mapPosition.getXFromPixels(width, width));
                return new double[] {minLat, minLon, maxLat, maxLon};
        }
+
+       /**
+        * Recentre the viewport on the data
+        */
+       public void recentreViewport()
+       {
+               _mapCanvas.zoomToFit();
+       }
 }
index aa25dbcd939e39b96a6642f188b68665d4c74c4f..ad38d8182700cf49a1d5055f66bbb4ec8b56a20e 100644 (file)
@@ -92,7 +92,7 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
        WpIconDefinition _waypointIconDefinition = null;
 
        /** Constant for click sensitivity when selecting nearest point */
-       private static final int CLICK_SENSITIVITY = 10;
+       private static final int CLICK_SENSITIVITY = 30;
        /** Constant for pan distance from key presses */
        private static final int PAN_DISTANCE = 20;
        /** Constant for pan distance from autopan */
@@ -259,8 +259,8 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
 
                // add control panels to this one
                setLayout(new BorderLayout());
-               _topPanel.setVisible(false);
-               _sidePanel.setVisible(false);
+               _topPanel.setVisible(true);
+               _sidePanel.setVisible(true);
                add(_topPanel, BorderLayout.NORTH);
                add(_sidePanel, BorderLayout.WEST);
                add(_scaleBar, BorderLayout.SOUTH);
@@ -337,16 +337,19 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
        /**
         * Zoom to fit the current data area
         */
-       private void zoomToFit()
+       public void zoomToFit()
        {
+               int maxZoom = (_track.getNumPoints() == 0)?2:_tileManager.getMaxZoomLevel();
                _latRange = _track.getLatRange();
                _lonRange = _track.getLonRange();
                _xRange = new DoubleRange(MapUtils.getXFromLongitude(_lonRange.getMinimum()),
                        MapUtils.getXFromLongitude(_lonRange.getMaximum()));
                _yRange = new DoubleRange(MapUtils.getYFromLatitude(_latRange.getMinimum()),
                        MapUtils.getYFromLatitude(_latRange.getMaximum()));
-               _mapPosition.zoomToXY(_xRange.getMinimum(), _xRange.getMaximum(), _yRange.getMinimum(), _yRange.getMaximum(),
-                       getWidth(), getHeight());
+               _mapPosition.zoomToXY(
+                       _xRange.getMinimum(), _xRange.getMaximum(),
+                       _yRange.getMinimum(), _yRange.getMaximum(),
+                       getWidth(), getHeight(), maxZoom);
        }
 
 
@@ -360,70 +363,59 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
                if (_mapImage != null && (_mapImage.getWidth() != getWidth() || _mapImage.getHeight() != getHeight())) {
                        _mapImage = null;
                }
-               if (_track.getNumPoints() > 0)
+               // Check for autopan if enabled / necessary
+               if (_autopanCheckBox.isSelected())
                {
-                       // Check for autopan if enabled / necessary
-                       if (_autopanCheckBox.isSelected())
+                       int selectedPoint = _selection.getCurrentPointIndex();
+                       if (selectedPoint >= 0 && _dragFromX == -1 && selectedPoint != _prevSelectedPoint)
                        {
-                               int selectedPoint = _selection.getCurrentPointIndex();
-                               if (selectedPoint >= 0 && _dragFromX == -1 && selectedPoint != _prevSelectedPoint)
-                               {
-                                       autopanToPoint(selectedPoint);
-                               }
-                               _prevSelectedPoint = selectedPoint;
+                               autopanToPoint(selectedPoint);
                        }
+                       _prevSelectedPoint = selectedPoint;
+               }
 
-                       // Draw the map contents if necessary
-                       if (_mapImage == null || _recalculate)
-                       {
-                               paintMapContents();
-                               _scaleBar.updateScale(_mapPosition.getZoom(), _mapPosition.getYFromPixels(0, 0));
-                       }
-                       // Draw the prepared image onto the panel
-                       if (_mapImage != null) {
-                               inG.drawImage(_mapImage, 0, 0, getWidth(), getHeight(), null);
-                       }
+               // Draw the map contents if necessary
+               if (_mapImage == null || _recalculate)
+               {
+                       paintMapContents();
+                       _scaleBar.updateScale(_mapPosition.getZoom(), _mapPosition.getYFromPixels(0, 0));
+               }
+               // Draw the prepared image onto the panel
+               if (_mapImage != null) {
+                       inG.drawImage(_mapImage, 0, 0, getWidth(), getHeight(), null);
+               }
 
-                       switch (_drawMode)
-                       {
-                               case MODE_DRAG_POINT:
-                                       drawDragLines(inG, _selection.getCurrentPointIndex()-1, _selection.getCurrentPointIndex()+1);
-                                       break;
+               switch (_drawMode)
+               {
+                       case MODE_DRAG_POINT:
+                               drawDragLines(inG, _selection.getCurrentPointIndex()-1, _selection.getCurrentPointIndex()+1);
+                               break;
 
-                               case MODE_CREATE_MIDPOINT:
-                                       drawDragLines(inG, _clickedPoint-1, _clickedPoint);
-                                       break;
+                       case MODE_CREATE_MIDPOINT:
+                               drawDragLines(inG, _clickedPoint-1, _clickedPoint);
+                               break;
 
-                               case MODE_ZOOM_RECT:
-                               case MODE_MARK_RECTANGLE:
-                                       if (_dragFromX != -1 && _dragFromY != -1)
-                                       {
-                                               // Draw the zoom rectangle if necessary
-                                               inG.setColor(Color.RED);
-                                               inG.drawLine(_dragFromX, _dragFromY, _dragFromX, _dragToY);
-                                               inG.drawLine(_dragFromX, _dragFromY, _dragToX, _dragFromY);
-                                               inG.drawLine(_dragToX, _dragFromY, _dragToX, _dragToY);
-                                               inG.drawLine(_dragFromX, _dragToY, _dragToX, _dragToY);
-                                       }
-                                       break;
-
-                               case MODE_DRAW_POINTS_CONT:
-                                       // draw line to mouse position to show drawing mode
-                                       inG.setColor(Config.getColourScheme().getColour(ColourScheme.IDX_POINT));
-                                       int prevIndex = _track.getNumPoints()-1;
-                                       int px = getWidth() / 2 + _mapPosition.getXFromCentre(_track.getX(prevIndex));
-                                       int py = getHeight() / 2 + _mapPosition.getYFromCentre(_track.getY(prevIndex));
-                                       inG.drawLine(px, py, _dragToX, _dragToY);
-                                       break;
-                       }
-               }
-               else
-               {
-                       inG.setColor(Config.getColourScheme().getColour(ColourScheme.IDX_BACKGROUND));
-                       inG.fillRect(0, 0, getWidth(), getHeight());
-                       inG.setColor(COLOR_MESSAGES);
-                       inG.drawString(I18nManager.getText("display.nodata"), 50, getHeight()/2);
-                       _scaleBar.updateScale(-1, 0);
+                       case MODE_ZOOM_RECT:
+                       case MODE_MARK_RECTANGLE:
+                               if (_dragFromX != -1 && _dragFromY != -1)
+                               {
+                                       // Draw the zoom rectangle if necessary
+                                       inG.setColor(Color.RED);
+                                       inG.drawLine(_dragFromX, _dragFromY, _dragFromX, _dragToY);
+                                       inG.drawLine(_dragFromX, _dragFromY, _dragToX, _dragFromY);
+                                       inG.drawLine(_dragToX, _dragFromY, _dragToX, _dragToY);
+                                       inG.drawLine(_dragFromX, _dragToY, _dragToX, _dragToY);
+                               }
+                               break;
+
+                       case MODE_DRAW_POINTS_CONT:
+                               // draw line to mouse position to show drawing mode
+                               inG.setColor(Config.getColourScheme().getColour(ColourScheme.IDX_POINT));
+                               int prevIndex = _track.getNumPoints()-1;
+                               int px = getWidth() / 2 + _mapPosition.getXFromCentre(_track.getX(prevIndex));
+                               int py = getHeight() / 2 + _mapPosition.getYFromCentre(_track.getY(prevIndex));
+                               inG.drawLine(px, py, _dragToX, _dragToY);
+                               break;
                }
                // Draw slider etc on top
                paintChildren(inG);
@@ -1074,66 +1066,63 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
         */
        public void mouseClicked(MouseEvent inE)
        {
-               if (_track != null && _track.getNumPoints() > 0)
+               // select point if it's a left-click
+               if (!inE.isMetaDown())
                {
-                       // select point if it's a left-click
-                       if (!inE.isMetaDown())
+                       if (inE.getClickCount() == 1)
                        {
-                               if (inE.getClickCount() == 1)
+                               // single click
+                               if (_drawMode == MODE_DEFAULT)
                                {
-                                       // single click
-                                       if (_drawMode == MODE_DEFAULT)
+                                       int pointIndex = _clickedPoint;
+                                       if (pointIndex == INDEX_UNKNOWN)
                                        {
-                                               int pointIndex = _clickedPoint;
-                                               if (pointIndex == INDEX_UNKNOWN)
-                                               {
-                                                       // index hasn't been calculated yet
-                                                       pointIndex = _track.getNearestPointIndex(
-                                                        _mapPosition.getXFromPixels(inE.getX(), getWidth()),
-                                                        _mapPosition.getYFromPixels(inE.getY(), getHeight()),
-                                                        _mapPosition.getBoundsFromPixels(CLICK_SENSITIVITY), false);
-                                               }
-                                               // Extend selection for shift-click
-                                               if (inE.isShiftDown()) {
-                                                       _trackInfo.extendSelection(pointIndex);
-                                               }
-                                               else {
-                                                       _trackInfo.selectPoint(pointIndex);
-                                               }
+                                               // index hasn't been calculated yet
+                                               pointIndex = _track.getNearestPointIndex(
+                                                       _mapPosition.getXFromPixels(inE.getX(), getWidth()),
+                                                       _mapPosition.getYFromPixels(inE.getY(), getHeight()),
+                                                       _mapPosition.getBoundsFromPixels(CLICK_SENSITIVITY), false);
                                        }
-                                       else if (_drawMode == MODE_DRAW_POINTS_START)
-                                       {
-                                               _app.createPoint(createPointFromClick(inE.getX(), inE.getY()));
-                                               _dragToX = inE.getX();
-                                               _dragToY = inE.getY();
-                                               _drawMode = MODE_DRAW_POINTS_CONT;
+                                       // Extend selection for shift-click
+                                       if (inE.isShiftDown()) {
+                                               _trackInfo.extendSelection(pointIndex);
                                        }
-                                       else if (_drawMode == MODE_DRAW_POINTS_CONT)
-                                       {
-                                               DataPoint point = createPointFromClick(inE.getX(), inE.getY());
-                                               _app.createPoint(point, false); // not a new segment
+                                       else {
+                                               _trackInfo.selectPoint(pointIndex);
                                        }
                                }
-                               else if (inE.getClickCount() == 2)
+                               else if (_drawMode == MODE_DRAW_POINTS_START)
                                {
-                                       // double click
-                                       if (_drawMode == MODE_DEFAULT) {
-                                               panMap(inE.getX() - getWidth()/2, inE.getY() - getHeight()/2);
-                                               zoomIn();
-                                       }
-                                       else if (_drawMode == MODE_DRAW_POINTS_START || _drawMode == MODE_DRAW_POINTS_CONT) {
-                                               _drawMode = MODE_DEFAULT;
-                                       }
+                                       _app.createPoint(createPointFromClick(inE.getX(), inE.getY()));
+                                       _dragToX = inE.getX();
+                                       _dragToY = inE.getY();
+                                       _drawMode = MODE_DRAW_POINTS_CONT;
+                               }
+                               else if (_drawMode == MODE_DRAW_POINTS_CONT)
+                               {
+                                       DataPoint point = createPointFromClick(inE.getX(), inE.getY());
+                                       _app.createPoint(point, false); // not a new segment
                                }
                        }
-                       else
+                       else if (inE.getClickCount() == 2)
                        {
-                               // show the popup menu for right-clicks
-                               _popupMenuX = inE.getX();
-                               _popupMenuY = inE.getY();
-                               _popup.show(this, _popupMenuX, _popupMenuY);
+                               // double click
+                               if (_drawMode == MODE_DEFAULT) {
+                                       panMap(inE.getX() - getWidth()/2, inE.getY() - getHeight()/2);
+                                       zoomIn();
+                               }
+                               else if (_drawMode == MODE_DRAW_POINTS_START || _drawMode == MODE_DRAW_POINTS_CONT) {
+                                       _drawMode = MODE_DEFAULT;
+                               }
                        }
                }
+               else
+               {
+                       // show the popup menu for right-clicks
+                       _popupMenuX = inE.getX();
+                       _popupMenuY = inE.getY();
+                       _popup.show(this, _popupMenuX, _popupMenuY);
+               }
                // Reset app mode
                _app.setCurrentMode(App.AppMode.NORMAL);
                if (_drawMode == MODE_MARK_RECTANGLE) _drawMode = MODE_DEFAULT;
@@ -1408,10 +1397,6 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
                        }
                }
                repaint();
-               // enable or disable components
-               boolean hasData = _track.getNumPoints() > 0;
-               _topPanel.setVisible(hasData);
-               _sidePanel.setVisible(hasData);
                // grab focus for the key presses
                this.requestFocus();
        }
index 25f05fc1a2a238370d8888ea4b807b7d3f5f8adb..71ab6cd4d88ed9eb9823db56ab19dc72d574db53 100644 (file)
@@ -30,14 +30,14 @@ public class MapPosition
         * @param inWidth width of display
         * @param inHeight height of display
         */
-       public void zoomToXY(double inMinX, double inMaxX, double inMinY, double inMaxY, int inWidth, int inHeight)
+       public void zoomToXY(double inMinX, double inMaxX, double inMinY, double inMaxY, int inWidth, int inHeight, int maxZoom)
        {
                // System.out.println("Zooming to " + inMinX + ", " + inMaxX + ", " + inMinY + ", " + inMaxY + "; width=" + inWidth + ", height=" + inHeight);
                double diffX = Math.abs(inMaxX - inMinX);
                double diffY = Math.abs(inMaxY - inMinY);
                // Find out what zoom level to go to
                int requiredZoom = -1;
-               for (int currZoom = MAX_ZOOM; currZoom >= 2; currZoom--)
+               for (int currZoom = maxZoom; currZoom >= 2; currZoom--)
                {
                        if (transformToPixels(diffX, currZoom) < inWidth
                                && transformToPixels(diffY, currZoom) < inHeight)
index c4e294665e128def7d1fcbfb048cb516624d5d00..177ad670b14d89664f6129cf46d85038c3f8cd8e 100644 (file)
@@ -104,7 +104,7 @@ public abstract class MapSource
                        urlstr = "http://" + urlstr;
                }
                // check trailing /
-               if (!urlstr.endsWith("/")) {
+               if (!urlstr.endsWith("/") && !urlstr.contains("?")) {
                        urlstr = urlstr + "/";
                }
                // Validate current url, return null if not ok
index f7370c5c90c833e7f053fc786eafdae37ab7f843..d1e0047a2bc2624284308fad0f4ab1ea9df2dc09 100644 (file)
@@ -70,10 +70,19 @@ public class MapTileManager implements ImageObserver
         * @return true if zoom is too high for tiles
         */
        public boolean isOverzoomed()
+       {
+               return _zoom > getMaxZoomLevel();
+       }
+
+       /**
+        * @return the maximum useable zoom level for tiles
+        */
+       public int getMaxZoomLevel()
        {
                // Ask current map source what maximum zoom is
                int maxZoom = (_mapSource == null?0:_mapSource.getMaxZoomLevel());
-               return (_zoom > maxZoom);
+               return maxZoom;
+
        }
 
        /**
index 925fcf623ea456154c512c5e5e89454eb5b46bf8..e3fe58987b800f54cf10b1b8bd9ed8fe023c0897 100644 (file)
@@ -152,12 +152,31 @@ public class OsmMapSource extends MapSource
 
        /**
         * Make the URL to get the specified tile
+        * @param inLayerNum layer number
+        * @param inZoom zoom level
+        * @param inX x coordinate
+        * @param inY y coordinate
+        * @return relative file path as String
         */
        public String makeURL(int inLayerNum, int inZoom, int inX, int inY)
        {
                // Check if the base url has a [1234], if so replace at random
-               StringBuffer url = new StringBuffer();
-               url.append(pickServerUrl(_baseUrls[inLayerNum]));
+               String baseUrl = pickServerUrl(_baseUrls[inLayerNum]);
+               return makeUrl(baseUrl, inLayerNum, inZoom, inX, inY);
+       }
+
+       public String makeUrl(String baseUrl, int inLayerNum, int inZoom, int inX, int inY)
+       {
+               // If the base URL has {x}/{y} placeholders, use them
+               if (baseUrl.contains("{x}")) {
+                       baseUrl = baseUrl.replace("{z}", Integer.toString(inZoom))
+                               .replace("{x}", Integer.toString(inX))
+                               .replace("{y}", Integer.toString(inY));
+                       return baseUrl;
+               }
+
+               // Else simply append the tile indices and file extension
+               StringBuffer url = new StringBuffer(baseUrl);
                url.append(inZoom).append('/').append(inX).append('/').append(inY);
                url.append('.').append(getFileExtension(inLayerNum));
                if (_apiKey != null)
@@ -167,6 +186,26 @@ public class OsmMapSource extends MapSource
                return url.toString();
        }
 
+       /**
+        * Make a relative file path from the base directory including site name
+        * @param inLayerNum layer number
+        * @param inZoom zoom level
+        * @param inX x coordinate
+        * @param inY y coordinate
+        * @return relative file path as String
+        */
+       public String makeFilePath(int inLayerNum, int inZoom, int inX, int inY)
+       {
+               String siteName = getSiteName(inLayerNum);
+               String filePath = makeUrl(siteName, inLayerNum, inZoom, inX, inY);
+               int indexParam = filePath.indexOf("?");
+               if (indexParam > 0)
+               {
+                       filePath = filePath.substring(0, indexParam);
+               }
+               return filePath;
+       }
+
        /**
         * @return maximum zoom level
         */
index 736c145151a73dffe163871ef251fa95069c5a62..82219b22e3f7c71411c364f7f0d5d4cc5b4686d9 100644 (file)
@@ -94,6 +94,7 @@ function.interpolate=Interpolate points
 function.deletebydate=Delete points by date
 function.addtimeoffset=Add time offset
 function.addaltitudeoffset=Add altitude offset
+function.removealtitudes=Remove altitudes
 function.findwaypoint=Find waypoint
 function.rearrangewaypoints=Rearrange waypoints
 function.convertnamestotimes=Convert waypoint names to times
@@ -641,6 +642,7 @@ confirm.mergetracksegments=Track segments merged
 confirm.reverserange=Range reversed
 confirm.addtimeoffset=Time offset added
 confirm.addaltitudeoffset=Altitude offset added
+confirm.removealtitudes=Altitudes removed
 confirm.rearrangewaypoints=Waypoints rearranged
 confirm.rearrangephotos=Photos rearranged
 confirm.splitsegments=%d segment splits were made
@@ -861,6 +863,7 @@ undo.splitsegments=split track segments
 undo.sewsegments=sew track segments
 undo.addtimeoffset=add time offset
 undo.addaltitudeoffset=add altitude offset
+undo.removealtitudes=remove altitudes
 undo.rearrangewaypoints=rearrange waypoints
 undo.cutandmove=move section
 undo.connect=connect
diff --git a/src/tim/prune/undo/UndoRemoveAltitudes.java b/src/tim/prune/undo/UndoRemoveAltitudes.java
new file mode 100644 (file)
index 0000000..becf2d7
--- /dev/null
@@ -0,0 +1,65 @@
+package tim.prune.undo;
+
+import tim.prune.I18nManager;
+import tim.prune.UpdateMessageBroker;
+import tim.prune.data.Altitude;
+import tim.prune.data.DataPoint;
+import tim.prune.data.TrackInfo;
+
+/**
+ * Undo removing (ie: restore the original) altitude from points
+ */
+public class UndoRemoveAltitudes implements UndoOperation
+{
+       /** Start index of section */
+       private int _startIndex;
+       /** altitude values before operation */
+       private Altitude[] _altitudes;
+
+
+       /**
+        * Constructor
+        * @param inTrackInfo track info object
+        */
+       public UndoRemoveAltitudes(TrackInfo inTrackInfo, int inStart, int inEnd)
+       {
+               _startIndex = inStart;
+               final int numPoints = inEnd - inStart + 1;
+               // Make array of cloned altitude objects
+               _altitudes = new Altitude[numPoints];
+               for (int i=0; i<numPoints; i++) {
+                       Altitude a = inTrackInfo.getTrack().getPoint(_startIndex+i).getAltitude();
+                       if (a != null && a.isValid()) {
+                               _altitudes[i] = a.clone();
+                       }
+               }
+       }
+
+
+       /**
+        * @return description of operation including number of points adjusted
+        */
+       public String getDescription()
+       {
+               return I18nManager.getText("undo.removealtitudes") + " (" + (_altitudes.length) + ")";
+       }
+
+
+       /**
+        * Perform the undo operation on the given Track
+        * @param inTrackInfo TrackInfo object on which to perform the operation
+        */
+       public void performUndo(TrackInfo inTrackInfo) throws UndoException
+       {
+               // Perform the inverse operation
+               final int numPoints = _altitudes.length;
+               for (int i=0; i<numPoints; i++)
+               {
+                       DataPoint point = inTrackInfo.getTrack().getPoint(i+_startIndex);
+                       point.resetAltitude(_altitudes[i]);
+               }
+               _altitudes = null;
+               inTrackInfo.getSelection().markInvalid();
+               UpdateMessageBroker.informSubscribers();
+       }
+}