Show edit contact photo options is a dialog

* Instead of a ListPopupWindow. This is more consistent with
  the behavior of the other edit contact menu options.
* Also add an option menu icon to change the photo to
  make this feature more easily accessible and since
  users may not realize they can click the photo to
  launch the choices dialog.

Bug 19124091

Change-Id: Ia4c37b3093f39d55784323f9a6d7bcf49ee96d16
diff --git a/res/drawable-hdpi/ic_photo_camera_white_24dp.png b/res/drawable-hdpi/ic_photo_camera_white_24dp.png
new file mode 100644
index 0000000..497c88c
--- /dev/null
+++ b/res/drawable-hdpi/ic_photo_camera_white_24dp.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_photo_camera_white_24dp.png b/res/drawable-mdpi/ic_photo_camera_white_24dp.png
new file mode 100644
index 0000000..e830522
--- /dev/null
+++ b/res/drawable-mdpi/ic_photo_camera_white_24dp.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_photo_camera_white_24dp.png b/res/drawable-xhdpi/ic_photo_camera_white_24dp.png
new file mode 100644
index 0000000..be9fb22
--- /dev/null
+++ b/res/drawable-xhdpi/ic_photo_camera_white_24dp.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_photo_camera_white_24dp.png b/res/drawable-xxhdpi/ic_photo_camera_white_24dp.png
new file mode 100644
index 0000000..c8e69dc
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_photo_camera_white_24dp.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_photo_camera_white_24dp.png b/res/drawable-xxxhdpi/ic_photo_camera_white_24dp.png
new file mode 100644
index 0000000..777658e
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_photo_camera_white_24dp.png
Binary files differ
diff --git a/res/menu/edit_contact.xml b/res/menu/edit_contact.xml
index fe6d2b9..be15720 100644
--- a/res/menu/edit_contact.xml
+++ b/res/menu/edit_contact.xml
@@ -37,6 +37,15 @@
         android:id="@+id/menu_delete"
         android:title="@string/menu_deleteContact" />
 
+    <!-- The compact contact editor will set this to visible but we don't want it
+         in the fully expanded contact editor. -->
+    <item
+        android:id="@+id/menu_change_photo"
+        android:title="@string/menu_change_photo"
+        android:icon="@drawable/ic_photo_camera_white_24dp"
+        android:showAsAction="always"
+        android:visible="false" />
+
     <item
         android:id="@+id/menu_set_ringtone"
         android:title="@string/menu_set_ring_tone" />
diff --git a/res/values/strings.xml b/res/values/strings.xml
index dd56162..3a1a55d 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -114,6 +114,9 @@
     <!-- Menu item used to delete a specific contact -->
     <string name="menu_deleteContact">Delete</string>
 
+    <!-- Menu item used to change the photo for a specific contact [CHAR LIMIT=30]-->
+    <string name="menu_change_photo">Change photo</string>
+
     <!-- Menu item used to create a contact shortcut when viewing contact details. [CHAR LIMIT=30] -->
     <string name="menu_create_contact_shortcut">Place on Home screen</string>
 
diff --git a/src/com/android/contacts/editor/CompactContactEditorFragment.java b/src/com/android/contacts/editor/CompactContactEditorFragment.java
index 5635d09..5145416 100644
--- a/src/com/android/contacts/editor/CompactContactEditorFragment.java
+++ b/src/com/android/contacts/editor/CompactContactEditorFragment.java
@@ -36,6 +36,8 @@
 import android.os.Bundle;
 import android.util.Log;
 import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.LinearLayout;
@@ -47,7 +49,7 @@
  * Contact editor with only the most important fields displayed initially.
  */
 public class CompactContactEditorFragment extends ContactEditorBaseFragment implements
-        CompactRawContactsEditorView.Listener {
+        CompactRawContactsEditorView.Listener, PhotoSourceDialogFragment.Listener {
 
     private static final String KEY_PHOTO_URI = "photo_uri";
     private static final String KEY_PHOTO_RAW_CONTACT_ID = "photo_raw_contact_id";
@@ -57,12 +59,13 @@
     /**
      * Displays a PopupWindow with photo edit options.
      */
-    final class PhotoHandler extends PhotoSelectionHandler {
+    final class PhotoHandler extends PhotoSelectionHandler implements View.OnClickListener {
 
         /**
          * Receiver of photo edit option callbacks.
          */
         private final class PhotoListener extends PhotoActionListener {
+
             @Override
             public void onRemovePictureChosen() {
                 getContent().setPhoto(/* bitmap =*/ null);
@@ -90,11 +93,21 @@
         }
 
         private PhotoListener mPhotoListener;
+        private int mPhotoMode;
 
-        public PhotoHandler(Context context, View changeAnchorView, int photoMode,
-                boolean isDirectoryContact, RawContactDeltaList state) {
-            super(context, changeAnchorView, photoMode, isDirectoryContact, state);
+        public PhotoHandler(Context context, int photoMode, RawContactDeltaList state) {
+            // We pass a null changeAnchorView since we are overriding onClick so that we
+            // can show the photo options in a dialog instead of a ListPopupWindow (which would
+            // be anchored at changeAnchorView).
+            super(context, /* changeAnchorView =*/ null, photoMode, /* isDirectoryContact =*/ false,
+                    state);
             mPhotoListener = new PhotoListener();
+            mPhotoMode = photoMode;
+        }
+
+        @Override
+        public void onClick(View view) {
+            PhotoSourceDialogFragment.show(CompactContactEditorFragment.this, mPhotoMode);
         }
 
         @Override
@@ -166,6 +179,26 @@
     }
 
     @Override
+    public void onPrepareOptionsMenu(Menu menu) {
+        super.onPrepareOptionsMenu(menu);
+        menu.findItem(R.id.menu_change_photo).setVisible(true);
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        if (super.onOptionsItemSelected(item)) {
+            return true;
+        }
+        if (item.getItemId() == R.id.menu_change_photo) {
+            if (mPhotoHandler != null) {
+                mPhotoHandler.onClick(/* view =*/ null);
+            }
+            return true;
+        }
+        return false;
+    }
+
+    @Override
     protected void bindEditors() {
         if (!isReadyToBindEditors()) {
             return;
@@ -231,8 +264,7 @@
                     ? PhotoActionPopup.Modes.NO_PHOTO : PhotoActionPopup.Modes.READ_ONLY_PHOTO;
         }
 
-        return new PhotoHandler(getActivity(), getContent().getPhotoPopupAnchorView(),
-                photoMode, /* isDirectoryContact =*/ false, mState);
+        return new PhotoHandler(getActivity(), photoMode, mState);
     }
 
     @Override
@@ -263,6 +295,27 @@
     }
 
     @Override
+    public void onRemovePictureChosen() {
+        if (mPhotoHandler != null) {
+            mPhotoHandler.getListener().onRemovePictureChosen();
+        }
+    }
+
+    @Override
+    public void onTakePhotoChosen() {
+        if (mPhotoHandler != null) {
+            mPhotoHandler.getListener().onTakePhotoChosen();
+        }
+    }
+
+    @Override
+    public void onPickFromGalleryChosen() {
+        if (mPhotoHandler != null) {
+            mPhotoHandler.getListener().onPickFromGalleryChosen();
+        }
+    }
+
+    @Override
     public void onExpandEditor() {
         Toast.makeText(mContext, "Not yet implemented", Toast.LENGTH_SHORT).show();
     }
diff --git a/src/com/android/contacts/editor/CompactHeaderView.java b/src/com/android/contacts/editor/CompactHeaderView.java
index 5634b8a..bf26866 100644
--- a/src/com/android/contacts/editor/CompactHeaderView.java
+++ b/src/com/android/contacts/editor/CompactHeaderView.java
@@ -161,13 +161,6 @@
     }
 
     /**
-     * Returns the View to anchor the PopupWindow with photo edit options to.
-     */
-    public View getPhotoPopupAnchorView() {
-        return mPhotoImageView;
-    }
-
-    /**
      * Set the given {@link Bitmap} as the photo in the underlying {@link ValuesDelta}
      * and bind a thumbnail to the UI.
      */
diff --git a/src/com/android/contacts/editor/CompactRawContactsEditorView.java b/src/com/android/contacts/editor/CompactRawContactsEditorView.java
index 6560ad0..3173c8c 100644
--- a/src/com/android/contacts/editor/CompactRawContactsEditorView.java
+++ b/src/com/android/contacts/editor/CompactRawContactsEditorView.java
@@ -169,14 +169,6 @@
     }
 
     /**
-     * Pass through to {@link CompactHeaderView#getPhotoPopupAnchorView}.
-     */
-    public View getPhotoPopupAnchorView() {
-        return mHeader.getPhotoPopupAnchorView();
-    }
-
-
-    /**
      * Get the raw contact ID for the CompactHeaderView photo.
      */
     // TODO: remove me once we support multiple accounts
diff --git a/src/com/android/contacts/editor/ContactEditorBaseFragment.java b/src/com/android/contacts/editor/ContactEditorBaseFragment.java
index 1f21190..d2f8aa7 100644
--- a/src/com/android/contacts/editor/ContactEditorBaseFragment.java
+++ b/src/com/android/contacts/editor/ContactEditorBaseFragment.java
@@ -67,7 +67,6 @@
 import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
 import android.provider.ContactsContract.Contacts;
 import android.provider.ContactsContract.Intents;
-import android.provider.ContactsContract.QuickContact;
 import android.provider.ContactsContract.RawContacts;
 import android.util.Log;
 import android.view.LayoutInflater;
diff --git a/src/com/android/contacts/editor/PhotoActionPopup.java b/src/com/android/contacts/editor/PhotoActionPopup.java
index 14b195b..be8db86 100644
--- a/src/com/android/contacts/editor/PhotoActionPopup.java
+++ b/src/com/android/contacts/editor/PhotoActionPopup.java
@@ -64,8 +64,7 @@
                 Flags.TAKE_OR_PICK_PHOTO_REPLACE_WORDING;
     }
 
-    public static ListPopupWindow createPopupMenu(Context context, View anchorView,
-            final Listener listener, int mode) {
+    public static ArrayList<ChoiceListItem> getChoices(Context context, int mode) {
         // Build choices, depending on the current mode. We assume this Dialog is never called
         // if there are NO choices (e.g. a read-only picture is already super-primary)
         final ArrayList<ChoiceListItem> choices = new ArrayList<ChoiceListItem>(4);
@@ -86,6 +85,12 @@
             }
             choices.add(new ChoiceListItem(ChoiceListItem.ID_PICK_PHOTO, pickPhotoString));
         }
+        return choices;
+    }
+
+    public static ListPopupWindow createPopupMenu(Context context, View anchorView,
+            final Listener listener, int mode) {
+        final ArrayList<ChoiceListItem> choices = getChoices(context, mode);
 
         final ListAdapter adapter = new ArrayAdapter<ChoiceListItem>(context,
                 R.layout.select_dialog_item, choices);
@@ -124,7 +129,7 @@
         return listPopupWindow;
     }
 
-    private static final class ChoiceListItem {
+    public static final class ChoiceListItem {
         private final int mId;
         private final String mCaption;
 
diff --git a/src/com/android/contacts/editor/PhotoSourceDialogFragment.java b/src/com/android/contacts/editor/PhotoSourceDialogFragment.java
new file mode 100644
index 0000000..e16fdae
--- /dev/null
+++ b/src/com/android/contacts/editor/PhotoSourceDialogFragment.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2015 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.contacts.editor;
+
+import com.android.contacts.R;
+import com.android.contacts.editor.PhotoActionPopup.ChoiceListItem;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
+import android.os.Bundle;
+
+import java.util.ArrayList;
+
+/**
+ * Displays the options for changing the contact photo.
+ */
+public class PhotoSourceDialogFragment extends DialogFragment {
+
+    private static final String ARG_PHOTO_MODE = "photoMode";
+
+    /**
+     * Callbacks for the host of the {@link PhotoSourceDialogFragment}.
+     */
+    public interface Listener {
+        void onRemovePictureChosen();
+        void onTakePhotoChosen();
+        void onPickFromGalleryChosen();
+    }
+
+    public static void show(CompactContactEditorFragment fragment, int photoMode) {
+        final Bundle args = new Bundle();
+        args.putInt(ARG_PHOTO_MODE, photoMode);
+
+        PhotoSourceDialogFragment dialog = new PhotoSourceDialogFragment();
+        dialog.setTargetFragment(fragment, 0);
+        dialog.setArguments(args);
+        dialog.show(fragment.getFragmentManager(), "photoSource");
+    }
+
+    @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        // Get the available options for changing the photo
+        final int photoMode = getArguments().getInt(ARG_PHOTO_MODE);
+        final ArrayList<ChoiceListItem> choices =
+                PhotoActionPopup.getChoices(getActivity(), photoMode);
+
+        // Prepare the AlertDialog items and click listener
+        final CharSequence[] items = new CharSequence[choices.size()];
+        for (int i = 0; i < items.length; i++) {
+            items[i] = choices.get(i).toString();
+        }
+        final OnClickListener clickListener = new OnClickListener() {
+            @Override
+            public void onClick(DialogInterface dialogInterface, int which) {
+                final Listener listener = (Listener) getTargetFragment();
+                final ChoiceListItem choice = choices.get(which);
+                switch (choice.getId()) {
+                    case ChoiceListItem.ID_REMOVE:
+                        listener.onRemovePictureChosen();
+                        break;
+                    case ChoiceListItem.ID_TAKE_PHOTO:
+                        listener.onTakePhotoChosen();
+                        break;
+                    case ChoiceListItem.ID_PICK_PHOTO:
+                        listener.onPickFromGalleryChosen();
+                        break;
+                }
+                dismiss();
+            }
+        };
+
+        // Build the AlertDialog
+        final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+        builder.setTitle(R.string.menu_change_photo);
+        builder.setItems(items, clickListener);
+        builder.setNegativeButton(android.R.string.cancel, /* listener =*/ null);
+        return builder.create();
+    }
+}