Index: images/mapmode/shear.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: images/mapmode/shear.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Index: src/org/openstreetmap/josm/plugins/piclayer/ResetPictureShearAction.java
===================================================================
--- src/org/openstreetmap/josm/plugins/piclayer/ResetPictureShearAction.java	(revision 0)
+++ src/org/openstreetmap/josm/plugins/piclayer/ResetPictureShearAction.java	(revision 0)
@@ -0,0 +1,59 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Patrick "Petschge" Kilian, based on code        *
+ *   Copyright (C) 2009 by Tomasz Stelmach                                 *
+ *   http://www.stelmach-online.net/                                       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+package org.openstreetmap.josm.plugins.piclayer;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.event.ActionEvent;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.JosmAction;
+
+/**
+ * Action for resetting properties of an image.
+ * 
+ * TODO Four almost identical classes. Refactoring needed.
+ */
+public class ResetPictureShearAction extends JosmAction {
+
+    // Owner layer of the action
+    PicLayerAbstract m_owner = null;
+    
+    /**
+     * Constructor
+     */
+    public ResetPictureShearAction( PicLayerAbstract owner ) {
+        super(tr("Shear"), null, tr("Resets picture shear"), null, false);
+        // Remember the owner...
+        m_owner = owner;
+    }
+    
+    /**
+     * Action handler
+     */
+    public void actionPerformed(ActionEvent arg0) {
+        // Reset
+        m_owner.resetShear();
+        // Redraw
+        Main.map.mapView.repaint();
+    }
+}
Index: src/org/openstreetmap/josm/plugins/piclayer/MovePictureAction.java
===================================================================
--- src/org/openstreetmap/josm/plugins/piclayer/MovePictureAction.java	(revision 25058)
+++ src/org/openstreetmap/josm/plugins/piclayer/MovePictureAction.java	(working copy)
@@ -32,7 +32,7 @@
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.data.coor.EastNorth;
 
-//TODO: Move/Rotate/Scale action classes are similar. Do the redesign!
+//TODO: Move/Rotate/Scale/Shear action classes are similar. Do the redesign!
 
 /**
  * This class handles the input during moving the picture.
Index: src/org/openstreetmap/josm/plugins/piclayer/ScaleXYPictureAction.java
===================================================================
--- src/org/openstreetmap/josm/plugins/piclayer/ScaleXYPictureAction.java	(revision 25058)
+++ src/org/openstreetmap/josm/plugins/piclayer/ScaleXYPictureAction.java	(working copy)
@@ -27,7 +27,7 @@
 import org.openstreetmap.josm.gui.MapFrame;
 import org.openstreetmap.josm.tools.ImageProvider;
 
-// TODO: Move/Rotate/Scale action classes are similar. Do the redesign!
+// TODO: Move/Rotate/Scale/Shear action classes are similar. Do the redesign!
 
 /**
  * This class handles the input during scaling the picture.
Index: src/org/openstreetmap/josm/plugins/piclayer/ResetPictureAllAction.java
===================================================================
--- src/org/openstreetmap/josm/plugins/piclayer/ResetPictureAllAction.java	(revision 25058)
+++ src/org/openstreetmap/josm/plugins/piclayer/ResetPictureAllAction.java	(working copy)
@@ -54,6 +54,7 @@
         m_owner.resetAngle();
         m_owner.resetPosition();
         m_owner.resetScale();
+        m_owner.resetShear();
         // Redraw
         Main.map.mapView.repaint();
     }
Index: src/org/openstreetmap/josm/plugins/piclayer/ScaleXPictureAction.java
===================================================================
--- src/org/openstreetmap/josm/plugins/piclayer/ScaleXPictureAction.java	(revision 25058)
+++ src/org/openstreetmap/josm/plugins/piclayer/ScaleXPictureAction.java	(working copy)
@@ -27,7 +27,7 @@
 import org.openstreetmap.josm.gui.MapFrame;
 import org.openstreetmap.josm.tools.ImageProvider;
 
-// TODO: Move/Rotate/Scale action classes are similar. Do the redesign!
+// TODO: Move/Rotate/Scale/Shear action classes are similar. Do the redesign!
 
 /**
  * This class handles the input during scaling the picture.
Index: src/org/openstreetmap/josm/plugins/piclayer/ScaleYPictureAction.java
===================================================================
--- src/org/openstreetmap/josm/plugins/piclayer/ScaleYPictureAction.java	(revision 25058)
+++ src/org/openstreetmap/josm/plugins/piclayer/ScaleYPictureAction.java	(working copy)
@@ -27,7 +27,7 @@
 import org.openstreetmap.josm.gui.MapFrame;
 import org.openstreetmap.josm.tools.ImageProvider;
 
-// TODO: Move/Rotate/Scale action classes are similar. Do the redesign!
+// TODO: Move/Rotate/Scale/Shear action classes are similar. Do the redesign!
 
 /**
  * This class handles the input during scaling the picture.
Index: src/org/openstreetmap/josm/plugins/piclayer/PicLayerPlugin.java
===================================================================
--- src/org/openstreetmap/josm/plugins/piclayer/PicLayerPlugin.java	(revision 25058)
+++ src/org/openstreetmap/josm/plugins/piclayer/PicLayerPlugin.java	(working copy)
@@ -49,6 +49,7 @@
     private IconToggleButton m_scalexPictureButton = null;
     private IconToggleButton m_scaleyPictureButton = null;
     private IconToggleButton m_scalexyPictureButton = null;
+    private IconToggleButton m_shearPictureButton = null;
 
     // Menu actions
     private NewLayerFromFileAction      m_newFromFileAction = null;
@@ -88,17 +89,20 @@
             ScaleXYPictureAction scaleXYPictureAction = new ScaleXYPictureAction(newFrame);
             ScaleXPictureAction scaleXPictureAction = new ScaleXPictureAction(newFrame);
             ScaleYPictureAction scaleYPictureAction = new ScaleYPictureAction(newFrame);
+            ShearPictureAction shearPictureAction = new ShearPictureAction(newFrame);
             // Create plugin buttons and add them to the toolbar
             m_movePictureButton = new IconToggleButton(movePictureAction);
             m_rotatePictureButton = new IconToggleButton(rotatePictureAction);
             m_scalexyPictureButton = new IconToggleButton(scaleXYPictureAction);
             m_scalexPictureButton = new IconToggleButton(scaleXPictureAction);
             m_scaleyPictureButton = new IconToggleButton(scaleYPictureAction);
+            m_shearPictureButton = new IconToggleButton(shearPictureAction);
             newFrame.addMapMode(m_movePictureButton);
             newFrame.addMapMode(m_rotatePictureButton);
             newFrame.addMapMode(m_scalexyPictureButton);
             newFrame.addMapMode(m_scalexPictureButton);
             newFrame.addMapMode(m_scaleyPictureButton);
+            newFrame.addMapMode(m_shearPictureButton);
 //            newFrame.toolGroup.add(m_movePictureButton);
 //            newFrame.toolGroup.add(m_rotatePictureButton);
 //            newFrame.toolGroup.add(m_scalePictureButton);
@@ -108,6 +112,7 @@
             m_scalexyPictureButton.setVisible(true);
             m_scalexPictureButton.setVisible(true);
             m_scaleyPictureButton.setVisible(true);
+            m_shearPictureButton.setVisible(true);
         }
     }
 
Index: src/org/openstreetmap/josm/plugins/piclayer/RotatePictureAction.java
===================================================================
--- src/org/openstreetmap/josm/plugins/piclayer/RotatePictureAction.java	(revision 25058)
+++ src/org/openstreetmap/josm/plugins/piclayer/RotatePictureAction.java	(working copy)
@@ -31,7 +31,7 @@
 import org.openstreetmap.josm.gui.MapFrame;
 import org.openstreetmap.josm.tools.ImageProvider;
 
-//TODO: Move/Rotate/Scale action classes are similar. Do the redesign!
+//TODO: Move/Rotate/Scale/Shear action classes are similar. Do the redesign!
 
 /**
  * This class handles the input during rotating the picture.
Index: src/org/openstreetmap/josm/plugins/piclayer/PicLayerAbstract.java
===================================================================
--- src/org/openstreetmap/josm/plugins/piclayer/PicLayerAbstract.java	(revision 25058)
+++ src/org/openstreetmap/josm/plugins/piclayer/PicLayerAbstract.java	(working copy)
@@ -73,6 +73,9 @@
     // Scale of the image
     private double m_scalex = 1.0;
     private double m_scaley = 1.0;
+    // Shear of the image
+    private double m_shearx = 0.0;
+    private double m_sheary = 0.0;
     // The scale that was set on the map during image creation
     private double m_initial_scale = 1.0;
     // Layer icon
@@ -87,6 +90,8 @@
     private final String INITIAL_SCALE = "INITIAL_SCALE";
     private final String SCALEX = "SCALEX";
     private final String SCALEY = "SCALEY";
+    private final String SHEARX = "SHEARX";
+    private final String SHEARY = "SHEARY";
 
     /**
      * Constructor
@@ -214,6 +219,8 @@
             double scalex = m_scalex * m_initial_scale / Main.map.mapView.getDist100Pixel();
             double scaley = m_scaley * m_initial_scale / Main.map.mapView.getDist100Pixel();
             g.scale( scalex, scaley );
+            // Shear
+            g.shear(m_shearx, m_sheary);
 
             // Draw picture
             g.drawImage( m_image, -m_image.getWidth() / 2, -m_image.getHeight() / 2, null );
@@ -257,6 +264,15 @@
     }
 
     /**
+     * Shear the picture. shearx and sheary will separately add to the
+     * corresponding current value
+     */
+    public void shearPictureBy( double shearx, double sheary ) {
+        m_shearx += shearx;
+        m_sheary += sheary;
+    }
+
+    /**
      * Sets the image position to the initial position
      */
     public void resetPosition() {
@@ -278,6 +294,14 @@
         m_angle = 0.0;
     }
 
+
+    /**
+     * Sets the image to no shear
+     */
+    public void resetShear() {
+        m_shearx = 0.0;
+        m_sheary = 0.0;
+    }
     @Override
     /**
      * Computes the (rough) bounding box.
@@ -329,6 +353,8 @@
         props.put(SCALEX, "" + m_scalex);
         props.put(SCALEY, "" + m_scaley);
         props.put(ANGLE, "" + m_angle);
+        props.put(SHEARX, "" + m_shearx);
+        props.put(SHEARY, "" + m_sheary);
     }
 
     /**
@@ -357,11 +383,15 @@
             double in_scale = Double.valueOf( props.getProperty(INITIAL_SCALE));
             double scale_x = Double.valueOf( props.getProperty(SCALEX));
             double scale_y = Double.valueOf( props.getProperty(SCALEY));
+            double shear_x = Double.valueOf( props.getProperty(SHEARX));
+            double shear_y = Double.valueOf( props.getProperty(SHEARY));
             m_position.setLocation(pos_x, pos_y);
             m_initial_position.setLocation(pos_x, pos_y);
             m_angle = angle;
             m_scalex = scale_x;
             m_scaley = scale_y;
+            m_shearx = shear_x;
+            m_sheary = shear_y;
             m_initial_scale = in_scale;
             // Refresh
             Main.map.mapView.repaint();
@@ -383,6 +413,7 @@
             reset_submenu.add( new ResetPicturePositionAction( PicLayerAbstract.this ) );
             reset_submenu.add( new ResetPictureAngleAction( PicLayerAbstract.this ) );
             reset_submenu.add( new ResetPictureScaleAction( PicLayerAbstract.this ) );
+            reset_submenu.add( new ResetPictureShearAction( PicLayerAbstract.this ) );
             return reset_submenu;
         }
 
Index: src/org/openstreetmap/josm/plugins/piclayer/ShearPictureAction.java
===================================================================
--- src/org/openstreetmap/josm/plugins/piclayer/ShearPictureAction.java	(revision 0)
+++ src/org/openstreetmap/josm/plugins/piclayer/ShearPictureAction.java	(revision 0)
@@ -0,0 +1,108 @@
+/***************************************************************************
+ *                                                                         *
+ *   Copyright (C) 2011 Patrick "Petschge" Kilian, based on code           *
+ *   (c) 2009 by Tomasz Stelmach                                           *
+ *   http://www.stelmach-online.net/                                       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+package org.openstreetmap.josm.plugins.piclayer;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.mapmode.MapMode;
+import org.openstreetmap.josm.gui.MapFrame;
+import org.openstreetmap.josm.tools.ImageProvider;
+import org.openstreetmap.josm.data.coor.EastNorth;
+
+//TODO: Move/Rotate/Scale/Shear action classes are similar. Do the redesign!
+
+/**
+ * This class handles the input during shearing of the picture.
+ */
+public class ShearPictureAction extends MapMode implements MouseListener, MouseMotionListener
+{
+    // Action ongoing?
+    private boolean mb_dragging = false;
+
+    // Last mouse position
+    private EastNorth m_prevEastNorth;
+
+    // The layer we're working on
+    private PicLayerAbstract m_currentLayer = null;
+
+    /**
+     * Constructor
+     */
+    public ShearPictureAction(MapFrame frame) {
+        super(tr("PicLayer shear"), "shear", tr("Drag to shear the picture"), frame, ImageProvider.getCursor("crosshair", null));
+    }
+
+    @Override
+    public void enterMode() {
+        super.enterMode();
+        Main.map.mapView.addMouseListener(this);
+        Main.map.mapView.addMouseMotionListener(this);
+    }
+
+    @Override
+    public void exitMode() {
+        super.exitMode();
+        Main.map.mapView.removeMouseListener(this);
+        Main.map.mapView.removeMouseMotionListener(this);
+    }
+
+    @Override
+    public void mousePressed(MouseEvent e) {
+
+        // If everything is OK, we start dragging/moving the picture
+        if ( Main.map.mapView.getActiveLayer() instanceof PicLayerAbstract ) {
+            m_currentLayer = (PicLayerAbstract)Main.map.mapView.getActiveLayer();
+
+            if ( m_currentLayer != null && e.getButton() == MouseEvent.BUTTON1 ) {
+                mb_dragging = true;
+                m_prevEastNorth=Main.map.mapView.getEastNorth(e.getX(),e.getY());
+            }
+        }
+    }
+
+    @Override
+    public void mouseDragged(MouseEvent e) {
+        // Picture moving is ongoing
+        if(mb_dragging) {
+            EastNorth eastNorth = Main.map.mapView.getEastNorth(e.getX(),e.getY());
+            m_currentLayer.shearPictureBy(
+                1000* (eastNorth.east()-m_prevEastNorth.east()),
+                1000* (eastNorth.north()-m_prevEastNorth.north())
+            );
+            m_prevEastNorth = eastNorth;
+            Main.map.mapView.repaint();
+        }
+    }
+
+    @Override
+    public void mouseReleased(MouseEvent e) {
+        // Stop moving
+        mb_dragging = false;
+    }
+
+}
