Index: applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/Demo.java
===================================================================
--- applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/Demo.java	(revision 26668)
+++ applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/Demo.java	(revision 26701)
@@ -17,4 +17,6 @@
 import javax.swing.JPanel;
 
+import org.openstreetmap.gui.jmapviewer.events.JMVCommandEvent;
+import org.openstreetmap.gui.jmapviewer.interfaces.JMapViewerEventListener;
 import org.openstreetmap.gui.jmapviewer.interfaces.TileLoader;
 import org.openstreetmap.gui.jmapviewer.interfaces.TileSource;
@@ -29,15 +31,30 @@
  *
  */
-public class Demo extends JFrame {
+public class Demo extends JFrame implements JMapViewerEventListener  {
 
     private static final long serialVersionUID = 1L;
+
+    private JMapViewer map = null;
+
+    private JLabel zoomLabel=null;
+    private JLabel zoomValue=null;
+
+    private JLabel mperpLabelName=null;
+    private JLabel mperpLabelValue = null;
 
     public Demo() {
         super("JMapViewer Demo");
         setSize(400, 400);
-        final JMapViewer map = new JMapViewer();
+
+        map = new JMapViewer();
+
+        // Listen to the map viewer for user operations so components will
+        // recieve events and update
+        map.addJMVListener(this);
+
         // final JMapViewer map = new JMapViewer(new MemoryTileCache(),4);
         // map.setTileLoader(new OsmFileCacheTileLoader(map));
         // new DefaultMapController(map);
+
         setLayout(new BorderLayout());
         setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
@@ -45,4 +62,11 @@
         JPanel panel = new JPanel();
         JPanel helpPanel = new JPanel();
+
+        mperpLabelName=new JLabel("Meters/Pixels: ");
+        mperpLabelValue=new JLabel(String.format("%s",map.getMeterPerPixel()));
+
+        zoomLabel=new JLabel("Zoom: ");
+        zoomValue=new JLabel(String.format("%s", map.getZoom()));
+
         add(panel, BorderLayout.NORTH);
         add(helpPanel, BorderLayout.SOUTH);
@@ -107,4 +131,10 @@
         panel.add(showZoomControls);
         panel.add(button);
+
+        panel.add(zoomLabel);
+        panel.add(zoomValue);
+        panel.add(mperpLabelName);
+        panel.add(mperpLabelValue);
+
         add(map, BorderLayout.CENTER);
 
@@ -130,3 +160,18 @@
     }
 
+    private void updateZoomParameters() {
+        if (mperpLabelValue!=null)
+            mperpLabelValue.setText(String.format("%s",map.getMeterPerPixel()));
+        if (zoomValue!=null)
+            zoomValue.setText(String.format("%s", map.getZoom()));
+    }
+
+    @Override
+    public void processCommand(JMVCommandEvent command) {
+        if (command.getCommand().equals(JMVCommandEvent.COMMAND.ZOOM) ||
+                command.getCommand().equals(JMVCommandEvent.COMMAND.MOVE)) {
+            updateZoomParameters();
+        }
+    }
+
 }
Index: applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/JMapViewer.java
===================================================================
--- applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/JMapViewer.java	(revision 26668)
+++ applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/JMapViewer.java	(revision 26701)
@@ -26,5 +26,9 @@
 import javax.swing.event.ChangeEvent;
 import javax.swing.event.ChangeListener;
-
+import javax.swing.event.EventListenerList;
+
+import org.openstreetmap.gui.jmapviewer.events.JMVCommandEvent;
+import org.openstreetmap.gui.jmapviewer.events.JMVCommandEvent.COMMAND;
+import org.openstreetmap.gui.jmapviewer.interfaces.JMapViewerEventListener;
 import org.openstreetmap.gui.jmapviewer.interfaces.MapMarker;
 import org.openstreetmap.gui.jmapviewer.interfaces.MapPolygon;
@@ -37,10 +41,10 @@
 
 /**
- * 
+ *
  * Provides a simple panel that displays pre-rendered map tiles loaded from the
  * OpenStreetMap project.
- * 
+ *
  * @author Jan Peter Stotz
- * 
+ *
  */
 public class JMapViewer extends JPanel implements TileLoaderListener {
@@ -118,6 +122,6 @@
         tileController = new TileController(tileSource, tileCache, this);
         mapMarkerList = new LinkedList<MapMarker>();
+        mapPolygonList = new LinkedList<MapPolygon>();
         mapRectangleList = new LinkedList<MapRectangle>();
-        mapPolygonList = new LinkedList<MapPolygon>();
         mapMarkersVisible = true;
         mapRectanglesVisible = true;
@@ -188,5 +192,5 @@
      * Changes the map pane so that it is centered on the specified coordinate
      * at the given zoom level.
-     * 
+     *
      * @param lat
      *            latitude of the specified coordinate
@@ -204,5 +208,5 @@
      * level is displayed on the map at the screen coordinate
      * <code>mapPoint</code>.
-     * 
+     *
      * @param mapPoint
      *            point on the map denoted in pixels where the coordinate should
@@ -265,5 +269,5 @@
         if (nbElemToCheck == 0)
             return;
-        
+
         int x_min = Integer.MAX_VALUE;
         int y_min = Integer.MAX_VALUE;
@@ -271,5 +275,5 @@
         int y_max = Integer.MIN_VALUE;
         int mapZoomMax = tileController.getTileSource().getMaxZoom();
-        
+
         if (markers) {
             for (MapMarker marker : mapMarkerList) {
@@ -282,5 +286,5 @@
             }
         }
-        
+
         if (rectangles) {
             for (MapRectangle rectangle : mapRectangleList) {
@@ -291,5 +295,5 @@
             }
         }
-        
+
         if (polygons) {
             for (MapPolygon polygon : mapPolygonList) {
@@ -304,5 +308,5 @@
             }
         }
-        
+
         int height = Math.max(0, getHeight());
         int width = Math.max(0, getWidth());
@@ -322,5 +326,6 @@
         setDisplayPosition(x, y, newZoom);
     }
-    
+
+
     /**
      * Sets the displayed map pane and zoom level so that all map markers are
@@ -338,5 +343,5 @@
         setDisplayToFitMapElements(false, true, false);
     }
-    
+
     /**
      * Sets the displayed map pane and zoom level so that all map polygons are
@@ -348,7 +353,21 @@
 
     /**
+     * @return the center
+     */
+    public Point getCenter() {
+        return center;
+    }
+
+    /**
+     * @param center the center to set
+     */
+    public void setCenter(Point center) {
+        this.center = center;
+    }
+
+    /**
      * Calculates the latitude/longitude coordinate of the center of the
      * currently displayed map area.
-     * 
+     *
      * @return latitude / longitude
      */
@@ -362,5 +381,5 @@
      * Converts the relative pixel coordinate (regarding the top left corner of
      * the displayed map) into a latitude / longitude coordinate
-     * 
+     *
      * @param mapPoint
      *            relative pixel coordinate regarding the top left corner of the
@@ -375,5 +394,5 @@
      * Converts the relative pixel coordinate (regarding the top left corner of
      * the displayed map) into a latitude / longitude coordinate
-     * 
+     *
      * @param mapPointX
      * @param mapPointY
@@ -390,5 +409,5 @@
     /**
      * Calculates the position on the map of a given coordinate
-     * 
+     *
      * @param lat
      * @param lon
@@ -411,5 +430,5 @@
     /**
      * Calculates the position on the map of a given coordinate
-     * 
+     *
      * @param lat
      * @param lon
@@ -422,5 +441,5 @@
     /**
      * Calculates the position on the map of a given coordinate
-     * 
+     *
      * @param coord
      * @return point on the map or <code>null</code> if the point is not visible
@@ -435,5 +454,5 @@
     /**
      * Calculates the position on the map of a given coordinate
-     * 
+     *
      * @param coord
      * @return point on the map or <code>null</code> if the point is not visible
@@ -445,4 +464,25 @@
         else
             return null;
+    }
+
+    /**
+     * Gets the meter per pixel.
+     *
+     * @return the meter per pixel
+     * @author Jason Huntley
+     */
+    public double getMeterPerPixel() {
+        Point origin=new Point(5,5);
+        Point center=new Point(getWidth()/2, getHeight()/2);
+
+        double pDistance=center.distance(origin);
+
+        Coordinate originCoord=getPosition(origin);
+        Coordinate centerCoord=getPosition(center);
+
+        double mDistance=OsmMercator.getDistance(originCoord.getLat(), originCoord.getLon(),
+                centerCoord.getLat(), centerCoord.getLon());
+
+        return mDistance/pDistance;
     }
 
@@ -543,4 +583,5 @@
             }
         }
+
         paintAttribution(g);
     }
@@ -588,8 +629,8 @@
         }
     }
-    
+
     /**
      * Moves the visible map pane.
-     * 
+     *
      * @param x
      *            horizontal movement in pixel.
@@ -601,4 +642,5 @@
         center.y += y;
         repaint();
+        this.fireJMVEvent(new JMVCommandEvent(COMMAND.MOVE, this));
     }
 
@@ -646,4 +688,6 @@
         // requests
         setDisplayPositionByLatLon(mapPoint, zoomPos.getLat(), zoomPos.getLon(), zoom);
+
+        this.fireJMVEvent(new JMVCommandEvent(COMMAND.ZOOM, this));
     }
 
@@ -656,5 +700,5 @@
      * derived implementations for adapting zoom dependent values. The new zoom
      * level can be obtained via {@link #getZoom()}.
-     * 
+     *
      * @param oldZoom
      *            the previous zoom level
@@ -683,5 +727,5 @@
     /**
      * Enables or disables painting of the {@link MapMarker}
-     * 
+     *
      * @param mapMarkersVisible
      * @see #addMapMarker(MapMarker)
@@ -764,5 +808,5 @@
         repaint();
     }
-    
+
     public void setZoomContolsVisible(boolean visible) {
         zoomSlider.setVisible(visible);
@@ -809,5 +853,5 @@
     /**
      * Enables or disables painting of the {@link MapRectangle}
-     * 
+     *
      * @param mapRectanglesVisible
      * @see #addMapRectangle(MapRectangle)
@@ -825,5 +869,5 @@
     /**
      * Enables or disables painting of the {@link MapPolygon}
-     * 
+     *
      * @param mapPolygonsVisible
      * @see #addMapPolygon(MapPolygon)
@@ -837,5 +881,5 @@
     /*
      * (non-Javadoc)
-     * 
+     *
      * @see
      * org.openstreetmap.gui.jmapviewer.interfaces.TileLoaderListener#getTileCache
@@ -899,3 +943,33 @@
         g.setFont(font);
     }
+
+    protected EventListenerList listenerList = new EventListenerList();
+
+    /**
+     * @param listener to set
+     */
+    public void addJMVListener(JMapViewerEventListener listener) {
+        listenerList.add(JMapViewerEventListener.class, listener);
+    }
+
+    /**
+     * @param listener to remove
+     */
+    public void removeJMVListener(JMapViewerEventListener listener) {
+        listenerList.remove(JMapViewerEventListener.class, listener);
+    }
+
+    /**
+     * Send an update to all objects registered with viewer
+     * 
+     * @param event to dispatch
+     */
+    void fireJMVEvent(JMVCommandEvent evt) {
+        Object[] listeners = listenerList.getListenerList();
+        for (int i=0; i<listeners.length; i+=2) {
+            if (listeners[i]==JMapViewerEventListener.class) {
+                ((JMapViewerEventListener)listeners[i+1]).processCommand(evt);
+            }
+        }
+    }
 }
Index: applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/OsmMercator.java
===================================================================
--- applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/OsmMercator.java	(revision 26668)
+++ applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/OsmMercator.java	(revision 26701)
@@ -19,4 +19,5 @@
     public static final double MAX_LAT = 85.05112877980659;
     public static final double MIN_LAT = -85.05112877980659;
+    private static double EARTH_RADIUS = 6378137; // equatorial earth radius for EPSG:3857 (Mercator) 
 
     public static double radius(int aZoomlevel) {
@@ -41,4 +42,48 @@
     public static int falseNorthing(int aZoomlevel) {
         return (-1 * getMaxPixels(aZoomlevel) / 2);
+    }
+
+    /**
+     * Transform pixelspace to coordinates and get the distance.
+     *
+     * @param x1 the first x coordinate
+     * @param y1 the first y coordinate
+     * @param x2 the second x coordinate
+     * @param y2 the second y coordinate
+     * 
+     * @param zoomLevel the zoom level
+     * @return the distance
+     * @author Jason Huntley
+     */
+    public static double getDistance(int x1, int y1, int x2, int y2, int zoomLevel) {
+        double la1 = YToLat(y1, zoomLevel);
+        double lo1 = XToLon(x1, zoomLevel);
+        double la2 = YToLat(y2, zoomLevel);
+        double lo2 = XToLon(x2, zoomLevel);
+
+        return getDistance(la1, lo1, la2, lo2);
+    }
+
+    /**
+     * Gets the distance using Spherical law of cosines.
+     *
+     * @param la1 the Latitude in degrees
+     * @param lo1 the Longitude in degrees
+     * @param la2 the Latitude from 2nd coordinate in degrees
+     * @param lo2 the Longitude from 2nd coordinate in degrees
+     * @return the distance
+     * @author Jason Huntley
+     */
+    public static double getDistance(double la1, double lo1, double la2, double lo2) {
+        double aStartLat = Math.toRadians(la1);
+        double aStartLong = Math.toRadians(lo1);
+        double aEndLat =Math.toRadians(la2);
+        double aEndLong = Math.toRadians(lo2);
+
+        double distance = Math.acos(Math.sin(aStartLat) * Math.sin(aEndLat)
+                + Math.cos(aStartLat) * Math.cos(aEndLat)
+                * Math.cos(aEndLong - aStartLong));
+
+        return (EARTH_RADIUS * distance);		
     }
 
Index: applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/events/JMVCommandEvent.java
===================================================================
--- applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/events/JMVCommandEvent.java	(revision 26701)
+++ applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/events/JMVCommandEvent.java	(revision 26701)
@@ -0,0 +1,49 @@
+package org.openstreetmap.gui.jmapviewer.events;
+
+//License: GPL.
+
+import java.util.EventObject;
+
+/**
+ * Used for passing events between UI components and other
+ * objects that register as a JMapViewerEventListener
+ * 
+ * @author Jason Huntley
+ *
+ */
+public class JMVCommandEvent extends EventObject {
+    public static enum COMMAND {
+        MOVE,
+        ZOOM
+    }
+
+    private COMMAND command;
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 8701544867914969620L;
+
+    public JMVCommandEvent(COMMAND cmd, Object source) {
+        super(source);
+
+        setCommand(cmd);
+    }
+
+    public JMVCommandEvent(Object source) {
+        super(source);
+    }
+
+    /**
+     * @return the command
+     */
+    public COMMAND getCommand() {
+        return command;
+    }
+
+    /**
+     * @param command the command to set
+     */
+    public void setCommand(COMMAND command) {
+        this.command = command;
+    }
+}
Index: applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/interfaces/JMapViewerEventListener.java
===================================================================
--- applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/interfaces/JMapViewerEventListener.java	(revision 26701)
+++ applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/interfaces/JMapViewerEventListener.java	(revision 26701)
@@ -0,0 +1,18 @@
+package org.openstreetmap.gui.jmapviewer.interfaces;
+
+//License: GPL.
+
+import java.util.EventListener;
+
+import org.openstreetmap.gui.jmapviewer.events.JMVCommandEvent;
+
+/**
+ * Must be implemented for processing commands while user
+ * interacts with map viewer.
+ * 
+ * @author Jason Huntley
+ *
+ */
+public interface JMapViewerEventListener extends EventListener {
+	public void processCommand(JMVCommandEvent command);
+}
