New tab rendering

    Rendering tabs from a fixed background asset

Change-Id: Ic02ed0c059486c2bb8157f19012f98099bf7e75a
diff --git a/res/drawable-hdpi/browsertab_add.png b/res/drawable-hdpi/browsertab_add.png
new file mode 100644
index 0000000..a48b0f8
--- /dev/null
+++ b/res/drawable-hdpi/browsertab_add.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_menu_new_window.png b/res/drawable-hdpi/ic_menu_new_window.png
index fa544fc..fd85bb7 100644
--- a/res/drawable-hdpi/ic_menu_new_window.png
+++ b/res/drawable-hdpi/ic_menu_new_window.png
Binary files differ
diff --git a/res/drawable-mdpi/bg_browsertabs.png b/res/drawable-mdpi/bg_browsertabs.png
new file mode 100644
index 0000000..9d0ff07
--- /dev/null
+++ b/res/drawable-mdpi/bg_browsertabs.png
Binary files differ
diff --git a/res/drawable-mdpi/browsertab_add.png b/res/drawable-mdpi/browsertab_add.png
new file mode 100644
index 0000000..cb12775
--- /dev/null
+++ b/res/drawable-mdpi/browsertab_add.png
Binary files differ
diff --git a/res/drawable-mdpi/browsertab_inactive.png b/res/drawable-mdpi/browsertab_inactive.png
new file mode 100644
index 0000000..d441604
--- /dev/null
+++ b/res/drawable-mdpi/browsertab_inactive.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_menu_new_window.png b/res/drawable-mdpi/ic_menu_new_window.png
index c767979..c495162 100644
--- a/res/drawable-mdpi/ic_menu_new_window.png
+++ b/res/drawable-mdpi/ic_menu_new_window.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_tab_close.png b/res/drawable-mdpi/ic_tab_close.png
index 2f23842..b86c714 100644
--- a/res/drawable-mdpi/ic_tab_close.png
+++ b/res/drawable-mdpi/ic_tab_close.png
Binary files differ
diff --git a/res/drawable-nodpi/bg_urlbar.png b/res/drawable-nodpi/bg_urlbar.png
new file mode 100644
index 0000000..ff173c4
--- /dev/null
+++ b/res/drawable-nodpi/bg_urlbar.png
Binary files differ
diff --git a/res/layout/tab_bar.xml b/res/layout/tab_bar.xml
index 2726055..e8f146c 100644
--- a/res/layout/tab_bar.xml
+++ b/res/layout/tab_bar.xml
@@ -14,20 +14,24 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/tabbarcontent"
     android:layout_width="match_parent"
-    android:layout_height="48dip"
+    android:layout_height="56dip"
     android:orientation="horizontal"
+    android:paddingLeft="12dip"
+    android:paddingTop="12dip"
+    android:paddingRight="0dip"
+    android:paddingBottom="0dip"
     style="@style/ActionBarStyle"
     >
     <com.android.browser.TabScrollView
         android:id="@+id/tabs"
         android:layout_width="wrap_content"
-        android:layout_height="match_parent"
+        android:layout_height="44dip"
         android:orientation="horizontal" />
     <ImageButton
         android:id="@+id/newtab"
         android:src="@drawable/ic_menu_new_window"
         android:layout_width="wrap_content"
-        android:layout_height="match_parent"
+        android:layout_height="44dip"
         style="@style/HoloButton"
-        android:background="@drawable/browserbarbutton" />
+        android:background="@drawable/browsertab_add" />
 </merge>
\ No newline at end of file
diff --git a/res/layout/tab_title.xml b/res/layout/tab_title.xml
index a2da03d..e4a4e58 100644
--- a/res/layout/tab_title.xml
+++ b/res/layout/tab_title.xml
@@ -15,8 +15,7 @@
     android:layout_width="wrap_content"
     android:layout_height="match_parent"
     android:gravity="center_vertical"
-    android:orientation="horizontal"
-    android:background="@drawable/tab_background">
+    android:orientation="horizontal">
     <ImageView
         android:id="@+id/incognito"
         android:layout_width="16dip"
@@ -56,6 +55,5 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_marginLeft="16dip"
-        android:layout_marginRight="16dip"
         android:src="@drawable/ic_tab_close" />
 </merge>
diff --git a/res/layout/url_bar.xml b/res/layout/url_bar.xml
index f695ae3..3636ca8 100644
--- a/res/layout/url_bar.xml
+++ b/res/layout/url_bar.xml
@@ -21,7 +21,7 @@
         android:layout_width="match_parent"
         android:layout_height="48dip"
         android:orientation="horizontal"
-        android:background="@drawable/urlbar_bg">
+        android:background="@drawable/bg_urlbar">
         <ImageButton
             android:id="@+id/back"
             android:src="@drawable/ic_back_normal"
diff --git a/res/values-xlarge/styles.xml b/res/values-xlarge/styles.xml
index 952d97a..d87a347 100644
--- a/res/values-xlarge/styles.xml
+++ b/res/values-xlarge/styles.xml
@@ -43,9 +43,8 @@
     <style name="ShortCutTheme" parent="@android:Theme.Holo">
     </style>
     <style name="ActionBarStyle">
-        <item name="android:height">48dip</item>
-        <item name="android:padding">0dip</item>
-        <item name="android:background">@drawable/tabbar_bg</item>
+        <item name="android:height">56dip</item>
+        <item name="android:background">@drawable/bg_browsertabs</item>
         <item name="android:displayOptions"></item>
     </style>
     <style name="ActionButton">
diff --git a/res/values/dimensions.xml b/res/values/dimensions.xml
index d51ab33..7cfa3f6 100644
--- a/res/values/dimensions.xml
+++ b/res/values/dimensions.xml
@@ -13,12 +13,14 @@
 <resources
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <!-- The width of a selected tab -->
-    <dimen
-        name="tab_width_selected">300dp</dimen>
+    <dimen name="tab_width_selected">280dp</dimen>
     <!-- The width of an unselected tab -->
-    <dimen
-        name="tab_width_unselected">300dp</dimen>
-
+    <dimen name="tab_width_unselected">240dp</dimen>
+    <dimen name="tab_height">44dp</dimen>
+    <dimen name="tab_overlap">8dp</dimen>
+    <dimen name="tab_slice">18dp</dimen>
+    <dimen name="tab_padding">16dp</dimen>
+    <dimen name="max_tab_width">300dp</dimen>
     <dimen name="bookmarkThumbnailWidth">90dip</dimen>
     <dimen name="bookmarkThumbnailHeight">80dip</dimen>
     <dimen name="add_bookmark_width">500dip</dimen>
diff --git a/res/values/integers.xml b/res/values/integers.xml
index 2864d47..e18676d 100644
--- a/res/values/integers.xml
+++ b/res/values/integers.xml
@@ -19,7 +19,7 @@
     <!--  The maximum number of open tabs -->
     <integer name="max_tabs">16</integer>
     <!--  The duration of the tab animations in millisecs  -->
-    <integer name="tab_animation_duration">500</integer>
+    <integer name="tab_animation_duration">200</integer>
     <integer name="max_width_crumb">200</integer>
     <!-- The maximum number of most visited URLs in the history tab -->
     <integer name="most_visits_limit">10</integer>
diff --git a/src/com/android/browser/BaseUi.java b/src/com/android/browser/BaseUi.java
index b7c5a82..4fca79d 100644
--- a/src/com/android/browser/BaseUi.java
+++ b/src/com/android/browser/BaseUi.java
@@ -508,6 +508,13 @@
         mContentView.addView(container, COVER_SCREEN_PARAMS);
     }
 
+    int getTitleBarWidth() {
+        if (mTitleBar != null) {
+            return mTitleBar.getWidth();
+        }
+        return 0;
+    }
+
     void showFakeTitleBar() {
         if (!isFakeTitleBarShowing() && mActiveTabsPage == null &&
                 !mActivityPaused) {
diff --git a/src/com/android/browser/TabBar.java b/src/com/android/browser/TabBar.java
index 14b1845..4f179b0 100644
--- a/src/com/android/browser/TabBar.java
+++ b/src/com/android/browser/TabBar.java
@@ -22,7 +22,13 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
+import android.graphics.BitmapShader;
+import android.graphics.Canvas;
 import android.graphics.Color;
+import android.graphics.LinearGradient;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.Shader;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.LayerDrawable;
@@ -74,6 +80,17 @@
     private Drawable mGenericFavicon;
     private String mLoadingText;
 
+    private Drawable mActiveDrawable;
+    private Drawable mInactiveDrawable;
+
+    private Bitmap mShaderBuffer;
+    private Canvas mShaderCanvas;
+    private Paint mShaderPaint;
+    private int mTabHeight;
+    private int mTabOverlap;
+    private int mTabSliceWidth;
+    private int mTabPadding;
+
     public TabBar(Activity activity, UiController controller, BaseUi ui) {
         super(activity);
         mActivity = activity;
@@ -83,16 +100,20 @@
         Resources res = activity.getResources();
         mTabWidthSelected = (int) res.getDimension(R.dimen.tab_width_selected);
         mTabWidthUnselected = (int) res.getDimension(R.dimen.tab_width_unselected);
+        mActiveDrawable = res.getDrawable(R.drawable.bg_urlbar);
+        mInactiveDrawable = res.getDrawable(R.drawable.browsertab_inactive);
 
         mTabMap = new HashMap<Tab, TabViewData>();
         Resources resources = activity.getResources();
         LayoutInflater factory = LayoutInflater.from(activity);
         factory.inflate(R.layout.tab_bar, this);
+        setPadding(12, 12, 0, 0);
         mTabs = (TabScrollView) findViewById(R.id.tabs);
         mNewTab = (ImageButton) findViewById(R.id.newtab);
         mNewTab.setOnClickListener(this);
         mGenericFavicon = res.getDrawable(R.drawable.app_web_browser_sm);
         mLoadingText = res.getString(R.string.title_bar_loading);
+        setChildrenDrawingOrderEnabled(true);
 
         // TODO: Change enabled states based on whether you can go
         // back/forward.  Probably should be done inside onPageStarted.
@@ -102,6 +123,22 @@
         mUserRequestedUrlbar = false;
         mTitleVisible = true;
         mButtonWidth = -1;
+        // tab dimensions
+        mTabHeight = (int) res.getDimension(R.dimen.tab_height);
+        mTabOverlap = (int) res.getDimension(R.dimen.tab_overlap);
+        mTabSliceWidth = (int) res.getDimension(R.dimen.tab_slice);
+        mTabPadding = (int) res.getDimension(R.dimen.tab_padding);
+        int maxTabWidth = (int) res.getDimension(R.dimen.max_tab_width);
+        // shader initialization
+        mShaderBuffer = Bitmap.createBitmap(maxTabWidth, mTabHeight,
+                Bitmap.Config.ARGB_8888);
+        mShaderCanvas = new Canvas(mShaderBuffer);
+        mShaderPaint = new Paint();
+        BitmapShader shader = new BitmapShader(mShaderBuffer,
+                Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
+        mShaderPaint.setShader(shader);
+        mShaderPaint.setStyle(Paint.Style.FILL);
+        mShaderPaint.setAntiAlias(true);
     }
 
     void updateTabs(List<Tab> tabs) {
@@ -115,17 +152,31 @@
     }
 
     @Override
+    protected void onMeasure(int hspec, int vspec) {
+        super.onMeasure(hspec, vspec);
+        int w = getMeasuredWidth();
+        // adjust for new tab overlap
+        w -= mTabOverlap;
+        setMeasuredDimension(w, getMeasuredHeight());
+    }
+
+    @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        // use paddingLeft and paddingTop
+        int pl = getPaddingLeft();
+        int pt = getPaddingTop();
         if (mButtonWidth == -1) {
-            mButtonWidth = mNewTab.getMeasuredWidth();
+            mButtonWidth = mNewTab.getMeasuredWidth() - mTabOverlap;
         }
         int sw = mTabs.getMeasuredWidth();
-        int w = right-left;
+        int w = right - left - pl;
         if (w-sw < mButtonWidth) {
             sw = w - mButtonWidth;
         }
-        mTabs.layout(0, 0, sw, bottom-top );
-        mNewTab.layout(sw, 0, sw+mButtonWidth, bottom-top);
+        mTabs.layout(pl, pt, pl + sw, bottom - top);
+        // adjust for overlap
+        mNewTab.layout(pl + sw - mTabOverlap, pt,
+                pl + sw + mButtonWidth - mTabOverlap, bottom - top);
     }
 
     public void onClick(View view) {
@@ -212,6 +263,12 @@
         return tv;
     }
 
+    @Override
+    protected int getChildDrawingOrder(int count, int i) {
+        // reverse
+        return count - 1 - i;
+    }
+
     /**
      * View used in the tab bar
      */
@@ -226,16 +283,21 @@
         ImageView mClose;
         boolean mSelected;
         boolean mInLoad;
+        Path mPath;
+        int[] mWindowPos;
 
         /**
          * @param context
          */
         public TabView(Context context, TabViewData tab) {
             super(context);
+            setWillNotDraw(false);
+            mPath = new Path();
+            mWindowPos = new int[2];
             mTabData = tab;
             setGravity(Gravity.CENTER_VERTICAL);
             setOrientation(LinearLayout.HORIZONTAL);
-            setBackgroundResource(R.drawable.tab_background);
+            setPadding(0, 0, mTabPadding, 0);
             LayoutInflater inflater = LayoutInflater.from(getContext());
             mTabContent = inflater.inflate(R.layout.tab_title, this, true);
             mTitle = (TextView) mTabContent.findViewById(R.id.title);
@@ -286,11 +348,11 @@
             mTitle.setTextAppearance(mActivity, mSelected ?
                     R.style.TabTitleSelected : R.style.TabTitleUnselected);
             setHorizontalFadingEdgeEnabled(!mSelected);
-            setFadingEdgeLength(50);
             super.setActivated(selected);
-            setLayoutParams(new LayoutParams(selected ?
-                    mTabWidthSelected : mTabWidthUnselected,
-                    LayoutParams.MATCH_PARENT));
+            LayoutParams lp = (LinearLayout.LayoutParams) getLayoutParams();
+            lp.width = selected ? mTabWidthSelected : mTabWidthUnselected;
+            lp.height =  LayoutParams.MATCH_PARENT;
+            setLayoutParams(lp);
         }
 
         void setDisplayTitle(String title) {
@@ -328,6 +390,42 @@
             }
         }
 
+        @Override
+        protected void onLayout(boolean changed, int l, int t, int r, int b) {
+            super.onLayout(changed, l, t, r, b);
+            setTabPath(mPath, 0, 0, r - l, b - t);
+        }
+
+        @Override
+        protected void dispatchDraw(Canvas canvas) {
+            int state = canvas.save();
+            int[] pos = new int[2];
+            getLocationInWindow(mWindowPos);
+            Drawable drawable = mSelected ? mActiveDrawable : mInactiveDrawable;
+            drawable.setBounds(0, 0, mUi.getTitleBarWidth(), getHeight());
+            drawClipped(canvas, drawable, mPath, mWindowPos[0]);
+            canvas.restoreToCount(state);
+            super.dispatchDraw(canvas);
+        }
+
+        private void drawClipped(Canvas canvas, Drawable drawable,
+                Path clipPath, int left) {
+            mShaderCanvas.drawColor(Color.TRANSPARENT);
+            mShaderCanvas.translate(-left, 0);
+            drawable.draw(mShaderCanvas);
+            canvas.drawPath(clipPath, mShaderPaint);
+            mShaderCanvas.translate(left, 0);
+        }
+
+        private void setTabPath(Path path, int l, int t, int r, int b) {
+            path.reset();
+            path.moveTo(l, b);
+            path.lineTo(l, t);
+            path.lineTo(r - mTabSliceWidth, t);
+            path.lineTo(r, b);
+            path.close();
+        }
+
     }
 
     /**
diff --git a/src/com/android/browser/TabScrollView.java b/src/com/android/browser/TabScrollView.java
index fbb40aa..04ed5a3 100644
--- a/src/com/android/browser/TabScrollView.java
+++ b/src/com/android/browser/TabScrollView.java
@@ -17,10 +17,8 @@
 package com.android.browser;
 
 import android.animation.Animator;
-import android.animation.Animator.AnimatorListener;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
-import android.animation.PropertyValuesHolder;
 import android.content.Context;
 import android.graphics.Canvas;
 import android.graphics.drawable.Drawable;
@@ -41,6 +39,7 @@
     private Drawable mArrowLeft;
     private Drawable mArrowRight;
     private int mAnimationDuration;
+    private int mTabOverlap;
 
     /**
      * @param context
@@ -73,8 +72,10 @@
         mContext = ctx;
         mAnimationDuration = ctx.getResources().getInteger(
                 R.integer.tab_animation_duration);
+        mTabOverlap = (int) ctx.getResources().getDimension(R.dimen.tab_overlap);
         setHorizontalScrollBarEnabled(false);
-        mContentView = new LinearLayout(mContext);
+        setOverScrollMode(OVER_SCROLL_NEVER);
+        mContentView = new TabLayout(mContext);
         mContentView.setOrientation(LinearLayout.HORIZONTAL);
         mContentView.setLayoutParams(
                 new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT));
@@ -211,4 +212,49 @@
         return getScrollX();
     }
 
+    class TabLayout extends LinearLayout {
+
+        public TabLayout(Context context) {
+            super(context);
+            setChildrenDrawingOrderEnabled(true);
+        }
+
+        @Override
+        protected void onMeasure(int hspec, int vspec) {
+            super.onMeasure(hspec, vspec);
+            int w = getMeasuredWidth();
+            w -= Math.max(0, mContentView.getChildCount() - 1) * mTabOverlap;
+            setMeasuredDimension(w, getMeasuredHeight());
+        }
+
+        @Override
+        protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+            super.onLayout(changed, left, top, right, bottom);
+            if (getChildCount() > 1) {
+                int nextLeft = getChildAt(0).getRight() - mTabOverlap;
+                for (int i = 1; i < getChildCount(); i++) {
+                    View tab = getChildAt(i);
+                    int w = tab.getRight() - tab.getLeft();
+                    tab.layout(nextLeft, tab.getTop(), nextLeft + w, tab.getBottom());
+                    nextLeft += w - mTabOverlap;
+                }
+            }
+        }
+
+        @Override
+        protected int getChildDrawingOrder(int count, int i) {
+            int next = -1;
+            if ((i == (count - 1)) && (mSelected >= 0)) {
+                next = mSelected;
+            } else {
+                next = count - i - 1;
+                if (next <= mSelected) {
+                    next--;
+                }
+            }
+            return next;
+        }
+
+    }
+
 }