Index: dist/photoadjust.jar
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/java-archive
Index: plugins/photoadjust/src/org/openstreetmap/josm/plugins/photoadjust/PhotoAdjustMapMode.java
===================================================================
--- plugins/photoadjust/src/org/openstreetmap/josm/plugins/photoadjust/PhotoAdjustMapMode.java	(revision 35105)
+++ plugins/photoadjust/src/org/openstreetmap/josm/plugins/photoadjust/PhotoAdjustMapMode.java	(working copy)
@@ -83,7 +83,7 @@
     @Override
     public String getModeHelpText() {
         if (hasLayersToAdjust()) {
-            return tr("Click+drag photo, shift+click to position photo, control+click to set direction.");
+            return tr("Click+drag photo, control+alt+click to position photo, control+click to set direction.");
         } else {
             return tr("Please load some photos.");
         }
Index: plugins/photoadjust/src/org/openstreetmap/josm/plugins/photoadjust/PhotoAdjustWorker.java
===================================================================
--- plugins/photoadjust/src/org/openstreetmap/josm/plugins/photoadjust/PhotoAdjustWorker.java	(revision 35105)
+++ plugins/photoadjust/src/org/openstreetmap/josm/plugins/photoadjust/PhotoAdjustWorker.java	(working copy)
@@ -1,13 +1,13 @@
 // License: GPL. For details, see LICENSE file.
 package org.openstreetmap.josm.plugins.photoadjust;
 
-import java.awt.event.InputEvent;
 import java.awt.event.MouseEvent;
-import java.awt.geom.Point2D;
 import java.util.List;
 
 import org.openstreetmap.josm.data.ImageData;
+import org.openstreetmap.josm.data.coor.EastNorth;
 import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.projection.ProjectionRegistry;
 import org.openstreetmap.josm.gui.MainApplication;
 import org.openstreetmap.josm.gui.layer.geoimage.GeoImageLayer;
 import org.openstreetmap.josm.gui.layer.geoimage.ImageEntry;
@@ -23,7 +23,7 @@
     // Offset between center of the photo and point where it is
     // clicked.  This must be in pixels to maintain the same offset if
     // the photo is moved very far.
-    private Point2D dragOffset;
+    private EastNorth dragOffset;
     private boolean centerViewIsDisabled = false;
     private boolean centerViewNeedsEnable = false;
 
@@ -33,7 +33,7 @@
     public void reset() {
         dragPhoto = null;
         dragData = null;
-        dragOffset = null;
+        dragOffset = EastNorth.ZERO;
     }
 
     /**
@@ -65,7 +65,7 @@
 
     /**
      * Mouse click handler.  Control+click changes the image direction if
-     * there is a photo selected on the map.  Shift+click positions the photo
+     * there is a photo selected on the map.  Alt+click positions the photo
      * from the ImageViewerDialog.  Click without shift or control checks if
      * there is a photo under the mouse.
      *
@@ -80,37 +80,42 @@
                 && imageLayers != null && !imageLayers.isEmpty()) {
             // Check if modifier key is pressed and change to
             // image viewer photo if it is.
-            final boolean isShift = (evt.getModifiers() & InputEvent.SHIFT_MASK) != 0;
-            final boolean isCtrl = (evt.getModifiers() & InputEvent.CTRL_MASK) != 0;
-            if (isShift || isCtrl) {
+            final boolean isAlt = (evt.getModifiersEx() & MouseEvent.ALT_DOWN_MASK) == MouseEvent.ALT_DOWN_MASK;
+            final boolean isCtrl = (evt.getModifiersEx() & MouseEvent.CTRL_DOWN_MASK) == MouseEvent.CTRL_DOWN_MASK;
+            final boolean isShift = (evt.getModifiersEx() & MouseEvent.SHIFT_DOWN_MASK) == MouseEvent.SHIFT_DOWN_MASK;
+            // ignore key press with shift, to not conflict with selection
+            if (isShift) {
+                return;
+            }
+            if (isAlt || isCtrl) {
                 for (GeoImageLayer layer: imageLayers) {
                     if (layer.isVisible()) {
-                        final ImageEntry img = layer.getImageData().getSelectedImage();
-                        if (img != null) {
+                        final List<ImageEntry> entries = layer.getImageData().getSelectedImages();
+                        if (!entries.isEmpty()) {
                             // Change direction if control is pressed, position
-                            // otherwise.  Shift+control changes direction, similar to
+                            // otherwise.  Alt+control changes direction, similar to
                             // rotate in select mode.
                             //
                             // Combinations:
-                            // S ... shift pressed
+                            // A ... alt pressed
                             // C ... control pressed
                             // pos ... photo has a position set == is displayed on the map
                             // nopos ... photo has no position set
                             //
-                            // S + pos: position at mouse
-                            // S + nopos: position at mouse
+                            // A + C + pos: position at mouse
+                            // A + C + nopos: position at mouse
                             // C + pos: change orientation
                             // C + nopos: ignored
-                            // S + C + pos: change orientation
-                            // S + C + nopos: ignore
-                            if (isCtrl) {
-                                if (img.getPos() != null) {
-                                    changeDirection(img, layer.getImageData(), evt);
+                            for (ImageEntry img: entries) {
+                                if (isCtrl && !isAlt) {
+                                    if (img.getPos() != null) {
+                                        changeDirection(img, layer.getImageData(), evt);
+                                    }
+                                } else if (isCtrl && isAlt) {
+                                    movePhoto(img, layer.getImageData(), evt);
                                 }
-                            } else { // shift pressed
-                                movePhoto(img, layer.getImageData(), evt);
+                                dragPhoto = img;
                             }
-                            dragPhoto = img;
                             dragData = layer.getImageData();
                             break;
                         }
@@ -140,10 +145,6 @@
      */
     public void doMouseReleased(MouseEvent evt) {
         restoreCenterView();
-        //if (dragLayer != null && dragPhoto != null) {
-        //    // Re-display the photo to update the OSD.
-        //    ImageViewerDialog.showImage(dragLayer, dragPhoto);
-        //}
     }
 
     /**
@@ -153,11 +154,28 @@
      */
     public void doMouseDragged(MouseEvent evt) {
         if (dragData != null && dragPhoto != null) {
-            if ((evt.getModifiers() & InputEvent.CTRL_MASK) != 0) {
-                changeDirection(dragPhoto, dragData, evt);
+            if ((evt.getModifiersEx() & MouseEvent.CTRL_DOWN_MASK) == MouseEvent.CTRL_DOWN_MASK) {
+                if (dragData.isImageSelected(dragPhoto)) {
+                    for (ImageEntry photo: dragData.getSelectedImages()) {
+                        changeDirection(photo, dragData, evt);
+                    }
+                } else {
+                    changeDirection(dragPhoto, dragData, evt);
+                }
             } else {
                 disableCenterView();
-                movePhoto(dragPhoto, dragData, evt);
+                final EastNorth startEN = dragPhoto.getPos().getEastNorth(ProjectionRegistry.getProjection()).subtract(dragOffset);
+                final EastNorth currentEN = MainApplication.getMap().mapView.getEastNorth(evt.getX(), evt.getY());
+                final EastNorth translation = currentEN.subtract(startEN);
+
+                if (dragData.isImageSelected(dragPhoto)) {
+                    for (ImageEntry photo: dragData.getSelectedImages()) {
+                        translatePhoto(photo, dragData, translation);
+                    }
+                } else {
+                    translatePhoto(dragPhoto, dragData, translation);
+                }
+                dragData.notifyImageUpdate();
             }
         }
     }
@@ -169,9 +187,9 @@
      * @param evt Mouse event from one of the mouse adapters.
      */
     private void setDragOffset(ImageEntry photo, MouseEvent evt) {
-        final Point2D centerPoint = MainApplication.getMap().mapView.getPoint2D(photo.getPos());
-        dragOffset = new Point2D.Double(centerPoint.getX() - evt.getX(),
-                                        centerPoint.getY() - evt.getY());
+        final EastNorth centerEN = photo.getPos().getEastNorth(ProjectionRegistry.getProjection());
+        final EastNorth offsetEN = MainApplication.getMap().mapView.getEastNorth(evt.getX(), evt.getY());
+        dragOffset = centerEN.subtract(offsetEN);
     }
 
     /**
@@ -181,23 +199,26 @@
      * @param data ImageData of the photo.
      * @param evt Mouse event from one of the mouse adapters.
      */
-    private void movePhoto(ImageEntry photo, ImageData data,
-            MouseEvent evt) {
-        LatLon newPos;
-        if (dragOffset != null) {
-            newPos = MainApplication.getMap().mapView.getLatLon(
-                dragOffset.getX() + evt.getX(),
-                dragOffset.getY() + evt.getY());
-        } else {
-            newPos = MainApplication.getMap().mapView.getLatLon(evt.getX(), evt.getY());
-        }
+    private void movePhoto(ImageEntry photo, ImageData data, MouseEvent evt) {
+        LatLon newPos = MainApplication.getMap().mapView.getLatLon(evt.getX(), evt.getY());
         data.updateImagePosition(photo, newPos);
-        // Re-display the photo because the OSD data might change (new
-        // coordinates).  Or do that in doMouseReleased().
-        //ImageViewerDialog.showImage(layer, photo);
     }
 
     /**
+     * Apply the given translation to the photo
+     * @param photo The photo to move
+     * @param data ImageData of the photo
+     * @param translation the translation to apply
+     */
+    private void translatePhoto(ImageEntry photo, ImageData data, EastNorth translation) {
+        final EastNorth startEN = photo.getPos().getEastNorth(ProjectionRegistry.getProjection());
+        final EastNorth newPosEN = startEN.add(translation);
+        final LatLon newPos = MainApplication.getMap().mapView.getProjection().eastNorth2latlon(newPosEN);
+        photo.setPos(newPos);
+        photo.flagNewGpsData();
+    }
+
+    /**
      * Set the image direction, i.e. let it point to where the mouse is.
      *
      * @param photo The photo to move.
Index: plugins/photoadjust/src/org/openstreetmap/josm/plugins/photoadjust/PhotoPropertyEditor.java
===================================================================
--- plugins/photoadjust/src/org/openstreetmap/josm/plugins/photoadjust/PhotoPropertyEditor.java	(revision 35105)
+++ plugins/photoadjust/src/org/openstreetmap/josm/plugins/photoadjust/PhotoPropertyEditor.java	(working copy)
@@ -86,8 +86,8 @@
 
         @Override
         public void actionPerformed(ActionEvent evt) {
-            final ImageData data = getLayerWithSelectedImage().get().getImageData();
-            final ImageEntry photo = data.getSelectedImage();
+            final ImageData data = getLayerWithOneSelectedImage().get().getImageData();
+            final ImageEntry photo = data.getSelectedImages().get(0);
 
             StringBuilder title =
                     new StringBuilder(tr("Edit Photo GPS Data"));
@@ -116,12 +116,12 @@
          *         image shown, {@code false} otherwise.
          */
         private static boolean enabled() {
-            return getLayerWithSelectedImage().isPresent();
+            return getLayerWithOneSelectedImage().isPresent();
         }
 
-        private static Optional<GeoImageLayer> getLayerWithSelectedImage() {
+        private static Optional<GeoImageLayer> getLayerWithOneSelectedImage() {
             List<GeoImageLayer> list = MainApplication.getLayerManager().getLayersOfType(GeoImageLayer.class);
-            return list.stream().filter(l -> l.getImageData().getSelectedImage() != null).findFirst();
+            return list.stream().filter(l -> l.getImageData().getSelectedImages().size() == 1).findFirst();
         }
 
         @Override
@@ -157,10 +157,10 @@
             // ignored
         }
 
-        @Override
-        public void selectedImageChanged(ImageData data) {
+		@Override
+		public void selectedImageChanged(ImageData data) {
             this.updateEnabledState();
-        }
+		}
     }
 
     /**
