19c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri/*
29c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri * Copyright (C) 2017 The Android Open Source Project
39c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri *
49c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri * Licensed under the Apache License, Version 2.0 (the "License");
59c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri * you may not use this file except in compliance with the License.
69c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri * You may obtain a copy of the License at
79c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri *
89c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri *      http://www.apache.org/licenses/LICENSE-2.0
99c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri *
109c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri * Unless required by applicable law or agreed to in writing, software
119c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri * distributed under the License is distributed on an "AS IS" BASIS,
129c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri * See the License for the specific language governing permissions and
149c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri * limitations under the License.
159c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri */
169c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri
179c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiripackage android.support.v7.widget;
189c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri
199c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiriimport android.support.annotation.IntDef;
209c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiriimport android.view.View;
219c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri
229c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiriimport java.lang.annotation.Retention;
239c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiriimport java.lang.annotation.RetentionPolicy;
249c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri
259c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri/**
269c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri * A utility class used to check the boundaries of a given view within its parent view based on
279c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri * a set of boundary flags.
289c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri */
299c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiriclass ViewBoundsCheck {
309c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri
319c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    static final int GT = 1 << 0;
329c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    static final int EQ = 1 << 1;
339c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    static final int LT = 1 << 2;
349c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri
359c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri
369c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    static final int CVS_PVS_POS = 0;
379c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    /**
389c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     * The child view's start should be strictly greater than parent view's start.
399c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     */
409c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    static final int FLAG_CVS_GT_PVS = GT << CVS_PVS_POS;
419c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri
429c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    /**
439c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     * The child view's start can be equal to its parent view's start. This flag follows with GT
449c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     * or LT indicating greater (less) than or equal relation.
459c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     */
469c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    static final int FLAG_CVS_EQ_PVS = EQ << CVS_PVS_POS;
479c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri
489c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    /**
499c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     * The child view's start should be strictly less than parent view's start.
509c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     */
519c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    static final int FLAG_CVS_LT_PVS = LT << CVS_PVS_POS;
529c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri
539c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri
549c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    static final int CVS_PVE_POS = 4;
559c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    /**
569c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     * The child view's start should be strictly greater than parent view's end.
579c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     */
589c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    static final int FLAG_CVS_GT_PVE = GT << CVS_PVE_POS;
599c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri
609c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    /**
619c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     * The child view's start can be equal to its parent view's end. This flag follows with GT
629c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     * or LT indicating greater (less) than or equal relation.
639c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     */
649c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    static final int FLAG_CVS_EQ_PVE = EQ << CVS_PVE_POS;
659c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri
669c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    /**
679c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     * The child view's start should be strictly less than parent view's end.
689c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     */
699c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    static final int FLAG_CVS_LT_PVE = LT << CVS_PVE_POS;
709c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri
719c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri
729c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    static final int CVE_PVS_POS = 8;
739c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    /**
749c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     * The child view's end should be strictly greater than parent view's start.
759c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     */
769c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    static final int FLAG_CVE_GT_PVS = GT << CVE_PVS_POS;
779c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri
789c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    /**
799c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     * The child view's end can be equal to its parent view's start. This flag follows with GT
809c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     * or LT indicating greater (less) than or equal relation.
819c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     */
829c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    static final int FLAG_CVE_EQ_PVS = EQ << CVE_PVS_POS;
839c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri
849c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    /**
859c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     * The child view's end should be strictly less than parent view's start.
869c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     */
879c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    static final int FLAG_CVE_LT_PVS = LT << CVE_PVS_POS;
889c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri
899c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri
909c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    static final int CVE_PVE_POS = 12;
919c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    /**
929c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     * The child view's end should be strictly greater than parent view's end.
939c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     */
949c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    static final int FLAG_CVE_GT_PVE = GT << CVE_PVE_POS;
959c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri
969c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    /**
979c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     * The child view's end can be equal to its parent view's end. This flag follows with GT
989c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     * or LT indicating greater (less) than or equal relation.
999c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     */
1009c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    static final int FLAG_CVE_EQ_PVE = EQ << CVE_PVE_POS;
1019c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri
1029c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    /**
1039c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     * The child view's end should be strictly less than parent view's end.
1049c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     */
1059c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    static final int FLAG_CVE_LT_PVE = LT << CVE_PVE_POS;
1069c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri
1079c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    static final int MASK = GT | EQ | LT;
1089c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri
1099c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    final Callback mCallback;
1109c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    BoundFlags mBoundFlags;
1119c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    /**
1129c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     * The set of flags that can be passed for checking the view boundary conditions.
1139c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     * CVS in the flag name indicates the child view, and PV indicates the parent view.\
1149c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     * The following S, E indicate a view's start and end points, respectively.
1159c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     * GT and LT indicate a strictly greater and less than relationship.
1169c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     * Greater than or equal (or less than or equal) can be specified by setting both GT and EQ (or
1179c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     * LT and EQ) flags.
1189c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     * For instance, setting both {@link #FLAG_CVS_GT_PVS} and {@link #FLAG_CVS_EQ_PVS} indicate the
1199c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     * child view's start should be greater than or equal to its parent start.
1209c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     */
1219c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    @IntDef(flag = true, value = {
1229c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri            FLAG_CVS_GT_PVS, FLAG_CVS_EQ_PVS, FLAG_CVS_LT_PVS,
1239c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri            FLAG_CVS_GT_PVE, FLAG_CVS_EQ_PVE, FLAG_CVS_LT_PVE,
1249c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri            FLAG_CVE_GT_PVS, FLAG_CVE_EQ_PVS, FLAG_CVE_LT_PVS,
1259c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri            FLAG_CVE_EQ_PVE, FLAG_CVE_EQ_PVE, FLAG_CVE_LT_PVE
1269c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    })
1279c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    @Retention(RetentionPolicy.SOURCE)
1289c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    public @interface ViewBounds {}
1299c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri
1309c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    ViewBoundsCheck(Callback callback) {
1319c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri        mCallback = callback;
1329c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri        mBoundFlags = new BoundFlags();
1339c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    }
1349c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri
1359c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    static class BoundFlags {
1369c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri        int mBoundFlags = 0;
1379c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri        int mRvStart, mRvEnd, mChildStart, mChildEnd;
1389c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri
1399c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri        void setBounds(int rvStart, int rvEnd, int childStart, int childEnd) {
1409c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri            mRvStart = rvStart;
1419c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri            mRvEnd = rvEnd;
1429c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri            mChildStart = childStart;
1439c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri            mChildEnd = childEnd;
1449c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri        }
1459c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri
1469c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri        void setFlags(@ViewBounds int flags, int mask) {
1479c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri            mBoundFlags = (mBoundFlags & ~mask) | (flags & mask);
1489c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri        }
1499c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri
1509c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri        void addFlags(@ViewBounds int flags) {
1519c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri            mBoundFlags |= flags;
1529c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri        }
1539c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri
1549c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri        void resetFlags() {
1559c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri            mBoundFlags = 0;
1569c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri        }
1579c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri
1589c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri        int compare(int x, int y) {
1599c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri            if (x > y) {
1609c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri                return GT;
1619c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri            }
1629c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri            if (x == y) {
1639c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri                return EQ;
1649c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri            }
1659c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri            return LT;
1669c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri        }
1679c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri
1689c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri        boolean boundsMatch() {
1699c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri            if ((mBoundFlags & (MASK << CVS_PVS_POS)) != 0) {
1709c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri                if ((mBoundFlags & (compare(mChildStart, mRvStart) << CVS_PVS_POS)) == 0) {
1719c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri                    return false;
1729c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri                }
1739c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri            }
1749c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri
1759c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri            if ((mBoundFlags & (MASK << CVS_PVE_POS)) != 0) {
1769c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri                if ((mBoundFlags & (compare(mChildStart, mRvEnd) << CVS_PVE_POS)) == 0) {
1779c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri                    return false;
1789c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri                }
1799c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri            }
1809c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri
1819c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri            if ((mBoundFlags & (MASK << CVE_PVS_POS)) != 0) {
1829c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri                if ((mBoundFlags & (compare(mChildEnd, mRvStart) << CVE_PVS_POS)) == 0) {
1839c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri                    return false;
1849c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri                }
1859c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri            }
1869c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri
1879c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri            if ((mBoundFlags & (MASK << CVE_PVE_POS)) != 0) {
1889c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri                if ((mBoundFlags & (compare(mChildEnd, mRvEnd) << CVE_PVE_POS)) == 0) {
1899c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri                    return false;
1909c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri                }
1919c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri            }
1929c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri            return true;
1939c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri        }
1949c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    };
1959c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri
1969c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    /**
1979c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     * Returns the first view starting from fromIndex to toIndex in views whose bounds lie within
1989c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     * its parent bounds based on the provided preferredBoundFlags. If no match is found based on
1999c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     * the preferred flags, and a nonzero acceptableBoundFlags is specified, the last view whose
2009c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     * bounds lie within its parent view based on the acceptableBoundFlags is returned. If no such
2019c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     * view is found based on either of these two flags, null is returned.
2029c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     * @param fromIndex The view position index to start the search from.
2039c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     * @param toIndex The view position index to end the search at.
2049c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     * @param preferredBoundFlags The flags indicating the preferred match. Once a match is found
2059c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     *                            based on this flag, that view is returned instantly.
2069c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     * @param acceptableBoundFlags The flags indicating the acceptable match if no preferred match
2079c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     *                             is found. If so, and if acceptableBoundFlags is non-zero, the
2089c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     *                             last matching acceptable view is returned. Otherwise, null is
2099c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     *                             returned.
2109c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     * @return The first view that satisfies acceptableBoundFlags or the last view satisfying
2119c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     * acceptableBoundFlags boundary conditions.
2129c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     */
2139c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    View findOneViewWithinBoundFlags(int fromIndex, int toIndex,
2149c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri            @ViewBounds int preferredBoundFlags,
2159c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri            @ViewBounds int acceptableBoundFlags) {
2169c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri        final int start = mCallback.getParentStart();
2179c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri        final int end = mCallback.getParentEnd();
2189c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri        final int next = toIndex > fromIndex ? 1 : -1;
2199c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri        View acceptableMatch = null;
2209c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri        for (int i = fromIndex; i != toIndex; i += next) {
2219c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri            final View child = mCallback.getChildAt(i);
2229c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri            final int childStart = mCallback.getChildStart(child);
2239c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri            final int childEnd = mCallback.getChildEnd(child);
2249c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri            mBoundFlags.setBounds(start, end, childStart, childEnd);
2259c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri            if (preferredBoundFlags != 0) {
2269c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri                mBoundFlags.resetFlags();
2279c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri                mBoundFlags.addFlags(preferredBoundFlags);
2289c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri                if (mBoundFlags.boundsMatch()) {
2299c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri                    // found a perfect match
2309c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri                    return child;
2319c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri                }
2329c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri            }
2339c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri            if (acceptableBoundFlags != 0) {
2349c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri                mBoundFlags.resetFlags();
2359c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri                mBoundFlags.addFlags(acceptableBoundFlags);
2369c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri                if (mBoundFlags.boundsMatch()) {
2379c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri                    acceptableMatch = child;
2389c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri                }
2399c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri            }
2409c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri        }
2419c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri        return acceptableMatch;
2429c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    }
2439c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri
2449c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    /**
2459c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     * Returns whether the specified view lies within the boundary condition of its parent view.
2469c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     * @param child The child view to be checked.
2479c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     * @param boundsFlags The flag against which the child view and parent view are matched.
2489c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     * @return True if the view meets the boundsFlag, false otherwise.
2499c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     */
2509c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    boolean isViewWithinBoundFlags(View child, @ViewBounds int boundsFlags) {
2519c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri        mBoundFlags.setBounds(mCallback.getParentStart(), mCallback.getParentEnd(),
2529c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri                mCallback.getChildStart(child), mCallback.getChildEnd(child));
2539c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri        if (boundsFlags != 0) {
2549c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri            mBoundFlags.resetFlags();
2559c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri            mBoundFlags.addFlags(boundsFlags);
2569c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri            return mBoundFlags.boundsMatch();
2579c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri        }
2589c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri        return false;
2599c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    }
2609c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri
2619c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    /**
2629c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     * Callback provided by the user of this class in order to retrieve information about child and
2639c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     * parent boundaries.
2649c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     */
2659c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    interface Callback {
2669c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri        int getChildCount();
2679c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri        View getParent();
2689c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri        View getChildAt(int index);
2699c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri        int getParentStart();
2709c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri        int getParentEnd();
2719c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri        int getChildStart(View view);
2729c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri        int getChildEnd(View view);
2739c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    }
2749c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri}
275