1b81db8a3add2ceb31350223ebcdca2e60845cd10Rajeev Kumar/*
2290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal * Copyright (C) 2015 The Android Open Source Project
3290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal *
4290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal * Licensed under the Apache License, Version 2.0 (the "License");
5290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal * you may not use this file except in compliance with the License.
6290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal * You may obtain a copy of the License at
7290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal *
8290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal *      http://www.apache.org/licenses/LICENSE-2.0
9290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal *
10290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal * Unless required by applicable law or agreed to in writing, software
11290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal * distributed under the License is distributed on an "AS IS" BASIS,
12290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal * See the License for the specific language governing permissions and
14290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal * limitations under the License.
15290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal */
16290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
17f9c184a619e4e4b82cf9e0bf318ca6d8deaaaee7Adam Cohenpackage com.android.launcher3.folder;
18290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
19e4766230ff8115c5897ebee74c145bcae822581eSunny Goyalimport android.annotation.SuppressLint;
20290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyalimport android.content.Context;
213333b0ced8e6743c41909f6f6b916f1f9ec5a004Sunny Goyalimport android.graphics.Canvas;
22828b11e5a934af781f620620dd20d312defa49b8Sunny Goyalimport android.graphics.drawable.Drawable;
23b81db8a3add2ceb31350223ebcdca2e60845cd10Rajeev Kumarimport android.util.ArrayMap;
24290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyalimport android.util.AttributeSet;
25290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyalimport android.util.Log;
26b7e15adc7b67cb1d70ca72014b200dd6cbbf166aSunny Goyalimport android.view.Gravity;
27290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyalimport android.view.LayoutInflater;
28290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyalimport android.view.View;
294ffec48dec5da7bcf719ac0c37ee5e58f9ea2c1aSunny Goyalimport android.view.ViewDebug;
30828b11e5a934af781f620620dd20d312defa49b8Sunny Goyal
31f9c184a619e4e4b82cf9e0bf318ca6d8deaaaee7Adam Cohenimport com.android.launcher3.BubbleTextView;
32f9c184a619e4e4b82cf9e0bf318ca6d8deaaaee7Adam Cohenimport com.android.launcher3.CellLayout;
33f9c184a619e4e4b82cf9e0bf318ca6d8deaaaee7Adam Cohenimport com.android.launcher3.DeviceProfile;
34f9c184a619e4e4b82cf9e0bf318ca6d8deaaaee7Adam Cohenimport com.android.launcher3.InvariantDeviceProfile;
35f9c184a619e4e4b82cf9e0bf318ca6d8deaaaee7Adam Cohenimport com.android.launcher3.ItemInfo;
36f9c184a619e4e4b82cf9e0bf318ca6d8deaaaee7Adam Cohenimport com.android.launcher3.Launcher;
37f9c184a619e4e4b82cf9e0bf318ca6d8deaaaee7Adam Cohenimport com.android.launcher3.LauncherAppState;
38f9c184a619e4e4b82cf9e0bf318ca6d8deaaaee7Adam Cohenimport com.android.launcher3.PagedView;
39f9c184a619e4e4b82cf9e0bf318ca6d8deaaaee7Adam Cohenimport com.android.launcher3.R;
40f9c184a619e4e4b82cf9e0bf318ca6d8deaaaee7Adam Cohenimport com.android.launcher3.ShortcutAndWidgetContainer;
41f9c184a619e4e4b82cf9e0bf318ca6d8deaaaee7Adam Cohenimport com.android.launcher3.ShortcutInfo;
42f9c184a619e4e4b82cf9e0bf318ca6d8deaaaee7Adam Cohenimport com.android.launcher3.Utilities;
43290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyalimport com.android.launcher3.Workspace.ItemOperator;
445bc6b6f14c676e7528be62e1355a4dec3d783524Sunny Goyalimport com.android.launcher3.anim.Interpolators;
453333b0ced8e6743c41909f6f6b916f1f9ec5a004Sunny Goyalimport com.android.launcher3.keyboard.ViewGroupFocusHelper;
460bd7f4f2dc5a24a10262b1e8bd61b4466123f84dSunny Goyalimport com.android.launcher3.pageindicators.PageIndicatorDots;
47972d121edbd9cab8616779c18fb7de2136be92f3Sunny Goyalimport com.android.launcher3.touch.ItemClickHandler;
48091440a9cb9d4f42406631004aa484cbb79214caAdam Cohenimport com.android.launcher3.util.Thunk;
49828b11e5a934af781f620620dd20d312defa49b8Sunny Goyal
50290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyalimport java.util.ArrayList;
51290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyalimport java.util.Iterator;
524846193300245c8c0a1f9bde3175f273df044309Sunny Goyalimport java.util.Map;
53290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
540bd7f4f2dc5a24a10262b1e8bd61b4466123f84dSunny Goyalpublic class FolderPagedView extends PagedView<PageIndicatorDots> {
55290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
56290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    private static final String TAG = "FolderPagedView";
57290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
58290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    private static final int REORDER_ANIMATION_DURATION = 230;
594846193300245c8c0a1f9bde3175f273df044309Sunny Goyal    private static final int START_VIEW_REORDER_DELAY = 30;
604846193300245c8c0a1f9bde3175f273df044309Sunny Goyal    private static final float VIEW_REORDER_DELAY_FACTOR = 0.9f;
615d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal
623b0883fcda88dd192549055a387fb41e1c2c17adSunny Goyal    /**
633b0883fcda88dd192549055a387fb41e1c2c17adSunny Goyal     * Fraction of the width to scroll when showing the next page hint.
643b0883fcda88dd192549055a387fb41e1c2c17adSunny Goyal     */
653b0883fcda88dd192549055a387fb41e1c2c17adSunny Goyal    private static final float SCROLL_HINT_FRACTION = 0.07f;
663b0883fcda88dd192549055a387fb41e1c2c17adSunny Goyal
67655ec42ce50e18f2ce597901707057b5898e110aJon Miranda    private static final int[] sTmpArray = new int[2];
68290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
697066003b2032a49ae5e59dab9b706259bdeb7e6eSunny Goyal    public final boolean mIsRtl;
703b0883fcda88dd192549055a387fb41e1c2c17adSunny Goyal
71290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    private final LayoutInflater mInflater;
723333b0ced8e6743c41909f6f6b916f1f9ec5a004Sunny Goyal    private final ViewGroupFocusHelper mFocusIndicatorHelper;
73091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen
74b81db8a3add2ceb31350223ebcdca2e60845cd10Rajeev Kumar    @Thunk final ArrayMap<View, Runnable> mPendingAnimations = new ArrayMap<>();
75290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
764ffec48dec5da7bcf719ac0c37ee5e58f9ea2c1aSunny Goyal    @ViewDebug.ExportedProperty(category = "launcher")
77e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal    private final int mMaxCountX;
784ffec48dec5da7bcf719ac0c37ee5e58f9ea2c1aSunny Goyal    @ViewDebug.ExportedProperty(category = "launcher")
79e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal    private final int mMaxCountY;
804ffec48dec5da7bcf719ac0c37ee5e58f9ea2c1aSunny Goyal    @ViewDebug.ExportedProperty(category = "launcher")
81e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal    private final int mMaxItemsPerPage;
82290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
83290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    private int mAllocatedContentSize;
844ffec48dec5da7bcf719ac0c37ee5e58f9ea2c1aSunny Goyal    @ViewDebug.ExportedProperty(category = "launcher")
85290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    private int mGridCountX;
864ffec48dec5da7bcf719ac0c37ee5e58f9ea2c1aSunny Goyal    @ViewDebug.ExportedProperty(category = "launcher")
87290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    private int mGridCountY;
88290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
89290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    private Folder mFolder;
90290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
91290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public FolderPagedView(Context context, AttributeSet attrs) {
92290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        super(context, attrs);
9387f784c285fdeed9091a4de8b9b44db3eca677d8Sunny Goyal        InvariantDeviceProfile profile = LauncherAppState.getIDP(context);
942c6e5ccbcd7c3f87e7e85029782440600dc0a3d8Winson Chung        mMaxCountX = profile.numFolderColumns;
952c6e5ccbcd7c3f87e7e85029782440600dc0a3d8Winson Chung        mMaxCountY = profile.numFolderRows;
96b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal
97290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        mMaxItemsPerPage = mMaxCountX * mMaxCountY;
98290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
99290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        mInflater = LayoutInflater.from(context);
1003b0883fcda88dd192549055a387fb41e1c2c17adSunny Goyal
1017066003b2032a49ae5e59dab9b706259bdeb7e6eSunny Goyal        mIsRtl = Utilities.isRtl(getResources());
102db184fdc7bd652e45216a453541ab4a266457a3aSunny Goyal        setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
1034d113a5ff44ff1a7f19263bde21581fbf9a54212Sunny Goyal
1043333b0ced8e6743c41909f6f6b916f1f9ec5a004Sunny Goyal        mFocusIndicatorHelper = new ViewGroupFocusHelper(this);
105290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
106290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
107290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public void setFolder(Folder folder) {
108290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        mFolder = folder;
109b81db8a3add2ceb31350223ebcdca2e60845cd10Rajeev Kumar        mPageIndicator = folder.findViewById(R.id.folder_page_indicator);
110d0a6ae7f645e6ba564aebb50316c53fa2e119459Sunny Goyal        initParentViews(folder);
111290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
112290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
113290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    /**
114655ec42ce50e18f2ce597901707057b5898e110aJon Miranda     * Calculates the grid size such that {@param count} items can fit in the grid.
115290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     * The grid size is calculated such that countY <= countX and countX = ceil(sqrt(count)) while
116290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     * maintaining the restrictions of {@link #mMaxCountX} &amp; {@link #mMaxCountY}.
117290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     */
118655ec42ce50e18f2ce597901707057b5898e110aJon Miranda    public static void calculateGridSize(int count, int countX, int countY, int maxCountX,
119655ec42ce50e18f2ce597901707057b5898e110aJon Miranda            int maxCountY, int maxItemsPerPage, int[] out) {
120290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        boolean done;
121655ec42ce50e18f2ce597901707057b5898e110aJon Miranda        int gridCountX = countX;
122655ec42ce50e18f2ce597901707057b5898e110aJon Miranda        int gridCountY = countY;
123655ec42ce50e18f2ce597901707057b5898e110aJon Miranda
124655ec42ce50e18f2ce597901707057b5898e110aJon Miranda        if (count >= maxItemsPerPage) {
125655ec42ce50e18f2ce597901707057b5898e110aJon Miranda            gridCountX = maxCountX;
126655ec42ce50e18f2ce597901707057b5898e110aJon Miranda            gridCountY = maxCountY;
127290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            done = true;
128290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        } else {
129290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            done = false;
130290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
131290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
132290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        while (!done) {
133655ec42ce50e18f2ce597901707057b5898e110aJon Miranda            int oldCountX = gridCountX;
134655ec42ce50e18f2ce597901707057b5898e110aJon Miranda            int oldCountY = gridCountY;
135655ec42ce50e18f2ce597901707057b5898e110aJon Miranda            if (gridCountX * gridCountY < count) {
136290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                // Current grid is too small, expand it
137655ec42ce50e18f2ce597901707057b5898e110aJon Miranda                if ((gridCountX <= gridCountY || gridCountY == maxCountY)
138655ec42ce50e18f2ce597901707057b5898e110aJon Miranda                        && gridCountX < maxCountX) {
139655ec42ce50e18f2ce597901707057b5898e110aJon Miranda                    gridCountX++;
140655ec42ce50e18f2ce597901707057b5898e110aJon Miranda                } else if (gridCountY < maxCountY) {
141655ec42ce50e18f2ce597901707057b5898e110aJon Miranda                    gridCountY++;
142290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                }
143655ec42ce50e18f2ce597901707057b5898e110aJon Miranda                if (gridCountY == 0) gridCountY++;
144655ec42ce50e18f2ce597901707057b5898e110aJon Miranda            } else if ((gridCountY - 1) * gridCountX >= count && gridCountY >= gridCountX) {
145655ec42ce50e18f2ce597901707057b5898e110aJon Miranda                gridCountY = Math.max(0, gridCountY - 1);
146655ec42ce50e18f2ce597901707057b5898e110aJon Miranda            } else if ((gridCountX - 1) * gridCountY >= count) {
147655ec42ce50e18f2ce597901707057b5898e110aJon Miranda                gridCountX = Math.max(0, gridCountX - 1);
148290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            }
149655ec42ce50e18f2ce597901707057b5898e110aJon Miranda            done = gridCountX == oldCountX && gridCountY == oldCountY;
150290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
151290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
152655ec42ce50e18f2ce597901707057b5898e110aJon Miranda        out[0] = gridCountX;
153655ec42ce50e18f2ce597901707057b5898e110aJon Miranda        out[1] = gridCountY;
154655ec42ce50e18f2ce597901707057b5898e110aJon Miranda    }
155655ec42ce50e18f2ce597901707057b5898e110aJon Miranda
156655ec42ce50e18f2ce597901707057b5898e110aJon Miranda    /**
157655ec42ce50e18f2ce597901707057b5898e110aJon Miranda     * Sets up the grid size such that {@param count} items can fit in the grid.
158655ec42ce50e18f2ce597901707057b5898e110aJon Miranda     */
159655ec42ce50e18f2ce597901707057b5898e110aJon Miranda    public void setupContentDimensions(int count) {
160655ec42ce50e18f2ce597901707057b5898e110aJon Miranda        mAllocatedContentSize = count;
161655ec42ce50e18f2ce597901707057b5898e110aJon Miranda        calculateGridSize(count, mGridCountX, mGridCountY, mMaxCountX, mMaxCountY, mMaxItemsPerPage,
162655ec42ce50e18f2ce597901707057b5898e110aJon Miranda                sTmpArray);
163655ec42ce50e18f2ce597901707057b5898e110aJon Miranda        mGridCountX = sTmpArray[0];
164655ec42ce50e18f2ce597901707057b5898e110aJon Miranda        mGridCountY = sTmpArray[1];
165655ec42ce50e18f2ce597901707057b5898e110aJon Miranda
166e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        // Update grid size
167e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        for (int i = getPageCount() - 1; i >= 0; i--) {
168290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            getPageAt(i).setGridSize(mGridCountX, mGridCountY);
169290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
170290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
171290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
1723333b0ced8e6743c41909f6f6b916f1f9ec5a004Sunny Goyal    @Override
1733333b0ced8e6743c41909f6f6b916f1f9ec5a004Sunny Goyal    protected void dispatchDraw(Canvas canvas) {
1743333b0ced8e6743c41909f6f6b916f1f9ec5a004Sunny Goyal        mFocusIndicatorHelper.draw(canvas);
1753333b0ced8e6743c41909f6f6b916f1f9ec5a004Sunny Goyal        super.dispatchDraw(canvas);
1763333b0ced8e6743c41909f6f6b916f1f9ec5a004Sunny Goyal    }
1773333b0ced8e6743c41909f6f6b916f1f9ec5a004Sunny Goyal
178b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal    /**
179b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     * Binds items to the layout.
180b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     */
1816bb51f425bc90c4b7b434a758377c65462fd817cSunny Goyal    public void bindItems(ArrayList<ShortcutInfo> items) {
182b81db8a3add2ceb31350223ebcdca2e60845cd10Rajeev Kumar        ArrayList<View> icons = new ArrayList<>();
183290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        for (ShortcutInfo item : items) {
1846bb51f425bc90c4b7b434a758377c65462fd817cSunny Goyal            icons.add(createNewView(item));
185290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
186e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        arrangeChildren(icons, icons.size(), false);
187290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
188290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
189c476d6e192494b14b91e76cbce5c9cec01588059Jon Miranda    public void allocateSpaceForRank(int rank) {
1908701cd58cf3b32c9d2b9269e3956b32f4726a81aJonathan Miranda        ArrayList<View> views = new ArrayList<>(mFolder.getItemsInReadingOrder());
191c476d6e192494b14b91e76cbce5c9cec01588059Jon Miranda        views.add(rank, null);
192c476d6e192494b14b91e76cbce5c9cec01588059Jon Miranda        arrangeChildren(views, views.size(), false);
193c476d6e192494b14b91e76cbce5c9cec01588059Jon Miranda    }
194c476d6e192494b14b91e76cbce5c9cec01588059Jon Miranda
195290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    /**
1968701cd58cf3b32c9d2b9269e3956b32f4726a81aJonathan Miranda     * Create space for a new item at the end, and returns the rank for that item.
197290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     * Also sets the current page to the last page.
198290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     */
199e393d3af369c452f3b5f5d9c0a23a83aa3aa736bSunny Goyal    public int allocateRankForNewItem() {
2008701cd58cf3b32c9d2b9269e3956b32f4726a81aJonathan Miranda        int rank = getItemCount();
2018701cd58cf3b32c9d2b9269e3956b32f4726a81aJonathan Miranda        allocateSpaceForRank(rank);
2025d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal        setCurrentPage(rank / mMaxItemsPerPage);
203290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        return rank;
204290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
205290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
206290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public View createAndAddViewForRank(ShortcutInfo item, int rank) {
207e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        View icon = createNewView(item);
208c476d6e192494b14b91e76cbce5c9cec01588059Jon Miranda        allocateSpaceForRank(rank);
2095d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal        addViewForRank(icon, item, rank);
210e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        return icon;
211290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
212290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
213b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal    /**
214b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     * Adds the {@param view} to the layout based on {@param rank} and updated the position
215b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     * related attributes. It assumes that {@param item} is already attached to the view.
216b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     */
217290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public void addViewForRank(View view, ShortcutInfo item, int rank) {
2188701cd58cf3b32c9d2b9269e3956b32f4726a81aJonathan Miranda        int pagePos = rank % mMaxItemsPerPage;
2198701cd58cf3b32c9d2b9269e3956b32f4726a81aJonathan Miranda        int pageNo = rank / mMaxItemsPerPage;
220290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
2218701cd58cf3b32c9d2b9269e3956b32f4726a81aJonathan Miranda        item.rank = rank;
2228701cd58cf3b32c9d2b9269e3956b32f4726a81aJonathan Miranda        item.cellX = pagePos % mGridCountX;
2238701cd58cf3b32c9d2b9269e3956b32f4726a81aJonathan Miranda        item.cellY = pagePos / mGridCountX;
224290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
225e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
226e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        lp.cellX = item.cellX;
227e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        lp.cellY = item.cellY;
228e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        getPageAt(pageNo).addViewToCellLayout(
229e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal                view, -1, mFolder.mLauncher.getViewIdForItem(item), lp, true);
230290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
231290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
232e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal    @SuppressLint("InflateParams")
233b8c663c492d32963b6ee33750fc985f037c58f10Sunny Goyal    public View createNewView(ShortcutInfo item) {
234290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        final BubbleTextView textView = (BubbleTextView) mInflater.inflate(
235e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal                R.layout.folder_application, null, false);
2361cd01b023acc123b771765b7297d8aaedac224e0Sunny Goyal        textView.applyFromShortcutInfo(item);
237234ca84a50bca1326f5ad1e717ce644d6bb6c47cTony        textView.setHapticFeedbackEnabled(false);
238972d121edbd9cab8616779c18fb7de2136be92f3Sunny Goyal        textView.setOnClickListener(ItemClickHandler.INSTANCE);
239290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        textView.setOnLongClickListener(mFolder);
2403333b0ced8e6743c41909f6f6b916f1f9ec5a004Sunny Goyal        textView.setOnFocusChangeListener(mFocusIndicatorHelper);
241290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
242e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        textView.setLayoutParams(new CellLayout.LayoutParams(
243e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal                item.cellX, item.cellY, item.spanX, item.spanY));
244290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        return textView;
245290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
246290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
247290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    @Override
248290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public CellLayout getPageAt(int index) {
249290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        return (CellLayout) getChildAt(index);
250290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
251290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
252290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public CellLayout getCurrentCellLayout() {
253290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        return getPageAt(getNextPage());
254290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
255290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
256e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal    private CellLayout createAndAddNewPage() {
2572fd020860533e18c64a93d14d11cb2d34bc9cbafTony        DeviceProfile grid = Launcher.getLauncher(getContext()).getDeviceProfile();
258c13403c612748bfdf06436510600230c4c4b55ecSunny Goyal        CellLayout page = (CellLayout) mInflater.inflate(R.layout.folder_page, this, false);
259e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        page.setCellDimensions(grid.folderCellWidthPx, grid.folderCellHeightPx);
260e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        page.getShortcutsAndWidgets().setMotionEventSplittingEnabled(false);
261e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        page.setInvertIfRtl(true);
262e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        page.setGridSize(mGridCountX, mGridCountY);
263290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
26422fc63ee298335b5f5c603ea1b77dc0e6180b16aSunny Goyal        addView(page, -1, generateDefaultLayoutParams());
265e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        return page;
266290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
267290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
268a1fbd84b791474a9e86b67caeaf27b8429afba73Sunny Goyal    @Override
269a1fbd84b791474a9e86b67caeaf27b8429afba73Sunny Goyal    protected int getChildGap() {
270a1fbd84b791474a9e86b67caeaf27b8429afba73Sunny Goyal        return getPaddingLeft() + getPaddingRight();
271a1fbd84b791474a9e86b67caeaf27b8429afba73Sunny Goyal    }
272a1fbd84b791474a9e86b67caeaf27b8429afba73Sunny Goyal
273290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public void setFixedSize(int width, int height) {
27422fc63ee298335b5f5c603ea1b77dc0e6180b16aSunny Goyal        width -= (getPaddingLeft() + getPaddingRight());
27522fc63ee298335b5f5c603ea1b77dc0e6180b16aSunny Goyal        height -= (getPaddingTop() + getPaddingBottom());
276290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        for (int i = getChildCount() - 1; i >= 0; i --) {
277290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            ((CellLayout) getChildAt(i)).setFixedSize(width, height);
278290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
279290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
280290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
281290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public void removeItem(View v) {
282290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        for (int i = getChildCount() - 1; i >= 0; i --) {
283290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            getPageAt(i).removeView(v);
284290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
285290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
286290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
287c64cfdd8fa18de45fc1646c8ef2449f39ef83022Sunny Goyal    @Override
288c64cfdd8fa18de45fc1646c8ef2449f39ef83022Sunny Goyal    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
289c64cfdd8fa18de45fc1646c8ef2449f39ef83022Sunny Goyal        super.onScrollChanged(l, t, oldl, oldt);
290c64cfdd8fa18de45fc1646c8ef2449f39ef83022Sunny Goyal        mPageIndicator.setScroll(l, mMaxScrollX);
291c64cfdd8fa18de45fc1646c8ef2449f39ef83022Sunny Goyal    }
292c64cfdd8fa18de45fc1646c8ef2449f39ef83022Sunny Goyal
293290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    /**
294290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     * Updates position and rank of all the children in the view.
295290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     * It essentially removes all views from all the pages and then adds them again in appropriate
296290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     * page.
297290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     *
2988701cd58cf3b32c9d2b9269e3956b32f4726a81aJonathan Miranda     * @param list the ordered list of children.
299290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     * @param itemCount if greater than the total children count, empty spaces are left
300290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     * at the end, otherwise it is ignored.
301290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     *
302290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal     */
3038701cd58cf3b32c9d2b9269e3956b32f4726a81aJonathan Miranda    public void arrangeChildren(ArrayList<View> list, int itemCount) {
3048701cd58cf3b32c9d2b9269e3956b32f4726a81aJonathan Miranda        arrangeChildren(list, itemCount, true);
305e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal    }
306e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal
307a07c2f5c80908e8a612f4681314a7068b92baa9fSunny Goyal    @SuppressLint("RtlHardcoded")
3088701cd58cf3b32c9d2b9269e3956b32f4726a81aJonathan Miranda    private void arrangeChildren(ArrayList<View> list, int itemCount, boolean saveChanges) {
3098701cd58cf3b32c9d2b9269e3956b32f4726a81aJonathan Miranda        ArrayList<CellLayout> pages = new ArrayList<>();
310290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        for (int i = 0; i < getChildCount(); i++) {
311290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            CellLayout page = (CellLayout) getChildAt(i);
312290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            page.removeAllViews();
313290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            pages.add(page);
314290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
315290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        setupContentDimensions(itemCount);
316290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
317290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        Iterator<CellLayout> pageItr = pages.iterator();
318290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        CellLayout currentPage = null;
319290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
320290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        int position = 0;
321290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        int newX, newY, rank;
322290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
323529af302dc2141f6e5e4eabbe981c228a9a0df2cJon Miranda        FolderIconPreviewVerifier verifier = new FolderIconPreviewVerifier(
324529af302dc2141f6e5e4eabbe981c228a9a0df2cJon Miranda                Launcher.getLauncher(getContext()).getDeviceProfile().inv);
325290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        rank = 0;
3264846193300245c8c0a1f9bde3175f273df044309Sunny Goyal        for (int i = 0; i < itemCount; i++) {
3278701cd58cf3b32c9d2b9269e3956b32f4726a81aJonathan Miranda            View v = list.size() > i ? list.get(i) : null;
328290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            if (currentPage == null || position >= mMaxItemsPerPage) {
329290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                // Next page
330290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                if (pageItr.hasNext()) {
331290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                    currentPage = pageItr.next();
332290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                } else {
333e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal                    currentPage = createAndAddNewPage();
334290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                }
335290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                position = 0;
336290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            }
337290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
3384846193300245c8c0a1f9bde3175f273df044309Sunny Goyal            if (v != null) {
3394846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                CellLayout.LayoutParams lp = (CellLayout.LayoutParams) v.getLayoutParams();
3408701cd58cf3b32c9d2b9269e3956b32f4726a81aJonathan Miranda                newX = position % mGridCountX;
3418701cd58cf3b32c9d2b9269e3956b32f4726a81aJonathan Miranda                newY = position / mGridCountX;
3424846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                ItemInfo info = (ItemInfo) v.getTag();
3434846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                if (info.cellX != newX || info.cellY != newY || info.rank != rank) {
3444846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                    info.cellX = newX;
3454846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                    info.cellY = newY;
3464846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                    info.rank = rank;
3474846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                    if (saveChanges) {
34843bf11d9c95f76c2dfeb625b23cb458df81252b3Sunny Goyal                        mFolder.mLauncher.getModelWriter().addOrMoveItemInDatabase(info,
3494846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                                mFolder.mInfo.id, 0, info.cellX, info.cellY);
3504846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                    }
351e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal                }
3524846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                lp.cellX = info.cellX;
3534846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                lp.cellY = info.cellY;
3544846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                currentPage.addViewToCellLayout(
3554846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                        v, -1, mFolder.mLauncher.getViewIdForItem(info), lp, true);
356317698bd012c1930b83bb4e2e47ac9e363fa6c6aSunny Goyal
357529af302dc2141f6e5e4eabbe981c228a9a0df2cJon Miranda                if (verifier.isItemInPreview(rank) && v instanceof BubbleTextView) {
358317698bd012c1930b83bb4e2e47ac9e363fa6c6aSunny Goyal                    ((BubbleTextView) v).verifyHighRes();
359317698bd012c1930b83bb4e2e47ac9e363fa6c6aSunny Goyal                }
360290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            }
3614846193300245c8c0a1f9bde3175f273df044309Sunny Goyal
362290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            rank ++;
363290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            position++;
364290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
365290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
366e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal        // Remove extra views.
367290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        boolean removed = false;
368290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        while (pageItr.hasNext()) {
369e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal            removeView(pageItr.next());
370e4766230ff8115c5897ebee74c145bcae822581eSunny Goyal            removed = true;
371290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
372290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        if (removed) {
373290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            setCurrentPage(0);
374290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
3755d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal
376b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal        setEnableOverscroll(getPageCount() > 1);
3775d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal
3785d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal        // Update footer
379c487bd34ace268dd8be5480ba884baed6096f76eSunny Goyal        mPageIndicator.setVisibility(getPageCount() > 1 ? View.VISIBLE : View.GONE);
380a07c2f5c80908e8a612f4681314a7068b92baa9fSunny Goyal        // Set the gravity as LEFT or RIGHT instead of START, as START depends on the actual text.
381a07c2f5c80908e8a612f4681314a7068b92baa9fSunny Goyal        mFolder.mFolderName.setGravity(getPageCount() > 1 ?
382a07c2f5c80908e8a612f4681314a7068b92baa9fSunny Goyal                (mIsRtl ? Gravity.RIGHT : Gravity.LEFT) : Gravity.CENTER_HORIZONTAL);
383290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
384290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
385290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public int getDesiredWidth() {
38622fc63ee298335b5f5c603ea1b77dc0e6180b16aSunny Goyal        return getPageCount() > 0 ?
38722fc63ee298335b5f5c603ea1b77dc0e6180b16aSunny Goyal                (getPageAt(0).getDesiredWidth() + getPaddingLeft() + getPaddingRight()) : 0;
388290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
389290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
390290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public int getDesiredHeight()  {
39122fc63ee298335b5f5c603ea1b77dc0e6180b16aSunny Goyal        return  getPageCount() > 0 ?
39222fc63ee298335b5f5c603ea1b77dc0e6180b16aSunny Goyal                (getPageAt(0).getDesiredHeight() + getPaddingTop() + getPaddingBottom()) : 0;
393290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
394290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
395290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public int getItemCount() {
396e85d7145222ba1311cd9280726d8419b84f2f94bSunny Goyal        int lastPageIndex = getChildCount() - 1;
397e85d7145222ba1311cd9280726d8419b84f2f94bSunny Goyal        if (lastPageIndex < 0) {
398e85d7145222ba1311cd9280726d8419b84f2f94bSunny Goyal            // If there are no pages, nothing has yet been added to the folder.
399e85d7145222ba1311cd9280726d8419b84f2f94bSunny Goyal            return 0;
4004846193300245c8c0a1f9bde3175f273df044309Sunny Goyal        }
401e85d7145222ba1311cd9280726d8419b84f2f94bSunny Goyal        return getPageAt(lastPageIndex).getShortcutsAndWidgets().getChildCount()
402e85d7145222ba1311cd9280726d8419b84f2f94bSunny Goyal                + lastPageIndex * mMaxItemsPerPage;
403290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
404290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
405b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal    /**
406b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     * @return the rank of the cell nearest to the provided pixel position.
407b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     */
408290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public int findNearestArea(int pixelX, int pixelY) {
409290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        int pageIndex = getNextPage();
410290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        CellLayout page = getPageAt(pageIndex);
411655ec42ce50e18f2ce597901707057b5898e110aJon Miranda        page.findNearestArea(pixelX, pixelY, 1, 1, sTmpArray);
412290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        if (mFolder.isLayoutRtl()) {
413655ec42ce50e18f2ce597901707057b5898e110aJon Miranda            sTmpArray[0] = page.getCountX() - sTmpArray[0] - 1;
414290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
415290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        return Math.min(mAllocatedContentSize - 1,
416655ec42ce50e18f2ce597901707057b5898e110aJon Miranda                pageIndex * mMaxItemsPerPage + sTmpArray[1] * mGridCountX + sTmpArray[0]);
417290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
418290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
419feec2171f84f465feab96631c9d067d032aa8f88Tony Wickham    public View getFirstItem() {
420feec2171f84f465feab96631c9d067d032aa8f88Tony Wickham        if (getChildCount() < 1) {
421feec2171f84f465feab96631c9d067d032aa8f88Tony Wickham            return null;
422feec2171f84f465feab96631c9d067d032aa8f88Tony Wickham        }
423feec2171f84f465feab96631c9d067d032aa8f88Tony Wickham        ShortcutAndWidgetContainer currContainer = getCurrentCellLayout().getShortcutsAndWidgets();
424feec2171f84f465feab96631c9d067d032aa8f88Tony Wickham        if (mGridCountX > 0) {
425feec2171f84f465feab96631c9d067d032aa8f88Tony Wickham            return currContainer.getChildAt(0, 0);
426feec2171f84f465feab96631c9d067d032aa8f88Tony Wickham        } else {
427feec2171f84f465feab96631c9d067d032aa8f88Tony Wickham            return currContainer.getChildAt(0);
428feec2171f84f465feab96631c9d067d032aa8f88Tony Wickham        }
429feec2171f84f465feab96631c9d067d032aa8f88Tony Wickham    }
430feec2171f84f465feab96631c9d067d032aa8f88Tony Wickham
431290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public View getLastItem() {
432290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        if (getChildCount() < 1) {
433290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            return null;
434290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
435feec2171f84f465feab96631c9d067d032aa8f88Tony Wickham        ShortcutAndWidgetContainer currContainer = getCurrentCellLayout().getShortcutsAndWidgets();
436feec2171f84f465feab96631c9d067d032aa8f88Tony Wickham        int lastRank = currContainer.getChildCount() - 1;
437290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        if (mGridCountX > 0) {
438feec2171f84f465feab96631c9d067d032aa8f88Tony Wickham            return currContainer.getChildAt(lastRank % mGridCountX, lastRank / mGridCountX);
439290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        } else {
440feec2171f84f465feab96631c9d067d032aa8f88Tony Wickham            return currContainer.getChildAt(lastRank);
441290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
442290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
443290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
444b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal    /**
445b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     * Iterates over all its items in a reading order.
446b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     * @return the view for which the operator returned true.
447b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     */
448290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public View iterateOverItems(ItemOperator op) {
449290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        for (int k = 0 ; k < getChildCount(); k++) {
450290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            CellLayout page = getPageAt(k);
451290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            for (int j = 0; j < page.getCountY(); j++) {
452290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                for (int i = 0; i < page.getCountX(); i++) {
453290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                    View v = page.getChildAt(i, j);
454c52ba710053e4c6927937dd1a26d1abe06b6fa99Sunny Goyal                    if ((v != null) && op.evaluate((ItemInfo) v.getTag(), v)) {
455290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                        return v;
456290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                    }
457290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                }
458290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            }
459290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
460290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        return null;
461290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
462290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
463290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public String getAccessibilityDescription() {
464f4f89ef608245d39bbddda05f291361d2ae06667Sunny Goyal        return getContext().getString(R.string.folder_opened, mGridCountX, mGridCountY);
465290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
466290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
467b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal    /**
468b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     * Sets the focus on the first visible child.
469b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     */
470290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public void setFocusOnFirstChild() {
471290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        View firstChild = getCurrentCellLayout().getChildAt(0, 0);
472290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        if (firstChild != null) {
473290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            firstChild.requestFocus();
474290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
475290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
476290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
477290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    @Override
4783f5a11f3a517975e108e8ccb749cddef8670fb54Hyunyoung Song    protected void notifyPageSwitchListener(int prevPage) {
4793f5a11f3a517975e108e8ccb749cddef8670fb54Hyunyoung Song        super.notifyPageSwitchListener(prevPage);
480290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        if (mFolder != null) {
481290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            mFolder.updateTextViewFocus();
482290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
483290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
484290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
4854846193300245c8c0a1f9bde3175f273df044309Sunny Goyal    /**
4864846193300245c8c0a1f9bde3175f273df044309Sunny Goyal     * Scrolls the current view by a fraction
4874846193300245c8c0a1f9bde3175f273df044309Sunny Goyal     */
4883b0883fcda88dd192549055a387fb41e1c2c17adSunny Goyal    public void showScrollHint(int direction) {
489f5440cbd6c0525769d24b890e16313a728831e04Sunny Goyal        float fraction = (direction == Folder.SCROLL_LEFT) ^ mIsRtl
4903b0883fcda88dd192549055a387fb41e1c2c17adSunny Goyal                ? -SCROLL_HINT_FRACTION : SCROLL_HINT_FRACTION;
4914846193300245c8c0a1f9bde3175f273df044309Sunny Goyal        int hint = (int) (fraction * getWidth());
4924846193300245c8c0a1f9bde3175f273df044309Sunny Goyal        int scroll = getScrollForPage(getNextPage()) + hint;
4934d113a5ff44ff1a7f19263bde21581fbf9a54212Sunny Goyal        int delta = scroll - getScrollX();
4944846193300245c8c0a1f9bde3175f273df044309Sunny Goyal        if (delta != 0) {
4955bc6b6f14c676e7528be62e1355a4dec3d783524Sunny Goyal            mScroller.setInterpolator(Interpolators.DEACCEL);
4964d113a5ff44ff1a7f19263bde21581fbf9a54212Sunny Goyal            mScroller.startScroll(getScrollX(), 0, delta, 0, Folder.SCROLL_HINT_DURATION);
4974846193300245c8c0a1f9bde3175f273df044309Sunny Goyal            invalidate();
4984846193300245c8c0a1f9bde3175f273df044309Sunny Goyal        }
4994846193300245c8c0a1f9bde3175f273df044309Sunny Goyal    }
5004846193300245c8c0a1f9bde3175f273df044309Sunny Goyal
5014846193300245c8c0a1f9bde3175f273df044309Sunny Goyal    public void clearScrollHint() {
5024d113a5ff44ff1a7f19263bde21581fbf9a54212Sunny Goyal        if (getScrollX() != getScrollForPage(getNextPage())) {
5034846193300245c8c0a1f9bde3175f273df044309Sunny Goyal            snapToPage(getNextPage());
5044846193300245c8c0a1f9bde3175f273df044309Sunny Goyal        }
5054846193300245c8c0a1f9bde3175f273df044309Sunny Goyal    }
5064846193300245c8c0a1f9bde3175f273df044309Sunny Goyal
5074846193300245c8c0a1f9bde3175f273df044309Sunny Goyal    /**
5084846193300245c8c0a1f9bde3175f273df044309Sunny Goyal     * Finish animation all the views which are animating across pages
5094846193300245c8c0a1f9bde3175f273df044309Sunny Goyal     */
5104846193300245c8c0a1f9bde3175f273df044309Sunny Goyal    public void completePendingPageChanges() {
5115d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal        if (!mPendingAnimations.isEmpty()) {
512b81db8a3add2ceb31350223ebcdca2e60845cd10Rajeev Kumar            ArrayMap<View, Runnable> pendingViews = new ArrayMap<>(mPendingAnimations);
5134846193300245c8c0a1f9bde3175f273df044309Sunny Goyal            for (Map.Entry<View, Runnable> e : pendingViews.entrySet()) {
5144846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                e.getKey().animate().cancel();
5154846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                e.getValue().run();
5164846193300245c8c0a1f9bde3175f273df044309Sunny Goyal            }
5174846193300245c8c0a1f9bde3175f273df044309Sunny Goyal        }
5184846193300245c8c0a1f9bde3175f273df044309Sunny Goyal    }
5194846193300245c8c0a1f9bde3175f273df044309Sunny Goyal
5204846193300245c8c0a1f9bde3175f273df044309Sunny Goyal    public boolean rankOnCurrentPage(int rank) {
5214846193300245c8c0a1f9bde3175f273df044309Sunny Goyal        int p = rank / mMaxItemsPerPage;
5224846193300245c8c0a1f9bde3175f273df044309Sunny Goyal        return p == getNextPage();
5234846193300245c8c0a1f9bde3175f273df044309Sunny Goyal    }
5244846193300245c8c0a1f9bde3175f273df044309Sunny Goyal
525290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    @Override
5269ccafbff26f5835ab9725d876d1bf7ccd08ccf84Sunny Goyal    protected void onPageBeginTransition() {
5279ccafbff26f5835ab9725d876d1bf7ccd08ccf84Sunny Goyal        super.onPageBeginTransition();
5289ccafbff26f5835ab9725d876d1bf7ccd08ccf84Sunny Goyal        // Ensure that adjacent pages have high resolution icons
5299ccafbff26f5835ab9725d876d1bf7ccd08ccf84Sunny Goyal        verifyVisibleHighResIcons(getCurrentPage() - 1);
5309ccafbff26f5835ab9725d876d1bf7ccd08ccf84Sunny Goyal        verifyVisibleHighResIcons(getCurrentPage() + 1);
53134b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal    }
53234b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal
53334b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal    /**
53434b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal     * Ensures that all the icons on the given page are of high-res
53534b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal     */
53634b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal    public void verifyVisibleHighResIcons(int pageNo) {
53734b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal        CellLayout page = getPageAt(pageNo);
53834b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal        if (page != null) {
53934b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal            ShortcutAndWidgetContainer parent = page.getShortcutsAndWidgets();
54034b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal            for (int i = parent.getChildCount() - 1; i >= 0; i--) {
541828b11e5a934af781f620620dd20d312defa49b8Sunny Goyal                BubbleTextView icon = ((BubbleTextView) parent.getChildAt(i));
542828b11e5a934af781f620620dd20d312defa49b8Sunny Goyal                icon.verifyHighRes();
543828b11e5a934af781f620620dd20d312defa49b8Sunny Goyal                // Set the callback back to the actual icon, in case
544828b11e5a934af781f620620dd20d312defa49b8Sunny Goyal                // it was captured by the FolderIcon
545828b11e5a934af781f620620dd20d312defa49b8Sunny Goyal                Drawable d = icon.getCompoundDrawables()[1];
546828b11e5a934af781f620620dd20d312defa49b8Sunny Goyal                if (d != null) {
547828b11e5a934af781f620620dd20d312defa49b8Sunny Goyal                    d.setCallback(icon);
548828b11e5a934af781f620620dd20d312defa49b8Sunny Goyal                }
54934b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal            }
55034b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal        }
55134b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal    }
55234b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal
553ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal    public int getAllocatedContentSize() {
554ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal        return mAllocatedContentSize;
555ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal    }
556ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal
557b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal    /**
558b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     * Reorders the items such that the {@param empty} spot moves to {@param target}
559b863415c17aaaf6012647df5ed14803f89f94bcbSunny Goyal     */
560290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    public void realTimeReorder(int empty, int target) {
5614846193300245c8c0a1f9bde3175f273df044309Sunny Goyal        completePendingPageChanges();
562290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        int delay = 0;
5634846193300245c8c0a1f9bde3175f273df044309Sunny Goyal        float delayAmount = START_VIEW_REORDER_DELAY;
564290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
565290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        // Animation only happens on the current page.
566290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        int pageToAnimate = getNextPage();
567290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
568290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        int pageT = target / mMaxItemsPerPage;
569290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        int pagePosT = target % mMaxItemsPerPage;
570290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
571290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        if (pageT != pageToAnimate) {
572290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            Log.e(TAG, "Cannot animate when the target cell is invisible");
573290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
574290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        int pagePosE = empty % mMaxItemsPerPage;
575290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        int pageE = empty / mMaxItemsPerPage;
576290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
577290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        int startPos, endPos;
578290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        int moveStart, moveEnd;
579290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        int direction;
580290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
581290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        if (target == empty) {
582290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            // No animation
583290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            return;
584290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        } else if (target > empty) {
585290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            // Items will move backwards to make room for the empty cell.
586290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            direction = 1;
587290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
588290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            // If empty cell is in a different page, move them instantly.
589290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            if (pageE < pageToAnimate) {
590290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                moveStart = empty;
591290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                // Instantly move the first item in the current page.
592290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                moveEnd = pageToAnimate * mMaxItemsPerPage;
593290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                // Animate the 2nd item in the current page, as the first item was already moved to
594290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                // the last page.
595290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                startPos = 0;
596290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            } else {
597290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                moveStart = moveEnd = -1;
598290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                startPos = pagePosE;
599290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            }
600290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
601290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            endPos = pagePosT;
602290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        } else {
603290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            // The items will move forward.
604290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            direction = -1;
605290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
606290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            if (pageE > pageToAnimate) {
607290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                // Move the items immediately.
608290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                moveStart = empty;
609290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                // Instantly move the last item in the current page.
610290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                moveEnd = (pageToAnimate + 1) * mMaxItemsPerPage - 1;
611290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
612290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                // Animations start with the second last item in the page
613290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                startPos = mMaxItemsPerPage - 1;
614290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            } else {
615290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                moveStart = moveEnd = -1;
616290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                startPos = pagePosE;
617290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            }
618290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
619290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            endPos = pagePosT;
620290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
621290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
622290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        // Instant moving views.
623290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        while (moveStart != moveEnd) {
624290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            int rankToMove = moveStart + direction;
625290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            int p = rankToMove / mMaxItemsPerPage;
626290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            int pagePos = rankToMove % mMaxItemsPerPage;
627290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            int x = pagePos % mGridCountX;
628290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            int y = pagePos / mGridCountX;
629290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
630290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            final CellLayout page = getPageAt(p);
631290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            final View v = page.getChildAt(x, y);
632290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            if (v != null) {
633290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                if (pageToAnimate != p) {
634290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                    page.removeView(v);
6358701cd58cf3b32c9d2b9269e3956b32f4726a81aJonathan Miranda                    addViewForRank(v, (ShortcutInfo) v.getTag(), moveStart);
636290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                } else {
637290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                    // Do a fake animation before removing it.
638290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                    final int newRank = moveStart;
639290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                    final float oldTranslateX = v.getTranslationX();
640290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
641290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                    Runnable endAction = new Runnable() {
642290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
643290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                        @Override
644290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                        public void run() {
6455d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal                            mPendingAnimations.remove(v);
646290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                            v.setTranslationX(oldTranslateX);
647290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                            ((CellLayout) v.getParent().getParent()).removeView(v);
6488701cd58cf3b32c9d2b9269e3956b32f4726a81aJonathan Miranda                            addViewForRank(v, (ShortcutInfo) v.getTag(), newRank);
649290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                        }
650290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                    };
651290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                    v.animate()
6528701cd58cf3b32c9d2b9269e3956b32f4726a81aJonathan Miranda                        .translationXBy((direction > 0 ^ mIsRtl) ? -v.getWidth() : v.getWidth())
6538701cd58cf3b32c9d2b9269e3956b32f4726a81aJonathan Miranda                        .setDuration(REORDER_ANIMATION_DURATION)
6548701cd58cf3b32c9d2b9269e3956b32f4726a81aJonathan Miranda                        .setStartDelay(0)
6558701cd58cf3b32c9d2b9269e3956b32f4726a81aJonathan Miranda                        .withEndAction(endAction);
6565d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal                    mPendingAnimations.put(v, endAction);
657290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                }
658290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            }
659290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            moveStart = rankToMove;
660290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
661290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
662290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        if ((endPos - startPos) * direction <= 0) {
663290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            // No animation
664290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            return;
665290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
666290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal
667290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        CellLayout page = getPageAt(pageToAnimate);
668290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        for (int i = startPos; i != endPos; i += direction) {
669290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            int nextPos = i + direction;
670290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            View v = page.getChildAt(nextPos % mGridCountX, nextPos / mGridCountX);
671290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            if (v != null) {
672290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                ((ItemInfo) v.getTag()).rank -= direction;
673290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            }
674290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            if (page.animateChildToPosition(v, i % mGridCountX, i / mGridCountX,
675290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                    REORDER_ANIMATION_DURATION, delay, true, true)) {
676290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal                delay += delayAmount;
6774846193300245c8c0a1f9bde3175f273df044309Sunny Goyal                delayAmount *= VIEW_REORDER_DELAY_FACTOR;
678290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal            }
679290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal        }
680290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal    }
681b7e15adc7b67cb1d70ca72014b200dd6cbbf166aSunny Goyal
682b7e15adc7b67cb1d70ca72014b200dd6cbbf166aSunny Goyal    public int itemsPerPage() {
683b7e15adc7b67cb1d70ca72014b200dd6cbbf166aSunny Goyal        return mMaxItemsPerPage;
684b7e15adc7b67cb1d70ca72014b200dd6cbbf166aSunny Goyal    }
685290800b5b7d575fd709f244f54a5fa5b63b58876Sunny Goyal}
686