19106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn/*
29106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn * Copyright (C) 2014 The Android Open Source Project
39106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn *
49106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
59106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn * in compliance with the License. You may obtain a copy of the License at
69106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn *
79106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn * http://www.apache.org/licenses/LICENSE-2.0
89106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn *
99106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn * Unless required by applicable law or agreed to in writing, software distributed under the License
109106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
119106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn * or implied. See the License for the specific language governing permissions and limitations under
129106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn * the License.
139106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn */
149106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
159106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbournpackage android.support.v17.leanback.widget;
169106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
17a8a3b898da49324e83ea32c3f08776a481312166Tim Kilbournimport static android.support.v17.leanback.widget.BaseGridView.WINDOW_ALIGN_LOW_EDGE;
18a8a3b898da49324e83ea32c3f08776a481312166Tim Kilbournimport static android.support.v17.leanback.widget.BaseGridView.WINDOW_ALIGN_HIGH_EDGE;
19a8a3b898da49324e83ea32c3f08776a481312166Tim Kilbournimport static android.support.v17.leanback.widget.BaseGridView.WINDOW_ALIGN_BOTH_EDGE;
20a8a3b898da49324e83ea32c3f08776a481312166Tim Kilbournimport static android.support.v17.leanback.widget.BaseGridView.WINDOW_ALIGN_OFFSET_PERCENT_DISABLED;
219106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
229106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbournimport static android.support.v7.widget.RecyclerView.HORIZONTAL;
239106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
248e3566285de4ac771d6188f62fe947e23d371a3dKris Giesingimport android.view.View;
258e3566285de4ac771d6188f62fe947e23d371a3dKris Giesing
269106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn/**
279106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn * Maintains Window Alignment information of two axis.
289106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn */
299106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbournclass WindowAlignment {
309106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
319106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn    /**
329106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn     * Maintains alignment information in one direction.
339106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn     */
349106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn    public static class Axis {
359106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        /**
369106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn         * mScrollCenter is used to calculate dynamic transformation based on how far a view
379106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn         * is from the mScrollCenter. For example, the views with center close to mScrollCenter
389106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn         * will be scaled up.
399106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn         */
409106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        private float mScrollCenter;
419106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        /**
429106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn         * Right or bottom edge of last child.
439106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn         */
449106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        private int mMaxEdge;
459106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        /**
469106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn         * Left or top edge of first child, typically should be zero.
479106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn         */
489106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        private int mMinEdge;
4979b86b227e6794937ec311522b50e727f8eec263Dake Gu        /**
5079b86b227e6794937ec311522b50e727f8eec263Dake Gu         * Max Scroll value
5179b86b227e6794937ec311522b50e727f8eec263Dake Gu         */
5279b86b227e6794937ec311522b50e727f8eec263Dake Gu        private int mMaxScroll;
5379b86b227e6794937ec311522b50e727f8eec263Dake Gu        /**
5479b86b227e6794937ec311522b50e727f8eec263Dake Gu         * Min Scroll value
5579b86b227e6794937ec311522b50e727f8eec263Dake Gu         */
5679b86b227e6794937ec311522b50e727f8eec263Dake Gu        private int mMinScroll;
579106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
589106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        private int mWindowAlignment = WINDOW_ALIGN_BOTH_EDGE;
599106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
609106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        private int mWindowAlignmentOffset = 0;
619106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
629106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        private float mWindowAlignmentOffsetPercent = 50f;
639106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
649106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        private int mSize;
659106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
669106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        private int mPaddingLow;
679106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
689106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        private int mPaddingHigh;
699106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
70e0e66a21916f94ebbced0d1ffe3dc652c9c7a15eKris Giesing        private boolean mReversedFlow;
71e0e66a21916f94ebbced0d1ffe3dc652c9c7a15eKris Giesing
729106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        private String mName; // for debugging
739106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
749106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        public Axis(String name) {
759106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            reset();
769106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            mName = name;
779106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        }
789106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
799106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        final public int getWindowAlignment() {
809106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            return mWindowAlignment;
819106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        }
829106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
839106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        final public void setWindowAlignment(int windowAlignment) {
849106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            mWindowAlignment = windowAlignment;
859106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        }
869106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
879106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        final public int getWindowAlignmentOffset() {
889106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            return mWindowAlignmentOffset;
899106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        }
909106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
919106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        final public void setWindowAlignmentOffset(int offset) {
929106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            mWindowAlignmentOffset = offset;
939106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        }
949106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
959106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        final public void setWindowAlignmentOffsetPercent(float percent) {
969106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            if ((percent < 0 || percent > 100)
979106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn                    && percent != WINDOW_ALIGN_OFFSET_PERCENT_DISABLED) {
989106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn                throw new IllegalArgumentException();
999106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            }
1009106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            mWindowAlignmentOffsetPercent = percent;
1019106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        }
1029106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
1039106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        final public float getWindowAlignmentOffsetPercent() {
1049106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            return mWindowAlignmentOffsetPercent;
1059106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        }
1069106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
1079106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        final public int getScrollCenter() {
1089106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            return (int) mScrollCenter;
1099106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        }
1109106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
1119106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        /** set minEdge,  Integer.MIN_VALUE means unknown*/
1129106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        final public void setMinEdge(int minEdge) {
1139106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            mMinEdge = minEdge;
1149106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        }
1159106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
1166ef7396cd226efcce83389c5107166c121e25785Dake Gu        final public int getMinEdge() {
1176ef7396cd226efcce83389c5107166c121e25785Dake Gu            return mMinEdge;
1186ef7396cd226efcce83389c5107166c121e25785Dake Gu        }
1196ef7396cd226efcce83389c5107166c121e25785Dake Gu
12079b86b227e6794937ec311522b50e727f8eec263Dake Gu        /** set minScroll,  Integer.MIN_VALUE means unknown*/
12179b86b227e6794937ec311522b50e727f8eec263Dake Gu        final public void setMinScroll(int minScroll) {
12279b86b227e6794937ec311522b50e727f8eec263Dake Gu            mMinScroll = minScroll;
12379b86b227e6794937ec311522b50e727f8eec263Dake Gu        }
12479b86b227e6794937ec311522b50e727f8eec263Dake Gu
12579b86b227e6794937ec311522b50e727f8eec263Dake Gu        final public int getMinScroll() {
12679b86b227e6794937ec311522b50e727f8eec263Dake Gu            return mMinScroll;
12779b86b227e6794937ec311522b50e727f8eec263Dake Gu        }
12879b86b227e6794937ec311522b50e727f8eec263Dake Gu
12979b86b227e6794937ec311522b50e727f8eec263Dake Gu        final public void invalidateScrollMin() {
1309106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            mMinEdge = Integer.MIN_VALUE;
13179b86b227e6794937ec311522b50e727f8eec263Dake Gu            mMinScroll = Integer.MIN_VALUE;
1329106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        }
1339106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
1349106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        /** update max edge,  Integer.MAX_VALUE means unknown*/
1359106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        final public void setMaxEdge(int maxEdge) {
1369106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            mMaxEdge = maxEdge;
1379106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        }
1389106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
1396ef7396cd226efcce83389c5107166c121e25785Dake Gu        final public int getMaxEdge() {
1406ef7396cd226efcce83389c5107166c121e25785Dake Gu            return mMaxEdge;
1416ef7396cd226efcce83389c5107166c121e25785Dake Gu        }
1426ef7396cd226efcce83389c5107166c121e25785Dake Gu
14379b86b227e6794937ec311522b50e727f8eec263Dake Gu        /** update max scroll,  Integer.MAX_VALUE means unknown*/
14479b86b227e6794937ec311522b50e727f8eec263Dake Gu        final public void setMaxScroll(int maxScroll) {
14579b86b227e6794937ec311522b50e727f8eec263Dake Gu            mMaxScroll = maxScroll;
14679b86b227e6794937ec311522b50e727f8eec263Dake Gu        }
14779b86b227e6794937ec311522b50e727f8eec263Dake Gu
14879b86b227e6794937ec311522b50e727f8eec263Dake Gu        final public int getMaxScroll() {
14979b86b227e6794937ec311522b50e727f8eec263Dake Gu            return mMaxScroll;
15079b86b227e6794937ec311522b50e727f8eec263Dake Gu        }
15179b86b227e6794937ec311522b50e727f8eec263Dake Gu
15279b86b227e6794937ec311522b50e727f8eec263Dake Gu        final public void invalidateScrollMax() {
1539106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            mMaxEdge = Integer.MAX_VALUE;
15479b86b227e6794937ec311522b50e727f8eec263Dake Gu            mMaxScroll = Integer.MAX_VALUE;
1559106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        }
1569106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
1579106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        final public float updateScrollCenter(float scrollTarget) {
1589106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            mScrollCenter = scrollTarget;
1599106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            return scrollTarget;
1609106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        }
1619106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
1629106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        private void reset() {
1639106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            mScrollCenter = Integer.MIN_VALUE;
1649106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            mMinEdge = Integer.MIN_VALUE;
1659106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            mMaxEdge = Integer.MAX_VALUE;
1669106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        }
1679106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
1689106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        final public boolean isMinUnknown() {
1699106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            return mMinEdge == Integer.MIN_VALUE;
1709106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        }
1719106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
1729106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        final public boolean isMaxUnknown() {
1739106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            return mMaxEdge == Integer.MAX_VALUE;
1749106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        }
1759106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
1769106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        final public void setSize(int size) {
1779106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            mSize = size;
1789106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        }
1799106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
1809106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        final public int getSize() {
1819106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            return mSize;
1829106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        }
1839106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
1849106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        final public void setPadding(int paddingLow, int paddingHigh) {
1859106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            mPaddingLow = paddingLow;
1869106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            mPaddingHigh = paddingHigh;
1879106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        }
1889106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
1899106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        final public int getPaddingLow() {
1909106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            return mPaddingLow;
1919106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        }
1929106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
1939106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        final public int getPaddingHigh() {
1949106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            return mPaddingHigh;
1959106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        }
1969106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
1979106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        final public int getClientSize() {
1989106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            return mSize - mPaddingLow - mPaddingHigh;
1999106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        }
2009106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
2017db64bb839e5589b38322f9f7456cb928ffc2c1cDake Gu        final public int getSystemScrollPos(boolean isAtMin, boolean isAtMax) {
2027db64bb839e5589b38322f9f7456cb928ffc2c1cDake Gu            return getSystemScrollPos((int) mScrollCenter, isAtMin, isAtMax);
2039106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        }
2049106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
2057db64bb839e5589b38322f9f7456cb928ffc2c1cDake Gu        final public int getSystemScrollPos(int scrollCenter, boolean isAtMin, boolean isAtMax) {
2069106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            int middlePosition;
207e0e66a21916f94ebbced0d1ffe3dc652c9c7a15eKris Giesing            if (!mReversedFlow) {
208e0e66a21916f94ebbced0d1ffe3dc652c9c7a15eKris Giesing                if (mWindowAlignmentOffset >= 0) {
209e0e66a21916f94ebbced0d1ffe3dc652c9c7a15eKris Giesing                    middlePosition = mWindowAlignmentOffset - mPaddingLow;
210e0e66a21916f94ebbced0d1ffe3dc652c9c7a15eKris Giesing                } else {
211e0e66a21916f94ebbced0d1ffe3dc652c9c7a15eKris Giesing                    middlePosition = mSize + mWindowAlignmentOffset - mPaddingLow;
212e0e66a21916f94ebbced0d1ffe3dc652c9c7a15eKris Giesing                }
213e0e66a21916f94ebbced0d1ffe3dc652c9c7a15eKris Giesing                if (mWindowAlignmentOffsetPercent != WINDOW_ALIGN_OFFSET_PERCENT_DISABLED) {
214e0e66a21916f94ebbced0d1ffe3dc652c9c7a15eKris Giesing                    middlePosition += (int) (mSize * mWindowAlignmentOffsetPercent / 100);
215e0e66a21916f94ebbced0d1ffe3dc652c9c7a15eKris Giesing                }
2169106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            } else {
217e0e66a21916f94ebbced0d1ffe3dc652c9c7a15eKris Giesing                if (mWindowAlignmentOffset >= 0) {
218e0e66a21916f94ebbced0d1ffe3dc652c9c7a15eKris Giesing                    middlePosition = mSize - mWindowAlignmentOffset - mPaddingLow;
219e0e66a21916f94ebbced0d1ffe3dc652c9c7a15eKris Giesing                } else {
220e0e66a21916f94ebbced0d1ffe3dc652c9c7a15eKris Giesing                    middlePosition = - mWindowAlignmentOffset - mPaddingLow;
221e0e66a21916f94ebbced0d1ffe3dc652c9c7a15eKris Giesing                }
222e0e66a21916f94ebbced0d1ffe3dc652c9c7a15eKris Giesing                if (mWindowAlignmentOffsetPercent != WINDOW_ALIGN_OFFSET_PERCENT_DISABLED) {
223e0e66a21916f94ebbced0d1ffe3dc652c9c7a15eKris Giesing                    middlePosition -= (int) (mSize * mWindowAlignmentOffsetPercent / 100);
224e0e66a21916f94ebbced0d1ffe3dc652c9c7a15eKris Giesing                }
2259106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            }
2269106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            int clientSize = getClientSize();
2279106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            int afterMiddlePosition = clientSize - middlePosition;
2289106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            boolean isMinUnknown = isMinUnknown();
2299106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            boolean isMaxUnknown = isMaxUnknown();
2309106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            if (!isMinUnknown && !isMaxUnknown &&
2319106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn                    (mWindowAlignment & WINDOW_ALIGN_BOTH_EDGE) == WINDOW_ALIGN_BOTH_EDGE) {
2329106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn                if (mMaxEdge - mMinEdge <= clientSize) {
2339106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn                    // total children size is less than view port and we want to align
2348e3566285de4ac771d6188f62fe947e23d371a3dKris Giesing                    // both edge:  align first child to start edge of view port
235e0e66a21916f94ebbced0d1ffe3dc652c9c7a15eKris Giesing                    return mReversedFlow ? mMaxEdge - mPaddingLow - clientSize
236e0e66a21916f94ebbced0d1ffe3dc652c9c7a15eKris Giesing                            : mMinEdge - mPaddingLow;
2379106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn                }
2389106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            }
2399106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            if (!isMinUnknown) {
240e0e66a21916f94ebbced0d1ffe3dc652c9c7a15eKris Giesing                if ((!mReversedFlow ? (mWindowAlignment & WINDOW_ALIGN_LOW_EDGE) != 0
241e0e66a21916f94ebbced0d1ffe3dc652c9c7a15eKris Giesing                     : (mWindowAlignment & WINDOW_ALIGN_HIGH_EDGE) != 0)
242e0e66a21916f94ebbced0d1ffe3dc652c9c7a15eKris Giesing                        && (isAtMin || scrollCenter - mMinEdge <= middlePosition)) {
2438e3566285de4ac771d6188f62fe947e23d371a3dKris Giesing                    // scroll center is within half of view port size: align the start edge
2448e3566285de4ac771d6188f62fe947e23d371a3dKris Giesing                    // of first child to the start edge of view port
2457db64bb839e5589b38322f9f7456cb928ffc2c1cDake Gu                    return mMinEdge - mPaddingLow;
2469106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn                }
2479106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            }
2489106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            if (!isMaxUnknown) {
249e0e66a21916f94ebbced0d1ffe3dc652c9c7a15eKris Giesing                if ((!mReversedFlow ? (mWindowAlignment & WINDOW_ALIGN_HIGH_EDGE) != 0
250e0e66a21916f94ebbced0d1ffe3dc652c9c7a15eKris Giesing                        : (mWindowAlignment & WINDOW_ALIGN_LOW_EDGE) != 0)
251e0e66a21916f94ebbced0d1ffe3dc652c9c7a15eKris Giesing                        && (isAtMax || mMaxEdge - scrollCenter <= afterMiddlePosition)) {
2528e3566285de4ac771d6188f62fe947e23d371a3dKris Giesing                    // scroll center is very close to the end edge of view port : align the
2538e3566285de4ac771d6188f62fe947e23d371a3dKris Giesing                    // end edge of last children (plus expanded size) to view port's end
2547db64bb839e5589b38322f9f7456cb928ffc2c1cDake Gu                    return mMaxEdge - mPaddingLow - clientSize;
2559106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn                }
2569106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            }
2579106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            // else put scroll center in middle of view port
2587db64bb839e5589b38322f9f7456cb928ffc2c1cDake Gu            return scrollCenter - middlePosition - mPaddingLow;
2599106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        }
2609106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
261e0e66a21916f94ebbced0d1ffe3dc652c9c7a15eKris Giesing        final public void setReversedFlow(boolean reversedFlow) {
262e0e66a21916f94ebbced0d1ffe3dc652c9c7a15eKris Giesing            mReversedFlow = reversedFlow;
263e0e66a21916f94ebbced0d1ffe3dc652c9c7a15eKris Giesing        }
264e0e66a21916f94ebbced0d1ffe3dc652c9c7a15eKris Giesing
2659106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        @Override
2669106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        public String toString() {
2679106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            return "center: " + mScrollCenter + " min:" + mMinEdge +
2689106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn                    " max:" + mMaxEdge;
2699106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        }
2709106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
2719106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn    }
2729106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
2739106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn    private int mOrientation = HORIZONTAL;
2749106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
2759106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn    final public Axis vertical = new Axis("vertical");
2769106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
2779106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn    final public Axis horizontal = new Axis("horizontal");
2789106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
2799106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn    private Axis mMainAxis = horizontal;
2809106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
2819106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn    private Axis mSecondAxis = vertical;
2829106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
2839106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn    final public Axis mainAxis() {
2849106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        return mMainAxis;
2859106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn    }
2869106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
2879106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn    final public Axis secondAxis() {
2889106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        return mSecondAxis;
2899106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn    }
2909106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
2919106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn    final public void setOrientation(int orientation) {
2929106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        mOrientation = orientation;
2939106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        if (mOrientation == HORIZONTAL) {
2949106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            mMainAxis = horizontal;
2959106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            mSecondAxis = vertical;
2969106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        } else {
2979106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            mMainAxis = vertical;
2989106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn            mSecondAxis = horizontal;
2999106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        }
3009106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn    }
3019106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
3029106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn    final public int getOrientation() {
3039106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        return mOrientation;
3049106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn    }
3059106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
3069106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn    final public void reset() {
3079106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        mainAxis().reset();
3089106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn    }
3099106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
3109106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn    @Override
3119106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn    public String toString() {
3129106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn        return new StringBuffer().append("horizontal=")
3139106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn                .append(horizontal.toString())
3148e3566285de4ac771d6188f62fe947e23d371a3dKris Giesing                .append("; vertical=")
3159106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn                .append(vertical.toString())
3169106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn                .toString();
3179106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn    }
3189106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn
3199106804a84e5e8733e0b9313f749fa1f726e5d11Tim Kilbourn}
320