Ext.gesture.Pinch = Ext.extend(Ext.gesture.Gesture, {
    handles: [
        'pinchstart',
        'pinch',
        'pinchend'
    ],
    
    touches: 2,
    
    onTouchStart : function(e) {
        var me = this;
        
        if (Ext.supports.Touch && e.targetTouches.length >= 2) {
            me.lock('swipe', 'scroll', 'scrollstart', 'scrollend', 'touchmove', 'touchend', 'touchstart', 'tap', 'tapstart', 'taphold', 'tapcancel', 'doubletap');
            me.pinching = true;
            
            var targetTouches = e.targetTouches,
                firstTouch = me.firstTouch = targetTouches[0],
                secondTouch = me.secondTouch = targetTouches[1];
            
            me.previousDistance = me.startDistance = me.getDistance();
            me.previousScale = 1;
            
            me.fire('pinchstart', e, {
                distance: me.startDistance,
                scale: me.previousScale
            });
        }
        else if (me.pinching) {
            me.unlock('swipe', 'scroll', 'scrollstart', 'scrollend', 'touchmove', 'touchend', 'touchstart', 'tap', 'tapstart', 'taphold', 'tapcancel', 'doubletap');
            me.pinching = false;
        }
    },
    
    onTouchMove : function(e) {
        if (this.pinching) {
            this.fire('pinch', e, this.getPinchInfo());
        }
    },
    
    onTouchEnd : function(e) {
        if (this.pinching) {
            this.fire('pinchend', e, this.getPinchInfo());
        }
    },
    
    getPinchInfo : function() {
        var me = this,
            distance = me.getDistance(),
            scale = distance / me.startDistance,
            firstTouch = me.firstTouch,
            secondTouch = me.secondTouch,
            info = {
                scale: scale,
                deltaScale: scale - 1,
                previousScale: me.previousScale,
                previousDeltaScale: scale - me.previousScale,
                distance: distance,
                deltaDistance: distance - me.startDistance,
                startDistance: me.startDistance,
                previousDistance: me.previousDistance,
                previousDeltaDistance: distance - me.previousDistance,
                firstTouch: firstTouch,
                secondTouch: secondTouch,
                firstPageX: firstTouch.pageX,
                firstPageY: firstTouch.pageY,
                secondPageX: secondTouch.pageX,
                secondPageY: secondTouch.pageY,
                // The midpoint between the touches is (x1 + x2) / 2, (y1 + y2) / 2
                midPointX: (firstTouch.pageX + secondTouch.pageX) / 2,
                midPointY: (firstTouch.pageY + secondTouch.pageY) / 2
            };
        
        me.previousScale = scale;
        me.previousDistance = distance;
        
        return info;  
    },
    
    getDistance : function() {
        var me = this;
        return Math.sqrt(
            Math.pow(Math.abs(me.firstTouch.pageX - me.secondTouch.pageX), 2) +
            Math.pow(Math.abs(me.firstTouch.pageY - me.secondTouch.pageY), 2)
        );        
    }
});

Ext.regGesture('pinch', Ext.gesture.Pinch);