blob: 7d0970b0aeca794673b855703c8a887903e58e3f [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
71 // ------------------------------------------------------------
Daniel Sandler73a05542010-03-09 14:45:57 -050072
73 public static class HomeButton extends ImageButton {
74 public HomeButton(Context context, AttributeSet attrs) {
75 super(context, attrs);
76 }
77 @Override
78 public View focusSearch(int direction) {
79 if (direction == FOCUS_UP) return super.focusSearch(direction);
80 return null;
81 }
82 }
Daniel Sandler388f6792010-03-02 14:08:08 -050083
84 public class AppsAdapter extends ArrayAdapter<ApplicationInfo> {
85 private final LayoutInflater mInflater;
86
87 public AppsAdapter(Context context, ArrayList<ApplicationInfo> apps) {
88 super(context, 0, apps);
89 mInflater = LayoutInflater.from(context);
90 }
91
92 @Override
93 public View getView(int position, View convertView, ViewGroup parent) {
94 final ApplicationInfo info = getItem(position);
95
96 if (convertView == null) {
97 convertView = mInflater.inflate(R.layout.application_boxed, parent, false);
98 }
99
100// if (!info.filtered) {
101// info.icon = Utilities.createIconThumbnail(info.icon, getContext());
102// info.filtered = true;
103// }
104
105 final TextView textView = (TextView) convertView;
Daniel Sandler86b40542010-06-01 14:48:12 -0700106 if (DEBUG) {
107 Log.d(TAG, "icon bitmap = " + info.iconBitmap
108 + " density = " + info.iconBitmap.getDensity());
109 }
110 info.iconBitmap.setDensity(Bitmap.DENSITY_NONE);
Daniel Sandler388f6792010-03-02 14:08:08 -0500111 textView.setCompoundDrawablesWithIntrinsicBounds(null, new BitmapDrawable(info.iconBitmap), null, null);
112 textView.setText(info.title);
113
114 return convertView;
115 }
116 }
117
118 public AllApps2D(Context context, AttributeSet attrs) {
119 super(context, attrs);
120 setVisibility(View.GONE);
121 setSoundEffectsEnabled(false);
122
123 mAppsAdapter = new AppsAdapter(getContext(), mAllAppsList);
124 mAppsAdapter.setNotifyOnChange(false);
125 }
126
127 @Override
128 protected void onFinishInflate() {
Daniel Sandlerc351eb82010-03-03 15:05:19 -0500129 try {
130 mGrid = (GridView)findViewWithTag("all_apps_2d_grid");
131 if (mGrid == null) throw new Resources.NotFoundException();
132 mGrid.setOnItemClickListener(this);
133 mGrid.setOnItemLongClickListener(this);
134
Patrick Dubroy558654c2010-07-23 16:48:11 -0700135 // The home button is optional; some layouts might not use it
Daniel Sandlerc351eb82010-03-03 15:05:19 -0500136 ImageButton homeButton = (ImageButton) findViewWithTag("all_apps_2d_home");
Patrick Dubroy558654c2010-07-23 16:48:11 -0700137 if (homeButton != null) {
138 homeButton.setOnClickListener(
139 new View.OnClickListener() {
140 public void onClick(View v) {
141 mLauncher.closeAllApps(true);
142 }
143 });
144 }
Daniel Sandlerc351eb82010-03-03 15:05:19 -0500145 } catch (Resources.NotFoundException e) {
146 Log.e(TAG, "Can't find necessary layout elements for AllApps2D");
147 }
Daniel Sandler388f6792010-03-02 14:08:08 -0500148
Daniel Sandlerc351eb82010-03-03 15:05:19 -0500149 setOnKeyListener(this);
Daniel Sandler388f6792010-03-02 14:08:08 -0500150 }
151
152 public AllApps2D(Context context, AttributeSet attrs, int defStyle) {
153 this(context, attrs);
154 }
155
156 public void setLauncher(Launcher launcher) {
157 mLauncher = launcher;
158 }
159
160 public boolean onKey(View v, int keyCode, KeyEvent event) {
161 if (!isVisible()) return false;
162
163 switch (keyCode) {
164 case KeyEvent.KEYCODE_BACK:
165 mLauncher.closeAllApps(true);
166 break;
167 default:
168 return false;
169 }
170
171 return true;
172 }
173
174 public void onItemClick(AdapterView parent, View v, int position, long id) {
175 ApplicationInfo app = (ApplicationInfo) parent.getItemAtPosition(position);
Joe Onoratof984e852010-03-25 09:47:45 -0700176 mLauncher.startActivitySafely(app.intent, app);
Daniel Sandler388f6792010-03-02 14:08:08 -0500177 }
178
179 public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
180 if (!view.isInTouchMode()) {
181 return false;
182 }
183
184 ApplicationInfo app = (ApplicationInfo) parent.getItemAtPosition(position);
185 app = new ApplicationInfo(app);
186
187 mDragController.startDrag(view, this, app, DragController.DRAG_ACTION_COPY);
188 mLauncher.closeAllApps(true);
189
190 return true;
191 }
192
Daniel Sandler73a05542010-03-09 14:45:57 -0500193 protected void onFocusChanged(boolean gainFocus, int direction, android.graphics.Rect prev) {
194 if (gainFocus) {
195 mGrid.requestFocus();
196 }
197 }
Daniel Sandler388f6792010-03-02 14:08:08 -0500198
199 public void setDragController(DragController dragger) {
200 mDragController = dragger;
201 }
202
203 public void onDropCompleted(View target, boolean success) {
204 }
205
206 /**
207 * Zoom to the specifed level.
208 *
209 * @param zoom [0..1] 0 is hidden, 1 is open
210 */
211 public void zoom(float zoom, boolean animate) {
212// Log.d(TAG, "zooming " + ((zoom == 1.0) ? "open" : "closed"));
213 cancelLongPress();
214
215 mZoom = zoom;
216
217 if (isVisible()) {
218 getParent().bringChildToFront(this);
219 setVisibility(View.VISIBLE);
220 mGrid.setAdapter(mAppsAdapter);
221 if (animate) {
222 startAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.all_apps_2d_fade_in));
223 } else {
224 onAnimationEnd();
225 }
226 } else {
227 if (animate) {
228 startAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.all_apps_2d_fade_out));
229 } else {
230 onAnimationEnd();
231 }
232 }
233 }
234
235 protected void onAnimationEnd() {
236 if (!isVisible()) {
237 setVisibility(View.GONE);
238 mGrid.setAdapter(null);
239 mZoom = 0.0f;
240 } else {
241 mZoom = 1.0f;
242 }
Daniel Sandlerc351eb82010-03-03 15:05:19 -0500243
244 mLauncher.zoomed(mZoom);
Daniel Sandler388f6792010-03-02 14:08:08 -0500245 }
246
247 public boolean isVisible() {
248 return mZoom > 0.001f;
249 }
250
Patrick Dubroyff5f0402010-07-26 15:23:26 -0700251 public boolean isAnimating() {
252 return (getAnimation() != null);
Daniel Sandler388f6792010-03-02 14:08:08 -0500253 }
254
255 public void setApps(ArrayList<ApplicationInfo> list) {
256 mAllAppsList.clear();
257 addApps(list);
258 }
259
260 public void addApps(ArrayList<ApplicationInfo> list) {
261// Log.d(TAG, "addApps: " + list.size() + " apps: " + list.toString());
262
263 final int N = list.size();
264
265 for (int i=0; i<N; i++) {
266 final ApplicationInfo item = list.get(i);
267 int index = Collections.binarySearch(mAllAppsList, item,
268 LauncherModel.APP_NAME_COMPARATOR);
269 if (index < 0) {
270 index = -(index+1);
271 }
272 mAllAppsList.add(index, item);
273 }
274 mAppsAdapter.notifyDataSetChanged();
275 }
276
277 public void removeApps(ArrayList<ApplicationInfo> list) {
278 final int N = list.size();
279 for (int i=0; i<N; i++) {
280 final ApplicationInfo item = list.get(i);
281 int index = findAppByComponent(mAllAppsList, item);
282 if (index >= 0) {
283 mAllAppsList.remove(index);
284 } else {
285 Log.w(TAG, "couldn't find a match for item \"" + item + "\"");
286 // Try to recover. This should keep us from crashing for now.
287 }
288 }
289 mAppsAdapter.notifyDataSetChanged();
290 }
291
Joe Onorato64e6be72010-03-05 15:05:52 -0500292 public void updateApps(ArrayList<ApplicationInfo> list) {
Daniel Sandler388f6792010-03-02 14:08:08 -0500293 // Just remove and add, because they may need to be re-sorted.
294 removeApps(list);
295 addApps(list);
296 }
297
298 private static int findAppByComponent(ArrayList<ApplicationInfo> list, ApplicationInfo item) {
299 ComponentName component = item.intent.getComponent();
300 final int N = list.size();
301 for (int i=0; i<N; i++) {
302 ApplicationInfo x = list.get(i);
303 if (x.intent.getComponent().equals(component)) {
304 return i;
305 }
306 }
307 return -1;
308 }
309
310 public void dumpState() {
311 ApplicationInfo.dumpApplicationInfoList(TAG, "mAllAppsList", mAllAppsList);
312 }
Romain Guy13c2e7b2010-03-10 19:45:00 -0800313
314 public void surrender() {
315 }
Daniel Sandler388f6792010-03-02 14:08:08 -0500316}
317
318