PagedViewCellLayout.java revision 8245a8685fc9f4802c9fa29a989854b2522fc588
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;
20321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chungimport android.util.AttributeSet;
21321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chungimport android.view.MotionEvent;
22321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chungimport android.view.View;
23321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chungimport android.view.ViewDebug;
24321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chungimport android.view.ViewGroup;
25321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
26321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung/**
27321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung * An abstraction of the original CellLayout which supports laying out items
28321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung * which span multiple cells into a grid-like layout.  Also supports dimming
29321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung * to give a preview of its contents.
30321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung */
318245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurkapublic class PagedViewCellLayout extends ViewGroup implements Page {
32321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    static final String TAG = "PagedViewCellLayout";
33321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
34321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    private int mCellCountX;
35321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    private int mCellCountY;
36321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    private int mCellWidth;
37321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    private int mCellHeight;
38df4b83dd9d6380ab963c62d1f9d1312efc87cb0fWinson Chung    private int mWidthGap;
39df4b83dd9d6380ab963c62d1f9d1312efc87cb0fWinson Chung    private int mHeightGap;
40321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    private static int sDefaultCellDimensions = 96;
418245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    protected PagedViewCellLayoutChildren mChildren;
428245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    private PagedViewCellLayoutChildren mHolographicChildren;
43321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
44321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    public PagedViewCellLayout(Context context) {
45321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        this(context, null);
46321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
47321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
48321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    public PagedViewCellLayout(Context context, AttributeSet attrs) {
49321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        this(context, attrs, 0);
50321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
51321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
52321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    public PagedViewCellLayout(Context context, AttributeSet attrs, int defStyle) {
53321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        super(context, attrs, defStyle);
54321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
55321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        setAlwaysDrawnWithCacheEnabled(false);
56321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
57321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        // setup default cell parameters
58321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        mCellWidth = mCellHeight = sDefaultCellDimensions;
59321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        mCellCountX = LauncherModel.getCellCountX();
60321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        mCellCountY = LauncherModel.getCellCountY();
61df4b83dd9d6380ab963c62d1f9d1312efc87cb0fWinson Chung        mWidthGap = mHeightGap = -1;
62321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
638245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        mChildren = new PagedViewCellLayoutChildren(context);
648245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        mChildren.setCellDimensions(mCellWidth, mCellHeight);
658245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        mChildren.setGap(mWidthGap, mHeightGap);
668245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka
678245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        addView(mChildren);
688245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        mHolographicChildren = new PagedViewCellLayoutChildren(context);
698245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        mHolographicChildren.setAlpha(0f);
708245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        mHolographicChildren.setCellDimensions(mCellWidth, mCellHeight);
718245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        mHolographicChildren.setGap(mWidthGap, mHeightGap);
728245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka
738245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        addView(mHolographicChildren);
74321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
75321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
76321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    @Override
77b3347bb9f4ccf41fb7043bca66c3a565bde1083bWinson Chung    public void setAlpha(float alpha) {
788245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        mChildren.setAlpha(alpha);
798245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        mHolographicChildren.setAlpha(1.0f - alpha);
80321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
81321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
82321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    @Override
83321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    public void cancelLongPress() {
84321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        super.cancelLongPress();
85321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
86321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        // Cancel long press for all children
87321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        final int count = getChildCount();
88321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        for (int i = 0; i < count; i++) {
89321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            final View child = getChildAt(i);
90321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            child.cancelLongPress();
91321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        }
92321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
93321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
94321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    public boolean addViewToCellLayout(View child, int index, int childId,
95321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            PagedViewCellLayout.LayoutParams params) {
96321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        final PagedViewCellLayout.LayoutParams lp = params;
97321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
98321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        // Generate an id for each view, this assumes we have at most 256x256 cells
99321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        // per workspace screen
100321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        if (lp.cellX >= 0 && lp.cellX <= (mCellCountX - 1) &&
101321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung                lp.cellY >= 0 && (lp.cellY <= mCellCountY - 1)) {
102321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            // If the horizontal or vertical span is set to -1, it is taken to
103321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            // mean that it spans the extent of the CellLayout
104321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            if (lp.cellHSpan < 0) lp.cellHSpan = mCellCountX;
105321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            if (lp.cellVSpan < 0) lp.cellVSpan = mCellCountY;
106321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
107321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            child.setId(childId);
1088245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka            mChildren.addView(child, index, lp);
109321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
1108245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka            if (child instanceof PagedViewIcon) {
1118245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka                PagedViewIcon pagedViewIcon = (PagedViewIcon) child;
1128245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka                mHolographicChildren.addView(pagedViewIcon.getHolographicOutlineView(), index, lp);
1138245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka            }
114321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            return true;
115321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        }
116321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        return false;
117321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
118321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
119321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    @Override
1208245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    public void removeAllViewsOnPage() {
1218245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        mChildren.removeAllViews();
1228245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        mHolographicChildren.removeAllViews();
123321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
124321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
125321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    @Override
1268245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    public void removeViewOnPageAt(int index) {
1278245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        mChildren.removeViewAt(index);
1288245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        mHolographicChildren.removeViewAt(index);
1298245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    }
1308245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka
1318245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    @Override
1328245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    public int getPageChildCount() {
1338245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        return mChildren.getChildCount();
1348245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    }
1358245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka
1368245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    @Override
1378245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    public View getChildOnPageAt(int i) {
1388245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        return mChildren.getChildAt(i);
1398245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    }
1408245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka
1418245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    @Override
1428245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    public int indexOfChildOnPage(View v) {
1438245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        return mChildren.indexOfChild(v);
1448245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    }
1458245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka
146321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
147321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        // TODO: currently ignoring padding
148321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
149321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
150321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
151321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
152321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
153321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        int heightSpecSize =  MeasureSpec.getSize(heightMeasureSpec);
154321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
155321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        if (widthSpecMode == MeasureSpec.UNSPECIFIED || heightSpecMode == MeasureSpec.UNSPECIFIED) {
156321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            throw new RuntimeException("CellLayout cannot have UNSPECIFIED dimensions");
157321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        }
158321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
159321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        final int cellWidth = mCellWidth;
160321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        final int cellHeight = mCellHeight;
161321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
162321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        int numWidthGaps = mCellCountX - 1;
163321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        int numHeightGaps = mCellCountY - 1;
164321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
165321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        int vSpaceLeft = heightSpecSize - mPaddingTop
166321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung                - mPaddingBottom - (cellHeight * mCellCountY);
167321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        int heightGap = vSpaceLeft / numHeightGaps;
168321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
169321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        int hSpaceLeft = widthSpecSize - mPaddingLeft
170321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung                - mPaddingRight - (cellWidth * mCellCountX);
171321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        int widthGap = hSpaceLeft / numWidthGaps;
172321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
173321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        // center it around the min gaps
174321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        int minGap = Math.min(widthGap, heightGap);
175321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        /*
176321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        if (minGap < heightGap) {
177321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            // vertical space has shrunken, so change padding accordingly
178321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            paddingTop += ((heightGap - minGap) * (mCellCountY - 1)) / 2;
179321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        } else if (minGap < widthGap) {
180321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            // horizontal space has shrunken, so change padding accordingly
181321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            paddingLeft += ((widthGap - minGap) * (mCellCountX - 1)) / 2;
182321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        }
183321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        */
184df4b83dd9d6380ab963c62d1f9d1312efc87cb0fWinson Chung        if (mWidthGap > -1 && mHeightGap > -1) {
185df4b83dd9d6380ab963c62d1f9d1312efc87cb0fWinson Chung            widthGap = mWidthGap;
186df4b83dd9d6380ab963c62d1f9d1312efc87cb0fWinson Chung            heightGap = mHeightGap;
187df4b83dd9d6380ab963c62d1f9d1312efc87cb0fWinson Chung        } else {
188df4b83dd9d6380ab963c62d1f9d1312efc87cb0fWinson Chung            widthGap = heightGap = minGap;
189df4b83dd9d6380ab963c62d1f9d1312efc87cb0fWinson Chung        }
190321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
191321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        int newWidth = mPaddingLeft + mPaddingRight + (mCellCountX * cellWidth) +
192df4b83dd9d6380ab963c62d1f9d1312efc87cb0fWinson Chung            ((mCellCountX - 1) * widthGap);
193321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        int newHeight = mPaddingTop + mPaddingBottom + (mCellCountY * cellHeight) +
194df4b83dd9d6380ab963c62d1f9d1312efc87cb0fWinson Chung            ((mCellCountY - 1) * heightGap);
195321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
196321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        final int count = getChildCount();
197321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        for (int i = 0; i < count; i++) {
198321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            View child = getChildAt(i);
1998245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka            int childWidthMeasureSpec =
2008245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka                MeasureSpec.makeMeasureSpec(newWidth, MeasureSpec.EXACTLY);
2018245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka            int childheightMeasureSpec =
2028245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka                MeasureSpec.makeMeasureSpec(newHeight, MeasureSpec.EXACTLY);
203321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            child.measure(childWidthMeasureSpec, childheightMeasureSpec);
204321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        }
205321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
206321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        setMeasuredDimension(newWidth, newHeight);
207321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
208321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
209321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    @Override
210321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    protected void onLayout(boolean changed, int l, int t, int r, int b) {
211321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        int count = getChildCount();
212321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        for (int i = 0; i < count; i++) {
213321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            View child = getChildAt(i);
2148245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka            child.layout(0, 0, r - l, b - t);
215321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        }
216321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
217321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
218321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    @Override
219321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    public boolean onTouchEvent(MotionEvent event) {
220321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        return super.onTouchEvent(event) || true;
221321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
222321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
22380baf5a6b3c62a62265f626d43d1167783c94131Winson Chung    public void enableCenteredContent(boolean enabled) {
2248245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        mChildren.enableCenteredContent(enabled);
2258245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        mHolographicChildren.enableCenteredContent(enabled);
22680baf5a6b3c62a62265f626d43d1167783c94131Winson Chung    }
22780baf5a6b3c62a62265f626d43d1167783c94131Winson Chung
228321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    @Override
229321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    protected void setChildrenDrawingCacheEnabled(boolean enabled) {
2308245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        mChildren.setChildrenDrawingCacheEnabled(enabled);
2318245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        mHolographicChildren.setChildrenDrawingCacheEnabled(enabled);
232321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
233321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
234321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    public void setCellCount(int xCount, int yCount) {
235321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        mCellCountX = xCount;
236321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        mCellCountY = yCount;
237321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        requestLayout();
238321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
239321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
240df4b83dd9d6380ab963c62d1f9d1312efc87cb0fWinson Chung    public void setGap(int widthGap, int heightGap) {
241df4b83dd9d6380ab963c62d1f9d1312efc87cb0fWinson Chung        mWidthGap = widthGap;
242df4b83dd9d6380ab963c62d1f9d1312efc87cb0fWinson Chung        mHeightGap = heightGap;
2438245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        mChildren.setGap(widthGap, heightGap);
2448245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        mHolographicChildren.setGap(widthGap, heightGap);
245df4b83dd9d6380ab963c62d1f9d1312efc87cb0fWinson Chung    }
246df4b83dd9d6380ab963c62d1f9d1312efc87cb0fWinson Chung
247e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung    public void setCellDimensions(int width, int height) {
248e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung        mCellWidth = width;
249e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung        mCellHeight = height;
2508245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        mChildren.setCellDimensions(width, height);
2518245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka        mHolographicChildren.setCellDimensions(width, height);
252e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung    }
253e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung
254e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung    public int getDefaultCellDimensions() {
255e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung        return sDefaultCellDimensions;
256e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung    }
257e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung
25880baf5a6b3c62a62265f626d43d1167783c94131Winson Chung    public int[] getCellCountForDimensions(int width, int height) {
25980baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        // Always assume we're working with the smallest span to make sure we
26080baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        // reserve enough space in both orientations
26180baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        int smallerSize = Math.min(mCellWidth, mCellHeight);
26280baf5a6b3c62a62265f626d43d1167783c94131Winson Chung
26380baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        // Always round up to next largest cell
26480baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        int spanX = (width + smallerSize) / smallerSize;
26580baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        int spanY = (height + smallerSize) / smallerSize;
26680baf5a6b3c62a62265f626d43d1167783c94131Winson Chung
26780baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        return new int[] { spanX, spanY };
26880baf5a6b3c62a62265f626d43d1167783c94131Winson Chung    }
26980baf5a6b3c62a62265f626d43d1167783c94131Winson Chung
270321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    /**
271321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung     * Start dragging the specified child
272321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung     *
273321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung     * @param child The child that is being dragged
274321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung     */
275321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    void onDragChild(View child) {
276321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        PagedViewCellLayout.LayoutParams lp = (PagedViewCellLayout.LayoutParams) child.getLayoutParams();
277321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        lp.isDragging = true;
278321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
279321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
280e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung    /**
281e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     * Estimates the number of cells that the specified width would take up.
282e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     */
28380baf5a6b3c62a62265f626d43d1167783c94131Winson Chung    public int estimateCellHSpan(int width) {
284e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung        // TODO: we need to take widthGap into effect
28580baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        return (width + mCellWidth) / mCellWidth;
28680baf5a6b3c62a62265f626d43d1167783c94131Winson Chung    }
287e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung
288e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung    /**
289e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     * Estimates the number of cells that the specified height would take up.
290e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     */
29180baf5a6b3c62a62265f626d43d1167783c94131Winson Chung    public int estimateCellVSpan(int height) {
292e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung        // TODO: we need to take heightGap into effect
29380baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        return (height + mCellHeight) / mCellHeight;
29480baf5a6b3c62a62265f626d43d1167783c94131Winson Chung    }
295e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung
296e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung    /**
297e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     * Estimates the width that the number of vSpan cells will take up.
298e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     */
299e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung    public int estimateCellWidth(int hSpan) {
300e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung        // TODO: we need to take widthGap into effect
301e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung        return hSpan * mCellWidth;
302e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung    }
303e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung
304e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung    /**
305e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     * Estimates the height that the number of vSpan cells will take up.
306e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     */
307e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung    public int estimateCellHeight(int vSpan) {
308e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung        // TODO: we need to take heightGap into effect
309e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung        return vSpan * mCellHeight;
31080baf5a6b3c62a62265f626d43d1167783c94131Winson Chung    }
31180baf5a6b3c62a62265f626d43d1167783c94131Winson Chung
312321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    @Override
313321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
314321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        return new PagedViewCellLayout.LayoutParams(getContext(), attrs);
315321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
316321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
317321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    @Override
318321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
319321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        return p instanceof PagedViewCellLayout.LayoutParams;
320321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
321321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
322321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    @Override
323321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
324321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        return new PagedViewCellLayout.LayoutParams(p);
325321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
326321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
327321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    public static class LayoutParams extends ViewGroup.MarginLayoutParams {
328321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        /**
329321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung         * Horizontal location of the item in the grid.
330321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung         */
331321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        @ViewDebug.ExportedProperty
332321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        public int cellX;
333321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
334321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        /**
335321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung         * Vertical location of the item in the grid.
336321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung         */
337321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        @ViewDebug.ExportedProperty
338321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        public int cellY;
339321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
340321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        /**
341321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung         * Number of cells spanned horizontally by the item.
342321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung         */
343321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        @ViewDebug.ExportedProperty
344321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        public int cellHSpan;
345321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
346321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        /**
347321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung         * Number of cells spanned vertically by the item.
348321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung         */
349321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        @ViewDebug.ExportedProperty
350321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        public int cellVSpan;
351321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
352321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        /**
353321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung         * Is this item currently being dragged
354321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung         */
355321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        public boolean isDragging;
356321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
35780baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        // a data object that you can bind to this layout params
35880baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        private Object mTag;
35980baf5a6b3c62a62265f626d43d1167783c94131Winson Chung
360321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        // X coordinate of the view in the layout.
361321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        @ViewDebug.ExportedProperty
362321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        int x;
363321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        // Y coordinate of the view in the layout.
364321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        @ViewDebug.ExportedProperty
365321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        int y;
366321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
36780baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        public LayoutParams() {
36880baf5a6b3c62a62265f626d43d1167783c94131Winson Chung            super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
36980baf5a6b3c62a62265f626d43d1167783c94131Winson Chung            cellHSpan = 1;
37080baf5a6b3c62a62265f626d43d1167783c94131Winson Chung            cellVSpan = 1;
37180baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        }
37280baf5a6b3c62a62265f626d43d1167783c94131Winson Chung
373321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        public LayoutParams(Context c, AttributeSet attrs) {
374321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            super(c, attrs);
375321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            cellHSpan = 1;
376321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            cellVSpan = 1;
377321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        }
378321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
379321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        public LayoutParams(ViewGroup.LayoutParams source) {
380321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            super(source);
381321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            cellHSpan = 1;
382321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            cellVSpan = 1;
383321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        }
384321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
385321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        public LayoutParams(LayoutParams source) {
386321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            super(source);
387321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            this.cellX = source.cellX;
388321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            this.cellY = source.cellY;
389321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            this.cellHSpan = source.cellHSpan;
390321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            this.cellVSpan = source.cellVSpan;
391321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        }
392321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
393321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        public LayoutParams(int cellX, int cellY, int cellHSpan, int cellVSpan) {
394321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
395321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            this.cellX = cellX;
396321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            this.cellY = cellY;
397321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            this.cellHSpan = cellHSpan;
398321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            this.cellVSpan = cellVSpan;
399321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        }
400321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
401321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        public void setup(int cellWidth, int cellHeight, int widthGap, int heightGap,
402321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung                int hStartPadding, int vStartPadding) {
403321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
404321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            final int myCellHSpan = cellHSpan;
405321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            final int myCellVSpan = cellVSpan;
406321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            final int myCellX = cellX;
407321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            final int myCellY = cellY;
408321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
409321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            width = myCellHSpan * cellWidth + ((myCellHSpan - 1) * widthGap) -
410321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung                    leftMargin - rightMargin;
411321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            height = myCellVSpan * cellHeight + ((myCellVSpan - 1) * heightGap) -
412321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung                    topMargin - bottomMargin;
413321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
414321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            x = hStartPadding + myCellX * (cellWidth + widthGap) + leftMargin;
415321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung            y = vStartPadding + myCellY * (cellHeight + heightGap) + topMargin;
416321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        }
417321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung
41880baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        public Object getTag() {
41980baf5a6b3c62a62265f626d43d1167783c94131Winson Chung            return mTag;
42080baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        }
42180baf5a6b3c62a62265f626d43d1167783c94131Winson Chung
42280baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        public void setTag(Object tag) {
42380baf5a6b3c62a62265f626d43d1167783c94131Winson Chung            mTag = tag;
42480baf5a6b3c62a62265f626d43d1167783c94131Winson Chung        }
42580baf5a6b3c62a62265f626d43d1167783c94131Winson Chung
426321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        public String toString() {
42780baf5a6b3c62a62265f626d43d1167783c94131Winson Chung            return "(" + this.cellX + ", " + this.cellY + ", " +
42880baf5a6b3c62a62265f626d43d1167783c94131Winson Chung                this.cellHSpan + ", " + this.cellVSpan + ")";
429321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung        }
430321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung    }
431321e9ee68848d9e782fd557f69cc070308ffbc9cWinson Chung}
4328245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka
4338245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurkainterface Page {
4348245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    public int getPageChildCount();
4358245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    public View getChildOnPageAt(int i);
4368245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    public void removeAllViewsOnPage();
4378245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    public void removeViewOnPageAt(int i);
4388245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka    public int indexOfChildOnPage(View v);
4398245a8685fc9f4802c9fa29a989854b2522fc588Michael Jurka}
440