blob: 90c87fb18bcf98b0c823c3a1e9e474a78577a603 [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 Sandler388f6792010-03-02 14:08:08 -050022import android.graphics.drawable.BitmapDrawable;
Daniel Sandler388f6792010-03-02 14:08:08 -050023import android.util.AttributeSet;
24import android.util.Log;
25import android.view.KeyEvent;
26import android.view.ViewGroup;
Daniel Sandler388f6792010-03-02 14:08:08 -050027import android.view.LayoutInflater;
Daniel Sandler388f6792010-03-02 14:08:08 -050028import android.view.View;
Daniel Sandler388f6792010-03-02 14:08:08 -050029import android.view.animation.AnimationUtils;
30import android.view.ViewConfiguration;
Daniel Sandler388f6792010-03-02 14:08:08 -050031import android.widget.AdapterView;
32import android.widget.ImageButton;
33import android.widget.TextView;
34import android.widget.ArrayAdapter;
35import android.widget.GridView;
36import android.widget.RelativeLayout;
37
38import java.util.ArrayList;
Daniel Sandler388f6792010-03-02 14:08:08 -050039import java.util.Collections;
Daniel Sandler388f6792010-03-02 14:08:08 -050040
Romain Guyedcce092010-03-04 13:03:17 -080041import com.android.launcher.R;
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";
52
53 private Launcher mLauncher;
54 private DragController mDragController;
55
56 private GridView mGrid;
57
58 private ArrayList<ApplicationInfo> mAllAppsList = new ArrayList<ApplicationInfo>();
59
Daniel Sandler73a05542010-03-09 14:45:57 -050060 // preserve compatibility with 3D all apps:
61 // 0.0 -> hidden
62 // 1.0 -> shown and opaque
63 // intermediate values -> partially shown & partially opaque
Daniel Sandler388f6792010-03-02 14:08:08 -050064 private float mZoom;
65
66 private AppsAdapter mAppsAdapter;
67
68 // ------------------------------------------------------------
Daniel Sandler73a05542010-03-09 14:45:57 -050069
70 public static class HomeButton extends ImageButton {
71 public HomeButton(Context context, AttributeSet attrs) {
72 super(context, attrs);
73 }
74 @Override
75 public View focusSearch(int direction) {
76 if (direction == FOCUS_UP) return super.focusSearch(direction);
77 return null;
78 }
79 }
Daniel Sandler388f6792010-03-02 14:08:08 -050080
81 public class AppsAdapter extends ArrayAdapter<ApplicationInfo> {
82 private final LayoutInflater mInflater;
83
84 public AppsAdapter(Context context, ArrayList<ApplicationInfo> apps) {
85 super(context, 0, apps);
86 mInflater = LayoutInflater.from(context);
87 }
88
89 @Override
90 public View getView(int position, View convertView, ViewGroup parent) {
91 final ApplicationInfo info = getItem(position);
92
93 if (convertView == null) {
94 convertView = mInflater.inflate(R.layout.application_boxed, parent, false);
95 }
96
97// if (!info.filtered) {
98// info.icon = Utilities.createIconThumbnail(info.icon, getContext());
99// info.filtered = true;
100// }
101
102 final TextView textView = (TextView) convertView;
103 textView.setCompoundDrawablesWithIntrinsicBounds(null, new BitmapDrawable(info.iconBitmap), null, null);
104 textView.setText(info.title);
105
106 return convertView;
107 }
108 }
109
110 public AllApps2D(Context context, AttributeSet attrs) {
111 super(context, attrs);
112 setVisibility(View.GONE);
113 setSoundEffectsEnabled(false);
114
115 mAppsAdapter = new AppsAdapter(getContext(), mAllAppsList);
116 mAppsAdapter.setNotifyOnChange(false);
117 }
118
119 @Override
120 protected void onFinishInflate() {
121 setBackgroundColor(0xFF000000);
122
Daniel Sandlerc351eb82010-03-03 15:05:19 -0500123 try {
124 mGrid = (GridView)findViewWithTag("all_apps_2d_grid");
125 if (mGrid == null) throw new Resources.NotFoundException();
126 mGrid.setOnItemClickListener(this);
127 mGrid.setOnItemLongClickListener(this);
128
129 ImageButton homeButton = (ImageButton) findViewWithTag("all_apps_2d_home");
130 if (homeButton == null) throw new Resources.NotFoundException();
131 homeButton.setOnClickListener(
132 new View.OnClickListener() {
133 public void onClick(View v) {
134 mLauncher.closeAllApps(true);
135 }
136 });
137 } catch (Resources.NotFoundException e) {
138 Log.e(TAG, "Can't find necessary layout elements for AllApps2D");
139 }
Daniel Sandler388f6792010-03-02 14:08:08 -0500140
Daniel Sandlerc351eb82010-03-03 15:05:19 -0500141 setOnKeyListener(this);
Daniel Sandler388f6792010-03-02 14:08:08 -0500142 }
143
144 public AllApps2D(Context context, AttributeSet attrs, int defStyle) {
145 this(context, attrs);
146 }
147
148 public void setLauncher(Launcher launcher) {
149 mLauncher = launcher;
150 }
151
152 public boolean onKey(View v, int keyCode, KeyEvent event) {
153 if (!isVisible()) return false;
154
155 switch (keyCode) {
156 case KeyEvent.KEYCODE_BACK:
157 mLauncher.closeAllApps(true);
158 break;
159 default:
160 return false;
161 }
162
163 return true;
164 }
165
166 public void onItemClick(AdapterView parent, View v, int position, long id) {
167 ApplicationInfo app = (ApplicationInfo) parent.getItemAtPosition(position);
Joe Onoratof984e852010-03-25 09:47:45 -0700168 mLauncher.startActivitySafely(app.intent, app);
Daniel Sandler388f6792010-03-02 14:08:08 -0500169 }
170
171 public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
172 if (!view.isInTouchMode()) {
173 return false;
174 }
175
176 ApplicationInfo app = (ApplicationInfo) parent.getItemAtPosition(position);
177 app = new ApplicationInfo(app);
178
179 mDragController.startDrag(view, this, app, DragController.DRAG_ACTION_COPY);
180 mLauncher.closeAllApps(true);
181
182 return true;
183 }
184
Daniel Sandler73a05542010-03-09 14:45:57 -0500185 protected void onFocusChanged(boolean gainFocus, int direction, android.graphics.Rect prev) {
186 if (gainFocus) {
187 mGrid.requestFocus();
188 }
189 }
Daniel Sandler388f6792010-03-02 14:08:08 -0500190
191 public void setDragController(DragController dragger) {
192 mDragController = dragger;
193 }
194
195 public void onDropCompleted(View target, boolean success) {
196 }
197
198 /**
199 * Zoom to the specifed level.
200 *
201 * @param zoom [0..1] 0 is hidden, 1 is open
202 */
203 public void zoom(float zoom, boolean animate) {
204// Log.d(TAG, "zooming " + ((zoom == 1.0) ? "open" : "closed"));
205 cancelLongPress();
206
207 mZoom = zoom;
208
209 if (isVisible()) {
210 getParent().bringChildToFront(this);
211 setVisibility(View.VISIBLE);
212 mGrid.setAdapter(mAppsAdapter);
213 if (animate) {
214 startAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.all_apps_2d_fade_in));
215 } else {
216 onAnimationEnd();
217 }
218 } else {
219 if (animate) {
220 startAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.all_apps_2d_fade_out));
221 } else {
222 onAnimationEnd();
223 }
224 }
225 }
226
227 protected void onAnimationEnd() {
228 if (!isVisible()) {
229 setVisibility(View.GONE);
230 mGrid.setAdapter(null);
231 mZoom = 0.0f;
232 } else {
233 mZoom = 1.0f;
234 }
Daniel Sandlerc351eb82010-03-03 15:05:19 -0500235
236 mLauncher.zoomed(mZoom);
Daniel Sandler388f6792010-03-02 14:08:08 -0500237 }
238
239 public boolean isVisible() {
240 return mZoom > 0.001f;
241 }
242
243 @Override
244 public boolean isOpaque() {
245 return mZoom > 0.999f;
246 }
247
248 public void setApps(ArrayList<ApplicationInfo> list) {
249 mAllAppsList.clear();
250 addApps(list);
251 }
252
253 public void addApps(ArrayList<ApplicationInfo> list) {
254// Log.d(TAG, "addApps: " + list.size() + " apps: " + list.toString());
255
256 final int N = list.size();
257
258 for (int i=0; i<N; i++) {
259 final ApplicationInfo item = list.get(i);
260 int index = Collections.binarySearch(mAllAppsList, item,
261 LauncherModel.APP_NAME_COMPARATOR);
262 if (index < 0) {
263 index = -(index+1);
264 }
265 mAllAppsList.add(index, item);
266 }
267 mAppsAdapter.notifyDataSetChanged();
268 }
269
270 public void removeApps(ArrayList<ApplicationInfo> list) {
271 final int N = list.size();
272 for (int i=0; i<N; i++) {
273 final ApplicationInfo item = list.get(i);
274 int index = findAppByComponent(mAllAppsList, item);
275 if (index >= 0) {
276 mAllAppsList.remove(index);
277 } else {
278 Log.w(TAG, "couldn't find a match for item \"" + item + "\"");
279 // Try to recover. This should keep us from crashing for now.
280 }
281 }
282 mAppsAdapter.notifyDataSetChanged();
283 }
284
Joe Onorato64e6be72010-03-05 15:05:52 -0500285 public void updateApps(ArrayList<ApplicationInfo> list) {
Daniel Sandler388f6792010-03-02 14:08:08 -0500286 // Just remove and add, because they may need to be re-sorted.
287 removeApps(list);
288 addApps(list);
289 }
290
291 private static int findAppByComponent(ArrayList<ApplicationInfo> list, ApplicationInfo item) {
292 ComponentName component = item.intent.getComponent();
293 final int N = list.size();
294 for (int i=0; i<N; i++) {
295 ApplicationInfo x = list.get(i);
296 if (x.intent.getComponent().equals(component)) {
297 return i;
298 }
299 }
300 return -1;
301 }
302
303 public void dumpState() {
304 ApplicationInfo.dumpApplicationInfoList(TAG, "mAllAppsList", mAllAppsList);
305 }
Romain Guy13c2e7b2010-03-10 19:45:00 -0800306
307 public void surrender() {
308 }
Daniel Sandler388f6792010-03-02 14:08:08 -0500309}
310
311