// FIXME factor out key precondition (shift et. al)

goog.provide('ol.Control');

goog.require('ol.MapBrowserEvent');
goog.require('ol.control.Constraints');



/**
 * @constructor
 * @param {ol.control.Constraints} constraints Constraints.
 */
ol.Control = function(constraints) {

  /**
   * @protected
   * @type {ol.control.Constraints}
   */
  this.constraints = constraints;

};


/**
 * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
 */
ol.Control.prototype.handleMapBrowserEvent = goog.abstractMethod;


/**
 * @param {ol.Map} map Map.
 * @param {ol.Extent} extent Extent.
 */
ol.Control.prototype.fitExtent = function(map, extent) {
  var resolution = map.getResolutionForExtent(extent);
  resolution = this.constraints.resolution(resolution, 0);
  var center = extent.getCenter();
  center = this.constraints.center(center, resolution, ol.Coordinate.ZERO);
  map.withFrozenRendering(function() {
    map.setCenter(center);
    map.setResolution(resolution);
  });
};


/**
 * @param {ol.Map} map Map.
 * @param {ol.Coordinate} delta Delta.
 * @param {ol.Coordinate=} opt_anchor Anchor.
 */
ol.Control.prototype.pan = function(map, delta, opt_anchor) {
  var center = opt_anchor ? opt_anchor : map.getCenter();
  var resolution = map.getResolution();
  center = this.constraints.center(center, resolution, delta);
  map.setCenter(center);
};


/**
 * @param {ol.Map} map Map.
 * @param {number|undefined} rotation Rotation.
 * @param {number} delta Delta.
 * @param {ol.Coordinate=} opt_anchor Anchor.
 */
ol.Control.prototype.rotate = function(map, rotation, delta, opt_anchor) {
  // FIXME handle rotation about anchor
  rotation = this.constraints.rotation(rotation, delta);
  map.setRotation(rotation);
};


/**
 * @param {ol.Map} map Map.
 * @param {number|undefined} resolution Resolution.
 */
ol.Control.prototype.setResolution = function(map, resolution) {
  resolution = this.constraints.resolution(resolution, 0);
  map.setResolution(resolution);
};


/**
 * @param {ol.Map} map Map.
 * @param {number|undefined} resolution Resolution.
 * @param {number} delta Delta.
 * @param {ol.Coordinate=} opt_anchor Anchor.
 */
ol.Control.prototype.zoom = function(map, resolution, delta, opt_anchor) {
  if (goog.isDefAndNotNull(opt_anchor)) {
    var mapCenter = /** @type {!ol.Coordinate} */ map.getCenter();
    var mapResolution = map.getResolution();
    resolution = this.constraints.resolution(resolution, delta);
    var center;
    if (resolution < mapResolution) {
      center = opt_anchor.clone();
      center.subtract(mapCenter);
      center.scale(resolution / mapResolution);
      center.add(mapCenter);
    } else if (resolution == mapResolution) {
      center = mapCenter;
    } else {
      center = mapCenter.clone();
      center.subtract(opt_anchor);
      center.scale(resolution / mapResolution);
      center.add(opt_anchor);
    }
    center = this.constraints.center(center, resolution, ol.Coordinate.ZERO);
    map.withFrozenRendering(function() {
      map.setCenter(center);
      map.setResolution(resolution);
    });
  } else {
    resolution = this.constraints.resolution(resolution, delta);
    map.setResolution(resolution);
  }
};

@@ -2260,24 +2260,53 @@
 _anchor)) %7B%0A
+    var anchor = opt_anchor;%0A
     var mapC
@@ -2356,24 +2356,24 @@
 etCenter();%0A
-
     var mapR
@@ -2482,152 +2482,61 @@
 var 
-center;%0A    if (resolution %3C mapResolution) %7B%0A      center = opt_anchor.clone();%0A      center.subtract(mapCenter);%0A      center.scale(resolution
+x = anchor.x - resolution *  (anchor.x - mapCenter.x)
  / m
@@ -2551,223 +2551,71 @@
 tion
-)
 ;%0A    
-  center.add(mapCenter);%0A    %7D else if (resolution == mapResolution) %7B%0A      center = mapCenter;%0A    %7D else %7B%0A      center = mapCenter.clone();%0A      center.subtract(opt_anchor);%0A      center.scale(resolution
+var y = anchor.y - resolution *  (anchor.y - mapCenter.y)
  / m
@@ -2630,46 +2630,51 @@
 tion
-)
 ;%0A    
- 
+var
  center
-.add(opt_anchor);%0A    %7D
+ = new ol.Coordinate(x, y);
 %0A   

Fix zoom to anchor