Fix bug 4818050 - Need a way to get notified when a PopupMenu gets
dismissed/canceled

Add an OnDismissListener to PopupMenu.

Change-Id: I7abe1b9c9bea5e758a9c32631185e50cd7eb1ed0
diff --git a/api/current.txt b/api/current.txt
index fa3130a..1bc0812 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -25281,10 +25281,16 @@
     method public void dismiss();
     method public android.view.Menu getMenu();
     method public android.view.MenuInflater getMenuInflater();
+    method public void inflate(int);
+    method public void setOnDismissListener(android.widget.PopupMenu.OnDismissListener);
     method public void setOnMenuItemClickListener(android.widget.PopupMenu.OnMenuItemClickListener);
     method public void show();
   }
 
+  public static abstract interface PopupMenu.OnDismissListener {
+    method public abstract void onDismiss(android.widget.PopupMenu);
+  }
+
   public static abstract interface PopupMenu.OnMenuItemClickListener {
     method public abstract boolean onMenuItemClick(android.view.MenuItem);
   }
diff --git a/core/java/android/widget/PopupMenu.java b/core/java/android/widget/PopupMenu.java
index 82770ad..17512d8 100644
--- a/core/java/android/widget/PopupMenu.java
+++ b/core/java/android/widget/PopupMenu.java
@@ -18,6 +18,7 @@
 
 import com.android.internal.view.menu.MenuBuilder;
 import com.android.internal.view.menu.MenuPopupHelper;
+import com.android.internal.view.menu.MenuPresenter;
 import com.android.internal.view.menu.SubMenuBuilder;
 
 import android.content.Context;
@@ -32,12 +33,25 @@
  * If the IME is visible the popup will not overlap it until it is touched. Touching outside
  * of the popup will dismiss it.
  */
-public class PopupMenu implements MenuBuilder.Callback {
+public class PopupMenu implements MenuBuilder.Callback, MenuPresenter.Callback {
     private Context mContext;
     private MenuBuilder mMenu;
     private View mAnchor;
     private MenuPopupHelper mPopup;
     private OnMenuItemClickListener mMenuItemClickListener;
+    private OnDismissListener mDismissListener;
+
+    /**
+     * Callback interface used to notify the application that the menu has closed.
+     */
+    public interface OnDismissListener {
+        /**
+         * Called when the associated menu has been dismissed.
+         *
+         * @param menu The PopupMenu that was dismissed.
+         */
+        public void onDismiss(PopupMenu menu);
+    }
 
     /**
      * Construct a new PopupMenu.
@@ -53,6 +67,7 @@
         mMenu.setCallback(this);
         mAnchor = anchor;
         mPopup = new MenuPopupHelper(context, mMenu, anchor);
+        mPopup.setCallback(this);
     }
 
     /**
@@ -77,6 +92,15 @@
     }
 
     /**
+     * Inflate a menu resource into this PopupMenu. This is equivalent to calling
+     * popupMenu.getMenuInflater().inflate(menuRes, popupMenu.getMenu()).
+     * @param menuRes Menu resource to inflate
+     */
+    public void inflate(int menuRes) {
+        getMenuInflater().inflate(menuRes, mMenu);
+    }
+
+    /**
      * Show the menu popup anchored to the view specified during construction.
      * @see #dismiss()
      */
@@ -92,11 +116,25 @@
         mPopup.dismiss();
     }
 
+    /**
+     * Set a listener that will be notified when the user selects an item from the menu.
+     *
+     * @param listener Listener to notify
+     */
     public void setOnMenuItemClickListener(OnMenuItemClickListener listener) {
         mMenuItemClickListener = listener;
     }
 
     /**
+     * Set a listener that will be notified when this menu is dismissed.
+     *
+     * @param listener Listener to notify
+     */
+    public void setOnDismissListener(OnDismissListener listener) {
+        mDismissListener = listener;
+    }
+
+    /**
      * @hide
      */
     public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
@@ -110,12 +148,15 @@
      * @hide
      */
     public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
+        if (mDismissListener != null) {
+            mDismissListener.onDismiss(this);
+        }
     }
 
     /**
      * @hide
      */
-    public boolean onSubMenuSelected(SubMenuBuilder subMenu) {
+    public boolean onOpenSubMenu(MenuBuilder subMenu) {
         if (!subMenu.hasVisibleItems()) {
             return true;
         }
diff --git a/core/java/com/android/internal/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
index 8db7e3c..cffbb4e 100644
--- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java
+++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
@@ -126,6 +126,7 @@
 
     public void onDismiss() {
         mPopup = null;
+        mMenu.close();
         if (mTreeObserver != null) {
             if (!mTreeObserver.isAlive()) mTreeObserver = mAnchorView.getViewTreeObserver();
             mTreeObserver.removeGlobalOnLayoutListener(this);