Action bar work for phones

Drop tabs to a second row at < w480dp

Make 9-patches for the cab's "done" button thinner

Add a "disable home" display option to the action bar to turn off
focus and touch feedback when tapping home would do nothing

Change-Id: Ib2eedf311655f02055357321e2e9ad5b9037fed1
diff --git a/api/current.txt b/api/current.txt
index fd05e48..e66b9a3 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2102,6 +2102,7 @@
     method public abstract void setCustomView(android.view.View);
     method public abstract void setCustomView(android.view.View, android.app.ActionBar.LayoutParams);
     method public abstract void setCustomView(int);
+    method public abstract void setDisplayDisableHomeEnabled(boolean);
     method public abstract void setDisplayHomeAsUpEnabled(boolean);
     method public abstract void setDisplayOptions(int);
     method public abstract void setDisplayOptions(int, int);
@@ -2121,6 +2122,7 @@
     method public abstract void setTitle(java.lang.CharSequence);
     method public abstract void setTitle(int);
     method public abstract void show();
+    field public static final int DISPLAY_DISABLE_HOME = 32; // 0x20
     field public static final int DISPLAY_HOME_AS_UP = 4; // 0x4
     field public static final int DISPLAY_SHOW_CUSTOM = 16; // 0x10
     field public static final int DISPLAY_SHOW_HOME = 2; // 0x2
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java
index a9e84d7..cac06ec 100644
--- a/core/java/android/app/ActionBar.java
+++ b/core/java/android/app/ActionBar.java
@@ -107,6 +107,18 @@
     public static final int DISPLAY_SHOW_CUSTOM = 0x10;
 
     /**
+     * Disable the 'home' element. This may be combined with
+     * {@link #DISPLAY_SHOW_HOME} to create a non-focusable/non-clickable
+     * 'home' element. Useful for a level of your app's navigation hierarchy
+     * where clicking 'home' doesn't do anything.
+     *
+     * @see #setDisplayOptions(int)
+     * @see #setDisplayOptions(int, int)
+     * @see #setDisplayDisableHomeEnabled(boolean)
+     */
+    public static final int DISPLAY_DISABLE_HOME = 0x20;
+
+    /**
      * Set the action bar into custom navigation mode, supplying a view
      * for custom navigation.
      *
@@ -393,6 +405,21 @@
     public abstract void setDisplayShowCustomEnabled(boolean showCustom);
 
     /**
+     * Set whether the 'home' affordance on the action bar should be disabled.
+     * If set, the 'home' element will not be focusable or clickable, useful if
+     * the user is at the top level of the app's navigation hierarchy.
+     *
+     * <p>To set several display options at once, see the setDisplayOptions methods.
+     *
+     * @param disableHome true to disable the 'home' element.
+     *
+     * @see #setDisplayOptions(int)
+     * @see #setDisplayOptions(int, int)
+     * @see #DISPLAY_DISABLE_HOME
+     */
+    public abstract void setDisplayDisableHomeEnabled(boolean disableHome);
+
+    /**
      * Set the ActionBar's background.
      * 
      * @param d Background drawable
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index 9652085..dccfa6c 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -42,8 +42,10 @@
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.Window;
 import android.view.animation.DecelerateInterpolator;
+import android.widget.HorizontalScrollView;
 import android.widget.LinearLayout;
 import android.widget.SpinnerAdapter;
 
@@ -71,6 +73,7 @@
     private ActionBarContextView mUpperContextView;
     private LinearLayout mLowerContextView;
     private View mContentView;
+    private ViewGroup mExternalTabView;
 
     private ArrayList<TabImpl> mTabs = new ArrayList<TabImpl>();
 
@@ -172,6 +175,18 @@
         mActionView.setContextView(mUpperContextView);
         mContextDisplayMode = mLowerContextView == null ?
                 CONTEXT_DISPLAY_NORMAL : CONTEXT_DISPLAY_SPLIT;
+
+        if (!mActionView.hasEmbeddedTabs()) {
+            HorizontalScrollView tabScroller = new HorizontalScrollView(mContext);
+            ViewGroup tabContainer = mActionView.createTabContainer();
+            tabScroller.setHorizontalFadingEdgeEnabled(true);
+            tabScroller.addView(tabContainer);
+            tabScroller.setVisibility(getNavigationMode() == NAVIGATION_MODE_TABS ?
+                    View.VISIBLE : View.GONE);
+            mActionView.setExternalTabLayout(tabContainer);
+            mContainerView.setTabContainer(tabScroller);
+            mExternalTabView = tabScroller;
+        }
     }
 
     /**
@@ -239,6 +254,11 @@
     }
 
     @Override
+    public void setDisplayDisableHomeEnabled(boolean disableHome) {
+        setDisplayOptions(disableHome ? DISPLAY_DISABLE_HOME : 0, DISPLAY_DISABLE_HOME);
+    }
+
+    @Override
     public void setTitle(int resId) {
         setTitle(mContext.getString(resId));
     }
@@ -533,7 +553,7 @@
         final int count = mContainerView.getChildCount();
         for (int i = 0; i < count; i++) {
             final View child = mContainerView.getChildAt(i);
-            if (i == viewIndex) {
+            if (i == viewIndex || child == mContainerView.getTabContainer()) {
                 continue;
             }
 
@@ -840,11 +860,17 @@
             case NAVIGATION_MODE_TABS:
                 mSavedTabPosition = getSelectedNavigationIndex();
                 selectTab(null);
+                if (!mActionView.hasEmbeddedTabs()) {
+                    mExternalTabView.setVisibility(View.GONE);
+                }
                 break;
         }
         mActionView.setNavigationMode(mode);
         switch (mode) {
             case NAVIGATION_MODE_TABS:
+                if (!mActionView.hasEmbeddedTabs()) {
+                    mExternalTabView.setVisibility(View.VISIBLE);
+                }
                 if (mSavedTabPosition != INVALID_POSITION) {
                     setSelectedNavigationItem(mSavedTabPosition);
                     mSavedTabPosition = INVALID_POSITION;
diff --git a/core/java/com/android/internal/widget/ActionBarContainer.java b/core/java/com/android/internal/widget/ActionBarContainer.java
index c9b0ec9..3deb036 100644
--- a/core/java/com/android/internal/widget/ActionBarContainer.java
+++ b/core/java/com/android/internal/widget/ActionBarContainer.java
@@ -20,6 +20,7 @@
 import android.content.res.TypedArray;
 import android.util.AttributeSet;
 import android.view.MotionEvent;
+import android.view.View;
 import android.widget.FrameLayout;
 
 /**
@@ -29,6 +30,7 @@
  */
 public class ActionBarContainer extends FrameLayout {
     private boolean mIsTransitioning;
+    private View mTabContainer;
 
     public ActionBarContainer(Context context) {
         this(context, null);
@@ -65,6 +67,44 @@
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
         super.onTouchEvent(ev);
+
+        // An action bar always eats touch events.
         return true;
     }
+
+    public void setTabContainer(View tabView) {
+        if (mTabContainer != null) {
+            removeView(mTabContainer);
+        }
+        mTabContainer = tabView;
+        addView(tabView);
+    }
+
+    public View getTabContainer() {
+        return mTabContainer;
+    }
+
+    @Override
+    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        if (mTabContainer != null && mTabContainer.getVisibility() != GONE) {
+            final int mode = MeasureSpec.getMode(heightMeasureSpec);
+            if (mode == MeasureSpec.AT_MOST) {
+                final int measuredHeight = getMeasuredHeight();
+                final int maxHeight = MeasureSpec.getSize(heightMeasureSpec);
+                setMeasuredDimension(getMeasuredWidth(),
+                        Math.min(measuredHeight + mTabContainer.getMeasuredHeight(), maxHeight));
+            }
+        }
+    }
+
+    @Override
+    public void onLayout(boolean changed, int l, int t, int r, int b) {
+        super.onLayout(changed, l, t, r, b);
+        if (mTabContainer != null && mTabContainer.getVisibility() != GONE) {
+            final int containerHeight = getMeasuredHeight();
+            mTabContainer.layout(l, containerHeight - mTabContainer.getMeasuredHeight(),
+                    r, containerHeight);
+        }
+    }
 }
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index fa8eb51..a572e116 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -97,7 +97,7 @@
     private Spinner mSpinner;
     private LinearLayout mListNavLayout;
     private HorizontalScrollView mTabScrollView;
-    private LinearLayout mTabLayout;
+    private ViewGroup mTabLayout;
     private View mCustomNavView;
     private ProgressBar mProgressView;
     private ProgressBar mIndeterminateProgressView;
@@ -112,6 +112,7 @@
 
     private boolean mShowMenu;
     private boolean mUserTitle;
+    private boolean mIncludeTabs;
 
     private MenuBuilder mOptionsMenu;
     private ActionMenuView mMenuView;
@@ -201,6 +202,8 @@
         mProgressBarPadding = a.getDimensionPixelOffset(R.styleable.ActionBar_progressBarPadding, 0);
         mItemPadding = a.getDimensionPixelOffset(R.styleable.ActionBar_itemPadding, 0);
 
+        mIncludeTabs = a.getBoolean(R.styleable.ActionBar_embeddedTabs, true);
+
         setDisplayOptions(a.getInt(R.styleable.ActionBar_displayOptions, DISPLAY_DEFAULT));
 
         final int customNavId = a.getResourceId(R.styleable.ActionBar_customNavigationLayout, 0);
@@ -242,6 +245,14 @@
         addView(mIndeterminateProgressView);
     }
 
+    public boolean hasEmbeddedTabs() {
+        return mIncludeTabs;
+    }
+
+    public void setExternalTabLayout(ViewGroup tabLayout) {
+        mTabLayout = tabLayout;
+    }
+
     @Override
     public ActionMode startActionModeForChild(View child, ActionMode.Callback callback) {
         // No starting an action mode for an action bar child! (Where would it go?)
@@ -389,6 +400,12 @@
     public void setDisplayOptions(int options) {
         final int flagsChanged = options ^ mDisplayOptions;
         mDisplayOptions = options;
+
+        if ((flagsChanged & ActionBar.DISPLAY_DISABLE_HOME) != 0) {
+            final boolean disableHome = (options & ActionBar.DISPLAY_DISABLE_HOME) != 0;
+            mHomeLayout.setEnabled(!disableHome);
+        }
+
         if ((flagsChanged & DISPLAY_RELAYOUT_MASK) != 0) {
             final int vis = (options & ActionBar.DISPLAY_SHOW_HOME) != 0 ? VISIBLE : GONE;
             mHomeLayout.setVisibility(vis);
@@ -477,7 +494,7 @@
                 }
                 break;
             case ActionBar.NAVIGATION_MODE_TABS:
-                if (mTabLayout != null) {
+                if (mTabScrollView != null) {
                     removeView(mTabScrollView);
                 }
             }
@@ -502,7 +519,9 @@
                 break;
             case ActionBar.NAVIGATION_MODE_TABS:
                 ensureTabsExist();
-                addView(mTabScrollView);
+                if (mTabScrollView != null) {
+                    addView(mTabScrollView);
+                }
                 break;
             }
             mNavigationMode = mode;
@@ -511,15 +530,24 @@
     }
     
     private void ensureTabsExist() {
+        if (!mIncludeTabs) return;
+
         if (mTabScrollView == null) {
             mTabScrollView = new HorizontalScrollView(getContext());
             mTabScrollView.setHorizontalFadingEdgeEnabled(true);
-            mTabLayout = new LinearLayout(getContext(), null,
-                    com.android.internal.R.attr.actionBarTabBarStyle);
+            mTabLayout = createTabContainer();
             mTabScrollView.addView(mTabLayout);
         }
     }
 
+    public ViewGroup createTabContainer() {
+        ViewGroup result = new LinearLayout(getContext(), null,
+                com.android.internal.R.attr.actionBarTabBarStyle);
+        result.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
+                mContentHeight));
+        return result;
+    }
+
     public void setDropdownAdapter(SpinnerAdapter adapter) {
         mSpinnerAdapter = adapter;
         if (mSpinner != null) {
diff --git a/core/res/res/drawable-hdpi/btn_cab_done_default_holo.9.png b/core/res/res/drawable-hdpi/btn_cab_done_default_holo.9.png
index c66716f..f5e6054 100644
--- a/core/res/res/drawable-hdpi/btn_cab_done_default_holo.9.png
+++ b/core/res/res/drawable-hdpi/btn_cab_done_default_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_cab_done_focused_holo.9.png b/core/res/res/drawable-hdpi/btn_cab_done_focused_holo.9.png
index 0f1d9a0..1121070 100644
--- a/core/res/res/drawable-hdpi/btn_cab_done_focused_holo.9.png
+++ b/core/res/res/drawable-hdpi/btn_cab_done_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_cab_done_pressed_holo.9.png b/core/res/res/drawable-hdpi/btn_cab_done_pressed_holo.9.png
index 391227e..1a072a9 100644
--- a/core/res/res/drawable-hdpi/btn_cab_done_pressed_holo.9.png
+++ b/core/res/res/drawable-hdpi/btn_cab_done_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_cab_done_default_holo.9.png b/core/res/res/drawable-mdpi/btn_cab_done_default_holo.9.png
index 3a113ee..7af26ca 100644
--- a/core/res/res/drawable-mdpi/btn_cab_done_default_holo.9.png
+++ b/core/res/res/drawable-mdpi/btn_cab_done_default_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_cab_done_focused_holo.9.png b/core/res/res/drawable-mdpi/btn_cab_done_focused_holo.9.png
index 8496965..486c37a 100644
--- a/core/res/res/drawable-mdpi/btn_cab_done_focused_holo.9.png
+++ b/core/res/res/drawable-mdpi/btn_cab_done_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_cab_done_pressed_holo.9.png b/core/res/res/drawable-mdpi/btn_cab_done_pressed_holo.9.png
index dc70c6a..3cfb4bd 100644
--- a/core/res/res/drawable-mdpi/btn_cab_done_pressed_holo.9.png
+++ b/core/res/res/drawable-mdpi/btn_cab_done_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable/btn_cab_done.xml b/core/res/res/drawable/btn_cab_done.xml
index 154837d..e3cf461 100644
--- a/core/res/res/drawable/btn_cab_done.xml
+++ b/core/res/res/drawable/btn_cab_done.xml
@@ -16,11 +16,11 @@
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:state_window_focused="false" android:state_enabled="true"
-        android:drawable="@drawable/btn_cab_done_holo" />
+        android:drawable="@drawable/btn_cab_done_default_holo" />
     <item android:state_pressed="true"
         android:drawable="@drawable/btn_cab_done_pressed_holo" />
     <item android:state_focused="true" android:state_enabled="true"
         android:drawable="@drawable/btn_cab_done_focused_holo" />
     <item android:state_enabled="true"
-        android:drawable="@drawable/btn_cab_done_holo" />
+        android:drawable="@drawable/btn_cab_done_default_holo" />
 </selector>
diff --git a/core/res/res/values-w480dp/bools.xml b/core/res/res/values-w480dp/bools.xml
index ea7eeb5..c202d90 100644
--- a/core/res/res/values-w480dp/bools.xml
+++ b/core/res/res/values-w480dp/bools.xml
@@ -18,4 +18,5 @@
 -->
 <resources>
     <bool name="allow_action_menu_item_text_with_icon">true</bool>
+    <bool name="action_bar_embed_tabs">true</bool>
 </resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index e8767d8..3a44e4f 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -4850,6 +4850,7 @@
             <flag name="homeAsUp" value="0x4" />
             <flag name="showTitle" value="0x8" />
             <flag name="showCustom" value="0x10" />
+            <flag name="disableHome" value="0x20" />
         </attr>
         <!-- Specifies title text used for navigationMode="normal" -->
         <attr name="title" />
@@ -4882,6 +4883,9 @@
         <!-- Specifies padding that should be applied to the left and right sides of
              system-provided items in the bar. -->
         <attr name="itemPadding" format="dimension" />
+        <!-- Specifies whether tabs should be embedded within the bar itself (true)
+             or displayed elsewhere (false). -->
+        <attr name="embeddedTabs" format="boolean" />
     </declare-styleable>
 
     <declare-styleable name="ActionMode">
diff --git a/core/res/res/values/bools.xml b/core/res/res/values/bools.xml
index c7dcb51..6eb006f 100644
--- a/core/res/res/values/bools.xml
+++ b/core/res/res/values/bools.xml
@@ -18,4 +18,5 @@
 -->
 <resources>
     <bool name="allow_action_menu_item_text_with_icon">false</bool>
+    <bool name="action_bar_embed_tabs">false</bool>
 </resources>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 198ff8b..8ce35f8 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1074,6 +1074,7 @@
         <item name="android:progressBarStyle">@android:style/Widget.ProgressBar.Horizontal</item>
         <item name="android:indeterminateProgressStyle">@android:style/Widget.ProgressBar.Small</item>
         <item name="android:homeLayout">@android:layout/action_bar_home</item>
+        <item name="android:embeddedTabs">@android:bool/action_bar_embed_tabs</item>
     </style>
 
     <style name="Widget.ActionMode">