AppsCustomizePagedView.java revision c10ba1396f49cde2faacb7001e7e97fcee325507
1282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
2282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Copyright (C) 2011 The Android Open Source Project
3282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
4282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License");
5282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * you may not use this file except in compliance with the License.
6282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * You may obtain a copy of the License at
7282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
8282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *      http://www.apache.org/licenses/LICENSE-2.0
9282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
10282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Unless required by applicable law or agreed to in writing, software
11282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS,
12282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * See the License for the specific language governing permissions and
14282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * limitations under the License.
15282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
16282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
17282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskipackage com.android.launcher2;
18282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
19b3e872be9e634c8d1f34d07778ea753880bbf2d9Deepanshu Guptaimport android.animation.AnimatorSet;
20d51834bdfad0cd3142ac464ab3a3b0db14f884c3Deepanshu Guptaimport android.animation.ObjectAnimator;
21282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.animation.ValueAnimator;
22282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.appwidget.AppWidgetHostView;
2337dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Guptaimport android.appwidget.AppWidgetManager;
24282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.appwidget.AppWidgetProviderInfo;
25282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.content.ComponentName;
26282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.content.Context;
27282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.content.Intent;
28282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.content.pm.PackageManager;
29282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.content.pm.ResolveInfo;
30282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.content.res.Configuration;
31282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.content.res.Resources;
32282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.content.res.TypedArray;
33282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.graphics.Bitmap;
34282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.graphics.Bitmap.Config;
35eaf1853b98d7bf2c3d693ad702050968ef0a404cDeepanshu Guptaimport android.graphics.Canvas;
36eaf1853b98d7bf2c3d693ad702050968ef0a404cDeepanshu Guptaimport android.graphics.ColorMatrix;
37282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.graphics.ColorMatrixColorFilter;
38282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.graphics.Insets;
39282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.graphics.MaskFilter;
40282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.graphics.Matrix;
414dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsenimport android.graphics.Paint;
42eb26f5cecd5366b29b3cb746a7edaf3769f40480Deepanshu Guptaimport android.graphics.PorterDuff;
43282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.graphics.Rect;
44282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.graphics.RectF;
45282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.graphics.Shader;
46282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.graphics.TableMaskFilter;
47ada8590547348b77d8cbd56abdb8fadb3e72c015Deepanshu Guptaimport android.graphics.drawable.BitmapDrawable;
48282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.graphics.drawable.Drawable;
49282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.os.AsyncTask;
50282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.os.Process;
51282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.util.AttributeSet;
52282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.util.Log;
53282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.view.Gravity;
54282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.view.KeyEvent;
55282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.view.LayoutInflater;
56d51834bdfad0cd3142ac464ab3a3b0db14f884c3Deepanshu Guptaimport android.view.MotionEvent;
57282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.view.View;
58282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.view.ViewGroup;
59282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.view.animation.AccelerateInterpolator;
60282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.view.animation.DecelerateInterpolator;
61e05f1c4684fcc7e3f6a429ff01b210aa19f75304Deepanshu Guptaimport android.widget.GridLayout;
62282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.widget.ImageView;
63282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.widget.LinearLayout;
64282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.widget.Toast;
65282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
66282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.launcher.R;
67664d6f1fe4d6dfa742b3e98051f924dbc190f8caDeepanshu Guptaimport com.android.launcher2.DropTarget.DragObject;
68282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
69b3e872be9e634c8d1f34d07778ea753880bbf2d9Deepanshu Guptaimport java.util.ArrayList;
70282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.util.Collections;
71282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.util.Iterator;
72b9b8aef94e5bad8f5f03f686a2d3d8a09c045a7bDeepanshu Guptaimport java.util.List;
73d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Guptaimport java.lang.ref.WeakReference;
74282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
75d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta/**
76282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * A simple callback interface which also provides the results of the task.
77d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta */
78e8a04cd5a68a5e5aa78a4f40b3269c86cc3f152fIan Pedowitzinterface AsyncTaskCallback {
79282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    void run(AppsCustomizeAsyncTask task, AsyncTaskPageData data);
80282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
81282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
82282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/**
83282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * The data needed to perform either of the custom AsyncTasks.
84282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
85282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiclass AsyncTaskPageData {
866e53931f49f49245deef8622eb8e7dc6ccf04536Jeff Brown    enum Type {
87282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        LoadWidgetPreviewData
88282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
89282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
90e64a5bd2fb54d84d6fd2119ef831df1eba4185ffDeepanshu Gupta    AsyncTaskPageData(int p, ArrayList<Object> l, ArrayList<Bitmap> si, AsyncTaskCallback bgR,
91282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            AsyncTaskCallback postR) {
92282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        page = p;
93282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        items = l;
94d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta        sourceImages = si;
95282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        generatedImages = new ArrayList<Bitmap>();
96282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        maxImageWidth = maxImageHeight = -1;
97282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        doInBackgroundCallback = bgR;
98282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        postExecuteCallback = postR;
99282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    AsyncTaskPageData(int p, ArrayList<Object> l, int cw, int ch, AsyncTaskCallback bgR,
101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            AsyncTaskCallback postR) {
102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        page = p;
103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        items = l;
104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        generatedImages = new ArrayList<Bitmap>();
105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        maxImageWidth = cw;
1062bc2daa74eef01135f717eadfab87538a9bef29fDeepanshu Gupta        maxImageHeight = ch;
1072bc2daa74eef01135f717eadfab87538a9bef29fDeepanshu Gupta        doInBackgroundCallback = bgR;
108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        postExecuteCallback = postR;
109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    void cleanup(boolean cancelled) {
11185d72c4535003af3b9df77bd6eaa2b33e8a7cba2Deepanshu Gupta        // Clean up any references to source/generated bitmaps
112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (sourceImages != null) {
113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (cancelled) {
1140ff4568ca07c16f2ad4c61872995200115292ecfDeepanshu Gupta                for (Bitmap b : sourceImages) {
11591253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta                    b.recycle();
1160ff4568ca07c16f2ad4c61872995200115292ecfDeepanshu Gupta                }
1170ff4568ca07c16f2ad4c61872995200115292ecfDeepanshu Gupta            }
1180ff4568ca07c16f2ad4c61872995200115292ecfDeepanshu Gupta            sourceImages.clear();
1190ff4568ca07c16f2ad4c61872995200115292ecfDeepanshu Gupta        }
1200ff4568ca07c16f2ad4c61872995200115292ecfDeepanshu Gupta        if (generatedImages != null) {
12191253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta            if (cancelled) {
122d51834bdfad0cd3142ac464ab3a3b0db14f884c3Deepanshu Gupta                for (Bitmap b : generatedImages) {
1230ff4568ca07c16f2ad4c61872995200115292ecfDeepanshu Gupta                    b.recycle();
124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            generatedImages.clear();
127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
12937dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta    int page;
130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ArrayList<Object> items;
131664d6f1fe4d6dfa742b3e98051f924dbc190f8caDeepanshu Gupta    ArrayList<Bitmap> sourceImages;
132d15459197f71f8cc940e2b057b399117df282f2cDiego Perez    ArrayList<Bitmap> generatedImages;
133d15459197f71f8cc940e2b057b399117df282f2cDiego Perez    int maxImageWidth;
134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int maxImageHeight;
135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    AsyncTaskCallback doInBackgroundCallback;
136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    AsyncTaskCallback postExecuteCallback;
13791253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta}
138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/**
140d758e042ce08c46712db3db2d63fc84795028dfeDeepanshu Gupta * A generic template for an async task used in AppsCustomize.
141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiclass AppsCustomizeAsyncTask extends AsyncTask<AsyncTaskPageData, Void, AsyncTaskPageData> {
143bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta    AppsCustomizeAsyncTask(int p, AsyncTaskPageData.Type ty) {
144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        page = p;
145eb26f5cecd5366b29b3cb746a7edaf3769f40480Deepanshu Gupta        threadPriority = Process.THREAD_PRIORITY_DEFAULT;
14691253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta        dataType = ty;
147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    protected AsyncTaskPageData doInBackground(AsyncTaskPageData... params) {
150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (params.length != 1) return null;
15191253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta        // Load each of the widget previews in the background
152dfeffd4c0ae165a3f225b818ef8d6f5d1cb89a2cDeepanshu Gupta        params[0].doInBackgroundCallback.run(this, params[0]);
153f8ea750455eec81e4e6d877b3e18e29a86d4ec95Deepanshu Gupta        return params[0];
154d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta    }
155490dd90c707de8426a068a90d74ec83c9c11fc83Deepanshu Gupta    @Override
156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    protected void onPostExecute(AsyncTaskPageData result) {
157b3e872be9e634c8d1f34d07778ea753880bbf2d9Deepanshu Gupta        // All the widget previews are loaded, so we can just callback to inflate the page
158b3e872be9e634c8d1f34d07778ea753880bbf2d9Deepanshu Gupta        result.postExecuteCallback.run(this, result);
159b3e872be9e634c8d1f34d07778ea753880bbf2d9Deepanshu Gupta    }
160b3e872be9e634c8d1f34d07778ea753880bbf2d9Deepanshu Gupta
161b3e872be9e634c8d1f34d07778ea753880bbf2d9Deepanshu Gupta    void setThreadPriority(int p) {
162b3e872be9e634c8d1f34d07778ea753880bbf2d9Deepanshu Gupta        threadPriority = p;
163b3e872be9e634c8d1f34d07778ea753880bbf2d9Deepanshu Gupta    }
16491253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta    void syncThreadPriority() {
165b3e872be9e634c8d1f34d07778ea753880bbf2d9Deepanshu Gupta        Process.setThreadPriority(threadPriority);
166b3e872be9e634c8d1f34d07778ea753880bbf2d9Deepanshu Gupta    }
167b3e872be9e634c8d1f34d07778ea753880bbf2d9Deepanshu Gupta
168b3e872be9e634c8d1f34d07778ea753880bbf2d9Deepanshu Gupta    // The page that this async task is associated with
169b3e872be9e634c8d1f34d07778ea753880bbf2d9Deepanshu Gupta    AsyncTaskPageData.Type dataType;
170b3e872be9e634c8d1f34d07778ea753880bbf2d9Deepanshu Gupta    int page;
171af0f3bda17ee3de4ad3560c9a675527b20e2af5fSiva Velusamy    int threadPriority;
172af0f3bda17ee3de4ad3560c9a675527b20e2af5fSiva Velusamy}
173b3e872be9e634c8d1f34d07778ea753880bbf2d9Deepanshu Gupta
174b3e872be9e634c8d1f34d07778ea753880bbf2d9Deepanshu Guptaabstract class WeakReferenceThreadLocal<T> {
175b3e872be9e634c8d1f34d07778ea753880bbf2d9Deepanshu Gupta    private ThreadLocal<WeakReference<T>> mThreadLocal;
176b3e872be9e634c8d1f34d07778ea753880bbf2d9Deepanshu Gupta    public WeakReferenceThreadLocal() {
177b3e872be9e634c8d1f34d07778ea753880bbf2d9Deepanshu Gupta        mThreadLocal = new ThreadLocal<WeakReference<T>>();
178b3e872be9e634c8d1f34d07778ea753880bbf2d9Deepanshu Gupta    }
179f8ea750455eec81e4e6d877b3e18e29a86d4ec95Deepanshu Gupta
180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    abstract T initialValue();
181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public void set(T t) {
183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mThreadLocal.set(new WeakReference<T>(t));
184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public T get() {
187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        WeakReference<T> reference = mThreadLocal.get();
188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        T obj;
189d51834bdfad0cd3142ac464ab3a3b0db14f884c3Deepanshu Gupta        if (reference == null) {
19037dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta            obj = initialValue();
191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mThreadLocal.set(new WeakReference<T>(obj));
1928930cb4f37ff0fbde65f7afd4bbe06ab77677f78Deepanshu Gupta            return obj;
1938930cb4f37ff0fbde65f7afd4bbe06ab77677f78Deepanshu Gupta        } else {
194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            obj = reference.get();
195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (obj == null) {
19637dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta                obj = initialValue();
197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                mThreadLocal.set(new WeakReference<T>(obj));
198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return obj;
2002ea852541fd7c7af14b6919c5c2f57584b896d2bDeepanshu Gupta        }
2012ea852541fd7c7af14b6919c5c2f57584b896d2bDeepanshu Gupta    }
2022ea852541fd7c7af14b6919c5c2f57584b896d2bDeepanshu Gupta}
2032ea852541fd7c7af14b6919c5c2f57584b896d2bDeepanshu Gupta
2042ea852541fd7c7af14b6919c5c2f57584b896d2bDeepanshu Guptaclass CanvasCache extends WeakReferenceThreadLocal<Canvas> {
2052ea852541fd7c7af14b6919c5c2f57584b896d2bDeepanshu Gupta    @Override
206d51834bdfad0cd3142ac464ab3a3b0db14f884c3Deepanshu Gupta    protected Canvas initialValue() {
207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return new Canvas();
208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2108930cb4f37ff0fbde65f7afd4bbe06ab77677f78Deepanshu Gupta
2118930cb4f37ff0fbde65f7afd4bbe06ab77677f78Deepanshu Guptaclass PaintCache extends WeakReferenceThreadLocal<Paint> {
2128930cb4f37ff0fbde65f7afd4bbe06ab77677f78Deepanshu Gupta    @Override
213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    protected Paint initialValue() {
214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return null;
215664d6f1fe4d6dfa742b3e98051f924dbc190f8caDeepanshu Gupta    }
216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiclass BitmapCache extends WeakReferenceThreadLocal<Bitmap> {
219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
22037dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta    protected Bitmap initialValue() {
221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return null;
222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiclass RectCache extends WeakReferenceThreadLocal<Rect> {
226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
227e05f1c4684fcc7e3f6a429ff01b210aa19f75304Deepanshu Gupta    protected Rect initialValue() {
228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return new Rect();
229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
23237dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta/**
233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * The Apps/Customize page that displays all the applications, widgets, and shortcuts.
234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskipublic class AppsCustomizePagedView extends PagedViewWithDraggableItems implements
236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        AllAppsView, View.OnClickListener, View.OnKeyListener, DragSource,
237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        PagedViewIcon.PressedCallback, PagedViewWidget.ShortPressListener,
238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        LauncherTransitionable {
239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    static final String TAG = "AppsCustomizePagedView";
240e05f1c4684fcc7e3f6a429ff01b210aa19f75304Deepanshu Gupta
241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * The different content types that this paged view can show.
243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public enum ContentType {
245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Applications,
246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Widgets
247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Refs
250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private Launcher mLauncher;
251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private DragController mDragController;
252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final LayoutInflater mLayoutInflater;
253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final PackageManager mPackageManager;
254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2550ff4568ca07c16f2ad4c61872995200115292ecfDeepanshu Gupta    // Save and Restore
2560ff4568ca07c16f2ad4c61872995200115292ecfDeepanshu Gupta    private int mSaveInstanceStateItemIndex = -1;
2570ff4568ca07c16f2ad4c61872995200115292ecfDeepanshu Gupta    private PagedViewIcon mPressedIcon;
2580ff4568ca07c16f2ad4c61872995200115292ecfDeepanshu Gupta
2590ff4568ca07c16f2ad4c61872995200115292ecfDeepanshu Gupta    // Content
2600ff4568ca07c16f2ad4c61872995200115292ecfDeepanshu Gupta    private ArrayList<ApplicationInfo> mApps;
2610ff4568ca07c16f2ad4c61872995200115292ecfDeepanshu Gupta    private ArrayList<Object> mWidgets;
2620ff4568ca07c16f2ad4c61872995200115292ecfDeepanshu Gupta
263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Cling
264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private boolean mHasShownAllAppsCling;
265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private int mClingFocusedX;
266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private int mClingFocusedY;
267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Caching
269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private Canvas mCanvas;
270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private Drawable mDefaultWidgetBackground;
27137dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta    private IconCache mIconCache;
27237dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta
273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Dimens
274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private int mContentWidth;
275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private int mAppIconSize;
276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private int mMaxAppCellCountX, mMaxAppCellCountY;
277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private int mWidgetCountX, mWidgetCountY;
278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private int mWidgetWidthGap, mWidgetHeightGap;
279eaf1853b98d7bf2c3d693ad702050968ef0a404cDeepanshu Gupta    private final float sWidgetPreviewIconPaddingPercentage = 0.25f;
280eaf1853b98d7bf2c3d693ad702050968ef0a404cDeepanshu Gupta    private PagedViewCellLayout mWidgetSpacingLayout;
281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private int mNumAppsPages;
282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private int mNumWidgetPages;
283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Relating to the scroll and overscroll effects
285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Workspace.ZInterpolator mZInterpolator = new Workspace.ZInterpolator(0.5f);
286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private static float CAMERA_DISTANCE = 6500;
287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private static float TRANSITION_SCALE_FACTOR = 0.74f;
288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private static float TRANSITION_PIVOT = 0.65f;
289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private static float TRANSITION_MAX_ROTATION = 22;
290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private static final boolean PERFORM_OVERSCROLL_ROTATION = true;
291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private AccelerateInterpolator mAlphaInterpolator = new AccelerateInterpolator(0.9f);
292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private DecelerateInterpolator mLeftScreenAlphaInterpolator = new DecelerateInterpolator(4);
293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Previews & outlines
295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ArrayList<AppsCustomizeAsyncTask> mRunningTasks;
296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private static final int sPageSleepDelay = 200;
297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private Runnable mInflateWidgetRunnable = null;
299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private Runnable mBindWidgetRunnable = null;
300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    static final int WIDGET_NO_CLEANUP_REQUIRED = -1;
301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    static final int WIDGET_PRELOAD_PENDING = 0;
302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    static final int WIDGET_BOUND = 1;
303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    static final int WIDGET_INFLATED = 2;
304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int mWidgetCleanupState = WIDGET_NO_CLEANUP_REQUIRED;
305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int mWidgetLoadingId = -1;
306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    PendingAddWidgetInfo mCreateWidgetInfo = null;
307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private boolean mDraggingWidget = false;
308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Deferral of loading widget previews during launcher transitions
310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private boolean mInTransition;
311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private ArrayList<AsyncTaskPageData> mDeferredSyncWidgetPageItems =
312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        new ArrayList<AsyncTaskPageData>();
313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private ArrayList<Runnable> mDeferredPrepareLoadWidgetPreviewsTasks =
314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        new ArrayList<Runnable>();
315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Used for drawing shortcut previews
317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    BitmapCache mCachedShortcutPreviewBitmap = new BitmapCache();
318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    PaintCache mCachedShortcutPreviewPaint = new PaintCache();
319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    CanvasCache mCachedShortcutPreviewCanvas = new CanvasCache();
320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Used for drawing widget previews
322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    CanvasCache mCachedAppWidgetPreviewCanvas = new CanvasCache();
323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    RectCache mCachedAppWidgetPreviewSrcRect = new RectCache();
324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    RectCache mCachedAppWidgetPreviewDestRect = new RectCache();
325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    PaintCache mCachedAppWidgetPreviewPaint = new PaintCache();
326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
32791253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta    public AppsCustomizePagedView(Context context, AttributeSet attrs) {
32891253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta        super(context, attrs);
329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mLayoutInflater = LayoutInflater.from(context);
330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mPackageManager = context.getPackageManager();
33191253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta        mApps = new ArrayList<ApplicationInfo>();
332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mWidgets = new ArrayList<Object>();
333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mIconCache = ((LauncherApplication) context.getApplicationContext()).getIconCache();
334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mCanvas = new Canvas();
335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mRunningTasks = new ArrayList<AppsCustomizeAsyncTask>();
336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Save the default widget preview background
338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Resources resources = context.getResources();
339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mDefaultWidgetBackground = resources.getDrawable(R.drawable.default_widget_preview_holo);
340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mAppIconSize = resources.getDimensionPixelSize(R.dimen.app_icon_size);
341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AppsCustomizePagedView, 0, 0);
343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mMaxAppCellCountX = a.getInt(R.styleable.AppsCustomizePagedView_maxAppCellCountX, -1);
344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mMaxAppCellCountY = a.getInt(R.styleable.AppsCustomizePagedView_maxAppCellCountY, -1);
345b6864ac6cde109be320e18188209eb8420c585f1Deepanshu Gupta        mWidgetWidthGap =
346b6864ac6cde109be320e18188209eb8420c585f1Deepanshu Gupta            a.getDimensionPixelSize(R.styleable.AppsCustomizePagedView_widgetCellWidthGap, 0);
347b6864ac6cde109be320e18188209eb8420c585f1Deepanshu Gupta        mWidgetHeightGap =
348b6864ac6cde109be320e18188209eb8420c585f1Deepanshu Gupta            a.getDimensionPixelSize(R.styleable.AppsCustomizePagedView_widgetCellHeightGap, 0);
349b6864ac6cde109be320e18188209eb8420c585f1Deepanshu Gupta        mWidgetCountX = a.getInt(R.styleable.AppsCustomizePagedView_widgetCountX, 2);
350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mWidgetCountY = a.getInt(R.styleable.AppsCustomizePagedView_widgetCountY, 2);
351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mClingFocusedX = a.getInt(R.styleable.AppsCustomizePagedView_clingFocusedX, 0);
352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mClingFocusedY = a.getInt(R.styleable.AppsCustomizePagedView_clingFocusedY, 0);
3532bc2daa74eef01135f717eadfab87538a9bef29fDeepanshu Gupta        a.recycle();
354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mWidgetSpacingLayout = new PagedViewCellLayout(getContext());
355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // The padding on the non-matched dimension for the default widget preview icons
357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // (top + bottom)
358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mFadeInAdjacentScreens = false;
359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Unless otherwise specified this view is important for accessibility.
361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    protected void init() {
368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        super.init();
369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mCenterPagesVertically = false;
370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Context context = getContext();
372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Resources r = context.getResources();
373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        setDragSlopeThreshold(r.getInteger(R.integer.config_appsCustomizeDragSlopeThreshold)/100f);
374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    protected void onUnhandledTap(MotionEvent ev) {
378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (LauncherApplication.isScreenLarge()) {
379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Dismiss AppsCustomize if we tap
380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mLauncher.showWorkspace(true);
381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /** Returns the item index of the center item on this page so that we can restore to this
385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *  item index when we rotate. */
386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private int getMiddleComponentIndexOnCurrentPage() {
38737dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta        int i = -1;
38837dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta        if (getPageCount() > 0) {
389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int currentPage = getCurrentPage();
390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (currentPage < mNumAppsPages) {
391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                PagedViewCellLayout layout = (PagedViewCellLayout) getPageAt(currentPage);
392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                PagedViewCellLayoutChildren childrenLayout = layout.getChildrenLayout();
393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                int numItemsPerPage = mCellCountX * mCellCountY;
394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                int childCount = childrenLayout.getChildCount();
395bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta                if (childCount > 0) {
396bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta                    i = (currentPage * numItemsPerPage) + (childCount / 2);
397bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta                }
398bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta            } else {
399bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta                int numApps = mApps.size();
400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                PagedViewGridLayout layout = (PagedViewGridLayout) getPageAt(currentPage);
401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                int numItemsPerPage = mWidgetCountX * mWidgetCountY;
402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                int childCount = layout.getChildCount();
403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (childCount > 0) {
404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    i = numApps +
405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ((currentPage - mNumAppsPages) * numItemsPerPage) + (childCount / 2);
406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
4079fa48b09ad06c39be0923d5ca64b81f6b0eee993Deepanshu Gupta            }
408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return i;
410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /** Get the index of the item to restore to if we need to restore the current page. */
413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int getSaveInstanceStateIndex() {
414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (mSaveInstanceStateItemIndex == -1) {
415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mSaveInstanceStateItemIndex = getMiddleComponentIndexOnCurrentPage();
416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return mSaveInstanceStateItemIndex;
41891fa3ba4cc8acd4caeeb88f90ce39198b5fea414Diego Perez    }
419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /** Returns the page in the current orientation which is expected to contain the specified
421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *  item index. */
422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int getPageForComponent(int index) {
423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (index < 0) return 0;
424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (index < mApps.size()) {
426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int numItemsPerPage = mCellCountX * mCellCountY;
427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return (index / numItemsPerPage);
428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int numItemsPerPage = mWidgetCountX * mWidgetCountY;
430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return mNumAppsPages + ((index - mApps.size()) / numItemsPerPage);
431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
434282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /** Restores the page for an item at the specified index */
435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    void restorePageForIndex(int index) {
436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (index < 0) return;
437282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mSaveInstanceStateItemIndex = index;
438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private void updatePageCounts() {
441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mNumWidgetPages = (int) Math.ceil(mWidgets.size() /
442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                (float) (mWidgetCountX * mWidgetCountY));
443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mNumAppsPages = (int) Math.ceil((float) mApps.size() / (mCellCountX * mCellCountY));
444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
445e91096c03dda225240b1487f019bf3d082854587Deepanshu Gupta
446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    protected void onDataReady(int width, int height) {
447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Note that we transpose the counts in portrait so that we get a similar layout
448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        boolean isLandscape = getResources().getConfiguration().orientation ==
449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Configuration.ORIENTATION_LANDSCAPE;
450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int maxCellCountX = Integer.MAX_VALUE;
451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int maxCellCountY = Integer.MAX_VALUE;
452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (LauncherApplication.isScreenLarge()) {
453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            maxCellCountX = (isLandscape ? LauncherModel.getCellCountX() :
454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                LauncherModel.getCellCountY());
455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            maxCellCountY = (isLandscape ? LauncherModel.getCellCountY() :
45691fa3ba4cc8acd4caeeb88f90ce39198b5fea414Diego Perez                LauncherModel.getCellCountX());
457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (mMaxAppCellCountX > -1) {
459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            maxCellCountX = Math.min(maxCellCountX, mMaxAppCellCountX);
460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (mMaxAppCellCountY > -1) {
462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            maxCellCountY = Math.min(maxCellCountY, mMaxAppCellCountY);
463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Now that the data is ready, we can calculate the content width, the number of cells to
466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // use for each page
467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mWidgetSpacingLayout.setGap(mPageLayoutWidthGap, mPageLayoutHeightGap);
468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mWidgetSpacingLayout.setPadding(mPageLayoutPaddingLeft, mPageLayoutPaddingTop,
469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                mPageLayoutPaddingRight, mPageLayoutPaddingBottom);
470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mWidgetSpacingLayout.calculateCellCount(width, height, maxCellCountX, maxCellCountY);
471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mCellCountX = mWidgetSpacingLayout.getCellCountX();
472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mCellCountY = mWidgetSpacingLayout.getCellCountY();
473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        updatePageCounts();
474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Force a measure to update recalculate the gaps
476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int widthSpec = MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.AT_MOST);
477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int heightSpec = MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.AT_MOST);
478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mWidgetSpacingLayout.measure(widthSpec, heightSpec);
47991fa3ba4cc8acd4caeeb88f90ce39198b5fea414Diego Perez        mContentWidth = mWidgetSpacingLayout.getContentWidth();
480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        AppsCustomizeTabHost host = (AppsCustomizeTabHost) getTabHost();
482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        final boolean hostIsTransitioning = host.isTransitioning();
483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Restore the page
485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int page = getPageForComponent(mSaveInstanceStateItemIndex);
48637dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta        invalidatePageData(Math.max(0, page), hostIsTransitioning);
487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
48837dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta        // Show All Apps cling if we are finished transitioning, otherwise, we will try again when
489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // the transition completes in AppsCustomizeTabHost (otherwise the wrong offsets will be
490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // returned while animating)
491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!hostIsTransitioning) {
492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            post(new Runnable() {
493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                @Override
494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                public void run() {
495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    showAllAppsCling();
496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            });
498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    void showAllAppsCling() {
502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!mHasShownAllAppsCling && isDataReady()) {
503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mHasShownAllAppsCling = true;
504282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Calculate the position for the cling punch through
505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int[] offset = new int[2];
506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int[] pos = mWidgetSpacingLayout.estimateCellPosition(mClingFocusedX, mClingFocusedY);
5076330971ed293a2777bbdab09288f90ea4b2d0255Deepanshu Gupta            mLauncher.getDragLayer().getLocationInDragLayer(this, offset);
5086330971ed293a2777bbdab09288f90ea4b2d0255Deepanshu Gupta            // PagedViews are centered horizontally but top aligned
5096330971ed293a2777bbdab09288f90ea4b2d0255Deepanshu Gupta            pos[0] += (getMeasuredWidth() - mWidgetSpacingLayout.getMeasuredWidth()) / 2 +
5106330971ed293a2777bbdab09288f90ea4b2d0255Deepanshu Gupta                    offset[0];
5116330971ed293a2777bbdab09288f90ea4b2d0255Deepanshu Gupta            pos[1] += offset[1];
5126330971ed293a2777bbdab09288f90ea4b2d0255Deepanshu Gupta            mLauncher.showFirstRunAllAppsCling(pos);
5136330971ed293a2777bbdab09288f90ea4b2d0255Deepanshu Gupta        }
5146330971ed293a2777bbdab09288f90ea4b2d0255Deepanshu Gupta    }
5156330971ed293a2777bbdab09288f90ea4b2d0255Deepanshu Gupta
5166330971ed293a2777bbdab09288f90ea4b2d0255Deepanshu Gupta    @Override
5176330971ed293a2777bbdab09288f90ea4b2d0255Deepanshu Gupta    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
5186330971ed293a2777bbdab09288f90ea4b2d0255Deepanshu Gupta        int width = MeasureSpec.getSize(widthMeasureSpec);
5196330971ed293a2777bbdab09288f90ea4b2d0255Deepanshu Gupta        int height = MeasureSpec.getSize(heightMeasureSpec);
5206330971ed293a2777bbdab09288f90ea4b2d0255Deepanshu Gupta        if (!isDataReady()) {
521f8ea750455eec81e4e6d877b3e18e29a86d4ec95Deepanshu Gupta            if (!mApps.isEmpty() && !mWidgets.isEmpty()) {
522f8ea750455eec81e4e6d877b3e18e29a86d4ec95Deepanshu Gupta                setDataIsReady();
523f8ea750455eec81e4e6d877b3e18e29a86d4ec95Deepanshu Gupta                setMeasuredDimension(width, height);
524f8ea750455eec81e4e6d877b3e18e29a86d4ec95Deepanshu Gupta                onDataReady(width, height);
525f8ea750455eec81e4e6d877b3e18e29a86d4ec95Deepanshu Gupta            }
526f8ea750455eec81e4e6d877b3e18e29a86d4ec95Deepanshu Gupta        }
527f8ea750455eec81e4e6d877b3e18e29a86d4ec95Deepanshu Gupta
528f8ea750455eec81e4e6d877b3e18e29a86d4ec95Deepanshu Gupta        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
529f8ea750455eec81e4e6d877b3e18e29a86d4ec95Deepanshu Gupta    }
530f8ea750455eec81e4e6d877b3e18e29a86d4ec95Deepanshu Gupta
531f8ea750455eec81e4e6d877b3e18e29a86d4ec95Deepanshu Gupta    public void onPackagesUpdated() {
532f8ea750455eec81e4e6d877b3e18e29a86d4ec95Deepanshu Gupta        // TODO: this isn't ideal, but we actually need to delay here. This call is triggered
533f8ea750455eec81e4e6d877b3e18e29a86d4ec95Deepanshu Gupta        // by a broadcast receiver, and in order for it to work correctly, we need to know that
534f8ea750455eec81e4e6d877b3e18e29a86d4ec95Deepanshu Gupta        // the AppWidgetService has already received and processed the same broadcast. Since there
535f8ea750455eec81e4e6d877b3e18e29a86d4ec95Deepanshu Gupta        // is no guarantee about ordering of broadcast receipt, we just delay here. This is a
536282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // workaround until we add a callback from AppWidgetService to AppWidgetHost when widget
537282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // packages are added, updated or removed.
538282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        postDelayed(new Runnable() {
539282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski           public void run() {
540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski               updatePackages();
541282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski           }
542282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }, 1500);
543282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
545282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public void updatePackages() {
546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Get the list of widgets and shortcuts
547282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mWidgets.clear();
548282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        List<AppWidgetProviderInfo> widgets =
549282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            AppWidgetManager.getInstance(mLauncher).getInstalledProviders();
550282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Intent shortcutsIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT);
551282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        List<ResolveInfo> shortcuts = mPackageManager.queryIntentActivities(shortcutsIntent, 0);
552282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (AppWidgetProviderInfo widget : widgets) {
553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (widget.minWidth > 0 && widget.minHeight > 0) {
554282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Ensure that all widgets we show can be added on a workspace of this size
555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                int[] spanXY = Launcher.getSpanForWidget(mLauncher, widget);
556282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                int[] minSpanXY = Launcher.getMinSpanForWidget(mLauncher, widget);
557282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                int minSpanX = Math.min(spanXY[0], minSpanXY[0]);
558282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                int minSpanY = Math.min(spanXY[1], minSpanXY[1]);
559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (minSpanX <= LauncherModel.getCellCountX() &&
560282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        minSpanY <= LauncherModel.getCellCountY()) {
561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    mWidgets.add(widget);
562664d6f1fe4d6dfa742b3e98051f924dbc190f8caDeepanshu Gupta                } else {
563664d6f1fe4d6dfa742b3e98051f924dbc190f8caDeepanshu Gupta                    Log.e(TAG, "Widget " + widget.provider + " can not fit on this device (" +
564664d6f1fe4d6dfa742b3e98051f924dbc190f8caDeepanshu Gupta                            widget.minWidth + ", " + widget.minHeight + ")");
565664d6f1fe4d6dfa742b3e98051f924dbc190f8caDeepanshu Gupta                }
566e64a5bd2fb54d84d6fd2119ef831df1eba4185ffDeepanshu Gupta            } else {
567e64a5bd2fb54d84d6fd2119ef831df1eba4185ffDeepanshu Gupta                Log.e(TAG, "Widget " + widget.provider + " has invalid dimensions (" +
568e64a5bd2fb54d84d6fd2119ef831df1eba4185ffDeepanshu Gupta                        widget.minWidth + ", " + widget.minHeight + ")");
569e64a5bd2fb54d84d6fd2119ef831df1eba4185ffDeepanshu Gupta            }
570282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mWidgets.addAll(shortcuts);
572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Collections.sort(mWidgets,
5736e53931f49f49245deef8622eb8e7dc6ccf04536Jeff Brown                new LauncherModel.WidgetAndShortcutNameComparator(mPackageManager));
5746e53931f49f49245deef8622eb8e7dc6ccf04536Jeff Brown        updatePageCounts();
5756e53931f49f49245deef8622eb8e7dc6ccf04536Jeff Brown        invalidateOnDataChange();
5766e53931f49f49245deef8622eb8e7dc6ccf04536Jeff Brown    }
5776e53931f49f49245deef8622eb8e7dc6ccf04536Jeff Brown
5786e53931f49f49245deef8622eb8e7dc6ccf04536Jeff Brown    @Override
5796e53931f49f49245deef8622eb8e7dc6ccf04536Jeff Brown    public void onClick(View v) {
5806e53931f49f49245deef8622eb8e7dc6ccf04536Jeff Brown        // When we have exited all apps or are in transition, disregard clicks
5816e53931f49f49245deef8622eb8e7dc6ccf04536Jeff Brown        if (!mLauncher.isAllAppsCustomizeOpen() ||
5826e53931f49f49245deef8622eb8e7dc6ccf04536Jeff Brown                mLauncher.getWorkspace().isSwitchingState()) return;
5836e53931f49f49245deef8622eb8e7dc6ccf04536Jeff Brown
5846e53931f49f49245deef8622eb8e7dc6ccf04536Jeff Brown        if (v instanceof PagedViewIcon) {
5856e53931f49f49245deef8622eb8e7dc6ccf04536Jeff Brown            // Animate some feedback to the click
5866e53931f49f49245deef8622eb8e7dc6ccf04536Jeff Brown            final ApplicationInfo appInfo = (ApplicationInfo) v.getTag();
5876e53931f49f49245deef8622eb8e7dc6ccf04536Jeff Brown
5886e53931f49f49245deef8622eb8e7dc6ccf04536Jeff Brown            // Lock the drawable state to pressed until we return to Launcher
5896e53931f49f49245deef8622eb8e7dc6ccf04536Jeff Brown            if (mPressedIcon != null) {
5906e53931f49f49245deef8622eb8e7dc6ccf04536Jeff Brown                mPressedIcon.lockDrawableState();
5916e53931f49f49245deef8622eb8e7dc6ccf04536Jeff Brown            }
5926e53931f49f49245deef8622eb8e7dc6ccf04536Jeff Brown
5936e53931f49f49245deef8622eb8e7dc6ccf04536Jeff Brown            // NOTE: We want all transitions from launcher to act as if the wallpaper were enabled
5946e53931f49f49245deef8622eb8e7dc6ccf04536Jeff Brown            // to be consistent.  So re-enable the flag here, and we will re-disable it as necessary
5956e53931f49f49245deef8622eb8e7dc6ccf04536Jeff Brown            // when Launcher resumes and we are still in AllApps.
5966e53931f49f49245deef8622eb8e7dc6ccf04536Jeff Brown            mLauncher.updateWallpaperVisibility(true);
5976e53931f49f49245deef8622eb8e7dc6ccf04536Jeff Brown            mLauncher.startActivitySafely(v, appInfo.intent, appInfo);
5986e53931f49f49245deef8622eb8e7dc6ccf04536Jeff Brown
5996e53931f49f49245deef8622eb8e7dc6ccf04536Jeff Brown        } else if (v instanceof PagedViewWidget) {
6006e53931f49f49245deef8622eb8e7dc6ccf04536Jeff Brown            // Let the user know that they have to long press to add a widget
601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Toast.makeText(getContext(), R.string.long_press_widget_to_add,
602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    Toast.LENGTH_SHORT).show();
6034a605c6fa0027ee116beb29fbc9625721f0441f0Deepanshu Gupta
60491253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta            // Create a little animation to show that the widget can move
605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float offsetY = getResources().getDimensionPixelSize(R.dimen.dragViewOffsetY);
606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            final ImageView p = (ImageView) v.findViewById(R.id.widget_preview);
607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            AnimatorSet bounce = new AnimatorSet();
60891253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta            ValueAnimator tyuAnim = ObjectAnimator.ofFloat(p, "translationY", offsetY);
609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            tyuAnim.setDuration(125);
610e64a5bd2fb54d84d6fd2119ef831df1eba4185ffDeepanshu Gupta            ValueAnimator tydAnim = ObjectAnimator.ofFloat(p, "translationY", 0f);
611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            tydAnim.setDuration(100);
61291253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta            bounce.play(tyuAnim).before(tydAnim);
61391253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta            bounce.setInterpolator(new AccelerateInterpolator());
614e64a5bd2fb54d84d6fd2119ef831df1eba4185ffDeepanshu Gupta            bounce.start();
615e64a5bd2fb54d84d6fd2119ef831df1eba4185ffDeepanshu Gupta        }
616e64a5bd2fb54d84d6fd2119ef831df1eba4185ffDeepanshu Gupta    }
61791253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta
618e64a5bd2fb54d84d6fd2119ef831df1eba4185ffDeepanshu Gupta    public boolean onKey(View v, int keyCode, KeyEvent event) {
619e64a5bd2fb54d84d6fd2119ef831df1eba4185ffDeepanshu Gupta        return FocusHelper.handleAppsCustomizeKeyEvent(v,  keyCode, event);
620e64a5bd2fb54d84d6fd2119ef831df1eba4185ffDeepanshu Gupta    }
6218657baa06d2efe845cafef571bd9dce627cf5045Deepanshu Gupta
6228657baa06d2efe845cafef571bd9dce627cf5045Deepanshu Gupta    /*
623e64a5bd2fb54d84d6fd2119ef831df1eba4185ffDeepanshu Gupta     * PagedViewWithDraggableItems implementation
624e64a5bd2fb54d84d6fd2119ef831df1eba4185ffDeepanshu Gupta     */
625e64a5bd2fb54d84d6fd2119ef831df1eba4185ffDeepanshu Gupta    @Override
626282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    protected void determineDraggingStart(android.view.MotionEvent ev) {
627282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Disable dragging by pulling an app down for now.
628282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
62991253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta
630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private void beginDraggingApplication(View v) {
631282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mLauncher.getWorkspace().onDragStartedWithItem(v);
632eb26f5cecd5366b29b3cb746a7edaf3769f40480Deepanshu Gupta        mLauncher.getWorkspace().beginDragShared(v, this);
633282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
63491253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta
63591253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta    private void preloadWidget(final PendingAddWidgetInfo info) {
636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        final AppWidgetProviderInfo pInfo = info.info;
63791253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta        if (pInfo.configure != null) {
63891253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta            return;
63991253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta        }
640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
64191253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta        mWidgetCleanupState = WIDGET_PRELOAD_PENDING;
64291253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta        mBindWidgetRunnable = new Runnable() {
6438cdf61a02e4652d53560c9758b8b15e76c50bfd7Diego Perez            @Override
6448cdf61a02e4652d53560c9758b8b15e76c50bfd7Diego Perez            public void run() {
64591253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta                mWidgetLoadingId = mLauncher.getAppWidgetHost().allocateAppWidgetId();
64691253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta                if (AppWidgetManager.getInstance(mLauncher)
64791253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta                            .bindAppWidgetIdIfAllowed(mWidgetLoadingId, info.componentName)) {
64891253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta                    mWidgetCleanupState = WIDGET_BOUND;
64991253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta                }
65091253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta            }
65191253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta        };
65291253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta        post(mBindWidgetRunnable);
65391253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta
65491253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta        mInflateWidgetRunnable = new Runnable() {
65591253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta            @Override
656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public void run() {
657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                AppWidgetHostView hostView = mLauncher.
658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        getAppWidgetHost().createView(getContext(), mWidgetLoadingId, pInfo);
6594a605c6fa0027ee116beb29fbc9625721f0441f0Deepanshu Gupta                info.boundWidget = hostView;
660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                mWidgetCleanupState = WIDGET_INFLATED;
661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                hostView.setVisibility(INVISIBLE);
662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                int[] unScaledSize = mLauncher.getWorkspace().estimateItemSize(info.spanX,
663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        info.spanY, info, false);
6644a605c6fa0027ee116beb29fbc9625721f0441f0Deepanshu Gupta
665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // We want the first widget layout to be the correct size. This will be important
666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // for width size reporting to the AppWidgetManager.
66791253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta                DragLayer.LayoutParams lp = new DragLayer.LayoutParams(unScaledSize[0],
668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        unScaledSize[1]);
669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                lp.x = lp.y = 0;
670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                lp.customPosition = true;
671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                hostView.setLayoutParams(lp);
67285d72c4535003af3b9df77bd6eaa2b33e8a7cba2Deepanshu Gupta                mLauncher.getDragLayer().addView(hostView);
673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        };
675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        post(mInflateWidgetRunnable);
676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
677282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
679282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public void onShortPress(View v) {
680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // We are anticipating a long press, and we use this time to load bind and instantiate
68191253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta        // the widget. This will need to be cleaned up if it turns out no long press occurs.
682282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (mCreateWidgetInfo != null) {
683282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Just in case the cleanup process wasn't properly executed. This shouldn't happen.
684282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            cleanupWidgetPreloading(false);
685282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
686282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mCreateWidgetInfo = new PendingAddWidgetInfo((PendingAddWidgetInfo) v.getTag());
687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        preloadWidget(mCreateWidgetInfo);
688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private void cleanupWidgetPreloading(boolean widgetWasAdded) {
691282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!widgetWasAdded) {
692282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // If the widget was not added, we may need to do further cleanup.
69385d72c4535003af3b9df77bd6eaa2b33e8a7cba2Deepanshu Gupta            PendingAddWidgetInfo info = mCreateWidgetInfo;
694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mCreateWidgetInfo = null;
695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (mWidgetCleanupState == WIDGET_PRELOAD_PENDING) {
697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // We never did any preloading, so just remove pending callbacks to do so
698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                removeCallbacks(mBindWidgetRunnable);
699e05f1c4684fcc7e3f6a429ff01b210aa19f75304Deepanshu Gupta                removeCallbacks(mInflateWidgetRunnable);
700e05f1c4684fcc7e3f6a429ff01b210aa19f75304Deepanshu Gupta            } else if (mWidgetCleanupState == WIDGET_BOUND) {
701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 // Delete the widget id which was allocated
702282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (mWidgetLoadingId != -1) {
703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    mLauncher.getAppWidgetHost().deleteAppWidgetId(mWidgetLoadingId);
704282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
70585d72c4535003af3b9df77bd6eaa2b33e8a7cba2Deepanshu Gupta
706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // We never got around to inflating the widget, so remove the callback to do so.
707282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                removeCallbacks(mInflateWidgetRunnable);
708282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (mWidgetCleanupState == WIDGET_INFLATED) {
709282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Delete the widget id which was allocated
710282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (mWidgetLoadingId != -1) {
711fba1dd24bf7b56071490ac62428f96d14f682244Deepanshu Gupta                    mLauncher.getAppWidgetHost().deleteAppWidgetId(mWidgetLoadingId);
712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
714282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // The widget was inflated and added to the DragLayer -- remove it.
715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                AppWidgetHostView widget = info.boundWidget;
716282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                mLauncher.getDragLayer().removeView(widget);
717282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
718282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
719282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mWidgetCleanupState = WIDGET_NO_CLEANUP_REQUIRED;
720282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mWidgetLoadingId = -1;
721282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mCreateWidgetInfo = null;
722282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        PagedViewWidget.resetShortPressTarget();
723282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
724282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
725282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
726282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public void cleanUpShortPress(View v) {
727282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!mDraggingWidget) {
72885d72c4535003af3b9df77bd6eaa2b33e8a7cba2Deepanshu Gupta            cleanupWidgetPreloading(false);
72985d72c4535003af3b9df77bd6eaa2b33e8a7cba2Deepanshu Gupta        }
73085d72c4535003af3b9df77bd6eaa2b33e8a7cba2Deepanshu Gupta    }
73185d72c4535003af3b9df77bd6eaa2b33e8a7cba2Deepanshu Gupta
73285d72c4535003af3b9df77bd6eaa2b33e8a7cba2Deepanshu Gupta    private boolean beginDraggingWidget(View v) {
73385d72c4535003af3b9df77bd6eaa2b33e8a7cba2Deepanshu Gupta        mDraggingWidget = true;
73485d72c4535003af3b9df77bd6eaa2b33e8a7cba2Deepanshu Gupta        // Get the widget preview as the drag representation
73579c59fe4a8544bdda5c56efecf9c2bc72f2f0e4eDeepanshu Gupta        ImageView image = (ImageView) v.findViewById(R.id.widget_preview);
736282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        PendingAddItemInfo createItemInfo = (PendingAddItemInfo) v.getTag();
73785d72c4535003af3b9df77bd6eaa2b33e8a7cba2Deepanshu Gupta
73879c59fe4a8544bdda5c56efecf9c2bc72f2f0e4eDeepanshu Gupta        // If the ImageView doesn't have a drawable yet, the widget preview hasn't been loaded and
73985d72c4535003af3b9df77bd6eaa2b33e8a7cba2Deepanshu Gupta        // we abort the drag.
740282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (image.getDrawable() == null) {
74185d72c4535003af3b9df77bd6eaa2b33e8a7cba2Deepanshu Gupta            mDraggingWidget = false;
74285d72c4535003af3b9df77bd6eaa2b33e8a7cba2Deepanshu Gupta            return false;
74385d72c4535003af3b9df77bd6eaa2b33e8a7cba2Deepanshu Gupta        }
7445d1eaf4a197130f561b16c4ed083cf016b20ab92Deepanshu Gupta
74585d72c4535003af3b9df77bd6eaa2b33e8a7cba2Deepanshu Gupta        // Compose the drag image
74685d72c4535003af3b9df77bd6eaa2b33e8a7cba2Deepanshu Gupta        Bitmap preview;
74785d72c4535003af3b9df77bd6eaa2b33e8a7cba2Deepanshu Gupta        Bitmap outline;
74879c59fe4a8544bdda5c56efecf9c2bc72f2f0e4eDeepanshu Gupta        float scale = 1f;
74979c59fe4a8544bdda5c56efecf9c2bc72f2f0e4eDeepanshu Gupta        if (createItemInfo instanceof PendingAddWidgetInfo) {
75079c59fe4a8544bdda5c56efecf9c2bc72f2f0e4eDeepanshu Gupta            // This can happen in some weird cases involving multi-touch. We can't start dragging
75179c59fe4a8544bdda5c56efecf9c2bc72f2f0e4eDeepanshu Gupta            // the widget if this is null, so we break out.
75279c59fe4a8544bdda5c56efecf9c2bc72f2f0e4eDeepanshu Gupta            if (mCreateWidgetInfo == null) {
75379c59fe4a8544bdda5c56efecf9c2bc72f2f0e4eDeepanshu Gupta                return false;
75485d72c4535003af3b9df77bd6eaa2b33e8a7cba2Deepanshu Gupta            }
75585d72c4535003af3b9df77bd6eaa2b33e8a7cba2Deepanshu Gupta
75685d72c4535003af3b9df77bd6eaa2b33e8a7cba2Deepanshu Gupta            PendingAddWidgetInfo createWidgetInfo = mCreateWidgetInfo;
75785d72c4535003af3b9df77bd6eaa2b33e8a7cba2Deepanshu Gupta            createItemInfo = createWidgetInfo;
75885d72c4535003af3b9df77bd6eaa2b33e8a7cba2Deepanshu Gupta            int spanX = createItemInfo.spanX;
75985d72c4535003af3b9df77bd6eaa2b33e8a7cba2Deepanshu Gupta            int spanY = createItemInfo.spanY;
760282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int[] size = mLauncher.getWorkspace().estimateItemSize(spanX, spanY,
761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    createWidgetInfo, true);
762282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
763d758e042ce08c46712db3db2d63fc84795028dfeDeepanshu Gupta            FastBitmapDrawable previewDrawable = (FastBitmapDrawable) image.getDrawable();
764d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta            float minScale = 1.25f;
765d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta            int maxWidth, maxHeight;
766d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta            maxWidth = Math.min((int) (previewDrawable.getIntrinsicWidth() * minScale), size[0]);
767d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta            maxHeight = Math.min((int) (previewDrawable.getIntrinsicHeight() * minScale), size[1]);
768d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta            preview = getWidgetPreview(createWidgetInfo.componentName, createWidgetInfo.previewImage,
769d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta                    createWidgetInfo.icon, spanX, spanY, maxWidth, maxHeight);
770d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta
771d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta            // Determine the image view drawable scale relative to the preview
772d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta            float[] mv = new float[9];
773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Matrix m = new Matrix();
774d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta            m.setRectToRect(
775d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta                    new RectF(0f, 0f, (float) preview.getWidth(), (float) preview.getHeight()),
776d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta                    new RectF(0f, 0f, (float) previewDrawable.getIntrinsicWidth(),
777d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta                            (float) previewDrawable.getIntrinsicHeight()),
778d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta                    Matrix.ScaleToFit.START);
779d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta            m.getValues(mv);
78079c59fe4a8544bdda5c56efecf9c2bc72f2f0e4eDeepanshu Gupta            scale = (float) mv[0];
78179c59fe4a8544bdda5c56efecf9c2bc72f2f0e4eDeepanshu Gupta        } else {
782d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta            PendingAddShortcutInfo createShortcutInfo = (PendingAddShortcutInfo) v.getTag();
783d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta            Drawable icon = mIconCache.getFullResIcon(createShortcutInfo.shortcutActivityInfo);
784d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta            preview = Bitmap.createBitmap(icon.getIntrinsicWidth(),
785d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta                    icon.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
786d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta
787d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta            mCanvas.setBitmap(preview);
788d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta            mCanvas.save();
789d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta            renderDrawableToBitmap(icon, preview, 0, 0,
790d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta                    icon.getIntrinsicWidth(), icon.getIntrinsicHeight());
791282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mCanvas.restore();
792282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mCanvas.setBitmap(null);
793282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            createItemInfo.spanX = createItemInfo.spanY = 1;
794282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
795d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta
796d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta        // We use a custom alpha clip table for the default widget previews
7974f8ce228195be123eeb9b5f066a6abc92b8d923aDeepanshu Gupta        Paint alphaClipPaint = null;
798282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (createItemInfo instanceof PendingAddWidgetInfo) {
799282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (((PendingAddWidgetInfo) createItemInfo).previewImage != 0) {
800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                MaskFilter alphaClipTable = TableMaskFilter.CreateClipTable(0, 255);
801282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                alphaClipPaint = new Paint();
802d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta                alphaClipPaint.setMaskFilter(alphaClipTable);
803d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta            }
8044f8ce228195be123eeb9b5f066a6abc92b8d923aDeepanshu Gupta        }
805282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
806282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Save the preview for the outline generation, then dim the preview
807282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        outline = Bitmap.createScaledBitmap(preview, preview.getWidth(), preview.getHeight(),
808282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                false);
80937dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta
810282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Start the drag
811282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        alphaClipPaint = null;
812282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mLauncher.lockScreenOrientation();
813282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mLauncher.getWorkspace().onDragStartedWithItem(createItemInfo, outline, alphaClipPaint);
814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mDragController.startDrag(image, preview, this, createItemInfo,
815282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                DragController.DRAG_ACTION_COPY, null, scale);
816282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        outline.recycle();
817282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        preview.recycle();
818282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
819282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
8209fa48b09ad06c39be0923d5ca64b81f6b0eee993Deepanshu Gupta
821282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
822282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    protected boolean beginDragging(final View v) {
823282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!super.beginDragging(v)) return false;
824282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
825282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (v instanceof PagedViewIcon) {
826282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            beginDraggingApplication(v);
827282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else if (v instanceof PagedViewWidget) {
828282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!beginDraggingWidget(v)) {
8299fa48b09ad06c39be0923d5ca64b81f6b0eee993Deepanshu Gupta                return false;
830282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
831282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
832282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
833282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // We delay entering spring-loaded mode slightly to make sure the UI
834282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // thready is free of any work.
835282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        postDelayed(new Runnable() {
836282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
837282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public void run() {
838282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // We don't enter spring-loaded mode if the drag has been cancelled
839282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (mLauncher.getDragController().isDragging()) {
840282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // Dismiss the cling
841282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    mLauncher.dismissAllAppsCling(null);
842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
843282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // Reset the alpha on the dragged icon before we drag
844282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    resetDrawableState();
845282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
846282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // Go into spring loaded mode (must happen before we startDrag())
847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    mLauncher.enterSpringLoadedDragMode();
848282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
849282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }, 150);
851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
853282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
854282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
855282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
856282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Clean up after dragging.
857282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
858282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param target where the item was dragged to (can be null if the item was flung)
859282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
86079c59fe4a8544bdda5c56efecf9c2bc72f2f0e4eDeepanshu Gupta    private void endDragging(View target, boolean isFlingToDelete, boolean success) {
86179c59fe4a8544bdda5c56efecf9c2bc72f2f0e4eDeepanshu Gupta        if (isFlingToDelete || !success || (target != mLauncher.getWorkspace() &&
86279c59fe4a8544bdda5c56efecf9c2bc72f2f0e4eDeepanshu Gupta                !(target instanceof DeleteDropTarget))) {
863282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Exit spring loaded mode if we have not successfully dropped or have not handled the
864a43c4fa09ff758400c17c3533b77d783e713a115Deepanshu Gupta            // drop in Workspace
865a43c4fa09ff758400c17c3533b77d783e713a115Deepanshu Gupta            mLauncher.exitSpringLoadedDragMode();
866a43c4fa09ff758400c17c3533b77d783e713a115Deepanshu Gupta        }
86779c59fe4a8544bdda5c56efecf9c2bc72f2f0e4eDeepanshu Gupta        mLauncher.unlockScreenOrientation(false);
868282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
869282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
870b3e872be9e634c8d1f34d07778ea753880bbf2d9Deepanshu Gupta    @Override
871b3e872be9e634c8d1f34d07778ea753880bbf2d9Deepanshu Gupta    public View getContent() {
872b3e872be9e634c8d1f34d07778ea753880bbf2d9Deepanshu Gupta        return null;
873b3e872be9e634c8d1f34d07778ea753880bbf2d9Deepanshu Gupta    }
874b3e872be9e634c8d1f34d07778ea753880bbf2d9Deepanshu Gupta
875b3e872be9e634c8d1f34d07778ea753880bbf2d9Deepanshu Gupta    @Override
876b3e872be9e634c8d1f34d07778ea753880bbf2d9Deepanshu Gupta    public void onLauncherTransitionPrepare(Launcher l, boolean animated, boolean toWorkspace) {
877b3e872be9e634c8d1f34d07778ea753880bbf2d9Deepanshu Gupta        mInTransition = true;
878b3e872be9e634c8d1f34d07778ea753880bbf2d9Deepanshu Gupta        if (toWorkspace) {
879b3e872be9e634c8d1f34d07778ea753880bbf2d9Deepanshu Gupta            cancelAllTasks();
880b3e872be9e634c8d1f34d07778ea753880bbf2d9Deepanshu Gupta        }
881b3e872be9e634c8d1f34d07778ea753880bbf2d9Deepanshu Gupta    }
882b3e872be9e634c8d1f34d07778ea753880bbf2d9Deepanshu Gupta
883b3e872be9e634c8d1f34d07778ea753880bbf2d9Deepanshu Gupta    @Override
884b3e872be9e634c8d1f34d07778ea753880bbf2d9Deepanshu Gupta    public void onLauncherTransitionStart(Launcher l, boolean animated, boolean toWorkspace) {
885282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
886282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
887282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
888282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public void onLauncherTransitionStep(Launcher l, float t) {
889282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
890282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
891282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
892282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public void onLauncherTransitionEnd(Launcher l, boolean animated, boolean toWorkspace) {
893282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mInTransition = false;
894282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (AsyncTaskPageData d : mDeferredSyncWidgetPageItems) {
895282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            onSyncWidgetPageItems(d);
896282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
897282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mDeferredSyncWidgetPageItems.clear();
898282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (Runnable r : mDeferredPrepareLoadWidgetPreviewsTasks) {
899282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            r.run();
900282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
901282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mDeferredPrepareLoadWidgetPreviewsTasks.clear();
902282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mForceDrawAllChildrenNextFrame = !toWorkspace;
903282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
904282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
905282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
906282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public void onDropCompleted(View target, DragObject d, boolean isFlingToDelete,
907282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            boolean success) {
9082bc2daa74eef01135f717eadfab87538a9bef29fDeepanshu Gupta        // Return early and wait for onFlingToDeleteCompleted if this was the result of a fling
9092bc2daa74eef01135f717eadfab87538a9bef29fDeepanshu Gupta        if (isFlingToDelete) return;
9102bc2daa74eef01135f717eadfab87538a9bef29fDeepanshu Gupta
9112bc2daa74eef01135f717eadfab87538a9bef29fDeepanshu Gupta        endDragging(target, false, success);
9122bc2daa74eef01135f717eadfab87538a9bef29fDeepanshu Gupta
9132bc2daa74eef01135f717eadfab87538a9bef29fDeepanshu Gupta        // Display an error message if the drag failed due to there not being enough space on the
9142bc2daa74eef01135f717eadfab87538a9bef29fDeepanshu Gupta        // target layout we were dropping on.
9152bc2daa74eef01135f717eadfab87538a9bef29fDeepanshu Gupta        if (!success) {
916490dd90c707de8426a068a90d74ec83c9c11fc83Deepanshu Gupta            boolean showOutOfSpaceMessage = false;
917490dd90c707de8426a068a90d74ec83c9c11fc83Deepanshu Gupta            if (target instanceof Workspace) {
918490dd90c707de8426a068a90d74ec83c9c11fc83Deepanshu Gupta                int currentScreen = mLauncher.getCurrentWorkspaceScreen();
919490dd90c707de8426a068a90d74ec83c9c11fc83Deepanshu Gupta                Workspace workspace = (Workspace) target;
920490dd90c707de8426a068a90d74ec83c9c11fc83Deepanshu Gupta                CellLayout layout = (CellLayout) workspace.getChildAt(currentScreen);
921490dd90c707de8426a068a90d74ec83c9c11fc83Deepanshu Gupta                ItemInfo itemInfo = (ItemInfo) d.dragInfo;
922490dd90c707de8426a068a90d74ec83c9c11fc83Deepanshu Gupta                if (layout != null) {
923490dd90c707de8426a068a90d74ec83c9c11fc83Deepanshu Gupta                    layout.calculateSpans(itemInfo);
924282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    showOutOfSpaceMessage =
925282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            !layout.findCellForSpan(null, itemInfo.spanX, itemInfo.spanY);
926282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
927282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
928bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta            if (showOutOfSpaceMessage) {
929bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta                mLauncher.showOutOfSpaceMessage(false);
930bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta            }
931282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
932282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            d.deferDragViewCleanupPostAnimation = false;
93391253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta        }
93491253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta        cleanupWidgetPreloading(success);
935282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mDraggingWidget = false;
936282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
937a43c4fa09ff758400c17c3533b77d783e713a115Deepanshu Gupta
938a43c4fa09ff758400c17c3533b77d783e713a115Deepanshu Gupta    @Override
939282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public void onFlingToDeleteCompleted() {
94091253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta        // We just dismiss the drag when we fling, so cleanup here
941282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        endDragging(null, true, true);
94291253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta        cleanupWidgetPreloading(false);
943282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mDraggingWidget = false;
944282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
945282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
946282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
947bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta    public boolean supportsFlingToDelete() {
94891253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta        return true;
949a43c4fa09ff758400c17c3533b77d783e713a115Deepanshu Gupta    }
950bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta
951a43c4fa09ff758400c17c3533b77d783e713a115Deepanshu Gupta    @Override
952bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta    protected void onDetachedFromWindow() {
953a43c4fa09ff758400c17c3533b77d783e713a115Deepanshu Gupta        super.onDetachedFromWindow();
954bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta        cancelAllTasks();
955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
956282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
95791253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta    public void clearAllWidgetPages() {
95879c59fe4a8544bdda5c56efecf9c2bc72f2f0e4eDeepanshu Gupta        cancelAllTasks();
959282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int count = getChildCount();
96079c59fe4a8544bdda5c56efecf9c2bc72f2f0e4eDeepanshu Gupta        for (int i = 0; i < count; i++) {
961a43c4fa09ff758400c17c3533b77d783e713a115Deepanshu Gupta            View v = getPageAt(i);
962a43c4fa09ff758400c17c3533b77d783e713a115Deepanshu Gupta            if (v instanceof PagedViewGridLayout) {
963a43c4fa09ff758400c17c3533b77d783e713a115Deepanshu Gupta                ((PagedViewGridLayout) v).removeAllViewsOnPage();
964a43c4fa09ff758400c17c3533b77d783e713a115Deepanshu Gupta                mDirtyPageContent.set(i, true);
965282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
966282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
967282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
968282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
969282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private void cancelAllTasks() {
970282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Clean up all the async tasks
97191253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta        Iterator<AppsCustomizeAsyncTask> iter = mRunningTasks.iterator();
972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        while (iter.hasNext()) {
973282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            AppsCustomizeAsyncTask task = (AppsCustomizeAsyncTask) iter.next();
974282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            task.cancel(false);
975282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            iter.remove();
976282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mDirtyPageContent.set(task.page, true);
977282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
978282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // We've already preallocated the views for the data to load into, so clear them as well
979282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            View v = getPageAt(task.page);
980282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (v instanceof PagedViewGridLayout) {
981282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ((PagedViewGridLayout) v).removeAllViewsOnPage();
982282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
98391253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta        }
984282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mDeferredSyncWidgetPageItems.clear();
985282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mDeferredPrepareLoadWidgetPreviewsTasks.clear();
9869fa48b09ad06c39be0923d5ca64b81f6b0eee993Deepanshu Gupta    }
9879fa48b09ad06c39be0923d5ca64b81f6b0eee993Deepanshu Gupta
988282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public void setContentType(ContentType type) {
989282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (type == ContentType.Widgets) {
990282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            invalidatePageData(mNumAppsPages, true);
991282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else if (type == ContentType.Applications) {
99237dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta            invalidatePageData(0, true);
993282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
994282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
995282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
996282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    protected void snapToPage(int whichPage, int delta, int duration) {
997282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        super.snapToPage(whichPage, delta, duration);
998282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        updateCurrentTab(whichPage);
999282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1000282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Update the thread priorities given the direction lookahead
1001282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Iterator<AppsCustomizeAsyncTask> iter = mRunningTasks.iterator();
1002282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        while (iter.hasNext()) {
1003282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            AppsCustomizeAsyncTask task = (AppsCustomizeAsyncTask) iter.next();
1004282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int pageIndex = task.page;
1005282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if ((mNextPage > mCurrentPage && pageIndex >= mCurrentPage) ||
1006282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                (mNextPage < mCurrentPage && pageIndex <= mCurrentPage)) {
1007282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                task.setThreadPriority(getThreadPriorityForPage(pageIndex));
1008282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
1009282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                task.setThreadPriority(Process.THREAD_PRIORITY_LOWEST);
1010282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1011282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
101291253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta    }
1013282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1014282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private void updateCurrentTab(int currentPage) {
1015282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        AppsCustomizeTabHost tabHost = getTabHost();
1016282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (tabHost != null) {
1017282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String tag = tabHost.getCurrentTabTag();
101837dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta            if (tag != null) {
1019282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (currentPage >= mNumAppsPages &&
1020282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        !tag.equals(tabHost.getTabTagForContentType(ContentType.Widgets))) {
1021282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    tabHost.setCurrentTabFromContent(ContentType.Widgets);
1022282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else if (currentPage < mNumAppsPages &&
1023282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        !tag.equals(tabHost.getTabTagForContentType(ContentType.Applications))) {
1024282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    tabHost.setCurrentTabFromContent(ContentType.Applications);
1025282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1026282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1027282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1028282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
102991253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta
103091253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta    /*
1031282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Apps PagedView implementation
1032282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
1033282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private void setVisibilityOnChildren(ViewGroup layout, int visibility) {
1034282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int childCount = layout.getChildCount();
1035282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (int i = 0; i < childCount; ++i) {
1036282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            layout.getChildAt(i).setVisibility(visibility);
1037282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
10389fa48b09ad06c39be0923d5ca64b81f6b0eee993Deepanshu Gupta    }
1039282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private void setupPage(PagedViewCellLayout layout) {
1040282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        layout.setCellCount(mCellCountX, mCellCountY);
1041282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        layout.setGap(mPageLayoutWidthGap, mPageLayoutHeightGap);
1042282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        layout.setPadding(mPageLayoutPaddingLeft, mPageLayoutPaddingTop,
1043282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                mPageLayoutPaddingRight, mPageLayoutPaddingBottom);
1044282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1045282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Note: We force a measure here to get around the fact that when we do layout calculations
1046282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // immediately after syncing, we don't have a proper width.  That said, we already know the
1047282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // expected page width, so we can actually optimize by hiding all the TextView-based
1048282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // children that are expensive to measure, and let that happen naturally later.
1049282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        setVisibilityOnChildren(layout, View.GONE);
1050282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int widthSpec = MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.AT_MOST);
1051282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int heightSpec = MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.AT_MOST);
1052282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        layout.setMinimumWidth(getPageContentWidth());
1053282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        layout.measure(widthSpec, heightSpec);
1054282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        setVisibilityOnChildren(layout, View.VISIBLE);
1055282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1056282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
10579fa48b09ad06c39be0923d5ca64b81f6b0eee993Deepanshu Gupta    public void syncAppsPageItems(int page, boolean immediate) {
10589fa48b09ad06c39be0923d5ca64b81f6b0eee993Deepanshu Gupta        // ensure that we have the right number of items on the pages
10599fa48b09ad06c39be0923d5ca64b81f6b0eee993Deepanshu Gupta        int numCells = mCellCountX * mCellCountY;
10609fa48b09ad06c39be0923d5ca64b81f6b0eee993Deepanshu Gupta        int startIndex = page * numCells;
1061282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int endIndex = Math.min(startIndex + numCells, mApps.size());
1062282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        PagedViewCellLayout layout = (PagedViewCellLayout) getPageAt(page);
1063282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1064282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        layout.removeAllViewsOnPage();
1065282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ArrayList<Object> items = new ArrayList<Object>();
1066282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ArrayList<Bitmap> images = new ArrayList<Bitmap>();
10679fa48b09ad06c39be0923d5ca64b81f6b0eee993Deepanshu Gupta        for (int i = startIndex; i < endIndex; ++i) {
10689fa48b09ad06c39be0923d5ca64b81f6b0eee993Deepanshu Gupta            ApplicationInfo info = mApps.get(i);
10699fa48b09ad06c39be0923d5ca64b81f6b0eee993Deepanshu Gupta            PagedViewIcon icon = (PagedViewIcon) mLayoutInflater.inflate(
107037dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta                    R.layout.apps_customize_application, layout, false);
107137dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta            icon.applyFromApplicationInfo(info, true, this);
10729fa48b09ad06c39be0923d5ca64b81f6b0eee993Deepanshu Gupta            icon.setOnClickListener(this);
10739fa48b09ad06c39be0923d5ca64b81f6b0eee993Deepanshu Gupta            icon.setOnLongClickListener(this);
10749fa48b09ad06c39be0923d5ca64b81f6b0eee993Deepanshu Gupta            icon.setOnTouchListener(this);
1075282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            icon.setOnKeyListener(this);
1076282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1077282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int index = i - startIndex;
1078282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int x = index % mCellCountX;
1079282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int y = index / mCellCountX;
1080282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            layout.addViewToCellLayout(icon, -1, i, new PagedViewCellLayout.LayoutParams(x,y, 1,1));
1081ada8590547348b77d8cbd56abdb8fadb3e72c015Deepanshu Gupta
1082ada8590547348b77d8cbd56abdb8fadb3e72c015Deepanshu Gupta            items.add(info);
1083ada8590547348b77d8cbd56abdb8fadb3e72c015Deepanshu Gupta            images.add(info.iconBitmap);
1084ada8590547348b77d8cbd56abdb8fadb3e72c015Deepanshu Gupta        }
1085ada8590547348b77d8cbd56abdb8fadb3e72c015Deepanshu Gupta
1086ada8590547348b77d8cbd56abdb8fadb3e72c015Deepanshu Gupta        layout.createHardwareLayers();
1087ada8590547348b77d8cbd56abdb8fadb3e72c015Deepanshu Gupta    }
1088d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta
1089d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta    /**
1090d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta     * A helper to return the priority for loading of the specified widget page.
1091d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta     */
1092d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta    private int getWidgetPageLoadPriority(int page) {
1093d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta        // If we are snapping to another page, use that index as the target page index
1094d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta        int toPage = mCurrentPage;
1095d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta        if (mNextPage > -1) {
1096d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta            toPage = mNextPage;
1097d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta        }
1098d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta
1099d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta        // We use the distance from the target page as an initial guess of priority, but if there
1100d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta        // are no pages of higher priority than the page specified, then bump up the priority of
1101d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta        // the specified page.
1102d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta        Iterator<AppsCustomizeAsyncTask> iter = mRunningTasks.iterator();
1103d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta        int minPageDiff = Integer.MAX_VALUE;
1104d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta        while (iter.hasNext()) {
1105d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta            AppsCustomizeAsyncTask task = (AppsCustomizeAsyncTask) iter.next();
1106d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta            minPageDiff = Math.abs(task.page - toPage);
1107d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta        }
1108d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta
1109d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta        int rawPageDiff = Math.abs(page - toPage);
1110d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta        return rawPageDiff - Math.min(rawPageDiff, minPageDiff);
1111d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta    }
1112d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta    /**
1113d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta     * Return the appropriate thread priority for loading for a given page (we give the current
1114d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta     * page much higher priority)
1115d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta     */
1116d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta    private int getThreadPriorityForPage(int page) {
1117d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta        // TODO-APPS_CUSTOMIZE: detect number of cores and set thread priorities accordingly below
1118d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta        int pageDiff = getWidgetPageLoadPriority(page);
1119d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta        if (pageDiff <= 0) {
1120d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta            return Process.THREAD_PRIORITY_LESS_FAVORABLE;
1121d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta        } else if (pageDiff <= 1) {
1122d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta            return Process.THREAD_PRIORITY_LOWEST;
1123d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta        } else {
1124d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta            return Process.THREAD_PRIORITY_LOWEST;
1125d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta        }
1126d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta    }
1127d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta    private int getSleepForPage(int page) {
1128d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta        int pageDiff = getWidgetPageLoadPriority(page);
1129d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta        return Math.max(0, pageDiff * sPageSleepDelay);
1130d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta    }
1131d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta    /**
1132d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta     * Creates and executes a new AsyncTask to load a page of widget previews.
1133d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta     */
1134d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta    private void prepareLoadWidgetPreviewsTask(int page, ArrayList<Object> widgets,
1135d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta            int cellWidth, int cellHeight, int cellCountX) {
1136d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta
1137d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta        // Prune all tasks that are no longer needed
1138e8a04cd5a68a5e5aa78a4f40b3269c86cc3f152fIan Pedowitz        Iterator<AppsCustomizeAsyncTask> iter = mRunningTasks.iterator();
1139e8a04cd5a68a5e5aa78a4f40b3269c86cc3f152fIan Pedowitz        while (iter.hasNext()) {
1140e8a04cd5a68a5e5aa78a4f40b3269c86cc3f152fIan Pedowitz            AppsCustomizeAsyncTask task = (AppsCustomizeAsyncTask) iter.next();
1141e8a04cd5a68a5e5aa78a4f40b3269c86cc3f152fIan Pedowitz            int taskPage = task.page;
1142e8a04cd5a68a5e5aa78a4f40b3269c86cc3f152fIan Pedowitz            if (taskPage < getAssociatedLowerPageBound(mCurrentPage) ||
1143d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta                    taskPage > getAssociatedUpperPageBound(mCurrentPage)) {
1144d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta                task.cancel(false);
1145d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta                iter.remove();
1146d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta            } else {
1147d5b82845450beac2d3c7db9cd80e9fc34d43a297Deepanshu Gupta                task.setThreadPriority(getThreadPriorityForPage(taskPage));
1148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // We introduce a slight delay to order the loading of side pages so that we don't thrash
1152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        final int sleepMs = getSleepForPage(page);
1153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        AsyncTaskPageData pageData = new AsyncTaskPageData(page, widgets, cellWidth, cellHeight,
1154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            new AsyncTaskCallback() {
1155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                @Override
1156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                public void run(AppsCustomizeAsyncTask task, AsyncTaskPageData data) {
1157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    try {
1158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        try {
1159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            Thread.sleep(sleepMs);
1160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } catch (Exception e) {}
1161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        loadWidgetPreviewsInBackground(task, data);
1162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } finally {
1163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (task.isCancelled()) {
1164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            data.cleanup(true);
1165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            },
1169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            new AsyncTaskCallback() {
1170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                @Override
1171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                public void run(AppsCustomizeAsyncTask task, AsyncTaskPageData data) {
1172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    mRunningTasks.remove(task);
1173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (task.isCancelled()) return;
1174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // do cleanup inside onSyncWidgetPageItems
1175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    onSyncWidgetPageItems(data);
1176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            });
1178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Ensure that the task is appropriately prioritized and runs in parallel
1180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        AppsCustomizeAsyncTask t = new AppsCustomizeAsyncTask(page,
1181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                AsyncTaskPageData.Type.LoadWidgetPreviewData);
1182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        t.setThreadPriority(getThreadPriorityForPage(page));
1183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        t.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, pageData);
1184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mRunningTasks.add(t);
1185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1187c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav    /*
1188c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav     * Widgets PagedView implementation
1189c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav     */
1190c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav    private void setupPage(PagedViewGridLayout layout) {
1191c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav        layout.setPadding(mPageLayoutPaddingLeft, mPageLayoutPaddingTop,
1192c6d1c345f41cf817bf2c07c97b97107d94296064Svetoslav                mPageLayoutPaddingRight, mPageLayoutPaddingBottom);
1193ff17024e583b170312d82089fd358d278ce16c9aDianne Hackborn
1194ff17024e583b170312d82089fd358d278ce16c9aDianne Hackborn        // Note: We force a measure here to get around the fact that when we do layout calculations
1195ff17024e583b170312d82089fd358d278ce16c9aDianne Hackborn        // immediately after syncing, we don't have a proper width.
1196ff17024e583b170312d82089fd358d278ce16c9aDianne Hackborn        int widthSpec = MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.AT_MOST);
1197ff17024e583b170312d82089fd358d278ce16c9aDianne Hackborn        int heightSpec = MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.AT_MOST);
1198ff17024e583b170312d82089fd358d278ce16c9aDianne Hackborn        layout.setMinimumWidth(getPageContentWidth());
1199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        layout.measure(widthSpec, heightSpec);
1200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private void renderDrawableToBitmap(Drawable d, Bitmap bitmap, int x, int y, int w, int h) {
1203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        renderDrawableToBitmap(d, bitmap, x, y, w, h, 1f);
1204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1205ff17024e583b170312d82089fd358d278ce16c9aDianne Hackborn
1206ff17024e583b170312d82089fd358d278ce16c9aDianne Hackborn    private void renderDrawableToBitmap(Drawable d, Bitmap bitmap, int x, int y, int w, int h,
1207ff17024e583b170312d82089fd358d278ce16c9aDianne Hackborn            float scale) {
1208ff17024e583b170312d82089fd358d278ce16c9aDianne Hackborn        if (bitmap != null) {
1209ff17024e583b170312d82089fd358d278ce16c9aDianne Hackborn            Canvas c = new Canvas(bitmap);
1210ff17024e583b170312d82089fd358d278ce16c9aDianne Hackborn            c.scale(scale, scale);
1211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Rect oldBounds = d.copyBounds();
1212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            d.setBounds(x, y, x + w, y + h);
1213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            d.draw(c);
1214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            d.setBounds(oldBounds); // Restore the bounds
1215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            c.setBitmap(null);
1216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private Bitmap getShortcutPreview(ResolveInfo info, int maxWidth, int maxHeight) {
1220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bitmap tempBitmap = mCachedShortcutPreviewBitmap.get();
1221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        final Canvas c = mCachedShortcutPreviewCanvas.get();
1222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (tempBitmap == null ||
1223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tempBitmap.getWidth() != maxWidth ||
1224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tempBitmap.getHeight() != maxHeight) {
1225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            tempBitmap = Bitmap.createBitmap(maxWidth, maxHeight, Config.ARGB_8888);
1226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mCachedShortcutPreviewBitmap.set(tempBitmap);
1227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
1228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            c.setBitmap(tempBitmap);
1229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            c.drawColor(0, PorterDuff.Mode.CLEAR);
1230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            c.setBitmap(null);
1231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Render the icon
1233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Drawable icon = mIconCache.getFullResIcon(info);
1234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int paddingTop =
1236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                getResources().getDimensionPixelOffset(R.dimen.shortcut_preview_padding_top);
1237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int paddingLeft =
1238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                getResources().getDimensionPixelOffset(R.dimen.shortcut_preview_padding_left);
1239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int paddingRight =
1240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                getResources().getDimensionPixelOffset(R.dimen.shortcut_preview_padding_right);
1241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int scaledIconWidth = (maxWidth - paddingLeft - paddingRight);
1243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float scaleSize = scaledIconWidth / (float) mAppIconSize;
1244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        renderDrawableToBitmap(
1246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                icon, tempBitmap, paddingLeft, paddingTop, scaledIconWidth, scaledIconWidth);
1247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bitmap preview = Bitmap.createBitmap(maxWidth, maxHeight, Config.ARGB_8888);
1249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        c.setBitmap(preview);
1250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Paint p = mCachedShortcutPreviewPaint.get();
1251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (p == null) {
1252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            p = new Paint();
1253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ColorMatrix colorMatrix = new ColorMatrix();
12544f6a6c48a4e6b9f6e4ced3d10bb51db5d2c22eadSvetoslav            colorMatrix.setSaturation(0);
12554f6a6c48a4e6b9f6e4ced3d10bb51db5d2c22eadSvetoslav            p.setColorFilter(new ColorMatrixColorFilter(colorMatrix));
12564f6a6c48a4e6b9f6e4ced3d10bb51db5d2c22eadSvetoslav            p.setAlpha((int) (255 * 0.06f));
12574f6a6c48a4e6b9f6e4ced3d10bb51db5d2c22eadSvetoslav            //float density = 1f;
12584f6a6c48a4e6b9f6e4ced3d10bb51db5d2c22eadSvetoslav            //p.setMaskFilter(new BlurMaskFilter(15*density, BlurMaskFilter.Blur.NORMAL));
12594f6a6c48a4e6b9f6e4ced3d10bb51db5d2c22eadSvetoslav            mCachedShortcutPreviewPaint.set(p);
12608a372a0a280127743ce9a7ce4b6198c7a02d2a4fJeff Sharkey        }
126135871f2c2bb114806b4e3f109960b7f863d7885cJeff Sharkey        c.drawBitmap(tempBitmap, 0, 0, p);
126235871f2c2bb114806b4e3f109960b7f863d7885cJeff Sharkey        c.setBitmap(null);
126335871f2c2bb114806b4e3f109960b7f863d7885cJeff Sharkey
126435871f2c2bb114806b4e3f109960b7f863d7885cJeff Sharkey        renderDrawableToBitmap(icon, preview, 0, 0, mAppIconSize, mAppIconSize);
126535871f2c2bb114806b4e3f109960b7f863d7885cJeff Sharkey
1266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return preview;
1267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private Bitmap getWidgetPreview(ComponentName provider, int previewImage,
1270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int iconId, int cellHSpan, int cellVSpan, int maxWidth,
1271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int maxHeight) {
1272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Load the preview image if possible
1273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String packageName = provider.getPackageName();
1274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (maxWidth < 0) maxWidth = Integer.MAX_VALUE;
1275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (maxHeight < 0) maxHeight = Integer.MAX_VALUE;
1276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Drawable drawable = null;
1278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (previewImage != 0) {
1279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            drawable = mPackageManager.getDrawable(packageName, previewImage, null);
1280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (drawable == null) {
1281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                Log.w(TAG, "Can't load widget preview drawable 0x" +
1282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        Integer.toHexString(previewImage) + " for provider: " + provider);
1283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int bitmapWidth;
1287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int bitmapHeight;
1288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bitmap defaultPreview = null;
1289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        boolean widgetPreviewExists = (drawable != null);
1290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (widgetPreviewExists) {
1291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bitmapWidth = drawable.getIntrinsicWidth();
1292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bitmapHeight = drawable.getIntrinsicHeight();
1293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
1294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Generate a preview image if we couldn't load one
1295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (cellHSpan < 1) cellHSpan = 1;
1296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (cellVSpan < 1) cellVSpan = 1;
1297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            BitmapDrawable previewDrawable = (BitmapDrawable) getResources()
1299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    .getDrawable(R.drawable.widget_preview_tile);
1300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            final int previewDrawableWidth = previewDrawable
1301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    .getIntrinsicWidth();
1302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            final int previewDrawableHeight = previewDrawable
1303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    .getIntrinsicHeight();
1304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bitmapWidth = previewDrawableWidth * cellHSpan; // subtract 2 dips
1305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bitmapHeight = previewDrawableHeight * cellVSpan;
1306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            defaultPreview = Bitmap.createBitmap(bitmapWidth, bitmapHeight,
1308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    Config.ARGB_8888);
1309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            final Canvas c = mCachedAppWidgetPreviewCanvas.get();
1310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            c.setBitmap(defaultPreview);
1311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            previewDrawable.setBounds(0, 0, bitmapWidth, bitmapHeight);
1312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            previewDrawable.setTileModeXY(Shader.TileMode.REPEAT,
1313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    Shader.TileMode.REPEAT);
1314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            previewDrawable.draw(c);
1315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            c.setBitmap(null);
1316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Draw the icon in the top left corner
1318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int minOffset = (int) (mAppIconSize * sWidgetPreviewIconPaddingPercentage);
1319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int smallestSide = Math.min(bitmapWidth, bitmapHeight);
1320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float iconScale = Math.min((float) smallestSide
1321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    / (mAppIconSize + 2 * minOffset), 1f);
1322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            try {
1324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                Drawable icon = null;
1325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                int hoffset =
1326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        (int) ((previewDrawableWidth - mAppIconSize * iconScale) / 2);
1327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                int yoffset =
1328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        (int) ((previewDrawableHeight - mAppIconSize * iconScale) / 2);
1329d51834bdfad0cd3142ac464ab3a3b0db14f884c3Deepanshu Gupta                if (iconId > 0)
1330d51834bdfad0cd3142ac464ab3a3b0db14f884c3Deepanshu Gupta                    icon = mIconCache.getFullResIcon(packageName, iconId);
1331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                Resources resources = mLauncher.getResources();
1332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (icon != null) {
1333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    renderDrawableToBitmap(icon, defaultPreview, hoffset,
1334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            yoffset, (int) (mAppIconSize * iconScale),
1335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            (int) (mAppIconSize * iconScale));
1336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } catch (Resources.NotFoundException e) {
1338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
13404ed745d359ada6986ac15d8718452e5c55f40170Jeff Sharkey
13414ed745d359ada6986ac15d8718452e5c55f40170Jeff Sharkey        // Scale to fit width only - let the widget preview be clipped in the
13424ed745d359ada6986ac15d8718452e5c55f40170Jeff Sharkey        // vertical dimension
13434ed745d359ada6986ac15d8718452e5c55f40170Jeff Sharkey        float scale = 1f;
13444ed745d359ada6986ac15d8718452e5c55f40170Jeff Sharkey        if (bitmapWidth > maxWidth) {
13454ed745d359ada6986ac15d8718452e5c55f40170Jeff Sharkey            scale = maxWidth / (float) bitmapWidth;
1346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (scale != 1f) {
1348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bitmapWidth = (int) (scale * bitmapWidth);
1349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bitmapHeight = (int) (scale * bitmapHeight);
1350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bitmap preview = Bitmap.createBitmap(bitmapWidth, bitmapHeight,
1353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                Config.ARGB_8888);
1354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Draw the scaled preview into the final bitmap
1356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (widgetPreviewExists) {
1357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            renderDrawableToBitmap(drawable, preview, 0, 0, bitmapWidth,
1358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    bitmapHeight);
1359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
1360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            final Canvas c = mCachedAppWidgetPreviewCanvas.get();
1361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            final Rect src = mCachedAppWidgetPreviewSrcRect.get();
1362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            final Rect dest = mCachedAppWidgetPreviewDestRect.get();
1363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            c.setBitmap(preview);
1364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            src.set(0, 0, defaultPreview.getWidth(), defaultPreview.getHeight());
1365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            dest.set(0, 0, preview.getWidth(), preview.getHeight());
1366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Paint p = mCachedAppWidgetPreviewPaint.get();
1368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (p == null) {
1369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                p = new Paint();
1370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                p.setFilterBitmap(true);
1371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                mCachedAppWidgetPreviewPaint.set(p);
1372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            c.drawBitmap(defaultPreview, src, dest, p);
1374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            c.setBitmap(null);
1375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return preview;
1377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
13786a6cdafaec56fcd793214678c7fcc52f0b860cfcJeff Sharkey
13796a6cdafaec56fcd793214678c7fcc52f0b860cfcJeff Sharkey    public void syncWidgetPageItems(final int page, final boolean immediate) {
13806a6cdafaec56fcd793214678c7fcc52f0b860cfcJeff Sharkey        int numItemsPerPage = mWidgetCountX * mWidgetCountY;
13816a6cdafaec56fcd793214678c7fcc52f0b860cfcJeff Sharkey
13826a6cdafaec56fcd793214678c7fcc52f0b860cfcJeff Sharkey        // Calculate the dimensions of each cell we are giving to each widget
13836a6cdafaec56fcd793214678c7fcc52f0b860cfcJeff Sharkey        final ArrayList<Object> items = new ArrayList<Object>();
13842c1ba9a961d4f96c26df260ee437655ad9e7c03eJeff Sharkey        int contentWidth = mWidgetSpacingLayout.getContentWidth();
13852c1ba9a961d4f96c26df260ee437655ad9e7c03eJeff Sharkey        final int cellWidth = ((contentWidth - mPageLayoutPaddingLeft - mPageLayoutPaddingRight
13862c1ba9a961d4f96c26df260ee437655ad9e7c03eJeff Sharkey                - ((mWidgetCountX - 1) * mWidgetWidthGap)) / mWidgetCountX);
13872c1ba9a961d4f96c26df260ee437655ad9e7c03eJeff Sharkey        int contentHeight = mWidgetSpacingLayout.getContentHeight();
13882c1ba9a961d4f96c26df260ee437655ad9e7c03eJeff Sharkey        final int cellHeight = ((contentHeight - mPageLayoutPaddingTop - mPageLayoutPaddingBottom
13892c1ba9a961d4f96c26df260ee437655ad9e7c03eJeff Sharkey                - ((mWidgetCountY - 1) * mWidgetHeightGap)) / mWidgetCountY);
1390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Prepare the set of widgets to load previews for in the background
1392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int offset = (page - mNumAppsPages) * numItemsPerPage;
1393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (int i = offset; i < Math.min(offset + numItemsPerPage, mWidgets.size()); ++i) {
1394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            items.add(mWidgets.get(i));
1395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
139665665aac6387d644f0f40c6bdddf558f096b6e6eChristopher Tate
139765665aac6387d644f0f40c6bdddf558f096b6e6eChristopher Tate        // Prepopulate the pages with the other widget info, and fill in the previews later
139865665aac6387d644f0f40c6bdddf558f096b6e6eChristopher Tate        final PagedViewGridLayout layout = (PagedViewGridLayout) getPageAt(page);
139965665aac6387d644f0f40c6bdddf558f096b6e6eChristopher Tate        layout.setColumnCount(layout.getCellCountX());
140065665aac6387d644f0f40c6bdddf558f096b6e6eChristopher Tate        for (int i = 0; i < items.size(); ++i) {
140165665aac6387d644f0f40c6bdddf558f096b6e6eChristopher Tate            Object rawInfo = items.get(i);
1402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            PendingAddItemInfo createItemInfo = null;
1403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            PagedViewWidget widget = (PagedViewWidget) mLayoutInflater.inflate(
1404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    R.layout.apps_customize_widget, layout, false);
1405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (rawInfo instanceof AppWidgetProviderInfo) {
1406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Fill in the widget information
1407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                AppWidgetProviderInfo info = (AppWidgetProviderInfo) rawInfo;
1408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                createItemInfo = new PendingAddWidgetInfo(info, null, null);
1409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Determine the widget spans and min resize spans.
1411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                int[] spanXY = Launcher.getSpanForWidget(mLauncher, info);
1412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                createItemInfo.spanX = spanXY[0];
1413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                createItemInfo.spanY = spanXY[1];
1414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                int[] minSpanXY = Launcher.getMinSpanForWidget(mLauncher, info);
1415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                createItemInfo.minSpanX = minSpanXY[0];
1416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                createItemInfo.minSpanY = minSpanXY[1];
1417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                widget.applyFromAppWidgetProviderInfo(info, -1, spanXY);
1419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                widget.setTag(createItemInfo);
14208732bd893ae507346dad068a33edcc4beb99faedKenny Root                widget.setShortPressListener(this);
14218732bd893ae507346dad068a33edcc4beb99faedKenny Root            } else if (rawInfo instanceof ResolveInfo) {
14228732bd893ae507346dad068a33edcc4beb99faedKenny Root                // Fill in the shortcuts information
14238732bd893ae507346dad068a33edcc4beb99faedKenny Root                ResolveInfo info = (ResolveInfo) rawInfo;
14248732bd893ae507346dad068a33edcc4beb99faedKenny Root                createItemInfo = new PendingAddShortcutInfo(info.activityInfo);
14258732bd893ae507346dad068a33edcc4beb99faedKenny Root                createItemInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
1426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                createItemInfo.componentName = new ComponentName(info.activityInfo.packageName,
1427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        info.activityInfo.name);
1428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                widget.applyFromResolveInfo(mPackageManager, info);
1429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                widget.setTag(createItemInfo);
1430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            widget.setOnClickListener(this);
1432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            widget.setOnLongClickListener(this);
1433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            widget.setOnTouchListener(this);
1434282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            widget.setOnKeyListener(this);
1435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Layout each widget
1437282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int ix = i % mWidgetCountX;
1438dfeffd4c0ae165a3f225b818ef8d6f5d1cb89a2cDeepanshu Gupta            int iy = i / mWidgetCountX;
1439dfeffd4c0ae165a3f225b818ef8d6f5d1cb89a2cDeepanshu Gupta            GridLayout.LayoutParams lp = new GridLayout.LayoutParams(
1440dfeffd4c0ae165a3f225b818ef8d6f5d1cb89a2cDeepanshu Gupta                    GridLayout.spec(iy, GridLayout.LEFT),
1441dfeffd4c0ae165a3f225b818ef8d6f5d1cb89a2cDeepanshu Gupta                    GridLayout.spec(ix, GridLayout.TOP));
1442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            lp.width = cellWidth;
1443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            lp.height = cellHeight;
1444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            lp.setGravity(Gravity.TOP | Gravity.LEFT);
14458fc29cf1052fd951a3a0828b65506db30df89eceJeff Sharkey            if (ix > 0) lp.leftMargin = mWidgetWidthGap;
14468fc29cf1052fd951a3a0828b65506db30df89eceJeff Sharkey            if (iy > 0) lp.topMargin = mWidgetHeightGap;
14478fc29cf1052fd951a3a0828b65506db30df89eceJeff Sharkey            layout.addView(widget, lp);
14488fc29cf1052fd951a3a0828b65506db30df89eceJeff Sharkey        }
14498fc29cf1052fd951a3a0828b65506db30df89eceJeff Sharkey
14508fc29cf1052fd951a3a0828b65506db30df89eceJeff Sharkey        // wait until a call on onLayout to start loading, because
14518fc29cf1052fd951a3a0828b65506db30df89eceJeff Sharkey        // PagedViewWidget.getPreviewSize() will return 0 if it hasn't been laid out
14528fc29cf1052fd951a3a0828b65506db30df89eceJeff Sharkey        // TODO: can we do a measure/layout immediately?
14538a372a0a280127743ce9a7ce4b6198c7a02d2a4fJeff Sharkey        layout.setOnLayoutListener(new Runnable() {
145435871f2c2bb114806b4e3f109960b7f863d7885cJeff Sharkey            public void run() {
145535871f2c2bb114806b4e3f109960b7f863d7885cJeff Sharkey                // Load the widget previews
145635871f2c2bb114806b4e3f109960b7f863d7885cJeff Sharkey                int maxPreviewWidth = cellWidth;
145735871f2c2bb114806b4e3f109960b7f863d7885cJeff Sharkey                int maxPreviewHeight = cellHeight;
145835871f2c2bb114806b4e3f109960b7f863d7885cJeff Sharkey                if (layout.getChildCount() > 0) {
145935871f2c2bb114806b4e3f109960b7f863d7885cJeff Sharkey                    PagedViewWidget w = (PagedViewWidget) layout.getChildAt(0);
146035871f2c2bb114806b4e3f109960b7f863d7885cJeff Sharkey                    int[] maxSize = w.getPreviewSize();
146135871f2c2bb114806b4e3f109960b7f863d7885cJeff Sharkey                    maxPreviewWidth = maxSize[0];
146235871f2c2bb114806b4e3f109960b7f863d7885cJeff Sharkey                    maxPreviewHeight = maxSize[1];
146335871f2c2bb114806b4e3f109960b7f863d7885cJeff Sharkey                }
146435871f2c2bb114806b4e3f109960b7f863d7885cJeff Sharkey                if (immediate) {
1465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    AsyncTaskPageData data = new AsyncTaskPageData(page, items,
1466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            maxPreviewWidth, maxPreviewHeight, null, null);
1467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    loadWidgetPreviewsInBackground(null, data);
1468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    onSyncWidgetPageItems(data);
1469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (mInTransition) {
1471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        mDeferredPrepareLoadWidgetPreviewsTasks.add(this);
1472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else {
1473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        prepareLoadWidgetPreviewsTask(page, items,
1474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                maxPreviewWidth, maxPreviewHeight, mWidgetCountX);
1475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        });
1479282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private void loadWidgetPreviewsInBackground(AppsCustomizeAsyncTask task,
1481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            AsyncTaskPageData data) {
1482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // loadWidgetPreviewsInBackground can be called without a task to load a set of widget
1483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // previews synchronously
1484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (task != null) {
1485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Ensure that this task starts running at the correct priority
1486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            task.syncThreadPriority();
1487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Load each of the widget/shortcut previews
1490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ArrayList<Object> items = data.items;
1491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ArrayList<Bitmap> images = data.generatedImages;
1492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int count = items.size();
1493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (int i = 0; i < count; ++i) {
1494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (task != null) {
1495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Ensure we haven't been cancelled yet
1496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (task.isCancelled()) break;
1497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Before work on each item, ensure that this task is running at the correct
1498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // priority
1499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                task.syncThreadPriority();
1500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Object rawInfo = items.get(i);
1503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (rawInfo instanceof AppWidgetProviderInfo) {
1504282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                AppWidgetProviderInfo info = (AppWidgetProviderInfo) rawInfo;
1505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                int[] cellSpans = Launcher.getSpanForWidget(mLauncher, info);
1506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1507282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                int maxWidth = Math.min(data.maxImageWidth,
1508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        mWidgetSpacingLayout.estimateCellWidth(cellSpans[0]));
1509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                int maxHeight = Math.min(data.maxImageHeight,
1510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        mWidgetSpacingLayout.estimateCellHeight(cellSpans[1]));
1511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                Bitmap b = getWidgetPreview(info.provider, info.previewImage, info.icon,
1512282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        cellSpans[0], cellSpans[1], maxWidth, maxHeight);
1513282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                images.add(b);
1514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (rawInfo instanceof ResolveInfo) {
1515282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Fill in the shortcuts information
1516282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ResolveInfo info = (ResolveInfo) rawInfo;
1517282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                images.add(getShortcutPreview(info, data.maxImageWidth, data.maxImageHeight));
1518282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1519282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1520282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1521282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1522282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private void onSyncWidgetPageItems(AsyncTaskPageData data) {
1523282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (mInTransition) {
1524282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mDeferredSyncWidgetPageItems.add(data);
1525282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
1526282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1527282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        try {
1528282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int page = data.page;
1529282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            PagedViewGridLayout layout = (PagedViewGridLayout) getPageAt(page);
1530282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1531282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ArrayList<Object> items = data.items;
1532282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int count = items.size();
1533282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (int i = 0; i < count; ++i) {
1534282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                PagedViewWidget widget = (PagedViewWidget) layout.getChildAt(i);
1535282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (widget != null) {
1536282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    Bitmap preview = data.generatedImages.get(i);
1537282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    widget.applyPreview(new FastBitmapDrawable(preview), i);
1538282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1539282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1541282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            layout.createHardwareLayer();
1542282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            invalidate();
1543282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Update all thread priorities
1545282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Iterator<AppsCustomizeAsyncTask> iter = mRunningTasks.iterator();
1546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            while (iter.hasNext()) {
1547282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                AppsCustomizeAsyncTask task = (AppsCustomizeAsyncTask) iter.next();
1548282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                int pageIndex = task.page;
1549282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                task.setThreadPriority(getThreadPriorityForPage(pageIndex));
1550282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1551282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } finally {
1552282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            data.cleanup(false);
1553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1554282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1556282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
1557282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public void syncPages() {
1558282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        removeAllViews();
1559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        cancelAllTasks();
1560282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Context context = getContext();
1562d4fd8c766da8a70e3359bbc7efbbc79496efe71aFyodor Kupolov        for (int j = 0; j < mNumWidgetPages; ++j) {
1563d4fd8c766da8a70e3359bbc7efbbc79496efe71aFyodor Kupolov            PagedViewGridLayout layout = new PagedViewGridLayout(context, mWidgetCountX,
1564d4fd8c766da8a70e3359bbc7efbbc79496efe71aFyodor Kupolov                    mWidgetCountY);
1565d4fd8c766da8a70e3359bbc7efbbc79496efe71aFyodor Kupolov            setupPage(layout);
1566d4fd8c766da8a70e3359bbc7efbbc79496efe71aFyodor Kupolov            addView(layout, new PagedView.LayoutParams(LayoutParams.MATCH_PARENT,
1567d4fd8c766da8a70e3359bbc7efbbc79496efe71aFyodor Kupolov                    LayoutParams.MATCH_PARENT));
1568a750a63d639f6936af456df904fa6b9ba941885eDianne Hackborn        }
1569a750a63d639f6936af456df904fa6b9ba941885eDianne Hackborn
1570a750a63d639f6936af456df904fa6b9ba941885eDianne Hackborn        for (int i = 0; i < mNumAppsPages; ++i) {
1571a750a63d639f6936af456df904fa6b9ba941885eDianne Hackborn            PagedViewCellLayout layout = new PagedViewCellLayout(context);
1572a750a63d639f6936af456df904fa6b9ba941885eDianne Hackborn            setupPage(layout);
1573a750a63d639f6936af456df904fa6b9ba941885eDianne Hackborn            addView(layout);
1574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
1578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public void syncPageItems(int page, boolean immediate) {
1579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (page < mNumAppsPages) {
1580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            syncAppsPageItems(page, immediate);
1581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
1582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            syncWidgetPageItems(page, immediate);
1583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // We want our pages to be z-ordered such that the further a page is to the left, the higher
1587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // it is in the z-order. This is important to insure touch events are handled correctly.
1588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    View getPageAt(int index) {
1589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return getChildAt(indexToPage(index));
1590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
1593a750a63d639f6936af456df904fa6b9ba941885eDianne Hackborn    protected int indexToPage(int index) {
1594a750a63d639f6936af456df904fa6b9ba941885eDianne Hackborn        return getChildCount() - index - 1;
1595a750a63d639f6936af456df904fa6b9ba941885eDianne Hackborn    }
1596a750a63d639f6936af456df904fa6b9ba941885eDianne Hackborn
1597a750a63d639f6936af456df904fa6b9ba941885eDianne Hackborn    // In apps customize, we have a scrolling effect which emulates pulling cards off of a stack.
1598a750a63d639f6936af456df904fa6b9ba941885eDianne Hackborn    @Override
1599a750a63d639f6936af456df904fa6b9ba941885eDianne Hackborn    protected void screenScrolled(int screenCenter) {
1600a750a63d639f6936af456df904fa6b9ba941885eDianne Hackborn        super.screenScrolled(screenCenter);
1601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (int i = 0; i < getChildCount(); i++) {
1603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            View v = getPageAt(i);
1604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (v != null) {
1605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                float scrollProgress = getScrollProgress(screenCenter, v, i);
1606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                float interpolatedProgress =
1608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        mZInterpolator.getInterpolation(Math.abs(Math.min(scrollProgress, 0)));
1609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                float scale = (1 - interpolatedProgress) +
1610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        interpolatedProgress * TRANSITION_SCALE_FACTOR;
1611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                float translationX = Math.min(0, scrollProgress) * v.getMeasuredWidth();
1612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                float alpha;
1614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (scrollProgress < 0) {
1616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    alpha = scrollProgress < 0 ? mAlphaInterpolator.getInterpolation(
1617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        1 - Math.abs(scrollProgress)) : 1.0f;
16186762301a10ba1176dc97083bef6785ec169378ffSvet Ganov                } else {
1619e8b6debd9b1035a8b8da102cfe476b71986b341cSvet Ganov                    // On large screens we need to fade the page as it nears its leftmost position
16206762301a10ba1176dc97083bef6785ec169378ffSvet Ganov                    alpha = mLeftScreenAlphaInterpolator.getInterpolation(1 - scrollProgress);
16216762301a10ba1176dc97083bef6785ec169378ffSvet Ganov                }
16226762301a10ba1176dc97083bef6785ec169378ffSvet Ganov
1623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                v.setCameraDistance(mDensity * CAMERA_DISTANCE);
1624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                int pageWidth = v.getMeasuredWidth();
1625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                int pageHeight = v.getMeasuredHeight();
1626282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1627282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (PERFORM_OVERSCROLL_ROTATION) {
1628282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (i == 0 && scrollProgress < 0) {
1629282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        // Overscroll to the left
1630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        v.setPivotX(TRANSITION_PIVOT * pageWidth);
16313cf75729d5a27b8ddd1ea174626dbcf0349a1d07Amith Yamasani                        v.setRotationY(-TRANSITION_MAX_ROTATION * scrollProgress);
16323cf75729d5a27b8ddd1ea174626dbcf0349a1d07Amith Yamasani                        scale = 1.0f;
16333cf75729d5a27b8ddd1ea174626dbcf0349a1d07Amith Yamasani                        alpha = 1.0f;
1634fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn                        // On the first page, we don't want the page to have any lateral motion
1635fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn                        translationX = 0;
1636fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn                    } else if (i == getChildCount() - 1 && scrollProgress > 0) {
1637fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn                        // Overscroll to the right
1638fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn                        v.setPivotX((1 - TRANSITION_PIVOT) * pageWidth);
1639fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn                        v.setRotationY(-TRANSITION_MAX_ROTATION * scrollProgress);
1640fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn                        scale = 1.0f;
1641fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn                        alpha = 1.0f;
16423cf75729d5a27b8ddd1ea174626dbcf0349a1d07Amith Yamasani                        // On the last page, we don't want the page to have any lateral motion.
16433cf75729d5a27b8ddd1ea174626dbcf0349a1d07Amith Yamasani                        translationX = 0;
16443cf75729d5a27b8ddd1ea174626dbcf0349a1d07Amith Yamasani                    } else {
16453cf75729d5a27b8ddd1ea174626dbcf0349a1d07Amith Yamasani                        v.setPivotY(pageHeight / 2.0f);
16463cf75729d5a27b8ddd1ea174626dbcf0349a1d07Amith Yamasani                        v.setPivotX(pageWidth / 2.0f);
1647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        v.setRotationY(0f);
1648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                v.setTranslationX(translationX);
1652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                v.setScaleX(scale);
1653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                v.setScaleY(scale);
1654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                v.setAlpha(alpha);
1655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // If the view has 0 alpha, we set it to be invisible so as to prevent
1657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // it from accepting touches
1658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (alpha == 0) {
1659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    v.setVisibility(INVISIBLE);
1660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else if (v.getVisibility() != VISIBLE) {
1661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    v.setVisibility(VISIBLE);
1662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1665e0e413e2b17a0164e15c77f4ab51b3166f9111d2Dianne Hackborn    }
1666e0e413e2b17a0164e15c77f4ab51b3166f9111d2Dianne Hackborn
1667e0e413e2b17a0164e15c77f4ab51b3166f9111d2Dianne Hackborn    protected void overScroll(float amount) {
1668e0e413e2b17a0164e15c77f4ab51b3166f9111d2Dianne Hackborn        acceleratedOverScroll(amount);
1669e0e413e2b17a0164e15c77f4ab51b3166f9111d2Dianne Hackborn    }
1670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
1672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Used by the parent to get the content width to set the tab bar to
1673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @return
1674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
1675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public int getPageContentWidth() {
1676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return mContentWidth;
1677282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1679282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
1680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    protected void onPageEndMoving() {
1681282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        super.onPageEndMoving();
1682282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mForceDrawAllChildrenNextFrame = true;
1683282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // We reset the save index when we change pages so that it will be recalculated on next
1684282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // rotation
1685282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mSaveInstanceStateItemIndex = -1;
1686282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*
1689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * AllAppsView implementation
1690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
1691282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
1692282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public void setup(Launcher launcher, DragController dragController) {
1693282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mLauncher = launcher;
1694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mDragController = dragController;
1695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
1697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public void zoom(float zoom, boolean animate) {
1698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // TODO-APPS_CUSTOMIZE: Call back to mLauncher.zoomed()
1699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1700282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
1701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public boolean isVisible() {
1702282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return (getVisibility() == VISIBLE);
1703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1704282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
1705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public boolean isAnimating() {
1706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return false;
1707282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1708282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1709282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
1710282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * We should call thise method whenever the core data changes (mApps, mWidgets) so that we can
1711282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * appropriately determine when to invalidate the PagedView page data.  In cases where the data
1712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * has yet to be set, we can requestLayout() and wait for onDataReady() to be called in the
1713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * next onMeasure() pass, which will trigger an invalidatePageData() itself.
1714282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
1715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private void invalidateOnDataChange() {
1716282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!isDataReady()) {
1717282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // The next layout pass will trigger data-ready if both widgets and apps are set, so
1718282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // request a layout to trigger the page data when ready.
1719282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            requestLayout();
1720282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
1721282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            cancelAllTasks();
1722282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            invalidatePageData();
1723282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1724282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1725282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1726282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
1727282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public void setApps(ArrayList<ApplicationInfo> list) {
1728282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mApps = list;
1729282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Collections.sort(mApps, LauncherModel.APP_NAME_COMPARATOR);
1730282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        updatePageCounts();
1731282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        invalidateOnDataChange();
1732282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1733282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private void addAppsWithoutInvalidate(ArrayList<ApplicationInfo> list) {
1734282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // We add it in place, in alphabetical order
1735282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int count = list.size();
1736282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (int i = 0; i < count; ++i) {
1737282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ApplicationInfo info = list.get(i);
1738282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int index = Collections.binarySearch(mApps, info, LauncherModel.APP_NAME_COMPARATOR);
1739282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (index < 0) {
1740282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                mApps.add(-(index + 1), info);
1741282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1742282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1743282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1744282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
1745282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public void addApps(ArrayList<ApplicationInfo> list) {
1746282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        addAppsWithoutInvalidate(list);
1747282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        updatePageCounts();
1748282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        invalidateOnDataChange();
1749282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private int findAppByComponent(List<ApplicationInfo> list, ApplicationInfo item) {
1751282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ComponentName removeComponent = item.intent.getComponent();
1752282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int length = list.size();
1753282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (int i = 0; i < length; ++i) {
1754282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ApplicationInfo info = list.get(i);
1755282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (info.intent.getComponent().equals(removeComponent)) {
1756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return i;
1757282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1758282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1759282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return -1;
1760282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private void removeAppsWithoutInvalidate(ArrayList<ApplicationInfo> list) {
1762282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // loop through all the apps and remove apps that have the same component
1763282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int length = list.size();
1764282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (int i = 0; i < length; ++i) {
1765282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ApplicationInfo info = list.get(i);
1766282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int removeIndex = findAppByComponent(mApps, info);
1767282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (removeIndex > -1) {
1768282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                mApps.remove(removeIndex);
1769282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1770282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1771282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
1773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public void removeApps(ArrayList<ApplicationInfo> list) {
1774282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        removeAppsWithoutInvalidate(list);
1775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        updatePageCounts();
1776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        invalidateOnDataChange();
1777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
1779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public void updateApps(ArrayList<ApplicationInfo> list) {
1780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // We remove and re-add the updated applications list because it's properties may have
1781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // changed (ie. the title), and this will ensure that the items will be in their proper
1782282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // place in the list.
1783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        removeAppsWithoutInvalidate(list);
1784282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        addAppsWithoutInvalidate(list);
1785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        updatePageCounts();
1786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        invalidateOnDataChange();
1787282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1788282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1789282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
1790282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public void reset() {
1791282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // If we have reset, then we should not continue to restore the previous state
1792282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mSaveInstanceStateItemIndex = -1;
1793282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1794282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        AppsCustomizeTabHost tabHost = getTabHost();
1795282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String tag = tabHost.getCurrentTabTag();
1796282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (tag != null) {
1797282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!tag.equals(tabHost.getTabTagForContentType(ContentType.Applications))) {
1798282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tabHost.setCurrentTabFromContent(ContentType.Applications);
1799282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1801282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
18020f5caab5762d9ace8e7d87e29296bcb8fdfe9b4bAdam Lesinski        if (mCurrentPage != 0) {
18030f5caab5762d9ace8e7d87e29296bcb8fdfe9b4bAdam Lesinski            invalidatePageData(0);
18040f5caab5762d9ace8e7d87e29296bcb8fdfe9b4bAdam Lesinski        }
18050f5caab5762d9ace8e7d87e29296bcb8fdfe9b4bAdam Lesinski    }
18060f5caab5762d9ace8e7d87e29296bcb8fdfe9b4bAdam Lesinski
18070f5caab5762d9ace8e7d87e29296bcb8fdfe9b4bAdam Lesinski    private AppsCustomizeTabHost getTabHost() {
1808282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return (AppsCustomizeTabHost) mLauncher.findViewById(R.id.apps_customize_pane);
1809282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1810282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1811282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
1812282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public void dumpState() {
1813282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // TODO: Dump information related to current list of Applications, Widgets, etc.
1814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ApplicationInfo.dumpApplicationInfoList(TAG, "mApps", mApps);
1815282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dumpAppWidgetProviderInfoList(TAG, "mWidgets", mWidgets);
1816282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1817282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1818282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private void dumpAppWidgetProviderInfoList(String tag, String label,
1819282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ArrayList<Object> list) {
1820282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Log.d(tag, label + " size=" + list.size());
1821282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (Object i: list) {
1822282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (i instanceof AppWidgetProviderInfo) {
1823282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                AppWidgetProviderInfo info = (AppWidgetProviderInfo) i;
1824282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                Log.d(tag, "   label=\"" + info.label + "\" previewImage=" + info.previewImage
1825282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        + " resizeMode=" + info.resizeMode + " configure=" + info.configure
1826282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        + " initialLayout=" + info.initialLayout
1827282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        + " minWidth=" + info.minWidth + " minHeight=" + info.minHeight);
1828282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (i instanceof ResolveInfo) {
18292ee3c1e189819cc6efb4d7de24f1438bdb824087Jeff Sharkey                ResolveInfo info = (ResolveInfo) i;
18302ee3c1e189819cc6efb4d7de24f1438bdb824087Jeff Sharkey                Log.d(tag, "   label=\"" + info.loadLabel(mPackageManager) + "\" icon="
18312ee3c1e189819cc6efb4d7de24f1438bdb824087Jeff Sharkey                        + info.icon);
18322ee3c1e189819cc6efb4d7de24f1438bdb824087Jeff Sharkey            }
18332ee3c1e189819cc6efb4d7de24f1438bdb824087Jeff Sharkey        }
18342ee3c1e189819cc6efb4d7de24f1438bdb824087Jeff Sharkey    }
18354dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen
18364dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen    @Override
18374dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen    public void surrender() {
18384dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen        // TODO: If we are in the middle of any process (ie. for holographic outlines, etc) we
18394dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen        // should stop this now.
18404dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen
18414dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen        // Stop all background tasks
18424dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen        cancelAllTasks();
18434dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen    }
18447a30a30ebece75f4a73fa604d4c7721d28eecc16Jeff Sharkey
1845d15459197f71f8cc940e2b057b399117df282f2cDiego Perez    @Override
1846d15459197f71f8cc940e2b057b399117df282f2cDiego Perez    public void iconPressed(PagedViewIcon icon) {
1847d15459197f71f8cc940e2b057b399117df282f2cDiego Perez        // Reset the previously pressed icon and store a reference to the pressed icon so that
1848d15459197f71f8cc940e2b057b399117df282f2cDiego Perez        // we can reset it on return to Launcher (in Launcher.onResume())
1849d15459197f71f8cc940e2b057b399117df282f2cDiego Perez        if (mPressedIcon != null) {
1850d15459197f71f8cc940e2b057b399117df282f2cDiego Perez            mPressedIcon.resetDrawableState();
1851d15459197f71f8cc940e2b057b399117df282f2cDiego Perez        }
1852d15459197f71f8cc940e2b057b399117df282f2cDiego Perez        mPressedIcon = icon;
1853d15459197f71f8cc940e2b057b399117df282f2cDiego Perez    }
18547a30a30ebece75f4a73fa604d4c7721d28eecc16Jeff Sharkey
18558a372a0a280127743ce9a7ce4b6198c7a02d2a4fJeff Sharkey    public void resetDrawableState() {
18567a30a30ebece75f4a73fa604d4c7721d28eecc16Jeff Sharkey        if (mPressedIcon != null) {
18577a30a30ebece75f4a73fa604d4c7721d28eecc16Jeff Sharkey            mPressedIcon.resetDrawableState();
18587a30a30ebece75f4a73fa604d4c7721d28eecc16Jeff Sharkey            mPressedIcon = null;
18597a30a30ebece75f4a73fa604d4c7721d28eecc16Jeff Sharkey        }
18607a30a30ebece75f4a73fa604d4c7721d28eecc16Jeff Sharkey    }
18618a372a0a280127743ce9a7ce4b6198c7a02d2a4fJeff Sharkey
18627a30a30ebece75f4a73fa604d4c7721d28eecc16Jeff Sharkey    /*
18637a30a30ebece75f4a73fa604d4c7721d28eecc16Jeff Sharkey     * We load an extra page on each side to prevent flashes from scrolling and loading of the
18647a30a30ebece75f4a73fa604d4c7721d28eecc16Jeff Sharkey     * widget previews in the background with the AsyncTasks.
18657a30a30ebece75f4a73fa604d4c7721d28eecc16Jeff Sharkey     */
18667a30a30ebece75f4a73fa604d4c7721d28eecc16Jeff Sharkey    final static int sLookBehindPageCount = 2;
18678a372a0a280127743ce9a7ce4b6198c7a02d2a4fJeff Sharkey    final static int sLookAheadPageCount = 2;
18687a30a30ebece75f4a73fa604d4c7721d28eecc16Jeff Sharkey    protected int getAssociatedLowerPageBound(int page) {
18697a30a30ebece75f4a73fa604d4c7721d28eecc16Jeff Sharkey        final int count = getChildCount();
18707a30a30ebece75f4a73fa604d4c7721d28eecc16Jeff Sharkey        int windowSize = Math.min(count, sLookBehindPageCount + sLookAheadPageCount + 1);
18717a30a30ebece75f4a73fa604d4c7721d28eecc16Jeff Sharkey        int windowMinIndex = Math.max(Math.min(page - sLookBehindPageCount, count - windowSize), 0);
18728a372a0a280127743ce9a7ce4b6198c7a02d2a4fJeff Sharkey        return windowMinIndex;
18737a30a30ebece75f4a73fa604d4c7721d28eecc16Jeff Sharkey    }
18747a30a30ebece75f4a73fa604d4c7721d28eecc16Jeff Sharkey    protected int getAssociatedUpperPageBound(int page) {
187591253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta        final int count = getChildCount();
187691253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta        int windowSize = Math.min(count, sLookBehindPageCount + sLookAheadPageCount + 1);
187791253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta        int windowMaxIndex = Math.min(Math.max(page + sLookAheadPageCount, windowSize - 1),
187891253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta                count - 1);
187991253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta        return windowMaxIndex;
188091253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta    }
188191253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta
188291253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta    @Override
188391253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta    protected String getCurrentPageDescription() {
188491253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta        int page = (mNextPage != INVALID_PAGE) ? mNextPage : mCurrentPage;
188591253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta        int stringId = R.string.default_scroll_format;
188691253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta        int count = 0;
188791253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta
188891253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta        if (page < mNumAppsPages) {
188991253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta            stringId = R.string.apps_customize_apps_scroll_format;
189091253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta            count = mNumAppsPages;
189191253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta        } else {
189291253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta            page -= mNumAppsPages;
189391253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta            stringId = R.string.apps_customize_widgets_scroll_format;
189491253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta            count = mNumWidgetPages;
189591253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta        }
189691253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta
189791253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta        return String.format(getContext().getString(stringId), page + 1, count);
189891253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta    }
189991253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta}
190091253ed04696ecd57636472dd8ac74660f65c5c2Deepanshu Gupta