1321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung/*
2321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung * Copyright (C) 2010 The Android Open Source Project
3321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung *
4321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung * Licensed under the Apache License, Version 2.0 (the "License");
5321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung * you may not use this file except in compliance with the License.
6321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung * You may obtain a copy of the License at
7321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung *
8321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung *      http://www.apache.org/licenses/LICENSE-2.0
9321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung *
10321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung * Unless required by applicable law or agreed to in writing, software
11321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung * distributed under the License is distributed on an "AS IS" BASIS,
12321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung * See the License for the specific language governing permissions and
14321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung * limitations under the License.
15321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung */
16321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
17321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chungpackage com.android.launcher2;
18321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
19321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chungimport android.content.Context;
20785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chungimport android.content.res.Resources;
21321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chungimport android.util.AttributeSet;
22321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chungimport android.view.MotionEvent;
23321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chungimport android.view.View;
24321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chungimport android.view.ViewDebug;
25321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chungimport android.view.ViewGroup;
26321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
27785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chungimport com.android.launcher.R;
28785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung
29321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung/**
30321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung * An abstraction of the original CellLayout which supports laying out items
31321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung * which span multiple cells into a grid-like layout.  Also supports dimming
32321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung * to give a preview of its contents.
33321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung */
348245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurkapublic class PagedViewCellLayout extends ViewGroup implements Page {
35321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    static final String TAG = "PagedViewCellLayout";
36321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
37321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    private int mCellCountX;
38321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    private int mCellCountY;
39db1138b4efae89a3b5833547958a3606e5408a71Winson Chung    private int mOriginalCellWidth;
40db1138b4efae89a3b5833547958a3606e5408a71Winson Chung    private int mOriginalCellHeight;
41321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    private int mCellWidth;
42321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    private int mCellHeight;
43234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen    private int mOriginalWidthGap;
44234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen    private int mOriginalHeightGap;
45df4b83dd9d6380ab963c62d1f9d1312efc87cb0fWinson Chung    private int mWidthGap;
46df4b83dd9d6380ab963c62d1f9d1312efc87cb0fWinson Chung    private int mHeightGap;
47db1138b4efae89a3b5833547958a3606e5408a71Winson Chung    private int mMaxGap;
488245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    protected PagedViewCellLayoutChildren mChildren;
49321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
50321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    public PagedViewCellLayout(Context context) {
51321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        this(context, null);
52321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
53321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
54321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    public PagedViewCellLayout(Context context, AttributeSet attrs) {
55321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        this(context, attrs, 0);
56321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
57321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
58321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    public PagedViewCellLayout(Context context, AttributeSet attrs, int defStyle) {
59321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        super(context, attrs, defStyle);
60321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
61321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        setAlwaysDrawnWithCacheEnabled(false);
62321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
63321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        // setup default cell parameters
64785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung        Resources resources = context.getResources();
65db1138b4efae89a3b5833547958a3606e5408a71Winson Chung        mOriginalCellWidth = mCellWidth =
66db1138b4efae89a3b5833547958a3606e5408a71Winson Chung            resources.getDimensionPixelSize(R.dimen.apps_customize_cell_width);
67db1138b4efae89a3b5833547958a3606e5408a71Winson Chung        mOriginalCellHeight = mCellHeight =
68db1138b4efae89a3b5833547958a3606e5408a71Winson Chung            resources.getDimensionPixelSize(R.dimen.apps_customize_cell_height);
69321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        mCellCountX = LauncherModel.getCellCountX();
70321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        mCellCountY = LauncherModel.getCellCountY();
716032e7ed8e6208348a6b3f8bc1a7ecafc7951af8Winson Chung        mOriginalWidthGap = mOriginalHeightGap = mWidthGap = mHeightGap = -1;
72db1138b4efae89a3b5833547958a3606e5408a71Winson Chung        mMaxGap = resources.getDimensionPixelSize(R.dimen.apps_customize_max_gap);
73321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
748245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        mChildren = new PagedViewCellLayoutChildren(context);
758245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        mChildren.setCellDimensions(mCellWidth, mCellHeight);
768245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        mChildren.setGap(mWidthGap, mHeightGap);
778245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka
788245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        addView(mChildren);
79321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
80321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
81244d74cb353f1260c4d633e719bf84bb3b6e52bcPatrick Dubroy    public int getCellWidth() {
82244d74cb353f1260c4d633e719bf84bb3b6e52bcPatrick Dubroy        return mCellWidth;
83244d74cb353f1260c4d633e719bf84bb3b6e52bcPatrick Dubroy    }
84244d74cb353f1260c4d633e719bf84bb3b6e52bcPatrick Dubroy
85244d74cb353f1260c4d633e719bf84bb3b6e52bcPatrick Dubroy    public int getCellHeight() {
86244d74cb353f1260c4d633e719bf84bb3b6e52bcPatrick Dubroy        return mCellHeight;
87244d74cb353f1260c4d633e719bf84bb3b6e52bcPatrick Dubroy    }
88244d74cb353f1260c4d633e719bf84bb3b6e52bcPatrick Dubroy
89321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    @Override
90b3347bb9f4ccf41fb7043bca66c3a565bde1083bWinson Chung    public void setAlpha(float alpha) {
9122f823d340710bcde587b18a1542570cbe0360f5Adam Cohen        mChildren.setAlpha(alpha);
92321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
93321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
94c0759f5090d9539d82ddc944b9f2da767c36b251Michael Jurka    void destroyHardwareLayers() {
95abded66084680bb31cc7ea403c88f44f79a3c884Michael Jurka        // called when a page is no longer visible (triggered by loadAssociatedPages ->
96abded66084680bb31cc7ea403c88f44f79a3c884Michael Jurka        // removeAllViewsOnPage)
9722f823d340710bcde587b18a1542570cbe0360f5Adam Cohen        mChildren.destroyHardwareLayer();
98c0759f5090d9539d82ddc944b9f2da767c36b251Michael Jurka    }
9922f823d340710bcde587b18a1542570cbe0360f5Adam Cohen
100c0759f5090d9539d82ddc944b9f2da767c36b251Michael Jurka    void createHardwareLayers() {
101abded66084680bb31cc7ea403c88f44f79a3c884Michael Jurka        // called when a page is visible (triggered by loadAssociatedPages -> syncPageItems)
10222f823d340710bcde587b18a1542570cbe0360f5Adam Cohen        mChildren.createHardwareLayer();
103c0759f5090d9539d82ddc944b9f2da767c36b251Michael Jurka    }
104c0759f5090d9539d82ddc944b9f2da767c36b251Michael Jurka
105321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    @Override
106321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    public void cancelLongPress() {
107321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        super.cancelLongPress();
108321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
109321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        // Cancel long press for all children
110321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        final int count = getChildCount();
111321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        for (int i = 0; i < count; i++) {
112321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            final View child = getChildAt(i);
113321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            child.cancelLongPress();
114321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        }
115321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
116321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
117321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    public boolean addViewToCellLayout(View child, int index, int childId,
1186a70e9fc3c62cc83d6abe59323d622dc6cd224a7Winson Chung            PagedViewCellLayout.LayoutParams params) {
119321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        final PagedViewCellLayout.LayoutParams lp = params;
120321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
121321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        // Generate an id for each view, this assumes we have at most 256x256 cells
122321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        // per workspace screen
123321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        if (lp.cellX >= 0 && lp.cellX <= (mCellCountX - 1) &&
124321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung                lp.cellY >= 0 && (lp.cellY <= mCellCountY - 1)) {
125321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            // If the horizontal or vertical span is set to -1, it is taken to
126321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            // mean that it spans the extent of the CellLayout
127321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            if (lp.cellHSpan < 0) lp.cellHSpan = mCellCountX;
128321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            if (lp.cellVSpan < 0) lp.cellVSpan = mCellCountY;
129321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
130321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            child.setId(childId);
1318245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka            mChildren.addView(child, index, lp);
132321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
133321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            return true;
134321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        }
135321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        return false;
136321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
137321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
138321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    @Override
1398245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    public void removeAllViewsOnPage() {
1408245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        mChildren.removeAllViews();
141c5e49022bea70a1b0b6ada5431afbb6e951cc3f6Michael Jurka        destroyHardwareLayers();
142321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
143321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
144321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    @Override
1458245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    public void removeViewOnPageAt(int index) {
1468245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        mChildren.removeViewAt(index);
1478245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    }
1488245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka
149c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung    /**
150c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung     * Clears all the key listeners for the individual icons.
151c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung     */
152c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung    public void resetChildrenOnKeyListeners() {
153c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung        int childCount = mChildren.getChildCount();
154c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung        for (int j = 0; j < childCount; ++j) {
155c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung            mChildren.getChildAt(j).setOnKeyListener(null);
156c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung        }
157c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung    }
158c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung
1598245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    @Override
1608245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    public int getPageChildCount() {
1618245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        return mChildren.getChildCount();
1628245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    }
1638245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka
1645afbf7bdd6f6879124c9b8283e005fe57f310d02Winson Chung    public PagedViewCellLayoutChildren getChildrenLayout() {
1655afbf7bdd6f6879124c9b8283e005fe57f310d02Winson Chung        return mChildren;
1665afbf7bdd6f6879124c9b8283e005fe57f310d02Winson Chung    }
1675afbf7bdd6f6879124c9b8283e005fe57f310d02Winson Chung
1688245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    @Override
1698245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    public View getChildOnPageAt(int i) {
1708245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        return mChildren.getChildAt(i);
1718245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    }
1728245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka
1738245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    @Override
1748245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    public int indexOfChildOnPage(View v) {
1758245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        return mChildren.indexOfChild(v);
1768245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    }
1778245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka
17897d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung    public int getCellCountX() {
17997d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung        return mCellCountX;
18097d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung    }
18197d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung
18297d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung    public int getCellCountY() {
18397d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung        return mCellCountY;
18497d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung    }
18597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung
186321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
187321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
188321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
189321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
190321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
191321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        int heightSpecSize =  MeasureSpec.getSize(heightMeasureSpec);
192321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
193321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        if (widthSpecMode == MeasureSpec.UNSPECIFIED || heightSpecMode == MeasureSpec.UNSPECIFIED) {
194321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            throw new RuntimeException("CellLayout cannot have UNSPECIFIED dimensions");
195321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        }
196321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
197321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        int numWidthGaps = mCellCountX - 1;
198321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        int numHeightGaps = mCellCountY - 1;
199321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
200234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen        if (mOriginalWidthGap < 0 || mOriginalHeightGap < 0) {
201db1138b4efae89a3b5833547958a3606e5408a71Winson Chung            int hSpace = widthSpecSize - mPaddingLeft - mPaddingRight;
202db1138b4efae89a3b5833547958a3606e5408a71Winson Chung            int vSpace = heightSpecSize - mPaddingTop - mPaddingBottom;
203db1138b4efae89a3b5833547958a3606e5408a71Winson Chung            int hFreeSpace = hSpace - (mCellCountX * mOriginalCellWidth);
204db1138b4efae89a3b5833547958a3606e5408a71Winson Chung            int vFreeSpace = vSpace - (mCellCountY * mOriginalCellHeight);
205db1138b4efae89a3b5833547958a3606e5408a71Winson Chung            mWidthGap = Math.min(mMaxGap, numWidthGaps > 0 ? (hFreeSpace / numWidthGaps) : 0);
206db1138b4efae89a3b5833547958a3606e5408a71Winson Chung            mHeightGap = Math.min(mMaxGap,numHeightGaps > 0 ? (vFreeSpace / numHeightGaps) : 0);
207db1138b4efae89a3b5833547958a3606e5408a71Winson Chung
208db1138b4efae89a3b5833547958a3606e5408a71Winson Chung            mChildren.setGap(mWidthGap, mHeightGap);
209234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen        } else {
210234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen            mWidthGap = mOriginalWidthGap;
211234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen            mHeightGap = mOriginalHeightGap;
212df4b83dd9d6380ab963c62d1f9d1312efc87cb0fWinson Chung        }
213321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
214db1138b4efae89a3b5833547958a3606e5408a71Winson Chung        // Initial values correspond to widthSpecMode == MeasureSpec.EXACTLY
215db1138b4efae89a3b5833547958a3606e5408a71Winson Chung        int newWidth = widthSpecSize;
216db1138b4efae89a3b5833547958a3606e5408a71Winson Chung        int newHeight = heightSpecSize;
217db1138b4efae89a3b5833547958a3606e5408a71Winson Chung        if (widthSpecMode == MeasureSpec.AT_MOST) {
218db1138b4efae89a3b5833547958a3606e5408a71Winson Chung            newWidth = mPaddingLeft + mPaddingRight + (mCellCountX * mCellWidth) +
219db1138b4efae89a3b5833547958a3606e5408a71Winson Chung                ((mCellCountX - 1) * mWidthGap);
220db1138b4efae89a3b5833547958a3606e5408a71Winson Chung            newHeight = mPaddingTop + mPaddingBottom + (mCellCountY * mCellHeight) +
221db1138b4efae89a3b5833547958a3606e5408a71Winson Chung                ((mCellCountY - 1) * mHeightGap);
222db1138b4efae89a3b5833547958a3606e5408a71Winson Chung            setMeasuredDimension(newWidth, newHeight);
223db1138b4efae89a3b5833547958a3606e5408a71Winson Chung        }
224321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
225321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        final int count = getChildCount();
226321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        for (int i = 0; i < count; i++) {
227321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            View child = getChildAt(i);
2288245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka            int childWidthMeasureSpec =
229db1138b4efae89a3b5833547958a3606e5408a71Winson Chung                MeasureSpec.makeMeasureSpec(newWidth - mPaddingLeft -
230db1138b4efae89a3b5833547958a3606e5408a71Winson Chung                        mPaddingRight, MeasureSpec.EXACTLY);
2318245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka            int childheightMeasureSpec =
232db1138b4efae89a3b5833547958a3606e5408a71Winson Chung                MeasureSpec.makeMeasureSpec(newHeight - mPaddingTop -
233db1138b4efae89a3b5833547958a3606e5408a71Winson Chung                        mPaddingBottom, MeasureSpec.EXACTLY);
234321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            child.measure(childWidthMeasureSpec, childheightMeasureSpec);
235321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        }
236321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
237db1138b4efae89a3b5833547958a3606e5408a71Winson Chung        setMeasuredDimension(newWidth, newHeight);
238321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
239321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
2407ef959b9177e1e715b0afe010904455a3d961fc4Michael Jurka    int getContentWidth() {
241f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        return getWidthBeforeFirstLayout() + mPaddingLeft + mPaddingRight;
2420413dfa01b822e349092636774dc948b9230adeaMichael Jurka    }
2430413dfa01b822e349092636774dc948b9230adeaMichael Jurka
2444b576be59e58072cc03b5a8d36afb6a322513575Winson Chung    int getContentHeight() {
2454a5ad095303ca1b6b745263269333bd087168d3cPatrick Dubroy        if (mCellCountY > 0) {
2464a5ad095303ca1b6b745263269333bd087168d3cPatrick Dubroy            return mCellCountY * mCellHeight + (mCellCountY - 1) * Math.max(0, mHeightGap);
2474a5ad095303ca1b6b745263269333bd087168d3cPatrick Dubroy        }
2484a5ad095303ca1b6b745263269333bd087168d3cPatrick Dubroy        return 0;
2494b576be59e58072cc03b5a8d36afb6a322513575Winson Chung    }
2504b576be59e58072cc03b5a8d36afb6a322513575Winson Chung
251d92e741ca67c58c4be01a64940847feafe26a4b1Michael Jurka    int getWidthBeforeFirstLayout() {
2524a5ad095303ca1b6b745263269333bd087168d3cPatrick Dubroy        if (mCellCountX > 0) {
2534a5ad095303ca1b6b745263269333bd087168d3cPatrick Dubroy            return mCellCountX * mCellWidth + (mCellCountX - 1) * Math.max(0, mWidthGap);
2544a5ad095303ca1b6b745263269333bd087168d3cPatrick Dubroy        }
2554a5ad095303ca1b6b745263269333bd087168d3cPatrick Dubroy        return 0;
2567ef959b9177e1e715b0afe010904455a3d961fc4Michael Jurka    }
2577ef959b9177e1e715b0afe010904455a3d961fc4Michael Jurka
258321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    @Override
259321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    protected void onLayout(boolean changed, int l, int t, int r, int b) {
260321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        int count = getChildCount();
261321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        for (int i = 0; i < count; i++) {
262321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            View child = getChildAt(i);
2639bfe2b2646f3849f5463c63876c184e820a7f03bMichael Jurka            child.layout(mPaddingLeft, mPaddingTop,
2649bfe2b2646f3849f5463c63876c184e820a7f03bMichael Jurka                r - l - mPaddingRight, b - t - mPaddingBottom);
265321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        }
266321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
267321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
268321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    @Override
269321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    public boolean onTouchEvent(MotionEvent event) {
270f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        boolean result = super.onTouchEvent(event);
271f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        int count = getPageChildCount();
272f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        if (count > 0) {
273f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung            // We only intercept the touch if we are tapping in empty space after the final row
274f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung            View child = getChildOnPageAt(count - 1);
275f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung            int bottom = child.getBottom();
276f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung            int numRows = (int) Math.ceil((float) getPageChildCount() / getCellCountX());
277f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung            if (numRows < getCellCountY()) {
278f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung                // Add a little bit of buffer if there is room for another row
279f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung                bottom += mCellHeight / 2;
280f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung            }
281f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung            result = result || (event.getY() < bottom);
282f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        }
283f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        return result;
284321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
285321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
28680baf5a6b3c62a62265f626d43d1167783c94131Winson Chung    public void enableCenteredContent(boolean enabled) {
2878245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        mChildren.enableCenteredContent(enabled);
28880baf5a6b3c62a62265f626d43d1167783c94131Winson Chung    }
28980baf5a6b3c62a62265f626d43d1167783c94131Winson Chung
290321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    @Override
291321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    protected void setChildrenDrawingCacheEnabled(boolean enabled) {
2928245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        mChildren.setChildrenDrawingCacheEnabled(enabled);
293321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
294321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
295321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    public void setCellCount(int xCount, int yCount) {
296321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        mCellCountX = xCount;
297321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        mCellCountY = yCount;
298321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        requestLayout();
299321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
300321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
301df4b83dd9d6380ab963c62d1f9d1312efc87cb0fWinson Chung    public void setGap(int widthGap, int heightGap) {
3026032e7ed8e6208348a6b3f8bc1a7ecafc7951af8Winson Chung        mOriginalWidthGap = mWidthGap = widthGap;
3036032e7ed8e6208348a6b3f8bc1a7ecafc7951af8Winson Chung        mOriginalHeightGap = mHeightGap = heightGap;
3048245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        mChildren.setGap(widthGap, heightGap);
305df4b83dd9d6380ab963c62d1f9d1312efc87cb0fWinson Chung    }
306df4b83dd9d6380ab963c62d1f9d1312efc87cb0fWinson Chung
30780baf5a6b3c62a62265f626d43d1167783c94131Winson Chung    public int[] getCellCountForDimensions(int width, int height) {
30880baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        // Always assume we're working with the smallest span to make sure we
30980baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        // reserve enough space in both orientations
31080baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        int smallerSize = Math.min(mCellWidth, mCellHeight);
31180baf5a6b3c62a62265f626d43d1167783c94131Winson Chung
31280baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        // Always round up to next largest cell
31380baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        int spanX = (width + smallerSize) / smallerSize;
31480baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        int spanY = (height + smallerSize) / smallerSize;
31580baf5a6b3c62a62265f626d43d1167783c94131Winson Chung
31680baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        return new int[] { spanX, spanY };
31780baf5a6b3c62a62265f626d43d1167783c94131Winson Chung    }
31880baf5a6b3c62a62265f626d43d1167783c94131Winson Chung
319321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    /**
320321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung     * Start dragging the specified child
321321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung     *
322321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung     * @param child The child that is being dragged
323321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung     */
324321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    void onDragChild(View child) {
325321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        PagedViewCellLayout.LayoutParams lp = (PagedViewCellLayout.LayoutParams) child.getLayoutParams();
326321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        lp.isDragging = true;
327321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
328321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
329e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung    /**
330e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     * Estimates the number of cells that the specified width would take up.
331e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     */
33280baf5a6b3c62a62265f626d43d1167783c94131Winson Chung    public int estimateCellHSpan(int width) {
3336032e7ed8e6208348a6b3f8bc1a7ecafc7951af8Winson Chung        // We don't show the next/previous pages any more, so we use the full width, minus the
3346032e7ed8e6208348a6b3f8bc1a7ecafc7951af8Winson Chung        // padding
3356032e7ed8e6208348a6b3f8bc1a7ecafc7951af8Winson Chung        int availWidth = width - (mPaddingLeft + mPaddingRight);
336f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung
337f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        // We know that we have to fit N cells with N-1 width gaps, so we just juggle to solve for N
338f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        int n = Math.max(1, (availWidth + mWidthGap) / (mCellWidth + mWidthGap));
339f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung
340f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        // We don't do anything fancy to determine if we squeeze another row in.
341f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        return n;
34280baf5a6b3c62a62265f626d43d1167783c94131Winson Chung    }
343e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung
344e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung    /**
345e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     * Estimates the number of cells that the specified height would take up.
346e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     */
34780baf5a6b3c62a62265f626d43d1167783c94131Winson Chung    public int estimateCellVSpan(int height) {
348f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        // The space for a page is the height - top padding (current page) - bottom padding (current
349f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        // page)
350f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        int availHeight = height - (mPaddingTop + mPaddingBottom);
351f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung
352f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        // We know that we have to fit N cells with N-1 height gaps, so we juggle to solve for N
353f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        int n = Math.max(1, (availHeight + mHeightGap) / (mCellHeight + mHeightGap));
354f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung
355f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        // We don't do anything fancy to determine if we squeeze another row in.
356f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        return n;
357f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung    }
358f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung
3597d7541e7b48fdc114c24b3b0aa75e70d7228041eWinson Chung    /** Returns an estimated center position of the cell at the specified index */
3607d7541e7b48fdc114c24b3b0aa75e70d7228041eWinson Chung    public int[] estimateCellPosition(int x, int y) {
3617d7541e7b48fdc114c24b3b0aa75e70d7228041eWinson Chung        return new int[] {
3627d7541e7b48fdc114c24b3b0aa75e70d7228041eWinson Chung                mPaddingLeft + (x * mCellWidth) + (x * mWidthGap) + (mCellWidth / 2),
3637d7541e7b48fdc114c24b3b0aa75e70d7228041eWinson Chung                mPaddingTop + (y * mCellHeight) + (y * mHeightGap) + (mCellHeight / 2)
3647d7541e7b48fdc114c24b3b0aa75e70d7228041eWinson Chung        };
3657d7541e7b48fdc114c24b3b0aa75e70d7228041eWinson Chung    }
3667d7541e7b48fdc114c24b3b0aa75e70d7228041eWinson Chung
367f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung    public void calculateCellCount(int width, int height, int maxCellCountX, int maxCellCountY) {
368f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        mCellCountX = Math.min(maxCellCountX, estimateCellHSpan(width));
369f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        mCellCountY = Math.min(maxCellCountY, estimateCellVSpan(height));
370f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        requestLayout();
37180baf5a6b3c62a62265f626d43d1167783c94131Winson Chung    }
372e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung
373e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung    /**
3745fc72b31863639e70b3d944a3b650f42e46932a6Winson Chung     * Estimates the width that the number of hSpan cells will take up.
375e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     */
376e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung    public int estimateCellWidth(int hSpan) {
377e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung        // TODO: we need to take widthGap into effect
378e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung        return hSpan * mCellWidth;
379e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung    }
380e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung
381e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung    /**
382e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     * Estimates the height that the number of vSpan cells will take up.
383e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     */
384e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung    public int estimateCellHeight(int vSpan) {
385e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung        // TODO: we need to take heightGap into effect
386e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung        return vSpan * mCellHeight;
38780baf5a6b3c62a62265f626d43d1167783c94131Winson Chung    }
38880baf5a6b3c62a62265f626d43d1167783c94131Winson Chung
389321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    @Override
390321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
391321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        return new PagedViewCellLayout.LayoutParams(getContext(), attrs);
392321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
393321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
394321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    @Override
395321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
396321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        return p instanceof PagedViewCellLayout.LayoutParams;
397321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
398321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
399321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    @Override
400321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
401321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        return new PagedViewCellLayout.LayoutParams(p);
402321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
403321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
404321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    public static class LayoutParams extends ViewGroup.MarginLayoutParams {
405321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        /**
406321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung         * Horizontal location of the item in the grid.
407321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung         */
408321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        @ViewDebug.ExportedProperty
409321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        public int cellX;
410321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
411321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        /**
412321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung         * Vertical location of the item in the grid.
413321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung         */
414321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        @ViewDebug.ExportedProperty
415321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        public int cellY;
416321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
417321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        /**
418321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung         * Number of cells spanned horizontally by the item.
419321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung         */
420321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        @ViewDebug.ExportedProperty
421321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        public int cellHSpan;
422321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
423321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        /**
424321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung         * Number of cells spanned vertically by the item.
425321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung         */
426321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        @ViewDebug.ExportedProperty
427321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        public int cellVSpan;
428321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
429321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        /**
430321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung         * Is this item currently being dragged
431321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung         */
432321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        public boolean isDragging;
433321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
43480baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        // a data object that you can bind to this layout params
43580baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        private Object mTag;
43680baf5a6b3c62a62265f626d43d1167783c94131Winson Chung
437321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        // X coordinate of the view in the layout.
438321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        @ViewDebug.ExportedProperty
439321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        int x;
440321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        // Y coordinate of the view in the layout.
441321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        @ViewDebug.ExportedProperty
442321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        int y;
443321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
44480baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        public LayoutParams() {
44580baf5a6b3c62a62265f626d43d1167783c94131Winson Chung            super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
44680baf5a6b3c62a62265f626d43d1167783c94131Winson Chung            cellHSpan = 1;
44780baf5a6b3c62a62265f626d43d1167783c94131Winson Chung            cellVSpan = 1;
44880baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        }
44980baf5a6b3c62a62265f626d43d1167783c94131Winson Chung
450321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        public LayoutParams(Context c, AttributeSet attrs) {
451321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            super(c, attrs);
452321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            cellHSpan = 1;
453321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            cellVSpan = 1;
454321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        }
455321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
456321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        public LayoutParams(ViewGroup.LayoutParams source) {
457321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            super(source);
458321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            cellHSpan = 1;
459321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            cellVSpan = 1;
460321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        }
461321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
462321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        public LayoutParams(LayoutParams source) {
463321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            super(source);
464321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            this.cellX = source.cellX;
465321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            this.cellY = source.cellY;
466321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            this.cellHSpan = source.cellHSpan;
467321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            this.cellVSpan = source.cellVSpan;
468321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        }
469321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
470321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        public LayoutParams(int cellX, int cellY, int cellHSpan, int cellVSpan) {
471321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
472321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            this.cellX = cellX;
473321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            this.cellY = cellY;
474321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            this.cellHSpan = cellHSpan;
475321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            this.cellVSpan = cellVSpan;
476321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        }
477321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
478321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        public void setup(int cellWidth, int cellHeight, int widthGap, int heightGap,
479321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung                int hStartPadding, int vStartPadding) {
480321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
481321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            final int myCellHSpan = cellHSpan;
482321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            final int myCellVSpan = cellVSpan;
483321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            final int myCellX = cellX;
484321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            final int myCellY = cellY;
485321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
486321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            width = myCellHSpan * cellWidth + ((myCellHSpan - 1) * widthGap) -
487321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung                    leftMargin - rightMargin;
488321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            height = myCellVSpan * cellHeight + ((myCellVSpan - 1) * heightGap) -
489321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung                    topMargin - bottomMargin;
490321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
491a2eb17095dcffa75c1e9681fdc318fe6e0564321Michael Jurka            if (LauncherApplication.isScreenLarge()) {
492785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung                x = hStartPadding + myCellX * (cellWidth + widthGap) + leftMargin;
493785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung                y = vStartPadding + myCellY * (cellHeight + heightGap) + topMargin;
494785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung            } else {
495785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung                x = myCellX * (cellWidth + widthGap) + leftMargin;
496785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung                y = myCellY * (cellHeight + heightGap) + topMargin;
497785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung            }
498321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        }
499321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
50080baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        public Object getTag() {
50180baf5a6b3c62a62265f626d43d1167783c94131Winson Chung            return mTag;
50280baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        }
50380baf5a6b3c62a62265f626d43d1167783c94131Winson Chung
50480baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        public void setTag(Object tag) {
50580baf5a6b3c62a62265f626d43d1167783c94131Winson Chung            mTag = tag;
50680baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        }
50780baf5a6b3c62a62265f626d43d1167783c94131Winson Chung
508321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        public String toString() {
50980baf5a6b3c62a62265f626d43d1167783c94131Winson Chung            return "(" + this.cellX + ", " + this.cellY + ", " +
51080baf5a6b3c62a62265f626d43d1167783c94131Winson Chung                this.cellHSpan + ", " + this.cellVSpan + ")";
511321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        }
512321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
513321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung}
5148245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka
5158245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurkainterface Page {
5168245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    public int getPageChildCount();
5178245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    public View getChildOnPageAt(int i);
5188245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    public void removeAllViewsOnPage();
5198245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    public void removeViewOnPageAt(int i);
5208245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    public int indexOfChildOnPage(View v);
5218245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka}
522