Updating the Static Wallpaper picker for Tablet

- Updated WallpaperChooser to use FragmentDialogs
- Backwards compatible with old WallpaperChooser
  UI on non XLarge screens
- There is a known bug with AlertDialogs (b/3225529)
  that prevents an AlertDialog to expand to fit its
  content. The squishing of the GridView is caused
  by that bug.

Change-Id: I49381aab4aa24362e8c92da284797fce0e63823c
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 4aa5d68..905b8b6 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -88,6 +88,7 @@
             android:name="com.android.launcher2.WallpaperChooser"
             android:label="@string/pick_wallpaper"
             android:icon="@drawable/ic_launcher_wallpaper"
+            android:theme="@style/Theme.WallpaperPicker"
             android:screenOrientation="nosensor"
             android:finishOnCloseSystemDialogs="true">
             <intent-filter>
diff --git a/res/layout-xlarge/wallpaper_chooser.xml b/res/layout-xlarge/wallpaper_chooser.xml
new file mode 100644
index 0000000..9649e88
--- /dev/null
+++ b/res/layout-xlarge/wallpaper_chooser.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2010, 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.
+*/
+-->
+
+<GridView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/gallery"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:numColumns="4"
+    android:columnWidth="@dimen/wallpaper_small_width"
+    android:stretchMode="columnWidth" />
\ No newline at end of file
diff --git a/res/layout-xlarge/wallpaper_item.xml b/res/layout-xlarge/wallpaper_item.xml
new file mode 100644
index 0000000..4246b9a
--- /dev/null
+++ b/res/layout-xlarge/wallpaper_item.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.
+-->
+
+<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="@dimen/wallpaper_small_width"
+    android:layout_height="wrap_content"
+    android:padding="5dp"
+    android:scaleType="fitXY"
+    android:adjustViewBounds="false"
+    android:focusable="false" />
diff --git a/res/layout/wallpaper_chooser_base.xml b/res/layout/wallpaper_chooser_base.xml
new file mode 100644
index 0000000..8447027
--- /dev/null
+++ b/res/layout/wallpaper_chooser_base.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2010, 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.
+*/
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/wallpaper_chooser_base"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+</FrameLayout>
diff --git a/res/values-xlarge/dimens.xml b/res/values-xlarge/dimens.xml
index d98674f..7033553 100644
--- a/res/values-xlarge/dimens.xml
+++ b/res/values-xlarge/dimens.xml
@@ -50,4 +50,7 @@
     <dimen name="delete_zone_size">50dip</dimen>
     <dimen name="delete_zone_min_padding">10dip</dimen>
     <dimen name="delete_zone_max_padding">20dip</dimen>
+
+    <!-- dimensions for the wallpaper picker wallpaper thumbnail width -->
+    <dimen name="wallpaper_small_width">170dp</dimen>
 </resources>
diff --git a/res/values-xlarge/strings.xml b/res/values-xlarge/strings.xml
new file mode 100644
index 0000000..738baf5
--- /dev/null
+++ b/res/values-xlarge/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* Copyright (C) 2010 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.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Option in "Select wallpaper from" dialog box -->
+    <string name="pick_wallpaper">Select wallpaper</string>
+    <string name="wallpaper_cancel">Cancel</string>
+</resources>
\ No newline at end of file
diff --git a/res/values-xlarge/styles.xml b/res/values-xlarge/styles.xml
index fcbd969..5198d30 100644
--- a/res/values-xlarge/styles.xml
+++ b/res/values-xlarge/styles.xml
@@ -18,6 +18,9 @@
 -->
 
 <resources>
+    <style name="Theme.WallpaperPicker" parent="android:Theme.Holo.Dialog.NoFrame">
+    </style>
+
     <style name="Theme" parent="android:Theme.Holo">
         <item name="android:windowNoTitle">true</item>
         <item name="android:windowActionModeOverlay">true</item>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index d6cd3ee..39739c2 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -44,4 +44,8 @@
     <!-- the area at the edge of the screen that makes the workspace go left
          or right while you're dragging. -->
     <dimen name="scroll_zone">20dp</dimen>
+
+    <!-- How much the content view of an alert dialog should be inset (currently used
+        for the WallpaperChooser in XLarge mode) -->
+    <dimen name="alert_dialog_content_inset">15dp</dimen>
 </resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index a97b3c5..c867d38 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -18,6 +18,10 @@
 -->
 
 <resources>
+    <style name="Theme.WallpaperPicker" parent="android:Theme">
+        <item name="android:windowNoTitle">true</item>
+    </style>
+
     <style name="Theme.Base" parent="android:Theme.Wallpaper">
     </style>
 
diff --git a/src/com/android/launcher2/WallpaperChooser.java b/src/com/android/launcher2/WallpaperChooser.java
index bf8ba2e..113a8e6 100644
--- a/src/com/android/launcher2/WallpaperChooser.java
+++ b/src/com/android/launcher2/WallpaperChooser.java
@@ -17,7 +17,13 @@
 package com.android.launcher2;
 
 import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.app.FragmentTransaction;
 import android.app.WallpaperManager;
+import android.content.Context;
+import android.content.DialogInterface;
 import android.content.res.Resources;
 import android.graphics.BitmapFactory;
 import android.graphics.Bitmap;
@@ -28,27 +34,26 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.Window;
 import android.view.View.OnClickListener;
 import android.widget.AdapterView;
 import android.widget.BaseAdapter;
 import android.widget.Gallery;
+import android.widget.GridView;
 import android.widget.ImageView;
+import android.widget.ListAdapter;
+import android.widget.SpinnerAdapter;
 
 import java.io.IOException;
 import java.util.ArrayList;
 
 import com.android.launcher.R;
 
-public class WallpaperChooser extends Activity implements AdapterView.OnItemSelectedListener,
-        OnClickListener {
+public class WallpaperChooser extends Activity {
     private static final String TAG = "Launcher.WallpaperChooser";
 
-    private Gallery mGallery;
-    private ImageView mImageView;
-    private boolean mIsWallpaperSet;
-
-    private Bitmap mBitmap;
+    private ViewGroup mWallpaperChooserBase;
+    private ImageView mImageView = null;
+    private Bitmap mBitmap = null;
 
     private ArrayList<Integer> mThumbs;
     private ArrayList<Integer> mImages;
@@ -57,20 +62,35 @@
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
-        requestWindowFeature(Window.FEATURE_NO_TITLE);
+        /* We need some container to attach to in order for the fragment to be
+         * considered embedded, so inflate an empty FrameLayout and use that
+         * as the parent view
+         */
+        setContentView(R.layout.wallpaper_chooser_base);
+        mWallpaperChooserBase = (ViewGroup) findViewById(R.id.wallpaper_chooser_base);
 
         findWallpapers();
 
-        setContentView(R.layout.wallpaper_chooser);
+        DialogFragment newFragment = new WallpaperDialogFragment(this);
+        if (LauncherApplication.isScreenXLarge()) {
+            // Display a dialog instead of embedding the view in the activity
+            newFragment.show(getFragmentManager(), "dialog");
+        } else {
+            // Embed the fragment in the base view
+            FragmentTransaction ft = getFragmentManager().openTransaction();
+            ft.add(R.id.wallpaper_chooser_base, newFragment);
+            ft.commit();
+        }
+    }
 
-        mGallery = (Gallery) findViewById(R.id.gallery);
-        mGallery.setAdapter(new ImageAdapter(this));
-        mGallery.setOnItemSelectedListener(this);
-        mGallery.setCallbackDuringFling(false);
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
 
-        findViewById(R.id.set).setOnClickListener(this);
-
-        mImageView = (ImageView) findViewById(R.id.wallpaper);
+        if (mLoader != null && mLoader.getStatus() != WallpaperLoader.Status.FINISHED) {
+            mLoader.cancel(true);
+            mLoader = null;
+        }
     }
 
     private void findWallpapers() {
@@ -105,40 +125,7 @@
         }
     }
 
-    @Override
-    protected void onResume() {
-        super.onResume();
-        mIsWallpaperSet = false;
-    }
-
-    @Override
-    protected void onDestroy() {
-        super.onDestroy();
-        
-        if (mLoader != null && mLoader.getStatus() != WallpaperLoader.Status.FINISHED) {
-            mLoader.cancel(true);
-            mLoader = null;
-        }
-    }
-
-    public void onItemSelected(AdapterView parent, View v, int position, long id) {
-        if (mLoader != null && mLoader.getStatus() != WallpaperLoader.Status.FINISHED) {
-            mLoader.cancel();
-        }
-        mLoader = (WallpaperLoader) new WallpaperLoader().execute(position);
-    }
-
-    /*
-     * When using touch if you tap an image it triggers both the onItemClick and
-     * the onTouchEvent causing the wallpaper to be set twice. Ensure we only
-     * set the wallpaper once.
-     */
     private void selectWallpaper(int position) {
-        if (mIsWallpaperSet) {
-            return;
-        }
-
-        mIsWallpaperSet = true;
         try {
             WallpaperManager wpm = (WallpaperManager)getSystemService(WALLPAPER_SERVICE);
             wpm.setResource(mImages.get(position));
@@ -149,10 +136,95 @@
         }
     }
 
-    public void onNothingSelected(AdapterView parent) {
+    private class WallpaperDialogFragment extends DialogFragment implements
+            AdapterView.OnItemSelectedListener, AdapterView.OnItemClickListener {
+        private Context mContext;
+
+        public WallpaperDialogFragment(Context context) {
+            super();
+            mContext = context;
+            setCancelable(true);
+        }
+
+        @Override
+        public void onDismiss(DialogInterface dialog) {
+            WallpaperChooser.this.finish();
+        }
+
+        /* This will only be called when in XLarge mode, since this Fragment is invoked like
+         * a dialog in that mode
+         */
+        @Override
+        public Dialog onCreateDialog(Bundle savedInstanceState) {
+            final View v = getLayoutInflater().inflate(
+                    R.layout.wallpaper_chooser, mWallpaperChooserBase, false);
+
+            GridView gridView = (GridView) v.findViewById(R.id.gallery);
+            gridView.setOnItemClickListener(this);
+            gridView.setAdapter(new ImageAdapter(WallpaperChooser.this));
+
+            final int viewInset =
+                    getResources().getDimensionPixelSize(R.dimen.alert_dialog_content_inset);
+
+            AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
+            builder.setCancelable(true);
+            builder.setNegativeButton(R.string.wallpaper_cancel, null);
+            builder.setTitle(R.string.pick_wallpaper);
+            builder.setView(gridView, viewInset, viewInset, viewInset, viewInset);
+            return builder.create();
+        }
+
+        /* This will be called on both XLarge and small screens, but since the dialog
+         * is already created on XLarge, we want to skip this view creation
+         */
+        @Override
+        public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                Bundle savedInstanceState) {
+            /* Only generate a custom view if this fragment is being embedded in a view,
+             * i.e: on a small screen
+             */
+            if (!LauncherApplication.isScreenXLarge()) {
+                View view = inflater.inflate(R.layout.wallpaper_chooser, container, false);
+
+                final Gallery gallery = (Gallery) view.findViewById(R.id.gallery);
+                gallery.setCallbackDuringFling(false);
+                gallery.setOnItemSelectedListener(this);
+                gallery.setAdapter(new ImageAdapter(WallpaperChooser.this));
+
+                View setButton = view.findViewById(R.id.set);
+                setButton.setOnClickListener(new OnClickListener() {
+                    @Override
+                    public void onClick(View v) {
+                        selectWallpaper(gallery.getSelectedItemPosition());
+                    }
+                });
+                mImageView = (ImageView) view.findViewById(R.id.wallpaper);
+                return view;
+            }
+            return super.onCreateView(inflater, container, savedInstanceState);
+        }
+
+        // Click handler for the Dialog's GridView
+        @Override
+        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+            selectWallpaper(position);
+        }
+
+        // Selection handler for the embedded Gallery view
+        @Override
+        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+            if (mLoader != null && mLoader.getStatus() != WallpaperLoader.Status.FINISHED) {
+                mLoader.cancel();
+            }
+            mLoader = (WallpaperLoader) new WallpaperLoader().execute(position);
+        }
+
+        @Override
+        public void onNothingSelected(AdapterView<?> parent) {
+        }
     }
 
-    private class ImageAdapter extends BaseAdapter {
+    private class ImageAdapter extends BaseAdapter implements ListAdapter, SpinnerAdapter {
         private LayoutInflater mLayoutInflater;
 
         ImageAdapter(WallpaperChooser context) {
@@ -179,7 +251,7 @@
             } else {
                 image = (ImageView) convertView;
             }
-            
+
             int thumbRes = mThumbs.get(position);
             image.setImageResource(thumbRes);
             Drawable thumbDrawable = image.getDrawable();
@@ -189,14 +261,11 @@
                 Log.e(TAG, "Error decoding thumbnail resId=" + thumbRes + " for wallpaper #"
                         + position);
             }
+
             return image;
         }
     }
 
-    public void onClick(View v) {
-        selectWallpaper(mGallery.getSelectedItemPosition());
-    }
-
     class WallpaperLoader extends AsyncTask<Integer, Void, Bitmap> {
         BitmapFactory.Options mOptions;
 
@@ -205,7 +274,8 @@
             mOptions.inDither = false;
             mOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;            
         }
-        
+
+        @Override
         protected Bitmap doInBackground(Integer... params) {
             if (isCancelled()) return null;
             try {
@@ -225,17 +295,20 @@
                 if (mBitmap != null) {
                     mBitmap.recycle();
                 }
-    
-                final ImageView view = mImageView;
-                view.setImageBitmap(b);
-    
-                mBitmap = b;
-    
-                final Drawable drawable = view.getDrawable();
-                drawable.setFilterBitmap(true);
-                drawable.setDither(true);
 
-                view.postInvalidate();
+                // This should always be the case, but check anyways
+                final ImageView view = mImageView;
+                if (view != null) {
+                    view.setImageBitmap(b);
+
+                    mBitmap = b;
+
+                    final Drawable drawable = view.getDrawable();
+                    drawable.setFilterBitmap(true);
+                    drawable.setDither(true);
+
+                    view.postInvalidate();
+                }
 
                 mLoader = null;
             } else {