blob: 44af7b7b1d9ff0ebbc2a7a378ddb64d58720cfcd [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
Winson Chung785d2eb2011-04-14 16:08:02 -0700161 @Override
162 public void setup(Launcher launcher, DragController dragController) {
Daniel Sandler388f6792010-03-02 14:08:08 -0500163 mLauncher = launcher;
Winson Chung785d2eb2011-04-14 16:08:02 -0700164 mDragController = dragController;
Daniel Sandler388f6792010-03-02 14:08:08 -0500165 }
166
167 public boolean onKey(View v, int keyCode, KeyEvent event) {
168 if (!isVisible()) return false;
169
170 switch (keyCode) {
171 case KeyEvent.KEYCODE_BACK:
Winson Chung097eb0a2011-03-18 16:56:08 -0700172 mLauncher.showWorkspace(true);
Daniel Sandler388f6792010-03-02 14:08:08 -0500173 break;
174 default:
175 return false;
176 }
177
178 return true;
179 }
180
181 public void onItemClick(AdapterView parent, View v, int position, long id) {
182 ApplicationInfo app = (ApplicationInfo) parent.getItemAtPosition(position);
Joe Onoratof984e852010-03-25 09:47:45 -0700183 mLauncher.startActivitySafely(app.intent, app);
Daniel Sandler388f6792010-03-02 14:08:08 -0500184 }
185
186 public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
187 if (!view.isInTouchMode()) {
188 return false;
189 }
190
191 ApplicationInfo app = (ApplicationInfo) parent.getItemAtPosition(position);
192 app = new ApplicationInfo(app);
193
194 mDragController.startDrag(view, this, app, DragController.DRAG_ACTION_COPY);
Winson Chung097eb0a2011-03-18 16:56:08 -0700195 mLauncher.showWorkspace(true);
Daniel Sandler388f6792010-03-02 14:08:08 -0500196
197 return true;
198 }
199
Daniel Sandler73a05542010-03-09 14:45:57 -0500200 protected void onFocusChanged(boolean gainFocus, int direction, android.graphics.Rect prev) {
201 if (gainFocus) {
202 mGrid.requestFocus();
203 }
204 }
Daniel Sandler388f6792010-03-02 14:08:08 -0500205
Patrick Dubroya669d792010-11-23 14:40:33 -0800206 @Override
Patrick Dubroya669d792010-11-23 14:40:33 -0800207 public void onDragViewVisible() {
208 }
209
210 @Override
Patrick Dubroy5f445422011-02-18 14:35:21 -0800211 public void onDropCompleted(View target, Object dragInfo, boolean success) {
Daniel Sandler388f6792010-03-02 14:08:08 -0500212 }
213
214 /**
215 * Zoom to the specifed level.
216 *
217 * @param zoom [0..1] 0 is hidden, 1 is open
218 */
219 public void zoom(float zoom, boolean animate) {
220// Log.d(TAG, "zooming " + ((zoom == 1.0) ? "open" : "closed"));
221 cancelLongPress();
222
223 mZoom = zoom;
224
225 if (isVisible()) {
226 getParent().bringChildToFront(this);
227 setVisibility(View.VISIBLE);
228 mGrid.setAdapter(mAppsAdapter);
229 if (animate) {
230 startAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.all_apps_2d_fade_in));
231 } else {
232 onAnimationEnd();
233 }
234 } else {
235 if (animate) {
236 startAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.all_apps_2d_fade_out));
237 } else {
238 onAnimationEnd();
239 }
240 }
241 }
242
243 protected void onAnimationEnd() {
244 if (!isVisible()) {
245 setVisibility(View.GONE);
246 mGrid.setAdapter(null);
247 mZoom = 0.0f;
248 } else {
249 mZoom = 1.0f;
250 }
Daniel Sandlerc351eb82010-03-03 15:05:19 -0500251
252 mLauncher.zoomed(mZoom);
Daniel Sandler388f6792010-03-02 14:08:08 -0500253 }
254
255 public boolean isVisible() {
256 return mZoom > 0.001f;
257 }
258
Patrick Dubroyff5f0402010-07-26 15:23:26 -0700259 public boolean isAnimating() {
260 return (getAnimation() != null);
Daniel Sandler388f6792010-03-02 14:08:08 -0500261 }
262
263 public void setApps(ArrayList<ApplicationInfo> list) {
264 mAllAppsList.clear();
265 addApps(list);
Patrick Dubroy3d605d52010-07-29 13:59:29 -0700266 filterApps(mCurrentFilter);
Daniel Sandler388f6792010-03-02 14:08:08 -0500267 }
268
269 public void addApps(ArrayList<ApplicationInfo> list) {
Daniel Sandler388f6792010-03-02 14:08:08 -0500270 final int N = list.size();
271
272 for (int i=0; i<N; i++) {
273 final ApplicationInfo item = list.get(i);
274 int index = Collections.binarySearch(mAllAppsList, item,
275 LauncherModel.APP_NAME_COMPARATOR);
276 if (index < 0) {
277 index = -(index+1);
278 }
279 mAllAppsList.add(index, item);
280 }
Patrick Dubroy3d605d52010-07-29 13:59:29 -0700281 filterApps(mCurrentFilter);
Daniel Sandler388f6792010-03-02 14:08:08 -0500282 }
283
284 public void removeApps(ArrayList<ApplicationInfo> list) {
285 final int N = list.size();
Patrick Dubroy3d605d52010-07-29 13:59:29 -0700286
Daniel Sandler388f6792010-03-02 14:08:08 -0500287 for (int i=0; i<N; i++) {
288 final ApplicationInfo item = list.get(i);
289 int index = findAppByComponent(mAllAppsList, item);
290 if (index >= 0) {
291 mAllAppsList.remove(index);
292 } else {
293 Log.w(TAG, "couldn't find a match for item \"" + item + "\"");
294 // Try to recover. This should keep us from crashing for now.
295 }
296 }
Patrick Dubroy3d605d52010-07-29 13:59:29 -0700297 filterApps(mCurrentFilter);
Daniel Sandler388f6792010-03-02 14:08:08 -0500298 }
299
Joe Onorato64e6be72010-03-05 15:05:52 -0500300 public void updateApps(ArrayList<ApplicationInfo> list) {
Daniel Sandler388f6792010-03-02 14:08:08 -0500301 // Just remove and add, because they may need to be re-sorted.
302 removeApps(list);
303 addApps(list);
304 }
305
Patrick Dubroy3d605d52010-07-29 13:59:29 -0700306 public void filterApps(AppType appType) {
307 mCurrentFilter = appType;
308
309 mAppsAdapter.setNotifyOnChange(false);
310 mVisibleAppsList.clear();
311 if (appType == AppType.ALL) {
312 mVisibleAppsList.addAll(mAllAppsList);
Patrick Dubroycd953712011-02-28 15:16:42 -0800313 } else if (appType == AppType.DOWNLOADED) {
Patrick Dubroy3d605d52010-07-29 13:59:29 -0700314 for (ApplicationInfo info : mAllAppsList) {
Patrick Dubroycd953712011-02-28 15:16:42 -0800315 if ((info.flags & ApplicationInfo.DOWNLOADED_FLAG) != 0) {
Patrick Dubroy3d605d52010-07-29 13:59:29 -0700316 mVisibleAppsList.add(info);
317 }
318 }
319 }
320 mAppsAdapter.notifyDataSetChanged();
321 }
322
Daniel Sandler388f6792010-03-02 14:08:08 -0500323 private static int findAppByComponent(ArrayList<ApplicationInfo> list, ApplicationInfo item) {
324 ComponentName component = item.intent.getComponent();
325 final int N = list.size();
326 for (int i=0; i<N; i++) {
327 ApplicationInfo x = list.get(i);
328 if (x.intent.getComponent().equals(component)) {
329 return i;
330 }
331 }
332 return -1;
333 }
334
335 public void dumpState() {
336 ApplicationInfo.dumpApplicationInfoList(TAG, "mAllAppsList", mAllAppsList);
337 }
Romain Guy13c2e7b2010-03-10 19:45:00 -0800338
339 public void surrender() {
340 }
Winson Chung337cd9d2011-03-30 10:39:30 -0700341
342 public void reset() {
343 // Do nothing
344 }
Daniel Sandler388f6792010-03-02 14:08:08 -0500345}
346
347