Introduce 2D All Apps and other support for sapphire-class devices.

AllAppsView is now the 2D, GridView-based version (very
similar to classic Launcher); AllApps3D is the
RenderScript/Rollo implementation.

TODO:
 - some mdpi assets are not in fact mdpi
 - related to above: static wallpapers not working yet
 - add dynamic selection of 2D/3D AA; currently you must
   choose one at build time by picking the appropriate class
   in all_apps.xml (see separate CL for sapphire overlay
   that does this)

Change-Id: I253d98404ea8a329a4049d2e48edd2e5129fa6ba
diff --git a/src/com/android/launcher2/AllApps2D.java b/src/com/android/launcher2/AllApps2D.java
new file mode 100644
index 0000000..4c7b28c
--- /dev/null
+++ b/src/com/android/launcher2/AllApps2D.java
@@ -0,0 +1,309 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher2;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.drawable.BitmapDrawable;
+import android.os.SystemClock;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.ViewGroup;
+import android.view.MotionEvent;
+import android.view.LayoutInflater;
+import android.view.SoundEffectConstants;
+import android.view.SurfaceHolder;
+import android.view.VelocityTracker;
+import android.view.View;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+import android.view.ViewConfiguration;
+import android.view.accessibility.AccessibilityEvent;
+import android.widget.AdapterView;
+import android.widget.ImageButton;
+import android.widget.TextView;
+import android.widget.ArrayAdapter;
+import android.widget.GridView;
+import android.widget.RelativeLayout;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+
+
+public class AllApps2D
+        extends RelativeLayout
+        implements AllAppsView,
+                   AdapterView.OnItemClickListener,
+                   AdapterView.OnItemLongClickListener,
+                   View.OnKeyListener,
+                   DragSource {
+
+    private static final String TAG = "Launcher.AllApps2D";
+
+    private Launcher mLauncher;
+    private DragController mDragController;
+
+    private GridView mGrid;
+
+    private ArrayList<ApplicationInfo> mAllAppsList = new ArrayList<ApplicationInfo>();
+
+    /**
+     * True when we are using arrow keys or trackball to drive navigation
+     */
+    private boolean mArrowNavigation = false;
+    private boolean mStartedScrolling;
+
+    /**
+     * Used to keep track of the selection when AllApps2D loses window focus.
+     * One of the SELECTION_ constants.
+     */
+    private int mLastSelection;
+
+    /**
+     * Used to keep track of the selection when AllApps2D loses window focus
+     */
+    private int mLastSelectedIcon;
+
+    private float mZoom;
+
+    private AppsAdapter mAppsAdapter;
+
+    // ------------------------------------------------------------
+
+    public class AppsAdapter extends ArrayAdapter<ApplicationInfo> {
+        private final LayoutInflater mInflater;
+
+        public AppsAdapter(Context context, ArrayList<ApplicationInfo> apps) {
+            super(context, 0, apps);
+            mInflater = LayoutInflater.from(context);
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            final ApplicationInfo info = getItem(position);
+
+            if (convertView == null) {
+                convertView = mInflater.inflate(R.layout.application_boxed, parent, false);
+            }
+
+//            if (!info.filtered) {
+//                info.icon = Utilities.createIconThumbnail(info.icon, getContext());
+//                info.filtered = true;
+//            }
+
+            final TextView textView = (TextView) convertView;
+            textView.setCompoundDrawablesWithIntrinsicBounds(null, new BitmapDrawable(info.iconBitmap), null, null);
+            textView.setText(info.title);
+
+            return convertView;
+        }
+    }
+
+    public AllApps2D(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        setVisibility(View.GONE);
+        setSoundEffectsEnabled(false);
+
+        mAppsAdapter = new AppsAdapter(getContext(), mAllAppsList);
+        mAppsAdapter.setNotifyOnChange(false);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        setBackgroundColor(0xFF000000);
+
+        mGrid = (GridView)findViewById(R.id.all_apps_2d_grid);
+        mGrid.setOnItemClickListener(this);
+        mGrid.setOnItemLongClickListener(this);
+        
+        setOnKeyListener(this);
+
+        ImageButton homeButton = (ImageButton) findViewById(R.id.all_apps_2d_home);
+        homeButton.setOnClickListener(
+            new View.OnClickListener() {
+                public void onClick(View v) {
+                    mLauncher.closeAllApps(true);
+                }
+            });
+    }
+
+    public AllApps2D(Context context, AttributeSet attrs, int defStyle) {
+        this(context, attrs);
+    }
+
+    public void setLauncher(Launcher launcher) {
+        mLauncher = launcher;
+    }
+
+    public boolean onKey(View v, int keyCode, KeyEvent event) {
+        if (!isVisible()) return false;
+
+        switch (keyCode) {
+            case KeyEvent.KEYCODE_BACK:
+                mLauncher.closeAllApps(true);
+                break;
+            default:
+                return false;
+        }
+
+        return true;
+    }
+
+    public void onItemClick(AdapterView parent, View v, int position, long id) {
+        ApplicationInfo app = (ApplicationInfo) parent.getItemAtPosition(position);
+        mLauncher.startActivitySafely(app.intent);
+    }
+
+    public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
+        if (!view.isInTouchMode()) {
+            return false;
+        }
+
+        ApplicationInfo app = (ApplicationInfo) parent.getItemAtPosition(position);
+        app = new ApplicationInfo(app);
+
+        mDragController.startDrag(view, this, app, DragController.DRAG_ACTION_COPY);
+        mLauncher.closeAllApps(true);
+
+        return true;
+    }
+
+
+    public void setDragController(DragController dragger) {
+        mDragController = dragger;
+    }
+
+    public void onDropCompleted(View target, boolean success) {
+    }
+
+    /**
+     * Zoom to the specifed level.
+     *
+     * @param zoom [0..1] 0 is hidden, 1 is open
+     */
+    public void zoom(float zoom, boolean animate) {
+//        Log.d(TAG, "zooming " + ((zoom == 1.0) ? "open" : "closed"));
+        cancelLongPress();
+
+        mZoom = zoom;
+
+        if (isVisible()) {
+            getParent().bringChildToFront(this);
+            setVisibility(View.VISIBLE);
+            mGrid.setAdapter(mAppsAdapter);
+            if (animate) {
+                startAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.all_apps_2d_fade_in));
+            } else {
+                onAnimationEnd();
+            }
+        } else {
+            if (animate) {
+                startAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.all_apps_2d_fade_out));
+            } else {
+                onAnimationEnd();
+            }
+        }
+    }
+
+    protected void onAnimationEnd() {
+        if (!isVisible()) {
+            setVisibility(View.GONE);
+            mGrid.setAdapter(null);
+            mZoom = 0.0f;
+        } else {
+            mZoom = 1.0f;
+        }
+    }
+
+    public boolean isVisible() {
+        return mZoom > 0.001f;
+    }
+
+    @Override
+    public boolean isOpaque() {
+        return mZoom > 0.999f;
+    }
+
+    public void setApps(ArrayList<ApplicationInfo> list) {
+        mAllAppsList.clear();
+        addApps(list);
+    }
+
+    public void addApps(ArrayList<ApplicationInfo> list) {
+//        Log.d(TAG, "addApps: " + list.size() + " apps: " + list.toString());
+
+        final int N = list.size();
+
+        for (int i=0; i<N; i++) {
+            final ApplicationInfo item = list.get(i);
+            int index = Collections.binarySearch(mAllAppsList, item,
+                    LauncherModel.APP_NAME_COMPARATOR);
+            if (index < 0) {
+                index = -(index+1);
+            }
+            mAllAppsList.add(index, item);
+        }
+        mAppsAdapter.notifyDataSetChanged();
+    }
+
+    public void removeApps(ArrayList<ApplicationInfo> list) {
+        final int N = list.size();
+        for (int i=0; i<N; i++) {
+            final ApplicationInfo item = list.get(i);
+            int index = findAppByComponent(mAllAppsList, item);
+            if (index >= 0) {
+                mAllAppsList.remove(index);
+            } else {
+                Log.w(TAG, "couldn't find a match for item \"" + item + "\"");
+                // Try to recover.  This should keep us from crashing for now.
+            }
+        }
+        mAppsAdapter.notifyDataSetChanged();
+    }
+
+    public void updateApps(String packageName, ArrayList<ApplicationInfo> list) {
+        // Just remove and add, because they may need to be re-sorted.
+        removeApps(list);
+        addApps(list);
+    }
+
+    private static int findAppByComponent(ArrayList<ApplicationInfo> list, ApplicationInfo item) {
+        ComponentName component = item.intent.getComponent();
+        final int N = list.size();
+        for (int i=0; i<N; i++) {
+            ApplicationInfo x = list.get(i);
+            if (x.intent.getComponent().equals(component)) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    public void dumpState() {
+        ApplicationInfo.dumpApplicationInfoList(TAG, "mAllAppsList", mAllAppsList);
+    }
+}
+
+