﻿/**
* @requires OpenLayers/Control/ZoomBox.js
* @requires OpenLayers/Control/DragPan.js
* @requires OpenLayers/Handler/MouseWheel.js
* @requires OpenLayers/Handler/Click.js
*/

OpenLayers.Control.ModifiedNavigator = OpenLayers.Class(OpenLayers.Control.Navigation, {

    /** 
    * Property: dragPan
    * {<OpenLayers.Control.DragPan>} 
    */
    dragPan: null,

    /**
    * APIProprety: dragPanOptions
    * {Object} Options passed to the DragPan control.
    */
    dragPanOptions: null,

    /** 
    * Property: zoomBox
    * {<OpenLayers.Control.ZoomBox>}
    */
    zoomBox: null,

    /**
    * APIProperty: zoomWheelEnabled
    * {Boolean} Whether the mousewheel should zoom the map
    */
    zoomWheelEnabled: true,

    /**
    * APIProperty: handleRightClicks
    * {Boolean} Whether or not to handle right clicks. Default is false.
    */
    handleRightClicks: false,

    /**
    * APIProperty: zoomBoxKeyMask
    * {Integer} <OpenLayers.Handler> key code of the key, which has to be
    *    pressed, while drawing the zoom box with the mouse on the screen. 
    *    You should probably set handleRightClicks to true if you use this
    *    with MOD_CTRL, to disable the context menu for machines which use
    *    CTRL-Click as a right click.
    * Default: <OpenLayers.Handler.MOD_SHIFT
    */
    zoomBoxKeyMask: OpenLayers.Handler.MOD_SHIFT,

    /**
    * Constructor: OpenLayers.Control.Navigation
    * Create a new navigation control
    * 
    * Parameters:
    * options - {Object} An optional object whose properties will be set on
    *                    the control
    */
    initialize: function(options) {
        this.handlers = {};
        OpenLayers.Control.prototype.initialize.apply(this, arguments);
    },

    /**
    * Method: destroy
    * The destroy method is used to perform any clean up before the control
    * is dereferenced.  Typically this is where event listeners are removed
    * to prevent memory leaks.
    */
    destroy: function() {
        this.deactivate();

        if (this.dragPan) {
            this.dragPan.destroy();
        }
        this.dragPan = null;

        if (this.zoomBox) {
            this.zoomBox.destroy();
        }
        this.zoomBox = null;
        OpenLayers.Control.prototype.destroy.apply(this, arguments);
    },

    /**
    * Method: activate
    */
    activate: function() {
        this.dragPan.activate();
        if (this.zoomWheelEnabled) {
            this.handlers.wheel.activate();
        }
        this.handlers.click.activate();
        this.zoomBox.activate();
        return OpenLayers.Control.prototype.activate.apply(this, arguments);
    },

    /**
    * Method: deactivate
    */
    deactivate: function() {
        this.zoomBox.deactivate();
        this.dragPan.deactivate();
        this.handlers.click.deactivate();
        this.handlers.wheel.deactivate();
        return OpenLayers.Control.prototype.deactivate.apply(this, arguments);
    },

    /**
    * Method: draw
    */
    draw: function() {
        // disable right mouse context menu for support of right click events
        if (this.handleRightClicks) {
            this.map.viewPortDiv.oncontextmenu = function() { return false; };
        }

        var clickCallbacks = {
            'dblclick': this.defaultDblClick,
            'dblrightclick': this.defaultDblRightClick
        };
        var clickOptions = {
            'double': true,
            'stopDouble': true
        };
        this.handlers.click = new OpenLayers.Handler.Click(
            this, clickCallbacks, clickOptions
        );
        this.dragPan = new OpenLayers.Control.DragPan(
            OpenLayers.Util.extend({ map: this.map }, this.dragPanOptions)
        );
        this.zoomBox = new OpenLayers.Control.ZoomBox(
                    { map: this.map, keyMask: this.zoomBoxKeyMask });
        this.dragPan.draw();
        this.zoomBox.draw();
        this.handlers.wheel = new OpenLayers.Handler.MouseWheel(
                                    this, { "up": this.wheelUp,
                                        "down": this.wheelDown
                                    });
        this.activate();
    },

    /**
    * Method: defaultDblClick 
    * 
    * Parameters:
    * evt - {Event} 
    */
    defaultDblClick: function(evt) {
        var newCenter = this.map.getLonLatFromViewPortPx(evt.xy);
        this.map.setCenter(newCenter, this.map.zoom + 1);
    },

    /**
    * Method: defaultDblRightClick 
    * 
    * Parameters:
    * evt - {Event} 
    */
    defaultDblRightClick: function(evt) {
        var newCenter = this.map.getLonLatFromViewPortPx(evt.xy);
        this.map.setCenter(newCenter, this.map.zoom - 1);
    },

    /**
    * Method: wheelChange  
    *
    * Parameters:
    * evt - {Event}
    * deltaZ - {Integer}
    */
    wheelChange: function(evt, deltaZ) {
        var newZoom = parseInt(this.map.getZoom()) + parseInt(deltaZ);
        if (!this.map.isValidZoomLevel(newZoom)) {
            return;
        }
        var size = this.map.getSize();
        var deltaX = size.w / 2 - evt.xy.x;
        var deltaY = evt.xy.y - size.h / 2;
        var newRes = this.map.baseLayer.getResolutionForZoom(newZoom);
        var zoomPoint = this.map.getLonLatFromPixel(evt.xy);
        var newCenter = new OpenLayers.LonLat(
                            zoomPoint.lon + deltaX * newRes,
                            zoomPoint.lat + deltaY * newRes);
        this.map.setCenter(newCenter, newZoom);
    },

    /** 
    * Method: wheelUp
    * User spun scroll wheel up
    * 
    * Parameters:
    * evt - {Event}
    */
    wheelUp: function(evt) {
        this.wheelChange(evt, 1);
    },

    /** 
    * Method: wheelDown
    * User spun scroll wheel down
    * 
    * Parameters:
    * evt - {Event}
    */
    wheelDown: function(evt) {
        this.wheelChange(evt, -1);
    },

    /**
    * Method: disableZoomWheel
    */

    disableZoomWheel: function() {
        this.zoomWheelEnabled = false;
        this.handlers.wheel.deactivate();
    },

    /**
    * Method: enableZoomWheel
    */

    enableZoomWheel: function() {
        this.zoomWheelEnabled = true;
        if (this.active) {
            this.handlers.wheel.activate();
        }
    },
    CLASS_NAME: "OpenLayers.Control.ModifiedNavigator"
});