blob: 4547f54b3233c87d47d0099f51509ee083c9ea00 [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
19import android.content.ComponentName;
20import android.content.Context;
21import android.content.res.Resources;
Daniel Sandler86b40542010-06-01 14:48:12 -070022import android.graphics.Bitmap;
Patrick Dubroy558654c2010-07-23 16:48:11 -070023import android.graphics.drawable.BitmapDrawable;
Daniel Sandler388f6792010-03-02 14:08:08 -050024import android.util.AttributeSet;
25import android.util.Log;
26import android.view.KeyEvent;
Daniel Sandler388f6792010-03-02 14:08:08 -050027import android.view.LayoutInflater;
Daniel Sandler388f6792010-03-02 14:08:08 -050028import android.view.View;
Winson Chungaafa03c2010-06-11 17:34:16 -070029import android.view.ViewGroup;
Daniel Sandler388f6792010-03-02 14:08:08 -050030import android.view.animation.AnimationUtils;
Daniel Sandler388f6792010-03-02 14:08:08 -050031import android.widget.AdapterView;
Daniel Sandler388f6792010-03-02 14:08:08 -050032import android.widget.ArrayAdapter;
33import android.widget.GridView;
Winson Chungaafa03c2010-06-11 17:34:16 -070034import android.widget.ImageButton;
Daniel Sandler388f6792010-03-02 14:08:08 -050035import android.widget.RelativeLayout;
Winson Chungaafa03c2010-06-11 17:34:16 -070036import android.widget.TextView;
Daniel Sandler388f6792010-03-02 14:08:08 -050037
Adam Cohenc0dcf592011-06-01 15:30:43 -070038import com.android.launcher.R;
39import com.android.launcher2.DropTarget.DragObject;
40
Patrick Dubroy558654c2010-07-23 16:48:11 -070041import java.util.ArrayList;
42import java.util.Collections;
Daniel Sandler388f6792010-03-02 14:08:08 -050043
44public class AllApps2D
45 extends RelativeLayout
46 implements AllAppsView,
47 AdapterView.OnItemClickListener,
48 AdapterView.OnItemLongClickListener,
49 View.OnKeyListener,
50 DragSource {
51
52 private static final String TAG = "Launcher.AllApps2D";
Daniel Sandler86b40542010-06-01 14:48:12 -070053 private static final boolean DEBUG = false;
Daniel Sandler388f6792010-03-02 14:08:08 -050054
55 private Launcher mLauncher;
56 private DragController mDragController;
57
58 private GridView mGrid;
59
Patrick Dubroy3d605d52010-07-29 13:59:29 -070060 /** All applications in the system (we might only be showing a subset) */
Daniel Sandler388f6792010-03-02 14:08:08 -050061 private ArrayList<ApplicationInfo> mAllAppsList = new ArrayList<ApplicationInfo>();
62
Patrick Dubroy3d605d52010-07-29 13:59:29 -070063 /** Currently visible applications in the grid */
64 private ArrayList<ApplicationInfo> mVisibleAppsList = new ArrayList<ApplicationInfo>();
65
66 public enum AppType { APP, GAME, DOWNLOADED, ALL };
67
68 private AppType mCurrentFilter = AppType.ALL;
69
Daniel Sandler73a05542010-03-09 14:45:57 -050070 // preserve compatibility with 3D all apps:
71 // 0.0 -> hidden
72 // 1.0 -> shown and opaque
73 // intermediate values -> partially shown & partially opaque
Daniel Sandler388f6792010-03-02 14:08:08 -050074 private float mZoom;
75
76 private AppsAdapter mAppsAdapter;
77
78 // ------------------------------------------------------------
Daniel Sandler73a05542010-03-09 14:45:57 -050079
80 public static class HomeButton extends ImageButton {
81 public HomeButton(Context context, AttributeSet attrs) {
82 super(context, attrs);
83 }
84 @Override
85 public View focusSearch(int direction) {
86 if (direction == FOCUS_UP) return super.focusSearch(direction);
87 return null;
88 }
89 }
Daniel Sandler388f6792010-03-02 14:08:08 -050090
91 public class AppsAdapter extends ArrayAdapter<ApplicationInfo> {
92 private final LayoutInflater mInflater;
93
94 public AppsAdapter(Context context, ArrayList<ApplicationInfo> apps) {
95 super(context, 0, apps);
96 mInflater = LayoutInflater.from(context);
97 }
98
99 @Override
100 public View getView(int position, View convertView, ViewGroup parent) {
101 final ApplicationInfo info = getItem(position);
102
103 if (convertView == null) {
104 convertView = mInflater.inflate(R.layout.application_boxed, parent, false);
105 }
106
107// if (!info.filtered) {
108// info.icon = Utilities.createIconThumbnail(info.icon, getContext());
109// info.filtered = true;
110// }
111
112 final TextView textView = (TextView) convertView;
Daniel Sandler86b40542010-06-01 14:48:12 -0700113 if (DEBUG) {
114 Log.d(TAG, "icon bitmap = " + info.iconBitmap
115 + " density = " + info.iconBitmap.getDensity());
116 }
117 info.iconBitmap.setDensity(Bitmap.DENSITY_NONE);
Daniel Sandler388f6792010-03-02 14:08:08 -0500118 textView.setCompoundDrawablesWithIntrinsicBounds(null, new BitmapDrawable(info.iconBitmap), null, null);
119 textView.setText(info.title);
120
121 return convertView;
122 }
123 }
124
125 public AllApps2D(Context context, AttributeSet attrs) {
126 super(context, attrs);
127 setVisibility(View.GONE);
128 setSoundEffectsEnabled(false);
129
Patrick Dubroy3d605d52010-07-29 13:59:29 -0700130 mAppsAdapter = new AppsAdapter(getContext(), mVisibleAppsList);
Daniel Sandler388f6792010-03-02 14:08:08 -0500131 }
132
133 @Override
134 protected void onFinishInflate() {
Daniel Sandlerc351eb82010-03-03 15:05:19 -0500135 try {
136 mGrid = (GridView)findViewWithTag("all_apps_2d_grid");
137 if (mGrid == null) throw new Resources.NotFoundException();
138 mGrid.setOnItemClickListener(this);
139 mGrid.setOnItemLongClickListener(this);
140
Patrick Dubroy558654c2010-07-23 16:48:11 -0700141 // The home button is optional; some layouts might not use it
Daniel Sandlerc351eb82010-03-03 15:05:19 -0500142 ImageButton homeButton = (ImageButton) findViewWithTag("all_apps_2d_home");
Patrick Dubroy558654c2010-07-23 16:48:11 -0700143 if (homeButton != null) {
144 homeButton.setOnClickListener(
145 new View.OnClickListener() {
146 public void onClick(View v) {
Winson Chung097eb0a2011-03-18 16:56:08 -0700147 mLauncher.showWorkspace(true);
Patrick Dubroy558654c2010-07-23 16:48:11 -0700148 }
149 });
150 }
Daniel Sandlerc351eb82010-03-03 15:05:19 -0500151 } catch (Resources.NotFoundException e) {
152 Log.e(TAG, "Can't find necessary layout elements for AllApps2D");
153 }
Daniel Sandler388f6792010-03-02 14:08:08 -0500154
Daniel Sandlerc351eb82010-03-03 15:05:19 -0500155 setOnKeyListener(this);
Daniel Sandler388f6792010-03-02 14:08:08 -0500156 }
157
158 public AllApps2D(Context context, AttributeSet attrs, int defStyle) {
159 this(context, attrs);
160 }
161
Winson Chung785d2eb2011-04-14 16:08:02 -0700162 @Override
163 public void setup(Launcher launcher, DragController dragController) {
Daniel Sandler388f6792010-03-02 14:08:08 -0500164 mLauncher = launcher;
Winson Chung785d2eb2011-04-14 16:08:02 -0700165 mDragController = dragController;
Daniel Sandler388f6792010-03-02 14:08:08 -0500166 }
167
168 public boolean onKey(View v, int keyCode, KeyEvent event) {
169 if (!isVisible()) return false;
170
171 switch (keyCode) {
172 case KeyEvent.KEYCODE_BACK:
Winson Chung097eb0a2011-03-18 16:56:08 -0700173 mLauncher.showWorkspace(true);
Daniel Sandler388f6792010-03-02 14:08:08 -0500174 break;
175 default:
176 return false;
177 }
178
179 return true;
180 }
181
182 public void onItemClick(AdapterView parent, View v, int position, long id) {
183 ApplicationInfo app = (ApplicationInfo) parent.getItemAtPosition(position);
Joe Onoratof984e852010-03-25 09:47:45 -0700184 mLauncher.startActivitySafely(app.intent, app);
Daniel Sandler388f6792010-03-02 14:08:08 -0500185 }
186
187 public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
188 if (!view.isInTouchMode()) {
189 return false;
190 }
191
192 ApplicationInfo app = (ApplicationInfo) parent.getItemAtPosition(position);
193 app = new ApplicationInfo(app);
194
195 mDragController.startDrag(view, this, app, DragController.DRAG_ACTION_COPY);
Winson Chung097eb0a2011-03-18 16:56:08 -0700196 mLauncher.showWorkspace(true);
Daniel Sandler388f6792010-03-02 14:08:08 -0500197
198 return true;
199 }
200
Daniel Sandler73a05542010-03-09 14:45:57 -0500201 protected void onFocusChanged(boolean gainFocus, int direction, android.graphics.Rect prev) {
202 if (gainFocus) {
203 mGrid.requestFocus();
204 }
205 }
Daniel Sandler388f6792010-03-02 14:08:08 -0500206
Patrick Dubroya669d792010-11-23 14:40:33 -0800207 @Override
Patrick Dubroya669d792010-11-23 14:40:33 -0800208 public void onDragViewVisible() {
209 }
210
211 @Override
Adam Cohenc0dcf592011-06-01 15:30:43 -0700212 public void onDropCompleted(View target, DragObject d, boolean success) {
Daniel Sandler388f6792010-03-02 14:08:08 -0500213 }
214
215 /**
216 * Zoom to the specifed level.
217 *
218 * @param zoom [0..1] 0 is hidden, 1 is open
219 */
220 public void zoom(float zoom, boolean animate) {
221// Log.d(TAG, "zooming " + ((zoom == 1.0) ? "open" : "closed"));
222 cancelLongPress();
223
224 mZoom = zoom;
225
226 if (isVisible()) {
227 getParent().bringChildToFront(this);
228 setVisibility(View.VISIBLE);
229 mGrid.setAdapter(mAppsAdapter);
230 if (animate) {
231 startAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.all_apps_2d_fade_in));
232 } else {
233 onAnimationEnd();
234 }
235 } else {
236 if (animate) {
237 startAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.all_apps_2d_fade_out));
238 } else {
239 onAnimationEnd();
240 }
241 }
242 }
243
244 protected void onAnimationEnd() {
245 if (!isVisible()) {
246 setVisibility(View.GONE);
247 mGrid.setAdapter(null);
248 mZoom = 0.0f;
249 } else {
250 mZoom = 1.0f;
251 }
Daniel Sandlerc351eb82010-03-03 15:05:19 -0500252
253 mLauncher.zoomed(mZoom);
Daniel Sandler388f6792010-03-02 14:08:08 -0500254 }
255
256 public boolean isVisible() {
257 return mZoom > 0.001f;
258 }
259
Patrick Dubroyff5f0402010-07-26 15:23:26 -0700260 public boolean isAnimating() {
261 return (getAnimation() != null);
Daniel Sandler388f6792010-03-02 14:08:08 -0500262 }
263
264 public void setApps(ArrayList<ApplicationInfo> list) {
265 mAllAppsList.clear();
266 addApps(list);
Patrick Dubroy3d605d52010-07-29 13:59:29 -0700267 filterApps(mCurrentFilter);
Daniel Sandler388f6792010-03-02 14:08:08 -0500268 }
269
270 public void addApps(ArrayList<ApplicationInfo> list) {
Daniel Sandler388f6792010-03-02 14:08:08 -0500271 final int N = list.size();
272
273 for (int i=0; i<N; i++) {
274 final ApplicationInfo item = list.get(i);
275 int index = Collections.binarySearch(mAllAppsList, item,
276 LauncherModel.APP_NAME_COMPARATOR);
277 if (index < 0) {
278 index = -(index+1);
279 }
280 mAllAppsList.add(index, item);
281 }
Patrick Dubroy3d605d52010-07-29 13:59:29 -0700282 filterApps(mCurrentFilter);
Daniel Sandler388f6792010-03-02 14:08:08 -0500283 }
284
285 public void removeApps(ArrayList<ApplicationInfo> list) {
286 final int N = list.size();
Patrick Dubroy3d605d52010-07-29 13:59:29 -0700287
Daniel Sandler388f6792010-03-02 14:08:08 -0500288 for (int i=0; i<N; i++) {
289 final ApplicationInfo item = list.get(i);
290 int index = findAppByComponent(mAllAppsList, item);
291 if (index >= 0) {
292 mAllAppsList.remove(index);
293 } else {
294 Log.w(TAG, "couldn't find a match for item \"" + item + "\"");
295 // Try to recover. This should keep us from crashing for now.
296 }
297 }
Patrick Dubroy3d605d52010-07-29 13:59:29 -0700298 filterApps(mCurrentFilter);
Daniel Sandler388f6792010-03-02 14:08:08 -0500299 }
300
Joe Onorato64e6be72010-03-05 15:05:52 -0500301 public void updateApps(ArrayList<ApplicationInfo> list) {
Daniel Sandler388f6792010-03-02 14:08:08 -0500302 // Just remove and add, because they may need to be re-sorted.
303 removeApps(list);
304 addApps(list);
305 }
306
Patrick Dubroy3d605d52010-07-29 13:59:29 -0700307 public void filterApps(AppType appType) {
308 mCurrentFilter = appType;
309
310 mAppsAdapter.setNotifyOnChange(false);
311 mVisibleAppsList.clear();
312 if (appType == AppType.ALL) {
313 mVisibleAppsList.addAll(mAllAppsList);
Patrick Dubroycd953712011-02-28 15:16:42 -0800314 } else if (appType == AppType.DOWNLOADED) {
Patrick Dubroy3d605d52010-07-29 13:59:29 -0700315 for (ApplicationInfo info : mAllAppsList) {
Patrick Dubroycd953712011-02-28 15:16:42 -0800316 if ((info.flags & ApplicationInfo.DOWNLOADED_FLAG) != 0) {
Patrick Dubroy3d605d52010-07-29 13:59:29 -0700317 mVisibleAppsList.add(info);
318 }
319 }
320 }
321 mAppsAdapter.notifyDataSetChanged();
322 }
323
Daniel Sandler388f6792010-03-02 14:08:08 -0500324 private static int findAppByComponent(ArrayList<ApplicationInfo> list, ApplicationInfo item) {
325 ComponentName component = item.intent.getComponent();
326 final int N = list.size();
327 for (int i=0; i<N; i++) {
328 ApplicationInfo x = list.get(i);
329 if (x.intent.getComponent().equals(component)) {
330 return i;
331 }
332 }
333 return -1;
334 }
335
336 public void dumpState() {
337 ApplicationInfo.dumpApplicationInfoList(TAG, "mAllAppsList", mAllAppsList);
338 }
Romain Guy13c2e7b2010-03-10 19:45:00 -0800339
340 public void surrender() {
341 }
Winson Chung337cd9d2011-03-30 10:39:30 -0700342
343 public void reset() {
344 // Do nothing
345 }
Daniel Sandler388f6792010-03-02 14:08:08 -0500346}
347
348