<commit_before>/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package androidx.constraintlayout.motion.widget;

import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.util.TypedValue;
import android.util.Xml;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AnimationUtils;
import android.view.animation.AnticipateInterpolator;
import android.view.animation.BounceInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import android.view.animation.OvershootInterpolator;

import androidx.constraintlayout.core.motion.utils.Easing;
import androidx.constraintlayout.widget.ConstraintSet;
import androidx.constraintlayout.widget.R;
import androidx.constraintlayout.widget.StateSet;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * The information to transition between multiple ConstraintSets
 * This Class is meant to be used from XML
 *
 */
public class MotionScene {
    private static final String TAG = "MotionScene";
    private static final boolean DEBUG = false;
    private static final int MIN_DURATION = 8;
    final static int TRANSITION_BACKWARD = 0;
    final static int TRANSITION_FORWARD = 1;
    private static final int SPLINE_STRING = -1;
    private static final int INTERPOLATOR_REFERENCE_ID = -2;
    public static final int UNSET = -1;
    private final MotionLayout mMotionLayout;
    StateSet mStateSet = null;
    Transition mCurrentTransition = null;
    private boolean mDisableAutoTransition = false;
    private ArrayList<Transition> mTransitionList = new ArrayList<>();
    private Transition mDefaultTransition = null;
    private ArrayList<Transition> mAbstractTransitionList = new ArrayList<>();

    private SparseArray<ConstraintSet> mConstraintSetMap = new SparseArray<>();
    private HashMap<String, Integer> mConstraintSetIdMap = new HashMap<>();
    private SparseIntArray mDeriveMap = new SparseIntArray();
    private boolean DEBUG_DESKTOP = false;
    private int mDefaultDuration = 400;
    private int mLayoutDuringTransition = 0;
    public static final int LAYOUT_IGNORE_REQUEST = 0;
    public static final int LAYOUT_HONOR_REQUEST = 1;
    private MotionEvent mLastTouchDown;
    private boolean mIgnoreTouch = false;
    private boolean mMotionOutsideRegion = false;
    private MotionLayout.MotionTracker mVelocityTracker; // used to support fling
    private boolean mRtl;
    private static final String MOTIONSCENE_TAG = "MotionScene";
    private static final String TRANSITION_TAG = "Transition";
    private static final String ONSWIPE_TAG = "OnSwipe";
    private static final String ONCLICK_TAG = "OnClick";
    private static final String STATESET_TAG = "StateSet";
    private static final String INCLUDE_TAG_UC = "Include";
    private static final String INCLUDE_TAG = "include";
    private static final String KEYFRAMESET_TAG = "KeyFrameSet";
    private static final String CONSTRAINTSET_TAG = "ConstraintSet";
    private static final String VIEW_TRANSITION = "ViewTransition";
    final ViewTransitionController mViewTransitionController;

    /**
     * Set the transition between two constraint set / states.
     * The transition will get created between the two sets
     * if it doesn't exist already.
     *
     * @param beginId id of the start constraint set or state
     * @param endId   id of the end constraint set or state
     */
    void setTransition(int beginId, int endId) {
        int start = beginId;
        int end = endId;
        if (mStateSet != null) {
            int tmp = mStateSet.stateGetConstraintID(beginId, -1, -1);
            if (tmp != -1) {
                start = tmp;
            }
            tmp = mStateSet.stateGetConstraintID(endId, -1, -1);
            if (tmp != -1) {
                end = tmp;
            }
        }
        if (DEBUG) {
            Log.v(TAG, Debug.getLocation() + " setTransition " +
                    Debug.getName(mMotionLayout.getContext(), beginId) + " -> " +
                    Debug.getName(mMotionLayout.getContext(), endId));
        }
        if (mCurrentTransition != null) {
            if (mCurrentTransition.mConstraintSetEnd == endId &&
                    mCurrentTransition.mConstraintSetStart == beginId) {
                return;
            }
        }
        for (Transition transition : mTransitionList) {
            if ((transition.mConstraintSetEnd == end
                    && transition.mConstraintSetStart == start)
                    || (transition.mConstraintSetEnd == endId
                    && transition.mConstraintSetStart == beginId)) {
                if (DEBUG) {
                    Log.v(TAG, Debug.getLocation() + " found transition  " +
                            Debug.getName(mMotionLayout.getContext(), beginId) + " -> " +
                            Debug.getName(mMotionLayout.getContext(), endId));
                }
                mCurrentTransition = transition;
                if (mCurrentTransition != null && mCurrentTransition.mTouchResponse != null) {
                    mCurrentTransition.mTouchResponse.setRTL(mRtl);
                }
                return;
            }
        }
        // No transition defined for this so we will create one?
        Transition matchTransition = mDefaultTransition;
        for (Transition transition : mAbstractTransitionList) {
            if (transition.mConstraintSetEnd == endId) {
                matchTransition = transition;
            }
        }
        Transition t = new Transition(this, matchTransition);

        t.mConstraintSetStart = start;
        t.mConstraintSetEnd = end;
        if (start != UNSET) {
            mTransitionList.add(t);
        }
        mCurrentTransition = t;
    }

    /**
     * Add a transition to the motion scene. If a transition with the same id already exists
     * in the scene, the new transition will replace the existing one.
     *
     * @throws IllegalArgumentException if the transition does not have an id.
     */
    public void addTransition(Transition transition) {
        int index = getIndex(transition);
        if (index == -1) {
            mTransitionList.add(transition);
        } else {
            mTransitionList.set(index, transition);
        }
    }

    /**
     * Remove the transition with the matching id from the motion scene. If no matching transition
     * is found, it does nothing.
     *
     * @throws IllegalArgumentException if the transition does not have an id.
     */
    public void removeTransition(Transition transition) {
        int index = getIndex(transition);
        if (index != -1) {
            mTransitionList.remove(index);
        }
    }

    /**
     * @return the index in the transition list. -1 if transition wasn't found.
     */
    private int getIndex(Transition transition) {
        int id = transition.mId;
        if (id == UNSET) {
            throw new IllegalArgumentException("The transition must have an id");
        }

        int index = 0;
        for (; index < mTransitionList.size(); index++) {
            if (mTransitionList.get(index).mId == id) {
                return index;
            }
        }

        return -1;
    }

    /**
     * @return true if the layout is valid for the scene. False otherwise. Use it for the debugging
     * purposes.
     */
    public boolean validateLayout(MotionLayout layout) {
        return (layout == mMotionLayout && layout.mScene == this);
    }

    /**
     * Set the transition to be the current transition of the motion scene.
     *
     * @param transition a transition to be set. The transition must exist within the motion scene.
     *                   (e.g. {@link #addTransition(Transition)})
     */
    public void setTransition(Transition transition) {
        mCurrentTransition = transition;
        if (mCurrentTransition != null && mCurrentTransition.mTouchResponse != null) {
            mCurrentTransition.mTouchResponse.setRTL(mRtl);
        }
    }

    private int getRealID(int stateId) {
        if (mStateSet != null) {
            int tmp = mStateSet.stateGetConstraintID(stateId, -1, -1);
            if (tmp != -1) {
                return tmp;
            }
        }
        return stateId;
    }

    public List<Transition> getTransitionsWithState(int stateId) {
        stateId = getRealID(stateId);
        ArrayList<Transition> ret = new ArrayList<>();
        for (Transition transition : mTransitionList) {
            if (transition.mConstraintSetStart == stateId || transition.mConstraintSetEnd == stateId) {
                ret.add(transition);
            }

        }
        return ret;
    }

    public void addOnClickListeners(MotionLayout motionLayout, int currentState) {
        // remove all on clicks listeners
        for (Transition transition : mTransitionList) {
            if (transition.mOnClicks.size() > 0) {
                for (Transition.TransitionOnClick onClick : transition.mOnClicks) {
                    onClick.removeOnClickListeners(motionLayout);
                }
            }
        }
        for (Transition transition : mAbstractTransitionList) {
            if (transition.mOnClicks.size() > 0) {
                for (Transition.TransitionOnClick onClick : transition.mOnClicks) {
                    onClick.removeOnClickListeners(motionLayout);
                }
            }
        }
        // add back all the listeners that are needed
        for (Transition transition : mTransitionList) {
            if (transition.mOnClicks.size() > 0) {
                for (Transition.TransitionOnClick onClick : transition.mOnClicks) {
                    onClick.addOnClickListeners(motionLayout, currentState, transition);
                }
            }
        }
        for (Transition transition : mAbstractTransitionList) {
            if (transition.mOnClicks.size() > 0) {
                for (Transition.TransitionOnClick onClick : transition.mOnClicks) {
                    onClick.addOnClickListeners(motionLayout, currentState, transition);
                }
            }
        }
    }

    public Transition bestTransitionFor(int currentState, float dx, float dy, MotionEvent lastTouchDown) {
        List<Transition> candidates = null;
        if (currentState != -1) {
            candidates = getTransitionsWithState(currentState);
            float max = 0;
            Transition best = null;
            RectF cache = new RectF();
            for (Transition transition : candidates) {
                if (transition.mDisable) {
                    continue;
                }
                if (transition.mTouchResponse != null) {
                    transition.mTouchResponse.setRTL(mRtl);
                    RectF region = transition.mTouchResponse.getTouchRegion(mMotionLayout, cache);
                    if (region != null && lastTouchDown != null && (!region.contains(lastTouchDown.getX(), lastTouchDown.getY()))) {
                        continue;
                    }

                    float val = transition.mTouchResponse.dot(dx, dy);
                    if (transition.mTouchResponse.mIsRotateMode && lastTouchDown != null) {
                        float startX = lastTouchDown.getX() - transition.mTouchResponse.mRotateCenterX;
                        float startY = lastTouchDown.getY() - transition.mTouchResponse.mRotateCenterY;
                        float endX = dx + startX;
                        float endY = dy + startY;
                        double endAngle = Math.atan2(endY, endX);
                        double startAngle = Math.atan2(startX, startY);
                        val = (float) (endAngle - startAngle) * 10;
                    }
                    if (transition.mConstraintSetEnd == currentState) { // flip because this would be backwards
                        val *= -1;
                    } else {
                        val *= 1.1f; // slightly bias towards the transition which is start over end
                    }

                    if (val > max) {
                        max = val;
                        best = transition;
                    }
                }
            }<commit_msg>fix limitRegionTo (#323)<commit_after>/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package androidx.constraintlayout.motion.widget;

import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.util.TypedValue;
import android.util.Xml;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AnimationUtils;
import android.view.animation.AnticipateInterpolator;
import android.view.animation.BounceInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import android.view.animation.OvershootInterpolator;

import androidx.constraintlayout.core.motion.utils.Easing;
import androidx.constraintlayout.widget.ConstraintSet;
import androidx.constraintlayout.widget.R;
import androidx.constraintlayout.widget.StateSet;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * The information to transition between multiple ConstraintSets
 * This Class is meant to be used from XML
 *
 */
public class MotionScene {
    private static final String TAG = "MotionScene";
    private static final boolean DEBUG = false;
    private static final int MIN_DURATION = 8;
    final static int TRANSITION_BACKWARD = 0;
    final static int TRANSITION_FORWARD = 1;
    private static final int SPLINE_STRING = -1;
    private static final int INTERPOLATOR_REFERENCE_ID = -2;
    public static final int UNSET = -1;
    private final MotionLayout mMotionLayout;
    StateSet mStateSet = null;
    Transition mCurrentTransition = null;
    private boolean mDisableAutoTransition = false;
    private ArrayList<Transition> mTransitionList = new ArrayList<>();
    private Transition mDefaultTransition = null;
    private ArrayList<Transition> mAbstractTransitionList = new ArrayList<>();

    private SparseArray<ConstraintSet> mConstraintSetMap = new SparseArray<>();
    private HashMap<String, Integer> mConstraintSetIdMap = new HashMap<>();
    private SparseIntArray mDeriveMap = new SparseIntArray();
    private boolean DEBUG_DESKTOP = false;
    private int mDefaultDuration = 400;
    private int mLayoutDuringTransition = 0;
    public static final int LAYOUT_IGNORE_REQUEST = 0;
    public static final int LAYOUT_HONOR_REQUEST = 1;
    private MotionEvent mLastTouchDown;
    private boolean mIgnoreTouch = false;
    private boolean mMotionOutsideRegion = false;
    private MotionLayout.MotionTracker mVelocityTracker; // used to support fling
    private boolean mRtl;
    private static final String MOTIONSCENE_TAG = "MotionScene";
    private static final String TRANSITION_TAG = "Transition";
    private static final String ONSWIPE_TAG = "OnSwipe";
    private static final String ONCLICK_TAG = "OnClick";
    private static final String STATESET_TAG = "StateSet";
    private static final String INCLUDE_TAG_UC = "Include";
    private static final String INCLUDE_TAG = "include";
    private static final String KEYFRAMESET_TAG = "KeyFrameSet";
    private static final String CONSTRAINTSET_TAG = "ConstraintSet";
    private static final String VIEW_TRANSITION = "ViewTransition";
    final ViewTransitionController mViewTransitionController;

    /**
     * Set the transition between two constraint set / states.
     * The transition will get created between the two sets
     * if it doesn't exist already.
     *
     * @param beginId id of the start constraint set or state
     * @param endId   id of the end constraint set or state
     */
    void setTransition(int beginId, int endId) {
        int start = beginId;
        int end = endId;
        if (mStateSet != null) {
            int tmp = mStateSet.stateGetConstraintID(beginId, -1, -1);
            if (tmp != -1) {
                start = tmp;
            }
            tmp = mStateSet.stateGetConstraintID(endId, -1, -1);
            if (tmp != -1) {
                end = tmp;
            }
        }
        if (DEBUG) {
            Log.v(TAG, Debug.getLocation() + " setTransition " +
                    Debug.getName(mMotionLayout.getContext(), beginId) + " -> " +
                    Debug.getName(mMotionLayout.getContext(), endId));
        }
        if (mCurrentTransition != null) {
            if (mCurrentTransition.mConstraintSetEnd == endId &&
                    mCurrentTransition.mConstraintSetStart == beginId) {
                return;
            }
        }
        for (Transition transition : mTransitionList) {
            if ((transition.mConstraintSetEnd == end
                    && transition.mConstraintSetStart == start)
                    || (transition.mConstraintSetEnd == endId
                    && transition.mConstraintSetStart == beginId)) {
                if (DEBUG) {
                    Log.v(TAG, Debug.getLocation() + " found transition  " +
                            Debug.getName(mMotionLayout.getContext(), beginId) + " -> " +
                            Debug.getName(mMotionLayout.getContext(), endId));
                }
                mCurrentTransition = transition;
                if (mCurrentTransition != null && mCurrentTransition.mTouchResponse != null) {
                    mCurrentTransition.mTouchResponse.setRTL(mRtl);
                }
                return;
            }
        }
        // No transition defined for this so we will create one?
        Transition matchTransition = mDefaultTransition;
        for (Transition transition : mAbstractTransitionList) {
            if (transition.mConstraintSetEnd == endId) {
                matchTransition = transition;
            }
        }
        Transition t = new Transition(this, matchTransition);

        t.mConstraintSetStart = start;
        t.mConstraintSetEnd = end;
        if (start != UNSET) {
            mTransitionList.add(t);
        }
        mCurrentTransition = t;
    }

    /**
     * Add a transition to the motion scene. If a transition with the same id already exists
     * in the scene, the new transition will replace the existing one.
     *
     * @throws IllegalArgumentException if the transition does not have an id.
     */
    public void addTransition(Transition transition) {
        int index = getIndex(transition);
        if (index == -1) {
            mTransitionList.add(transition);
        } else {
            mTransitionList.set(index, transition);
        }
    }

    /**
     * Remove the transition with the matching id from the motion scene. If no matching transition
     * is found, it does nothing.
     *
     * @throws IllegalArgumentException if the transition does not have an id.
     */
    public void removeTransition(Transition transition) {
        int index = getIndex(transition);
        if (index != -1) {
            mTransitionList.remove(index);
        }
    }

    /**
     * @return the index in the transition list. -1 if transition wasn't found.
     */
    private int getIndex(Transition transition) {
        int id = transition.mId;
        if (id == UNSET) {
            throw new IllegalArgumentException("The transition must have an id");
        }

        int index = 0;
        for (; index < mTransitionList.size(); index++) {
            if (mTransitionList.get(index).mId == id) {
                return index;
            }
        }

        return -1;
    }

    /**
     * @return true if the layout is valid for the scene. False otherwise. Use it for the debugging
     * purposes.
     */
    public boolean validateLayout(MotionLayout layout) {
        return (layout == mMotionLayout && layout.mScene == this);
    }

    /**
     * Set the transition to be the current transition of the motion scene.
     *
     * @param transition a transition to be set. The transition must exist within the motion scene.
     *                   (e.g. {@link #addTransition(Transition)})
     */
    public void setTransition(Transition transition) {
        mCurrentTransition = transition;
        if (mCurrentTransition != null && mCurrentTransition.mTouchResponse != null) {
            mCurrentTransition.mTouchResponse.setRTL(mRtl);
        }
    }

    private int getRealID(int stateId) {
        if (mStateSet != null) {
            int tmp = mStateSet.stateGetConstraintID(stateId, -1, -1);
            if (tmp != -1) {
                return tmp;
            }
        }
        return stateId;
    }

    public List<Transition> getTransitionsWithState(int stateId) {
        stateId = getRealID(stateId);
        ArrayList<Transition> ret = new ArrayList<>();
        for (Transition transition : mTransitionList) {
            if (transition.mConstraintSetStart == stateId || transition.mConstraintSetEnd == stateId) {
                ret.add(transition);
            }

        }
        return ret;
    }

    public void addOnClickListeners(MotionLayout motionLayout, int currentState) {
        // remove all on clicks listeners
        for (Transition transition : mTransitionList) {
            if (transition.mOnClicks.size() > 0) {
                for (Transition.TransitionOnClick onClick : transition.mOnClicks) {
                    onClick.removeOnClickListeners(motionLayout);
                }
            }
        }
        for (Transition transition : mAbstractTransitionList) {
            if (transition.mOnClicks.size() > 0) {
                for (Transition.TransitionOnClick onClick : transition.mOnClicks) {
                    onClick.removeOnClickListeners(motionLayout);
                }
            }
        }
        // add back all the listeners that are needed
        for (Transition transition : mTransitionList) {
            if (transition.mOnClicks.size() > 0) {
                for (Transition.TransitionOnClick onClick : transition.mOnClicks) {
                    onClick.addOnClickListeners(motionLayout, currentState, transition);
                }
            }
        }
        for (Transition transition : mAbstractTransitionList) {
            if (transition.mOnClicks.size() > 0) {
                for (Transition.TransitionOnClick onClick : transition.mOnClicks) {
                    onClick.addOnClickListeners(motionLayout, currentState, transition);
                }
            }
        }
    }

    public Transition bestTransitionFor(int currentState, float dx, float dy, MotionEvent lastTouchDown) {
        List<Transition> candidates = null;
        if (currentState != -1) {
            candidates = getTransitionsWithState(currentState);
            float max = 0;
            Transition best = null;
            RectF cache = new RectF();
            for (Transition transition : candidates) {
                if (transition.mDisable) {
                    continue;
                }
                if (transition.mTouchResponse != null) {
                    transition.mTouchResponse.setRTL(mRtl);
                    RectF region = transition.mTouchResponse.getTouchRegion(mMotionLayout, cache);
                    if (region != null && lastTouchDown != null && (!region.contains(lastTouchDown.getX(), lastTouchDown.getY()))) {
                        continue;
                    }
                    region = transition.mTouchResponse.getLimitBoundsTo(mMotionLayout, cache);
                    if (region != null && lastTouchDown != null && (!region.contains(lastTouchDown.getX(), lastTouchDown.getY()))) {
                        continue;
                    }

                    float val = transition.mTouchResponse.dot(dx, dy);
                    if (transition.mTouchResponse.mIsRotateMode && lastTouchDown != null) {
                        float startX = lastTouchDown.getX() - transition.mTouchResponse.mRotateCenterX;
                        float startY = lastTouchDown.getY() - transition.mTouchResponse.mRotateCenterY;
                        float endX = dx + startX;
                        float endY = dy + startY;
                        double endAngle = Math.atan2(endY, endX);
                        double startAngle = Math.atan2(startX, startY);
                        val = (float) (endAngle - startAngle) * 10;
                    }
                    if (transition.mConstraintSetEnd == currentState) { // flip because this would be backwards
                        val *= -1;
                    } else {
                        val *= 1.1f; // slightly bias towards the transition which is start over end
                    }

                    if (val > max) {
                        max = val;
                        best = transition;
                    }
                }
            }
{'fraction_non_alphanumeric': 0.08341063411376201, 'fraction_numerical': 0.003747541835182368, 'mean_word_length': 2.171569781124971, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 4}, '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': '3146686', 'n_tokens_mistral': 6948, 'n_tokens_neox': 6673, 'n_words': 1949}