<commit_before>package com.mapzen.tangram;

import android.content.Context;
import android.view.GestureDetector;
import android.view.GestureDetector.OnDoubleTapListener;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.ScaleGestureDetector.OnScaleGestureListener;
import android.view.View;
import android.view.View.OnTouchListener;

import com.almeros.android.multitouch.RotateGestureDetector;
import com.almeros.android.multitouch.RotateGestureDetector.OnRotateGestureListener;
import com.almeros.android.multitouch.ShoveGestureDetector;
import com.almeros.android.multitouch.ShoveGestureDetector.OnShoveGestureListener;

import java.util.Arrays;

/**
 * Collects touch data, applies gesture detectors, resolves simultaneous detection, and calls the
 * appropriate input responders
 */
public class TouchManager implements OnTouchListener, OnScaleGestureListener,
        OnRotateGestureListener, OnGestureListener, OnDoubleTapListener, OnShoveGestureListener {

    public enum Gestures {
        TAP,
        DOUBLE_TAP,
        LONG_PRESS,
        PAN,
        ROTATE,
        SCALE,
        SHOVE,
    }

    public interface TapResponder {
        boolean onSingleTapUp(float x, float y);
        boolean onSingleTapConfirmed(float x, float y);
    }

    public interface DoubleTapResponder {
        boolean onDoubleTap(float x, float y);
    }

    public interface LongPressResponder {
        void onLongPress(float x, float y);
    }

    public interface PanResponder {
        boolean onPan(float startX, float startY, float endX, float endY);
    }

    public interface ScaleResponder {
        boolean onScale(float x, float y, float scale, float velocity);
    }

    public interface RotateResponder {
        boolean onRotate(float x, float y, float rotation);
    }

    public interface ShoveResponder {
        boolean onShove(float distance);
    }

    private GestureDetector panTapGestureDetector;
    private ScaleGestureDetector scaleGestureDetector;
    private RotateGestureDetector rotateGestureDetector;
    private ShoveGestureDetector shoveGestureDetector;

    private TapResponder tapResponder;
    private DoubleTapResponder doubleTapResponder;
    private LongPressResponder longPressResponder;
    private PanResponder panResponder;
    private ScaleResponder scaleResponder;
    private RotateResponder rotateResponder;
    private ShoveResponder shoveResponder;

    private boolean[] detectedGestures;
    private boolean[][] allowedSimultaneousGestures;

    public TouchManager(Context context) {

        this.panTapGestureDetector = new GestureDetector(context, this);
        this.scaleGestureDetector = new ScaleGestureDetector(context, this);
        this.rotateGestureDetector = new RotateGestureDetector(context, this);
        this.shoveGestureDetector = new ShoveGestureDetector(context, this);

        int nGestures = Gestures.values().length;
        this.detectedGestures = new boolean[nGestures];
        this.allowedSimultaneousGestures = new boolean[nGestures][nGestures];

        // By default, all gestures are allowed to detect simultaneously
        for (boolean[] arr : allowedSimultaneousGestures) {
            Arrays.fill(arr, true);
        }
    }

    public void setTapResponder(TapResponder responder) {
        this.tapResponder = responder;
    }

    public void setDoubleTapResponder(DoubleTapResponder responder) {
        this.doubleTapResponder = responder;
    }

    public void setLongPressResponder(LongPressResponder responder) {
        this.longPressResponder = responder;
    }

    public void setPanResponder(PanResponder responder) {
        this.panResponder = responder;
    }

    public void setScaleResponder(ScaleResponder responder) {
        this.scaleResponder = responder;
    }

    public void setRotateResponder(RotateResponder responder) {
        this.rotateResponder = responder;
    }

    public void setShoveResponder(ShoveResponder responder) {
        this.shoveResponder = responder;
    }

    // Set whether 'second' can detect while 'first' is in progress
    public void setSimultaneousDetectionAllowed(Gestures first, Gestures second, boolean allowed) {
        if (first != second) {
            allowedSimultaneousGestures[second.ordinal()][first.ordinal()] = allowed;
        }
    }

    public boolean isSimultaneousDetectionAllowed(Gestures first, Gestures second) {
        return allowedSimultaneousGestures[second.ordinal()][first.ordinal()];
    }

    private boolean isDetectionAllowed(Gestures g) {
        boolean [] allowed = allowedSimultaneousGestures[g.ordinal()];
        for (int i = 0; i < allowed.length; ++i) {
            if (!allowed[i] && detectedGestures[i]) {
                return false;
            }
        }
        return true;
    }

    private void setGestureDetected(Gestures g, boolean detected) {
        detectedGestures[g.ordinal()] = detected;
    }
<commit_msg>Add time buffer between multi-touch gestures and single-touch gestures<commit_after>package com.mapzen.tangram;

import android.content.Context;
import android.os.SystemClock;
import android.view.GestureDetector;
import android.view.GestureDetector.OnDoubleTapListener;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.ScaleGestureDetector.OnScaleGestureListener;
import android.view.View;
import android.view.View.OnTouchListener;

import com.almeros.android.multitouch.RotateGestureDetector;
import com.almeros.android.multitouch.RotateGestureDetector.OnRotateGestureListener;
import com.almeros.android.multitouch.ShoveGestureDetector;
import com.almeros.android.multitouch.ShoveGestureDetector.OnShoveGestureListener;

import java.util.Arrays;

/**
 * Collects touch data, applies gesture detectors, resolves simultaneous detection, and calls the
 * appropriate input responders
 */
public class TouchManager implements OnTouchListener, OnScaleGestureListener,
        OnRotateGestureListener, OnGestureListener, OnDoubleTapListener, OnShoveGestureListener {

    public enum Gestures {
        TAP(1),
        DOUBLE_TAP(1),
        LONG_PRESS(1),
        PAN(1),
        ROTATE(2),
        SCALE(2),
        SHOVE(2),
        ;

        private int touches;

        Gestures(int touches) {
            this.touches = touches;
        }

        public int getTouchesRequired() {
            return touches;
        }

        public boolean isMultiTouch() {
            return touches > 1;
        }
    }

    public interface TapResponder {
        boolean onSingleTapUp(float x, float y);
        boolean onSingleTapConfirmed(float x, float y);
    }

    public interface DoubleTapResponder {
        boolean onDoubleTap(float x, float y);
    }

    public interface LongPressResponder {
        void onLongPress(float x, float y);
    }

    public interface PanResponder {
        boolean onPan(float startX, float startY, float endX, float endY);
    }

    public interface ScaleResponder {
        boolean onScale(float x, float y, float scale, float velocity);
    }

    public interface RotateResponder {
        boolean onRotate(float x, float y, float rotation);
    }

    public interface ShoveResponder {
        boolean onShove(float distance);
    }

    private static final long MULTITOUCH_BUFFER_TIME = 256; // milliseconds

    private GestureDetector panTapGestureDetector;
    private ScaleGestureDetector scaleGestureDetector;
    private RotateGestureDetector rotateGestureDetector;
    private ShoveGestureDetector shoveGestureDetector;

    private TapResponder tapResponder;
    private DoubleTapResponder doubleTapResponder;
    private LongPressResponder longPressResponder;
    private PanResponder panResponder;
    private ScaleResponder scaleResponder;
    private RotateResponder rotateResponder;
    private ShoveResponder shoveResponder;

    private boolean[] detectedGestures;
    private boolean[][] allowedSimultaneousGestures;

    private long lastMultiTouchEndTime = -MULTITOUCH_BUFFER_TIME;

    public TouchManager(Context context) {

        this.panTapGestureDetector = new GestureDetector(context, this);
        this.scaleGestureDetector = new ScaleGestureDetector(context, this);
        this.rotateGestureDetector = new RotateGestureDetector(context, this);
        this.shoveGestureDetector = new ShoveGestureDetector(context, this);

        int nGestures = Gestures.values().length;
        this.detectedGestures = new boolean[nGestures];
        this.allowedSimultaneousGestures = new boolean[nGestures][nGestures];

        // By default, all gestures are allowed to detect simultaneously
        for (boolean[] arr : allowedSimultaneousGestures) {
            Arrays.fill(arr, true);
        }
    }

    public void setTapResponder(TapResponder responder) {
        this.tapResponder = responder;
    }

    public void setDoubleTapResponder(DoubleTapResponder responder) {
        this.doubleTapResponder = responder;
    }

    public void setLongPressResponder(LongPressResponder responder) {
        this.longPressResponder = responder;
    }

    public void setPanResponder(PanResponder responder) {
        this.panResponder = responder;
    }

    public void setScaleResponder(ScaleResponder responder) {
        this.scaleResponder = responder;
    }

    public void setRotateResponder(RotateResponder responder) {
        this.rotateResponder = responder;
    }

    public void setShoveResponder(ShoveResponder responder) {
        this.shoveResponder = responder;
    }

    // Set whether 'second' can detect while 'first' is in progress
    public void setSimultaneousDetectionAllowed(Gestures first, Gestures second, boolean allowed) {
        if (first != second) {
            allowedSimultaneousGestures[second.ordinal()][first.ordinal()] = allowed;
        }
    }

    public boolean isSimultaneousDetectionAllowed(Gestures first, Gestures second) {
        return allowedSimultaneousGestures[second.ordinal()][first.ordinal()];
    }

    private boolean isDetectionAllowed(Gestures g) {
        boolean [] allowed = allowedSimultaneousGestures[g.ordinal()];
        for (int i = 0; i < allowed.length; ++i) {
            if (!allowed[i] && detectedGestures[i]) {
                return false;
            }
        }
        if (!g.isMultiTouch()) {
            // Return false if a multitouch gesture has finished within a time threshold
            long t = SystemClock.uptimeMillis() - lastMultiTouchEndTime;
            if (t < MULTITOUCH_BUFFER_TIME) {
                return false;
            }
        }
        return true;
    }

    private void setGestureDetected(Gestures g, boolean detected) {
        detectedGestures[g.ordinal()] = detected;
        if (!detected && g.isMultiTouch()) {
            lastMultiTouchEndTime = SystemClock.uptimeMillis();
        }
    }

{'fraction_non_alphanumeric': 0.07315521628498728, 'fraction_numerical': 0.0011813885859687386, 'mean_word_length': 3.3173793644566496, 'pattern_counts': {'":': 0, '<': 6, '<?xml version=': 0, '>': 4, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5008686', 'n_tokens_mistral': 3338, 'n_tokens_neox': 3061, 'n_words': 703}