blob: 9764f2338dbe553c76ed8f19f1cb051342319c6e [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) {
146 mLauncher.closeAllApps(true);
147 }
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:
170 mLauncher.closeAllApps(true);
171 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);
193 mLauncher.closeAllApps(true);
194
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
204 public void setDragController(DragController dragger) {
205 mDragController = dragger;
206 }
207
208 public void onDropCompleted(View target, boolean success) {
209 }
210
211 /**
212 * Zoom to the specifed level.
213 *
214 * @param zoom [0..1] 0 is hidden, 1 is open
215 */
216 public void zoom(float zoom, boolean animate) {
217// Log.d(TAG, "zooming " + ((zoom == 1.0) ? "open" : "closed"));
218 cancelLongPress();
219
220 mZoom = zoom;
221
222 if (isVisible()) {
223 getParent().bringChildToFront(this);
224 setVisibility(View.VISIBLE);
225 mGrid.setAdapter(mAppsAdapter);
226 if (animate) {
227 startAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.all_apps_2d_fade_in));
228 } else {
229 onAnimationEnd();
230 }
231 } else {
232 if (animate) {
233 startAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.all_apps_2d_fade_out));
234 } else {
235 onAnimationEnd();
236 }
237 }
238 }
239
240 protected void onAnimationEnd() {
241 if (!isVisible()) {
242 setVisibility(View.GONE);
243 mGrid.setAdapter(null);
244 mZoom = 0.0f;
245 } else {
246 mZoom = 1.0f;
247 }
Daniel Sandlerc351eb82010-03-03 15:05:19 -0500248
249 mLauncher.zoomed(mZoom);
Daniel Sandler388f6792010-03-02 14:08:08 -0500250 }
251
252 public boolean isVisible() {
253 return mZoom > 0.001f;
254 }
255
Patrick Dubroyff5f0402010-07-26 15:23:26 -0700256 public boolean isAnimating() {
257 return (getAnimation() != null);
Daniel Sandler388f6792010-03-02 14:08:08 -0500258 }
259
260 public void setApps(ArrayList<ApplicationInfo> list) {
261 mAllAppsList.clear();
262 addApps(list);
Patrick Dubroy3d605d52010-07-29 13:59:29 -0700263 filterApps(mCurrentFilter);
Daniel Sandler388f6792010-03-02 14:08:08 -0500264 }
265
266 public void addApps(ArrayList<ApplicationInfo> list) {
Daniel Sandler388f6792010-03-02 14:08:08 -0500267 final int N = list.size();
268
269 for (int i=0; i<N; i++) {
270 final ApplicationInfo item = list.get(i);
271 int index = Collections.binarySearch(mAllAppsList, item,
272 LauncherModel.APP_NAME_COMPARATOR);
273 if (index < 0) {
274 index = -(index+1);
275 }
276 mAllAppsList.add(index, item);
277 }
Patrick Dubroy3d605d52010-07-29 13:59:29 -0700278 filterApps(mCurrentFilter);
Daniel Sandler388f6792010-03-02 14:08:08 -0500279 }
280
281 public void removeApps(ArrayList<ApplicationInfo> list) {
282 final int N = list.size();
Patrick Dubroy3d605d52010-07-29 13:59:29 -0700283
Daniel Sandler388f6792010-03-02 14:08:08 -0500284 for (int i=0; i<N; i++) {
285 final ApplicationInfo item = list.get(i);
286 int index = findAppByComponent(mAllAppsList, item);
287 if (index >= 0) {
288 mAllAppsList.remove(index);
289 } else {
290 Log.w(TAG, "couldn't find a match for item \"" + item + "\"");
291 // Try to recover. This should keep us from crashing for now.
292 }
293 }
Patrick Dubroy3d605d52010-07-29 13:59:29 -0700294 filterApps(mCurrentFilter);
Daniel Sandler388f6792010-03-02 14:08:08 -0500295 }
296
Joe Onorato64e6be72010-03-05 15:05:52 -0500297 public void updateApps(ArrayList<ApplicationInfo> list) {
Daniel Sandler388f6792010-03-02 14:08:08 -0500298 // Just remove and add, because they may need to be re-sorted.
299 removeApps(list);
300 addApps(list);
301 }
302
Patrick Dubroy3d605d52010-07-29 13:59:29 -0700303 public void filterApps(AppType appType) {
304 mCurrentFilter = appType;
305
306 mAppsAdapter.setNotifyOnChange(false);
307 mVisibleAppsList.clear();
308 if (appType == AppType.ALL) {
309 mVisibleAppsList.addAll(mAllAppsList);
310 } else {
311 int searchFlags = 0;
312
313 if (appType == AppType.APP) {
314 searchFlags = ApplicationInfo.APP_FLAG;
315 } else if (appType == AppType.GAME) {
316 searchFlags = ApplicationInfo.GAME_FLAG;
317 } else if (appType == AppType.DOWNLOADED) {
318 searchFlags = ApplicationInfo.DOWNLOADED_FLAG;
319 }
320
321 for (ApplicationInfo info : mAllAppsList) {
322 if ((info.flags & searchFlags) != 0) {
323 mVisibleAppsList.add(info);
324 }
325 }
326 }
327 mAppsAdapter.notifyDataSetChanged();
328 }
329
Daniel Sandler388f6792010-03-02 14:08:08 -0500330 private static int findAppByComponent(ArrayList<ApplicationInfo> list, ApplicationInfo item) {
331 ComponentName component = item.intent.getComponent();
332 final int N = list.size();
333 for (int i=0; i<N; i++) {
334 ApplicationInfo x = list.get(i);
335 if (x.intent.getComponent().equals(component)) {
336 return i;
337 }
338 }
339 return -1;
340 }
341
342 public void dumpState() {
343 ApplicationInfo.dumpApplicationInfoList(TAG, "mAllAppsList", mAllAppsList);
344 }
Romain Guy13c2e7b2010-03-10 19:45:00 -0800345
346 public void surrender() {
347 }
Daniel Sandler388f6792010-03-02 14:08:08 -0500348}
349
350