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
90321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    public void cancelLongPress() {
91321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        super.cancelLongPress();
92321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
93321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        // Cancel long press for all children
94321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        final int count = getChildCount();
95321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        for (int i = 0; i < count; i++) {
96321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            final View child = getChildAt(i);
97321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            child.cancelLongPress();
98321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        }
99321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
100321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
101321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    public boolean addViewToCellLayout(View child, int index, int childId,
1026a70e9fc3c62cc83d6abe59323d622dc6cd224a7Winson Chung            PagedViewCellLayout.LayoutParams params) {
103321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        final PagedViewCellLayout.LayoutParams lp = params;
104321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
105321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        // Generate an id for each view, this assumes we have at most 256x256 cells
106321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        // per workspace screen
107321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        if (lp.cellX >= 0 && lp.cellX <= (mCellCountX - 1) &&
108321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung                lp.cellY >= 0 && (lp.cellY <= mCellCountY - 1)) {
109321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            // If the horizontal or vertical span is set to -1, it is taken to
110321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            // mean that it spans the extent of the CellLayout
111321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            if (lp.cellHSpan < 0) lp.cellHSpan = mCellCountX;
112321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            if (lp.cellVSpan < 0) lp.cellVSpan = mCellCountY;
113321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
114321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            child.setId(childId);
1158245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka            mChildren.addView(child, index, lp);
116321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
117321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            return true;
118321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        }
119321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        return false;
120321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
121321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
122321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    @Override
1238245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    public void removeAllViewsOnPage() {
1248245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        mChildren.removeAllViews();
12547639b9c1db9a5d0d89ce6b4b36d6b3c0d489602Michael Jurka        setLayerType(LAYER_TYPE_NONE, null);
126321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
127321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
128321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    @Override
1298245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    public void removeViewOnPageAt(int index) {
1308245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        mChildren.removeViewAt(index);
1318245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    }
1328245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka
133c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung    /**
134c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung     * Clears all the key listeners for the individual icons.
135c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung     */
136c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung    public void resetChildrenOnKeyListeners() {
137c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung        int childCount = mChildren.getChildCount();
138c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung        for (int j = 0; j < childCount; ++j) {
139c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung            mChildren.getChildAt(j).setOnKeyListener(null);
140c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung        }
141c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung    }
142c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung
1438245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    @Override
1448245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    public int getPageChildCount() {
1458245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        return mChildren.getChildCount();
1468245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    }
1478245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka
1485afbf7bdd6f6879124c9b8283e005fe57f310d02Winson Chung    public PagedViewCellLayoutChildren getChildrenLayout() {
1495afbf7bdd6f6879124c9b8283e005fe57f310d02Winson Chung        return mChildren;
1505afbf7bdd6f6879124c9b8283e005fe57f310d02Winson Chung    }
1515afbf7bdd6f6879124c9b8283e005fe57f310d02Winson Chung
1528245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    @Override
1538245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    public View getChildOnPageAt(int i) {
1548245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        return mChildren.getChildAt(i);
1558245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    }
1568245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka
1578245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    @Override
1588245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    public int indexOfChildOnPage(View v) {
1598245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        return mChildren.indexOfChild(v);
1608245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    }
1618245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka
16297d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung    public int getCellCountX() {
16397d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung        return mCellCountX;
16497d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung    }
16597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung
16697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung    public int getCellCountY() {
16797d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung        return mCellCountY;
16897d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung    }
16997d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung
170321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
171321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
172321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
173321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
174321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
175321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        int heightSpecSize =  MeasureSpec.getSize(heightMeasureSpec);
176321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
177321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        if (widthSpecMode == MeasureSpec.UNSPECIFIED || heightSpecMode == MeasureSpec.UNSPECIFIED) {
178321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            throw new RuntimeException("CellLayout cannot have UNSPECIFIED dimensions");
179321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        }
180321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
181321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        int numWidthGaps = mCellCountX - 1;
182321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        int numHeightGaps = mCellCountY - 1;
183321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
184234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen        if (mOriginalWidthGap < 0 || mOriginalHeightGap < 0) {
1858b805b17158886035b38261eb611d8641701ae43Michael Jurka            int hSpace = widthSpecSize - getPaddingLeft() - getPaddingRight();
1868b805b17158886035b38261eb611d8641701ae43Michael Jurka            int vSpace = heightSpecSize - getPaddingTop() - getPaddingBottom();
187db1138b4efae89a3b5833547958a3606e5408a71Winson Chung            int hFreeSpace = hSpace - (mCellCountX * mOriginalCellWidth);
188db1138b4efae89a3b5833547958a3606e5408a71Winson Chung            int vFreeSpace = vSpace - (mCellCountY * mOriginalCellHeight);
189db1138b4efae89a3b5833547958a3606e5408a71Winson Chung            mWidthGap = Math.min(mMaxGap, numWidthGaps > 0 ? (hFreeSpace / numWidthGaps) : 0);
190db1138b4efae89a3b5833547958a3606e5408a71Winson Chung            mHeightGap = Math.min(mMaxGap,numHeightGaps > 0 ? (vFreeSpace / numHeightGaps) : 0);
191db1138b4efae89a3b5833547958a3606e5408a71Winson Chung
192db1138b4efae89a3b5833547958a3606e5408a71Winson Chung            mChildren.setGap(mWidthGap, mHeightGap);
193234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen        } else {
194234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen            mWidthGap = mOriginalWidthGap;
195234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen            mHeightGap = mOriginalHeightGap;
196df4b83dd9d6380ab963c62d1f9d1312efc87cb0fWinson Chung        }
197321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
198db1138b4efae89a3b5833547958a3606e5408a71Winson Chung        // Initial values correspond to widthSpecMode == MeasureSpec.EXACTLY
199db1138b4efae89a3b5833547958a3606e5408a71Winson Chung        int newWidth = widthSpecSize;
200db1138b4efae89a3b5833547958a3606e5408a71Winson Chung        int newHeight = heightSpecSize;
201db1138b4efae89a3b5833547958a3606e5408a71Winson Chung        if (widthSpecMode == MeasureSpec.AT_MOST) {
2028b805b17158886035b38261eb611d8641701ae43Michael Jurka            newWidth = getPaddingLeft() + getPaddingRight() + (mCellCountX * mCellWidth) +
203db1138b4efae89a3b5833547958a3606e5408a71Winson Chung                ((mCellCountX - 1) * mWidthGap);
2048b805b17158886035b38261eb611d8641701ae43Michael Jurka            newHeight = getPaddingTop() + getPaddingBottom() + (mCellCountY * mCellHeight) +
205db1138b4efae89a3b5833547958a3606e5408a71Winson Chung                ((mCellCountY - 1) * mHeightGap);
206db1138b4efae89a3b5833547958a3606e5408a71Winson Chung            setMeasuredDimension(newWidth, newHeight);
207db1138b4efae89a3b5833547958a3606e5408a71Winson Chung        }
208321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
209321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        final int count = getChildCount();
210321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        for (int i = 0; i < count; i++) {
211321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            View child = getChildAt(i);
2128245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka            int childWidthMeasureSpec =
2138b805b17158886035b38261eb611d8641701ae43Michael Jurka                MeasureSpec.makeMeasureSpec(newWidth - getPaddingLeft() -
2148b805b17158886035b38261eb611d8641701ae43Michael Jurka                        getPaddingRight(), MeasureSpec.EXACTLY);
2158245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka            int childheightMeasureSpec =
2168b805b17158886035b38261eb611d8641701ae43Michael Jurka                MeasureSpec.makeMeasureSpec(newHeight - getPaddingTop() -
2178b805b17158886035b38261eb611d8641701ae43Michael Jurka                        getPaddingBottom(), MeasureSpec.EXACTLY);
218321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            child.measure(childWidthMeasureSpec, childheightMeasureSpec);
219321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        }
220321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
221db1138b4efae89a3b5833547958a3606e5408a71Winson Chung        setMeasuredDimension(newWidth, newHeight);
222321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
223321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
2247ef959b9177e1e715b0afe010904455a3d961fc4Michael Jurka    int getContentWidth() {
2258b805b17158886035b38261eb611d8641701ae43Michael Jurka        return getWidthBeforeFirstLayout() + getPaddingLeft() + getPaddingRight();
2260413dfa01b822e349092636774dc948b9230adeaMichael Jurka    }
2270413dfa01b822e349092636774dc948b9230adeaMichael Jurka
2284b576be59e58072cc03b5a8d36afb6a322513575Winson Chung    int getContentHeight() {
2294a5ad095303ca1b6b745263269333bd087168d3cPatrick Dubroy        if (mCellCountY > 0) {
2304a5ad095303ca1b6b745263269333bd087168d3cPatrick Dubroy            return mCellCountY * mCellHeight + (mCellCountY - 1) * Math.max(0, mHeightGap);
2314a5ad095303ca1b6b745263269333bd087168d3cPatrick Dubroy        }
2324a5ad095303ca1b6b745263269333bd087168d3cPatrick Dubroy        return 0;
2334b576be59e58072cc03b5a8d36afb6a322513575Winson Chung    }
2344b576be59e58072cc03b5a8d36afb6a322513575Winson Chung
235d92e741ca67c58c4be01a64940847feafe26a4b1Michael Jurka    int getWidthBeforeFirstLayout() {
2364a5ad095303ca1b6b745263269333bd087168d3cPatrick Dubroy        if (mCellCountX > 0) {
2374a5ad095303ca1b6b745263269333bd087168d3cPatrick Dubroy            return mCellCountX * mCellWidth + (mCellCountX - 1) * Math.max(0, mWidthGap);
2384a5ad095303ca1b6b745263269333bd087168d3cPatrick Dubroy        }
2394a5ad095303ca1b6b745263269333bd087168d3cPatrick Dubroy        return 0;
2407ef959b9177e1e715b0afe010904455a3d961fc4Michael Jurka    }
2417ef959b9177e1e715b0afe010904455a3d961fc4Michael Jurka
242321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    @Override
243321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    protected void onLayout(boolean changed, int l, int t, int r, int b) {
244321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        int count = getChildCount();
245321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        for (int i = 0; i < count; i++) {
246321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            View child = getChildAt(i);
2478b805b17158886035b38261eb611d8641701ae43Michael Jurka            child.layout(getPaddingLeft(), getPaddingTop(),
2488b805b17158886035b38261eb611d8641701ae43Michael Jurka                r - l - getPaddingRight(), b - t - getPaddingBottom());
249321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        }
250321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
251321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
252321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    @Override
253321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    public boolean onTouchEvent(MotionEvent event) {
254f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        boolean result = super.onTouchEvent(event);
255f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        int count = getPageChildCount();
256f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        if (count > 0) {
257f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung            // We only intercept the touch if we are tapping in empty space after the final row
258f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung            View child = getChildOnPageAt(count - 1);
259f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung            int bottom = child.getBottom();
260f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung            int numRows = (int) Math.ceil((float) getPageChildCount() / getCellCountX());
261f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung            if (numRows < getCellCountY()) {
262f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung                // Add a little bit of buffer if there is room for another row
263f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung                bottom += mCellHeight / 2;
264f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung            }
265f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung            result = result || (event.getY() < bottom);
266f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        }
267f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        return result;
268321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
269321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
27080baf5a6b3c62a62265f626d43d1167783c94131Winson Chung    public void enableCenteredContent(boolean enabled) {
2718245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        mChildren.enableCenteredContent(enabled);
27280baf5a6b3c62a62265f626d43d1167783c94131Winson Chung    }
27380baf5a6b3c62a62265f626d43d1167783c94131Winson Chung
274321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    @Override
275321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    protected void setChildrenDrawingCacheEnabled(boolean enabled) {
2768245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        mChildren.setChildrenDrawingCacheEnabled(enabled);
277321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
278321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
279321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    public void setCellCount(int xCount, int yCount) {
280321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        mCellCountX = xCount;
281321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        mCellCountY = yCount;
282321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        requestLayout();
283321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
284321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
285df4b83dd9d6380ab963c62d1f9d1312efc87cb0fWinson Chung    public void setGap(int widthGap, int heightGap) {
2866032e7ed8e6208348a6b3f8bc1a7ecafc7951af8Winson Chung        mOriginalWidthGap = mWidthGap = widthGap;
2876032e7ed8e6208348a6b3f8bc1a7ecafc7951af8Winson Chung        mOriginalHeightGap = mHeightGap = heightGap;
2888245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        mChildren.setGap(widthGap, heightGap);
289df4b83dd9d6380ab963c62d1f9d1312efc87cb0fWinson Chung    }
290df4b83dd9d6380ab963c62d1f9d1312efc87cb0fWinson Chung
29180baf5a6b3c62a62265f626d43d1167783c94131Winson Chung    public int[] getCellCountForDimensions(int width, int height) {
29280baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        // Always assume we're working with the smallest span to make sure we
29380baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        // reserve enough space in both orientations
29480baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        int smallerSize = Math.min(mCellWidth, mCellHeight);
29580baf5a6b3c62a62265f626d43d1167783c94131Winson Chung
29680baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        // Always round up to next largest cell
29780baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        int spanX = (width + smallerSize) / smallerSize;
29880baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        int spanY = (height + smallerSize) / smallerSize;
29980baf5a6b3c62a62265f626d43d1167783c94131Winson Chung
30080baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        return new int[] { spanX, spanY };
30180baf5a6b3c62a62265f626d43d1167783c94131Winson Chung    }
30280baf5a6b3c62a62265f626d43d1167783c94131Winson Chung
303321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    /**
304321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung     * Start dragging the specified child
305321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung     *
306321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung     * @param child The child that is being dragged
307321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung     */
308321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    void onDragChild(View child) {
309321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        PagedViewCellLayout.LayoutParams lp = (PagedViewCellLayout.LayoutParams) child.getLayoutParams();
310321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        lp.isDragging = true;
311321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
312321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
313e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung    /**
314e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     * Estimates the number of cells that the specified width would take up.
315e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     */
31680baf5a6b3c62a62265f626d43d1167783c94131Winson Chung    public int estimateCellHSpan(int width) {
3176032e7ed8e6208348a6b3f8bc1a7ecafc7951af8Winson Chung        // We don't show the next/previous pages any more, so we use the full width, minus the
3186032e7ed8e6208348a6b3f8bc1a7ecafc7951af8Winson Chung        // padding
3198b805b17158886035b38261eb611d8641701ae43Michael Jurka        int availWidth = width - (getPaddingLeft() + getPaddingRight());
320f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung
321f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        // We know that we have to fit N cells with N-1 width gaps, so we just juggle to solve for N
322f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        int n = Math.max(1, (availWidth + mWidthGap) / (mCellWidth + mWidthGap));
323f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung
324f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        // We don't do anything fancy to determine if we squeeze another row in.
325f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        return n;
32680baf5a6b3c62a62265f626d43d1167783c94131Winson Chung    }
327e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung
328e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung    /**
329e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     * Estimates the number of cells that the specified height would take up.
330e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     */
33180baf5a6b3c62a62265f626d43d1167783c94131Winson Chung    public int estimateCellVSpan(int height) {
332f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        // The space for a page is the height - top padding (current page) - bottom padding (current
333f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        // page)
3348b805b17158886035b38261eb611d8641701ae43Michael Jurka        int availHeight = height - (getPaddingTop() + getPaddingBottom());
335f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung
336f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        // We know that we have to fit N cells with N-1 height gaps, so we juggle to solve for N
337f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        int n = Math.max(1, (availHeight + mHeightGap) / (mCellHeight + mHeightGap));
338f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung
339f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        // We don't do anything fancy to determine if we squeeze another row in.
340f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        return n;
341f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung    }
342f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung
3437d7541e7b48fdc114c24b3b0aa75e70d7228041eWinson Chung    /** Returns an estimated center position of the cell at the specified index */
3447d7541e7b48fdc114c24b3b0aa75e70d7228041eWinson Chung    public int[] estimateCellPosition(int x, int y) {
3457d7541e7b48fdc114c24b3b0aa75e70d7228041eWinson Chung        return new int[] {
3468b805b17158886035b38261eb611d8641701ae43Michael Jurka                getPaddingLeft() + (x * mCellWidth) + (x * mWidthGap) + (mCellWidth / 2),
3478b805b17158886035b38261eb611d8641701ae43Michael Jurka                getPaddingTop() + (y * mCellHeight) + (y * mHeightGap) + (mCellHeight / 2)
3487d7541e7b48fdc114c24b3b0aa75e70d7228041eWinson Chung        };
3497d7541e7b48fdc114c24b3b0aa75e70d7228041eWinson Chung    }
3507d7541e7b48fdc114c24b3b0aa75e70d7228041eWinson Chung
351f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung    public void calculateCellCount(int width, int height, int maxCellCountX, int maxCellCountY) {
352f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        mCellCountX = Math.min(maxCellCountX, estimateCellHSpan(width));
353f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        mCellCountY = Math.min(maxCellCountY, estimateCellVSpan(height));
354f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        requestLayout();
35580baf5a6b3c62a62265f626d43d1167783c94131Winson Chung    }
356e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung
357e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung    /**
3585fc72b31863639e70b3d944a3b650f42e46932a6Winson Chung     * Estimates the width that the number of hSpan cells will take up.
359e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     */
360e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung    public int estimateCellWidth(int hSpan) {
361e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung        // TODO: we need to take widthGap into effect
362e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung        return hSpan * mCellWidth;
363e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung    }
364e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung
365e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung    /**
366e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     * Estimates the height that the number of vSpan cells will take up.
367e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     */
368e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung    public int estimateCellHeight(int vSpan) {
369e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung        // TODO: we need to take heightGap into effect
370e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung        return vSpan * mCellHeight;
37180baf5a6b3c62a62265f626d43d1167783c94131Winson Chung    }
37280baf5a6b3c62a62265f626d43d1167783c94131Winson Chung
373321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    @Override
374321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
375321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        return new PagedViewCellLayout.LayoutParams(getContext(), attrs);
376321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
377321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
378321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    @Override
379321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
380321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        return p instanceof PagedViewCellLayout.LayoutParams;
381321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
382321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
383321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    @Override
384321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
385321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        return new PagedViewCellLayout.LayoutParams(p);
386321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
387321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
388321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    public static class LayoutParams extends ViewGroup.MarginLayoutParams {
389321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        /**
390321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung         * Horizontal location of the item in the grid.
391321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung         */
392321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        @ViewDebug.ExportedProperty
393321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        public int cellX;
394321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
395321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        /**
396321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung         * Vertical location of the item in the grid.
397321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung         */
398321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        @ViewDebug.ExportedProperty
399321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        public int cellY;
400321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
401321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        /**
402321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung         * Number of cells spanned horizontally by the item.
403321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung         */
404321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        @ViewDebug.ExportedProperty
405321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        public int cellHSpan;
406321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
407321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        /**
408321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung         * Number of cells spanned vertically by the item.
409321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung         */
410321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        @ViewDebug.ExportedProperty
411321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        public int cellVSpan;
412321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
413321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        /**
414321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung         * Is this item currently being dragged
415321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung         */
416321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        public boolean isDragging;
417321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
41880baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        // a data object that you can bind to this layout params
41980baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        private Object mTag;
42080baf5a6b3c62a62265f626d43d1167783c94131Winson Chung
421321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        // X coordinate of the view in the layout.
422321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        @ViewDebug.ExportedProperty
423321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        int x;
424321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        // Y coordinate of the view in the layout.
425321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        @ViewDebug.ExportedProperty
426321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        int y;
427321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
42880baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        public LayoutParams() {
42980baf5a6b3c62a62265f626d43d1167783c94131Winson Chung            super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
43080baf5a6b3c62a62265f626d43d1167783c94131Winson Chung            cellHSpan = 1;
43180baf5a6b3c62a62265f626d43d1167783c94131Winson Chung            cellVSpan = 1;
43280baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        }
43380baf5a6b3c62a62265f626d43d1167783c94131Winson Chung
434321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        public LayoutParams(Context c, AttributeSet attrs) {
435321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            super(c, attrs);
436321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            cellHSpan = 1;
437321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            cellVSpan = 1;
438321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        }
439321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
440321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        public LayoutParams(ViewGroup.LayoutParams source) {
441321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            super(source);
442321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            cellHSpan = 1;
443321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            cellVSpan = 1;
444321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        }
445321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
446321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        public LayoutParams(LayoutParams source) {
447321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            super(source);
448321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            this.cellX = source.cellX;
449321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            this.cellY = source.cellY;
450321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            this.cellHSpan = source.cellHSpan;
451321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            this.cellVSpan = source.cellVSpan;
452321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        }
453321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
454321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        public LayoutParams(int cellX, int cellY, int cellHSpan, int cellVSpan) {
455321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
456321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            this.cellX = cellX;
457321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            this.cellY = cellY;
458321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            this.cellHSpan = cellHSpan;
459321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            this.cellVSpan = cellVSpan;
460321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        }
461321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
462321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        public void setup(int cellWidth, int cellHeight, int widthGap, int heightGap,
463321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung                int hStartPadding, int vStartPadding) {
464321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
465321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            final int myCellHSpan = cellHSpan;
466321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            final int myCellVSpan = cellVSpan;
467321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            final int myCellX = cellX;
468321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            final int myCellY = cellY;
469321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
470321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            width = myCellHSpan * cellWidth + ((myCellHSpan - 1) * widthGap) -
471321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung                    leftMargin - rightMargin;
472321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            height = myCellVSpan * cellHeight + ((myCellVSpan - 1) * heightGap) -
473321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung                    topMargin - bottomMargin;
474321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
475a2eb17095dcffa75c1e9681fdc318fe6e0564321Michael Jurka            if (LauncherApplication.isScreenLarge()) {
476785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung                x = hStartPadding + myCellX * (cellWidth + widthGap) + leftMargin;
477785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung                y = vStartPadding + myCellY * (cellHeight + heightGap) + topMargin;
478785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung            } else {
479785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung                x = myCellX * (cellWidth + widthGap) + leftMargin;
480785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung                y = myCellY * (cellHeight + heightGap) + topMargin;
481785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung            }
482321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        }
483321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
48480baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        public Object getTag() {
48580baf5a6b3c62a62265f626d43d1167783c94131Winson Chung            return mTag;
48680baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        }
48780baf5a6b3c62a62265f626d43d1167783c94131Winson Chung
48880baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        public void setTag(Object tag) {
48980baf5a6b3c62a62265f626d43d1167783c94131Winson Chung            mTag = tag;
49080baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        }
49180baf5a6b3c62a62265f626d43d1167783c94131Winson Chung
492321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        public String toString() {
49380baf5a6b3c62a62265f626d43d1167783c94131Winson Chung            return "(" + this.cellX + ", " + this.cellY + ", " +
49480baf5a6b3c62a62265f626d43d1167783c94131Winson Chung                this.cellHSpan + ", " + this.cellVSpan + ")";
495321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        }
496321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
497321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung}
4988245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka
4998245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurkainterface Page {
5008245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    public int getPageChildCount();
5018245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    public View getChildOnPageAt(int i);
5028245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    public void removeAllViewsOnPage();
5038245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    public void removeViewOnPageAt(int i);
5048245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    public int indexOfChildOnPage(View v);
5058245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka}
506