Merge "ActionBarCompat support for ActionBarDrawerToggle" into jb-mr2-dev
diff --git a/v4/java/android/support/v4/app/ActionBarDrawerToggle.java b/v4/java/android/support/v4/app/ActionBarDrawerToggle.java
index 67801d1..11eea28 100644
--- a/v4/java/android/support/v4/app/ActionBarDrawerToggle.java
+++ b/v4/java/android/support/v4/app/ActionBarDrawerToggle.java
@@ -55,6 +55,42 @@
  */
 public class ActionBarDrawerToggle implements DrawerLayout.DrawerListener {
 
+    /**
+     * Allows an implementing Activity to return an {@link ActionBarDrawerToggle.Delegate} to use
+     * with ActionBarDrawerToggle.
+     */
+    public interface DelegateProvider {
+
+        /**
+         * @return Delegate to use for ActionBarDrawableToggles, or null if the Activity
+         *         does not wish to override the default behavior.
+         */
+        Delegate getDrawerToggleDelegate();
+    }
+
+    public interface Delegate {
+        /**
+         * @return Up indicator drawable as defined in the Activity's theme, or null if one is not
+         *         defined.
+         */
+        Drawable getThemeUpIndicator();
+
+        /**
+         * Set the Action Bar's up indicator drawable and content description.
+         *
+         * @param upDrawable     - Drawable to set as up indicator
+         * @param contentDescRes - Content description to set
+         */
+        void setActionBarUpIndicator(Drawable upDrawable, int contentDescRes);
+
+        /**
+         * Set the Action Bar's up indicator content description.
+         *
+         * @param contentDescRes - Content description to set
+         */
+        void setActionBarDescription(int contentDescRes);
+    }
+
     private interface ActionBarDrawerToggleImpl {
         Drawable getThemeUpIndicator(Activity activity);
         Object setActionBarUpIndicator(Object info, Activity activity,
@@ -117,6 +153,7 @@
     private static final int ID_HOME = 0x0102002c;
 
     private final Activity mActivity;
+    private final Delegate mActivityImpl;
     private final DrawerLayout mDrawerLayout;
     private boolean mDrawerIndicatorEnabled = true;
 
@@ -156,10 +193,17 @@
         mOpenDrawerContentDescRes = openDrawerContentDescRes;
         mCloseDrawerContentDescRes = closeDrawerContentDescRes;
 
-        mThemeImage = IMPL.getThemeUpIndicator(activity);
+        mThemeImage = getThemeUpIndicator();
         mDrawerImage = activity.getResources().getDrawable(drawerImageRes);
         mSlider = new SlideDrawable(mDrawerImage);
         mSlider.setOffsetBy(1.f / 3);
+
+        // Allow the Activity to provide an impl
+        if (activity instanceof DelegateProvider) {
+            mActivityImpl = ((DelegateProvider) activity).getDrawerToggleDelegate();
+        } else {
+            mActivityImpl = null;
+        }
     }
 
     /**
@@ -179,8 +223,7 @@
         }
 
         if (mDrawerIndicatorEnabled) {
-            mSetIndicatorInfo = IMPL.setActionBarUpIndicator(mSetIndicatorInfo, mActivity,
-                    mSlider, mDrawerLayout.isDrawerOpen(GravityCompat.START) ?
+            setActionBarUpIndicator(mSlider, mDrawerLayout.isDrawerOpen(GravityCompat.START) ?
                     mOpenDrawerContentDescRes : mCloseDrawerContentDescRes);
         }
     }
@@ -198,12 +241,10 @@
     public void setDrawerIndicatorEnabled(boolean enable) {
         if (enable != mDrawerIndicatorEnabled) {
             if (enable) {
-                mSetIndicatorInfo = IMPL.setActionBarUpIndicator(mSetIndicatorInfo,
-                        mActivity, mSlider, mDrawerLayout.isDrawerOpen(GravityCompat.START) ?
-                        mOpenDrawerContentDescRes : mCloseDrawerContentDescRes);
+                setActionBarUpIndicator(mSlider, mDrawerLayout.isDrawerOpen(GravityCompat.START) ?
+                                mOpenDrawerContentDescRes : mCloseDrawerContentDescRes);
             } else {
-                mSetIndicatorInfo = IMPL.setActionBarUpIndicator(mSetIndicatorInfo,
-                        mActivity, mThemeImage, 0);
+                setActionBarUpIndicator(mThemeImage, 0);
             }
             mDrawerIndicatorEnabled = enable;
         }
@@ -226,7 +267,7 @@
      */
     public void onConfigurationChanged(Configuration newConfig) {
         // Reload drawables that can change with configuration
-        mThemeImage = IMPL.getThemeUpIndicator(mActivity);
+        mThemeImage = getThemeUpIndicator();
         mDrawerImage = mActivity.getResources().getDrawable(mDrawerImageResource);
         syncState();
     }
@@ -282,8 +323,7 @@
     public void onDrawerOpened(View drawerView) {
         mSlider.setOffset(1.f);
         if (mDrawerIndicatorEnabled) {
-            mSetIndicatorInfo = IMPL.setActionBarDescription(mSetIndicatorInfo, mActivity,
-                    mOpenDrawerContentDescRes);
+            setActionBarDescription(mOpenDrawerContentDescRes);
         }
     }
 
@@ -298,8 +338,7 @@
     public void onDrawerClosed(View drawerView) {
         mSlider.setOffset(0.f);
         if (mDrawerIndicatorEnabled) {
-            mSetIndicatorInfo = IMPL.setActionBarDescription(mSetIndicatorInfo, mActivity,
-                    mCloseDrawerContentDescRes);
+            setActionBarDescription(mCloseDrawerContentDescRes);
         }
     }
 
@@ -314,6 +353,31 @@
     public void onDrawerStateChanged(int newState) {
     }
 
+    Drawable getThemeUpIndicator() {
+        if (mActivityImpl != null) {
+            return mActivityImpl.getThemeUpIndicator();
+        }
+        return IMPL.getThemeUpIndicator(mActivity);
+    }
+
+    void setActionBarUpIndicator(Drawable upDrawable, int contentDescRes) {
+        if (mActivityImpl != null) {
+            mActivityImpl.setActionBarUpIndicator(upDrawable, contentDescRes);
+            return;
+        }
+        mSetIndicatorInfo = IMPL
+                .setActionBarUpIndicator(mSetIndicatorInfo, mActivity, upDrawable, contentDescRes);
+    }
+
+    void setActionBarDescription(int contentDescRes) {
+        if (mActivityImpl != null) {
+            mActivityImpl.setActionBarDescription(contentDescRes);
+            return;
+        }
+        mSetIndicatorInfo = IMPL
+                .setActionBarDescription(mSetIndicatorInfo, mActivity, contentDescRes);
+    }
+
     private static class SlideDrawable extends Drawable implements Drawable.Callback {
         private Drawable mWrapped;
         private float mOffset;
diff --git a/v7/appcompat/src/android/support/v7/app/ActionBarActivity.java b/v7/appcompat/src/android/support/v7/app/ActionBarActivity.java
index b06556d..b6f1568 100644
--- a/v7/appcompat/src/android/support/v7/app/ActionBarActivity.java
+++ b/v7/appcompat/src/android/support/v7/app/ActionBarActivity.java
@@ -21,6 +21,7 @@
 import android.content.res.Configuration;
 import android.os.Build;
 import android.os.Bundle;
+import android.support.v4.app.ActionBarDrawerToggle;
 import android.support.v4.app.ActivityCompat;
 import android.support.v4.app.FragmentActivity;
 import android.support.v4.app.NavUtils;
@@ -38,7 +39,7 @@
  * Base class for activities that use the support library action bar features.
  */
 public class ActionBarActivity extends FragmentActivity implements ActionBar.Callback,
-        TaskStackBuilder.SupportParentable {
+        TaskStackBuilder.SupportParentable, ActionBarDrawerToggle.DelegateProvider {
     ActionBarActivityDelegate mImpl;
 
     /**
@@ -425,4 +426,8 @@
         NavUtils.navigateUpTo(this, upIntent);
     }
 
+    @Override
+    public final ActionBarDrawerToggle.Delegate getDrawerToggleDelegate() {
+        return mImpl.getDrawerToggleDelegate();
+    }
 }
diff --git a/v7/appcompat/src/android/support/v7/app/ActionBarActivityDelegate.java b/v7/appcompat/src/android/support/v7/app/ActionBarActivityDelegate.java
index e8a943d..c53f1bb 100644
--- a/v7/appcompat/src/android/support/v7/app/ActionBarActivityDelegate.java
+++ b/v7/appcompat/src/android/support/v7/app/ActionBarActivityDelegate.java
@@ -23,6 +23,7 @@
 import android.content.res.TypedArray;
 import android.os.Build;
 import android.os.Bundle;
+import android.support.v4.app.ActionBarDrawerToggle;
 import android.support.v7.appcompat.R;
 import android.support.v7.internal.view.SupportMenuInflater;
 import android.support.v7.view.ActionMode;
@@ -145,6 +146,8 @@
 
     abstract void setSupportProgress(int progress);
 
+    abstract ActionBarDrawerToggle.Delegate getDrawerToggleDelegate();
+
     protected final String getUiOptionsFromMetadata() {
         try {
             PackageManager pm = mActivity.getPackageManager();
diff --git a/v7/appcompat/src/android/support/v7/app/ActionBarActivityDelegateBase.java b/v7/appcompat/src/android/support/v7/app/ActionBarActivityDelegateBase.java
index 62a2c74..93923cf 100644
--- a/v7/appcompat/src/android/support/v7/app/ActionBarActivityDelegateBase.java
+++ b/v7/appcompat/src/android/support/v7/app/ActionBarActivityDelegateBase.java
@@ -19,6 +19,8 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.support.v4.app.ActionBarDrawerToggle;
 import android.support.v4.view.WindowCompat;
 import android.support.v7.appcompat.R;
 import android.support.v7.internal.view.menu.ListMenuPresenter;
@@ -31,7 +33,6 @@
 import android.support.v7.internal.widget.ActionBarView;
 import android.support.v7.internal.widget.ProgressBarICS;
 import android.support.v7.view.ActionMode;
-import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuItem;
@@ -44,6 +45,10 @@
         MenuPresenter.Callback, MenuBuilder.Callback {
     private static final String TAG = "ActionBarActivityDelegateBase";
 
+    private static final int[] ACTION_BAR_DRAWABLE_TOGGLE_ATTRS = new int[] {
+            R.attr.homeAsUpIndicator
+    };
+
     private ActionBarView mActionBarView;
     private ListMenuPresenter mListMenuPresenter;
     private MenuBuilder mMenu;
@@ -471,6 +476,11 @@
         updateProgressBars(Window.PROGRESS_START + progress);
     }
 
+    @Override
+    ActionBarDrawerToggle.Delegate getDrawerToggleDelegate() {
+        return new ActionBarDrawableToggleImpl();
+    }
+
     /**
      * Progress Bar function. Mostly extracted from PhoneWindow.java
      */
@@ -579,4 +589,28 @@
         }
     }
 
+    private class ActionBarDrawableToggleImpl
+            implements ActionBarDrawerToggle.Delegate {
+
+        @Override
+        public Drawable getThemeUpIndicator() {
+            final TypedArray a = mActivity.obtainStyledAttributes(ACTION_BAR_DRAWABLE_TOGGLE_ATTRS);
+            final Drawable result = a.getDrawable(0);
+            a.recycle();
+            return result;
+        }
+
+        @Override
+        public void setActionBarUpIndicator(Drawable upDrawable, int contentDescRes) {
+            if (mActionBarView != null) {
+                mActionBarView.setHomeAsUpIndicator(upDrawable);
+            }
+        }
+
+        @Override
+        public void setActionBarDescription(int contentDescRes) {
+            // No support for setting Action Bar content description
+        }
+    }
+
 }
diff --git a/v7/appcompat/src/android/support/v7/app/ActionBarActivityDelegateHC.java b/v7/appcompat/src/android/support/v7/app/ActionBarActivityDelegateHC.java
index 4610c1a..7540cc4 100644
--- a/v7/appcompat/src/android/support/v7/app/ActionBarActivityDelegateHC.java
+++ b/v7/appcompat/src/android/support/v7/app/ActionBarActivityDelegateHC.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.os.Bundle;
+import android.support.v4.app.ActionBarDrawerToggle;
 import android.support.v4.view.WindowCompat;
 import android.support.v7.internal.view.ActionModeWrapper;
 import android.support.v7.internal.view.menu.MenuWrapperFactory;
@@ -219,6 +220,12 @@
         return false;
     }
 
+    @Override
+    public ActionBarDrawerToggle.Delegate getDrawerToggleDelegate() {
+        // Return null so that ActionBarDrawableToggle uses it's standard impl
+        return null;
+    }
+
     class WindowCallbackWrapper implements Window.Callback {
         final Window.Callback mWrapped;
 
diff --git a/v7/appcompat/src/android/support/v7/internal/widget/ActionBarView.java b/v7/appcompat/src/android/support/v7/internal/widget/ActionBarView.java
index d30e2ad..8232081 100644
--- a/v7/appcompat/src/android/support/v7/internal/widget/ActionBarView.java
+++ b/v7/appcompat/src/android/support/v7/internal/widget/ActionBarView.java
@@ -1191,6 +1191,14 @@
         }
     }
 
+    public void setHomeAsUpIndicator(Drawable indicator) {
+        mHomeLayout.setUpIndicator(indicator);
+    }
+
+    public void setHomeAsUpIndicator(int resId) {
+        mHomeLayout.setUpIndicator(resId);
+    }
+
     static class SavedState extends BaseSavedState {
 
         int expandedMenuItemId;
@@ -1226,12 +1234,11 @@
     }
 
     private static class HomeView extends FrameLayout {
-
-        private View mUpView;
-
+        private ImageView mUpView;
         private ImageView mIconView;
-
         private int mUpWidth;
+        private int mUpIndicatorRes;
+        private Drawable mDefaultUpIndicator;
 
         public HomeView(Context context) {
             this(context, null);
@@ -1249,6 +1256,25 @@
             mIconView.setImageDrawable(icon);
         }
 
+        public void setUpIndicator(Drawable d) {
+            mUpView.setImageDrawable(d != null ? d : mDefaultUpIndicator);
+            mUpIndicatorRes = 0;
+        }
+
+        public void setUpIndicator(int resId) {
+            mUpIndicatorRes = resId;
+            mUpView.setImageDrawable(resId != 0 ? getResources().getDrawable(resId) : null);
+        }
+
+        @Override
+        protected void onConfigurationChanged(Configuration newConfig) {
+            super.onConfigurationChanged(newConfig);
+            if (mUpIndicatorRes != 0) {
+                // Reload for config change
+                setUpIndicator(mUpIndicatorRes);
+            }
+        }
+
         @Override
         public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
             final CharSequence cdesc = getContentDescription();
@@ -1260,8 +1286,9 @@
 
         @Override
         protected void onFinishInflate() {
-            mUpView = findViewById(R.id.up);
+            mUpView = (ImageView) findViewById(R.id.up);
             mIconView = (ImageView) findViewById(R.id.home);
+            mDefaultUpIndicator = mUpView.getDrawable();
         }
 
         public int getLeftOffset() {