blob: 854c1eef05b160564bfe05295eb9bfa903021d2b [file] [log] [blame]
Daniel Sandler388f6792010-03-02 14:08:08 -05001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.launcher2;
18
Patrick Dubroy558654c2010-07-23 16:48:11 -070019import com.android.launcher.R;
Winson Chungaafa03c2010-06-11 17:34:16 -070020
Daniel Sandler388f6792010-03-02 14:08:08 -050021import android.content.ComponentName;
22import android.content.Context;
23import android.content.res.Resources;
Daniel Sandler86b40542010-06-01 14:48:12 -070024import android.graphics.Bitmap;
Patrick Dubroy558654c2010-07-23 16:48:11 -070025import android.graphics.drawable.BitmapDrawable;
Daniel Sandler388f6792010-03-02 14:08:08 -050026import android.util.AttributeSet;
27import android.util.Log;
28import android.view.KeyEvent;
Daniel Sandler388f6792010-03-02 14:08:08 -050029import android.view.LayoutInflater;
Daniel Sandler388f6792010-03-02 14:08:08 -050030import android.view.View;
Winson Chungaafa03c2010-06-11 17:34:16 -070031import android.view.ViewGroup;
Daniel Sandler388f6792010-03-02 14:08:08 -050032import android.view.animation.AnimationUtils;
Daniel Sandler388f6792010-03-02 14:08:08 -050033import android.widget.AdapterView;
Daniel Sandler388f6792010-03-02 14:08:08 -050034import android.widget.ArrayAdapter;
35import android.widget.GridView;
Winson Chungaafa03c2010-06-11 17:34:16 -070036import android.widget.ImageButton;
Daniel Sandler388f6792010-03-02 14:08:08 -050037import android.widget.RelativeLayout;
Winson Chungaafa03c2010-06-11 17:34:16 -070038import android.widget.TextView;
Daniel Sandler388f6792010-03-02 14:08:08 -050039
Patrick Dubroy558654c2010-07-23 16:48:11 -070040import java.util.ArrayList;
41import java.util.Collections;
Daniel Sandler388f6792010-03-02 14:08:08 -050042
43public class AllApps2D
44 extends RelativeLayout
45 implements AllAppsView,
46 AdapterView.OnItemClickListener,
47 AdapterView.OnItemLongClickListener,
48 View.OnKeyListener,
49 DragSource {
50
51 private static final String TAG = "Launcher.AllApps2D";
Daniel Sandler86b40542010-06-01 14:48:12 -070052 private static final boolean DEBUG = false;
Daniel Sandler388f6792010-03-02 14:08:08 -050053
54 private Launcher mLauncher;
55 private DragController mDragController;
56
57 private GridView mGrid;
58
Patrick Dubroy3d605d52010-07-29 13:59:29 -070059 /** All applications in the system (we might only be showing a subset) */
Daniel Sandler388f6792010-03-02 14:08:08 -050060 private ArrayList<ApplicationInfo> mAllAppsList = new ArrayList<ApplicationInfo>();
61
Patrick Dubroy3d605d52010-07-29 13:59:29 -070062 /** Currently visible applications in the grid */
63 private ArrayList<ApplicationInfo> mVisibleAppsList = new ArrayList<ApplicationInfo>();
64
65 public enum AppType { APP, GAME, DOWNLOADED, ALL };
66
67 private AppType mCurrentFilter = AppType.ALL;
68
Daniel Sandler73a05542010-03-09 14:45:57 -050069 // preserve compatibility with 3D all apps:
70 // 0.0 -> hidden
71 // 1.0 -> shown and opaque
72 // intermediate values -> partially shown & partially opaque
Daniel Sandler388f6792010-03-02 14:08:08 -050073 private float mZoom;
74
75 private AppsAdapter mAppsAdapter;
76
77 // ------------------------------------------------------------
Daniel Sandler73a05542010-03-09 14:45:57 -050078
79 public static class HomeButton extends ImageButton {
80 public HomeButton(Context context, AttributeSet attrs) {
81 super(context, attrs);
82 }
83 @Override
84 public View focusSearch(int direction) {
85 if (direction == FOCUS_UP) return super.focusSearch(direction);
86 return null;
87 }
88 }
Daniel Sandler388f6792010-03-02 14:08:08 -050089
90 public class AppsAdapter extends ArrayAdapter<ApplicationInfo> {
91 private final LayoutInflater mInflater;
92
93 public AppsAdapter(Context context, ArrayList<ApplicationInfo> apps) {
94 super(context, 0, apps);
95 mInflater = LayoutInflater.from(context);
96 }
97
98 @Override
99 public View getView(int position, View convertView, ViewGroup parent) {
100 final ApplicationInfo info = getItem(position);
101
102 if (convertView == null) {
103 convertView = mInflater.inflate(R.layout.application_boxed, parent, false);
104 }
105
106// if (!info.filtered) {
107// info.icon = Utilities.createIconThumbnail(info.icon, getContext());
108// info.filtered = true;
109// }
110
111 final TextView textView = (TextView) convertView;
Daniel Sandler86b40542010-06-01 14:48:12 -0700112 if (DEBUG) {
113 Log.d(TAG, "icon bitmap = " + info.iconBitmap
114 + " density = " + info.iconBitmap.getDensity());
115 }
116 info.iconBitmap.setDensity(Bitmap.DENSITY_NONE);
Daniel Sandler388f6792010-03-02 14:08:08 -0500117 textView.setCompoundDrawablesWithIntrinsicBounds(null, new BitmapDrawable(info.iconBitmap), null, null);
118 textView.setText(info.title);
119
120 return convertView;
121 }
122 }
123
124 public AllApps2D(Context context, AttributeSet attrs) {
125 super(context, attrs);
126 setVisibility(View.GONE);
127 setSoundEffectsEnabled(false);
128
Patrick Dubroy3d605d52010-07-29 13:59:29 -0700129 mAppsAdapter = new AppsAdapter(getContext(), mVisibleAppsList);
Daniel Sandler388f6792010-03-02 14:08:08 -0500130 }
131
132 @Override
133 protected void onFinishInflate() {
Daniel Sandlerc351eb82010-03-03 15:05:19 -0500134 try {
135 mGrid = (GridView)findViewWithTag("all_apps_2d_grid");
136 if (mGrid == null) throw new Resources.NotFoundException();
137 mGrid.setOnItemClickListener(this);
138 mGrid.setOnItemLongClickListener(this);
139
Patrick Dubroy558654c2010-07-23 16:48:11 -0700140 // The home button is optional; some layouts might not use it
Daniel Sandlerc351eb82010-03-03 15:05:19 -0500141 ImageButton homeButton = (ImageButton) findViewWithTag("all_apps_2d_home");
Patrick Dubroy558654c2010-07-23 16:48:11 -0700142 if (homeButton != null) {
143 homeButton.setOnClickListener(
144 new View.OnClickListener() {
145 public void onClick(View v) {
Winson Chung097eb0a2011-03-18 16:56:08 -0700146 mLauncher.showWorkspace(true);
Patrick Dubroy558654c2010-07-23 16:48:11 -0700147 }
148 });
149 }
Daniel Sandlerc351eb82010-03-03 15:05:19 -0500150 } catch (Resources.NotFoundException e) {
151 Log.e(TAG, "Can't find necessary layout elements for AllApps2D");
152 }
Daniel Sandler388f6792010-03-02 14:08:08 -0500153
Daniel Sandlerc351eb82010-03-03 15:05:19 -0500154 setOnKeyListener(this);
Daniel Sandler388f6792010-03-02 14:08:08 -0500155 }
156
157 public AllApps2D(Context context, AttributeSet attrs, int defStyle) {
158 this(context, attrs);
159 }
160
161 public void setLauncher(Launcher launcher) {
162 mLauncher = launcher;
163 }
164
165 public boolean onKey(View v, int keyCode, KeyEvent event) {
166 if (!isVisible()) return false;
167
168 switch (keyCode) {
169 case KeyEvent.KEYCODE_BACK:
Winson Chung097eb0a2011-03-18 16:56:08 -0700170 mLauncher.showWorkspace(true);
Daniel Sandler388f6792010-03-02 14:08:08 -0500171 break;
172 default:
173 return false;
174 }
175
176 return true;
177 }
178
179 public void onItemClick(AdapterView parent, View v, int position, long id) {
180 ApplicationInfo app = (ApplicationInfo) parent.getItemAtPosition(position);
Joe Onoratof984e852010-03-25 09:47:45 -0700181 mLauncher.startActivitySafely(app.intent, app);
Daniel Sandler388f6792010-03-02 14:08:08 -0500182 }
183
184 public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
185 if (!view.isInTouchMode()) {
186 return false;
187 }
188
189 ApplicationInfo app = (ApplicationInfo) parent.getItemAtPosition(position);
190 app = new ApplicationInfo(app);
191
192 mDragController.startDrag(view, this, app, DragController.DRAG_ACTION_COPY);
Winson Chung097eb0a2011-03-18 16:56:08 -0700193 mLauncher.showWorkspace(true);
Daniel Sandler388f6792010-03-02 14:08:08 -0500194
195 return true;
196 }
197
Daniel Sandler73a05542010-03-09 14:45:57 -0500198 protected void onFocusChanged(boolean gainFocus, int direction, android.graphics.Rect prev) {
199 if (gainFocus) {
200 mGrid.requestFocus();
201 }
202 }
Daniel Sandler388f6792010-03-02 14:08:08 -0500203
Patrick Dubroya669d792010-11-23 14:40:33 -0800204 @Override
Daniel Sandler388f6792010-03-02 14:08:08 -0500205 public void setDragController(DragController dragger) {
206 mDragController = dragger;
207 }
208
Patrick Dubroya669d792010-11-23 14:40:33 -0800209 @Override
210 public void onDragViewVisible() {
211 }
212
213 @Override
Patrick Dubroy5f445422011-02-18 14:35:21 -0800214 public void onDropCompleted(View target, Object dragInfo, boolean success) {
Daniel Sandler388f6792010-03-02 14:08:08 -0500215 }
216
217 /**
218 * Zoom to the specifed level.
219 *
220 * @param zoom [0..1] 0 is hidden, 1 is open
221 */
222 public void zoom(float zoom, boolean animate) {
223// Log.d(TAG, "zooming " + ((zoom == 1.0) ? "open" : "closed"));
224 cancelLongPress();
225
226 mZoom = zoom;
227
228 if (isVisible()) {
229 getParent().bringChildToFront(this);
230 setVisibility(View.VISIBLE);
231 mGrid.setAdapter(mAppsAdapter);
232 if (animate) {
233 startAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.all_apps_2d_fade_in));
234 } else {
235 onAnimationEnd();
236 }
237 } else {
238 if (animate) {
239 startAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.all_apps_2d_fade_out));
240 } else {
241 onAnimationEnd();
242 }
243 }
244 }
245
246 protected void onAnimationEnd() {
247 if (!isVisible()) {
248 setVisibility(View.GONE);
249 mGrid.setAdapter(null);
250 mZoom = 0.0f;
251 } else {
252 mZoom = 1.0f;
253 }
Daniel Sandlerc351eb82010-03-03 15:05:19 -0500254
255 mLauncher.zoomed(mZoom);
Daniel Sandler388f6792010-03-02 14:08:08 -0500256 }
257
258 public boolean isVisible() {
259 return mZoom > 0.001f;
260 }
261
Patrick Dubroyff5f0402010-07-26 15:23:26 -0700262 public boolean isAnimating() {
263 return (getAnimation() != null);
Daniel Sandler388f6792010-03-02 14:08:08 -0500264 }
265
266 public void setApps(ArrayList<ApplicationInfo> list) {
267 mAllAppsList.clear();
268 addApps(list);
Patrick Dubroy3d605d52010-07-29 13:59:29 -0700269 filterApps(mCurrentFilter);
Daniel Sandler388f6792010-03-02 14:08:08 -0500270 }
271
272 public void addApps(ArrayList<ApplicationInfo> list) {
Daniel Sandler388f6792010-03-02 14:08:08 -0500273 final int N = list.size();
274
275 for (int i=0; i<N; i++) {
276 final ApplicationInfo item = list.get(i);
277 int index = Collections.binarySearch(mAllAppsList, item,
278 LauncherModel.APP_NAME_COMPARATOR);
279 if (index < 0) {
280 index = -(index+1);
281 }
282 mAllAppsList.add(index, item);
283 }
Patrick Dubroy3d605d52010-07-29 13:59:29 -0700284 filterApps(mCurrentFilter);
Daniel Sandler388f6792010-03-02 14:08:08 -0500285 }
286
287 public void removeApps(ArrayList<ApplicationInfo> list) {
288 final int N = list.size();
Patrick Dubroy3d605d52010-07-29 13:59:29 -0700289
Daniel Sandler388f6792010-03-02 14:08:08 -0500290 for (int i=0; i<N; i++) {
291 final ApplicationInfo item = list.get(i);
292 int index = findAppByComponent(mAllAppsList, item);
293 if (index >= 0) {
294 mAllAppsList.remove(index);
295 } else {
296 Log.w(TAG, "couldn't find a match for item \"" + item + "\"");
297 // Try to recover. This should keep us from crashing for now.
298 }
299 }
Patrick Dubroy3d605d52010-07-29 13:59:29 -0700300 filterApps(mCurrentFilter);
Daniel Sandler388f6792010-03-02 14:08:08 -0500301 }
302
Joe Onorato64e6be72010-03-05 15:05:52 -0500303 public void updateApps(ArrayList<ApplicationInfo> list) {
Daniel Sandler388f6792010-03-02 14:08:08 -0500304 // Just remove and add, because they may need to be re-sorted.
305 removeApps(list);
306 addApps(list);
307 }
308
Patrick Dubroy3d605d52010-07-29 13:59:29 -0700309 public void filterApps(AppType appType) {
310 mCurrentFilter = appType;
311
312 mAppsAdapter.setNotifyOnChange(false);
313 mVisibleAppsList.clear();
314 if (appType == AppType.ALL) {
315 mVisibleAppsList.addAll(mAllAppsList);
Patrick Dubroycd953712011-02-28 15:16:42 -0800316 } else if (appType == AppType.DOWNLOADED) {
Patrick Dubroy3d605d52010-07-29 13:59:29 -0700317 for (ApplicationInfo info : mAllAppsList) {
Patrick Dubroycd953712011-02-28 15:16:42 -0800318 if ((info.flags & ApplicationInfo.DOWNLOADED_FLAG) != 0) {
Patrick Dubroy3d605d52010-07-29 13:59:29 -0700319 mVisibleAppsList.add(info);
320 }
321 }
322 }
323 mAppsAdapter.notifyDataSetChanged();
324 }
325
Daniel Sandler388f6792010-03-02 14:08:08 -0500326 private static int findAppByComponent(ArrayList<ApplicationInfo> list, ApplicationInfo item) {
327 ComponentName component = item.intent.getComponent();
328 final int N = list.size();
329 for (int i=0; i<N; i++) {
330 ApplicationInfo x = list.get(i);
331 if (x.intent.getComponent().equals(component)) {
332 return i;
333 }
334 }
335 return -1;
336 }
337
338 public void dumpState() {
339 ApplicationInfo.dumpApplicationInfoList(TAG, "mAllAppsList", mAllAppsList);
340 }
Romain Guy13c2e7b2010-03-10 19:45:00 -0800341
342 public void surrender() {
343 }
Winson Chung337cd9d2011-03-30 10:39:30 -0700344
345 public void reset() {
346 // Do nothing
347 }
Daniel Sandler388f6792010-03-02 14:08:08 -0500348}
349
350