blob: b993364bf99e8bf399eafa88430bcdcce5497cbb [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.PixelFormat;
26import android.graphics.drawable.BitmapDrawable;
27import android.graphics.drawable.Drawable;
Daniel Sandler388f6792010-03-02 14:08:08 -050028import android.util.AttributeSet;
29import android.util.Log;
30import android.view.KeyEvent;
Daniel Sandler388f6792010-03-02 14:08:08 -050031import android.view.LayoutInflater;
Daniel Sandler388f6792010-03-02 14:08:08 -050032import android.view.View;
Winson Chungaafa03c2010-06-11 17:34:16 -070033import android.view.ViewGroup;
Daniel Sandler388f6792010-03-02 14:08:08 -050034import android.view.animation.AnimationUtils;
Daniel Sandler388f6792010-03-02 14:08:08 -050035import android.widget.AdapterView;
Daniel Sandler388f6792010-03-02 14:08:08 -050036import android.widget.ArrayAdapter;
37import android.widget.GridView;
Winson Chungaafa03c2010-06-11 17:34:16 -070038import android.widget.ImageButton;
Daniel Sandler388f6792010-03-02 14:08:08 -050039import android.widget.RelativeLayout;
Winson Chungaafa03c2010-06-11 17:34:16 -070040import android.widget.TextView;
Daniel Sandler388f6792010-03-02 14:08:08 -050041
Patrick Dubroy558654c2010-07-23 16:48:11 -070042import java.util.ArrayList;
43import java.util.Collections;
Daniel Sandler388f6792010-03-02 14:08:08 -050044
45public class AllApps2D
46 extends RelativeLayout
47 implements AllAppsView,
48 AdapterView.OnItemClickListener,
49 AdapterView.OnItemLongClickListener,
50 View.OnKeyListener,
51 DragSource {
52
53 private static final String TAG = "Launcher.AllApps2D";
Daniel Sandler86b40542010-06-01 14:48:12 -070054 private static final boolean DEBUG = false;
Daniel Sandler388f6792010-03-02 14:08:08 -050055
56 private Launcher mLauncher;
57 private DragController mDragController;
58
59 private GridView mGrid;
60
61 private ArrayList<ApplicationInfo> mAllAppsList = new ArrayList<ApplicationInfo>();
62
Daniel Sandler73a05542010-03-09 14:45:57 -050063 // preserve compatibility with 3D all apps:
64 // 0.0 -> hidden
65 // 1.0 -> shown and opaque
66 // intermediate values -> partially shown & partially opaque
Daniel Sandler388f6792010-03-02 14:08:08 -050067 private float mZoom;
68
69 private AppsAdapter mAppsAdapter;
70
Patrick Dubroy558654c2010-07-23 16:48:11 -070071 private boolean mIsViewOpaque;
72
Daniel Sandler388f6792010-03-02 14:08:08 -050073 // ------------------------------------------------------------
Daniel Sandler73a05542010-03-09 14:45:57 -050074
75 public static class HomeButton extends ImageButton {
76 public HomeButton(Context context, AttributeSet attrs) {
77 super(context, attrs);
78 }
79 @Override
80 public View focusSearch(int direction) {
81 if (direction == FOCUS_UP) return super.focusSearch(direction);
82 return null;
83 }
84 }
Daniel Sandler388f6792010-03-02 14:08:08 -050085
86 public class AppsAdapter extends ArrayAdapter<ApplicationInfo> {
87 private final LayoutInflater mInflater;
88
89 public AppsAdapter(Context context, ArrayList<ApplicationInfo> apps) {
90 super(context, 0, apps);
91 mInflater = LayoutInflater.from(context);
92 }
93
94 @Override
95 public View getView(int position, View convertView, ViewGroup parent) {
96 final ApplicationInfo info = getItem(position);
97
98 if (convertView == null) {
99 convertView = mInflater.inflate(R.layout.application_boxed, parent, false);
100 }
101
102// if (!info.filtered) {
103// info.icon = Utilities.createIconThumbnail(info.icon, getContext());
104// info.filtered = true;
105// }
106
107 final TextView textView = (TextView) convertView;
Daniel Sandler86b40542010-06-01 14:48:12 -0700108 if (DEBUG) {
109 Log.d(TAG, "icon bitmap = " + info.iconBitmap
110 + " density = " + info.iconBitmap.getDensity());
111 }
112 info.iconBitmap.setDensity(Bitmap.DENSITY_NONE);
Daniel Sandler388f6792010-03-02 14:08:08 -0500113 textView.setCompoundDrawablesWithIntrinsicBounds(null, new BitmapDrawable(info.iconBitmap), null, null);
114 textView.setText(info.title);
115
116 return convertView;
117 }
118 }
119
120 public AllApps2D(Context context, AttributeSet attrs) {
121 super(context, attrs);
122 setVisibility(View.GONE);
123 setSoundEffectsEnabled(false);
124
125 mAppsAdapter = new AppsAdapter(getContext(), mAllAppsList);
126 mAppsAdapter.setNotifyOnChange(false);
127 }
128
129 @Override
130 protected void onFinishInflate() {
Patrick Dubroy558654c2010-07-23 16:48:11 -0700131 mIsViewOpaque = super.isOpaque();
Daniel Sandler388f6792010-03-02 14:08:08 -0500132
Daniel Sandlerc351eb82010-03-03 15:05:19 -0500133 try {
134 mGrid = (GridView)findViewWithTag("all_apps_2d_grid");
135 if (mGrid == null) throw new Resources.NotFoundException();
136 mGrid.setOnItemClickListener(this);
137 mGrid.setOnItemLongClickListener(this);
138
Patrick Dubroy558654c2010-07-23 16:48:11 -0700139 // The home button is optional; some layouts might not use it
Daniel Sandlerc351eb82010-03-03 15:05:19 -0500140 ImageButton homeButton = (ImageButton) findViewWithTag("all_apps_2d_home");
Patrick Dubroy558654c2010-07-23 16:48:11 -0700141 if (homeButton != null) {
142 homeButton.setOnClickListener(
143 new View.OnClickListener() {
144 public void onClick(View v) {
145 mLauncher.closeAllApps(true);
146 }
147 });
148 }
Daniel Sandlerc351eb82010-03-03 15:05:19 -0500149 } catch (Resources.NotFoundException e) {
150 Log.e(TAG, "Can't find necessary layout elements for AllApps2D");
151 }
Daniel Sandler388f6792010-03-02 14:08:08 -0500152
Daniel Sandlerc351eb82010-03-03 15:05:19 -0500153 setOnKeyListener(this);
Daniel Sandler388f6792010-03-02 14:08:08 -0500154 }
155
156 public AllApps2D(Context context, AttributeSet attrs, int defStyle) {
157 this(context, attrs);
158 }
159
160 public void setLauncher(Launcher launcher) {
161 mLauncher = launcher;
162 }
163
164 public boolean onKey(View v, int keyCode, KeyEvent event) {
165 if (!isVisible()) return false;
166
167 switch (keyCode) {
168 case KeyEvent.KEYCODE_BACK:
169 mLauncher.closeAllApps(true);
170 break;
171 default:
172 return false;
173 }
174
175 return true;
176 }
177
178 public void onItemClick(AdapterView parent, View v, int position, long id) {
179 ApplicationInfo app = (ApplicationInfo) parent.getItemAtPosition(position);
Joe Onoratof984e852010-03-25 09:47:45 -0700180 mLauncher.startActivitySafely(app.intent, app);
Daniel Sandler388f6792010-03-02 14:08:08 -0500181 }
182
183 public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
184 if (!view.isInTouchMode()) {
185 return false;
186 }
187
188 ApplicationInfo app = (ApplicationInfo) parent.getItemAtPosition(position);
189 app = new ApplicationInfo(app);
190
191 mDragController.startDrag(view, this, app, DragController.DRAG_ACTION_COPY);
192 mLauncher.closeAllApps(true);
193
194 return true;
195 }
196
Daniel Sandler73a05542010-03-09 14:45:57 -0500197 protected void onFocusChanged(boolean gainFocus, int direction, android.graphics.Rect prev) {
198 if (gainFocus) {
199 mGrid.requestFocus();
200 }
201 }
Daniel Sandler388f6792010-03-02 14:08:08 -0500202
203 public void setDragController(DragController dragger) {
204 mDragController = dragger;
205 }
206
207 public void onDropCompleted(View target, boolean success) {
208 }
209
210 /**
211 * Zoom to the specifed level.
212 *
213 * @param zoom [0..1] 0 is hidden, 1 is open
214 */
215 public void zoom(float zoom, boolean animate) {
216// Log.d(TAG, "zooming " + ((zoom == 1.0) ? "open" : "closed"));
217 cancelLongPress();
218
219 mZoom = zoom;
220
221 if (isVisible()) {
222 getParent().bringChildToFront(this);
223 setVisibility(View.VISIBLE);
224 mGrid.setAdapter(mAppsAdapter);
225 if (animate) {
226 startAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.all_apps_2d_fade_in));
227 } else {
228 onAnimationEnd();
229 }
230 } else {
231 if (animate) {
232 startAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.all_apps_2d_fade_out));
233 } else {
234 onAnimationEnd();
235 }
236 }
237 }
238
239 protected void onAnimationEnd() {
240 if (!isVisible()) {
241 setVisibility(View.GONE);
242 mGrid.setAdapter(null);
243 mZoom = 0.0f;
244 } else {
245 mZoom = 1.0f;
246 }
Daniel Sandlerc351eb82010-03-03 15:05:19 -0500247
248 mLauncher.zoomed(mZoom);
Daniel Sandler388f6792010-03-02 14:08:08 -0500249 }
250
251 public boolean isVisible() {
252 return mZoom > 0.001f;
253 }
254
255 @Override
256 public boolean isOpaque() {
Patrick Dubroy558654c2010-07-23 16:48:11 -0700257 return mIsViewOpaque && mZoom > 0.999f;
Daniel Sandler388f6792010-03-02 14:08:08 -0500258 }
259
260 public void setApps(ArrayList<ApplicationInfo> list) {
261 mAllAppsList.clear();
262 addApps(list);
263 }
264
265 public void addApps(ArrayList<ApplicationInfo> list) {
266// Log.d(TAG, "addApps: " + list.size() + " apps: " + list.toString());
267
268 final int N = list.size();
269
270 for (int i=0; i<N; i++) {
271 final ApplicationInfo item = list.get(i);
272 int index = Collections.binarySearch(mAllAppsList, item,
273 LauncherModel.APP_NAME_COMPARATOR);
274 if (index < 0) {
275 index = -(index+1);
276 }
277 mAllAppsList.add(index, item);
278 }
279 mAppsAdapter.notifyDataSetChanged();
280 }
281
282 public void removeApps(ArrayList<ApplicationInfo> list) {
283 final int N = list.size();
284 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 }
294 mAppsAdapter.notifyDataSetChanged();
295 }
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
303 private static int findAppByComponent(ArrayList<ApplicationInfo> list, ApplicationInfo item) {
304 ComponentName component = item.intent.getComponent();
305 final int N = list.size();
306 for (int i=0; i<N; i++) {
307 ApplicationInfo x = list.get(i);
308 if (x.intent.getComponent().equals(component)) {
309 return i;
310 }
311 }
312 return -1;
313 }
314
315 public void dumpState() {
316 ApplicationInfo.dumpApplicationInfoList(TAG, "mAllAppsList", mAllAppsList);
317 }
Romain Guy13c2e7b2010-03-10 19:45:00 -0800318
319 public void surrender() {
320 }
Daniel Sandler388f6792010-03-02 14:08:08 -0500321}
322
323