add tabs to QuickControls

    Bug: 4084343
    The final act in a 3 act drama.
    Adds tab thumbnails to QuickControls menu and
    removes the tab bar.

Change-Id: Id667e8020745c3d77920858fcd9dd7f510973dd9
diff --git a/src/com/android/browser/Controller.java b/src/com/android/browser/Controller.java
index 19ad40e..d02f05c 100644
--- a/src/com/android/browser/Controller.java
+++ b/src/com/android/browser/Controller.java
@@ -1956,17 +1956,17 @@
         int thumbnailWidth = thumbnail.getWidth();
         int thumbnailHeight = thumbnail.getHeight();
         float scaleFactor = 1.0f;
-        if (thumbnailWidth > 0) {
+        if (thumbnailWidth > 0 && thumbnailHeight > 0) {
             scaleFactor = (float) width / (float)thumbnailWidth;
         } else {
             return null;
         }
 
-        if (view.getWidth() > view.getHeight() &&
-                thumbnailHeight < view.getHeight() && thumbnailHeight > 0) {
-            // If the device is in landscape and the page is shorter
-            // than the height of the view, center the thumnail and crop the sides
-            scaleFactor = (float) height / (float)thumbnailHeight;
+        float scaleFactorY = (float) height / (float)thumbnailHeight;
+        if (scaleFactorY > scaleFactor) {
+            // The picture is narrower than the requested AR
+            // Center the thumnail and crop the sides
+            scaleFactor = scaleFactorY;
             float wx = (thumbnailWidth * scaleFactor) - width;
             canvas.translate((int) -(wx / 2), 0);
         }
diff --git a/src/com/android/browser/PieControl.java b/src/com/android/browser/PieControl.java
index 302cbc0..5e95684 100644
--- a/src/com/android/browser/PieControl.java
+++ b/src/com/android/browser/PieControl.java
@@ -19,9 +19,15 @@
 import com.android.browser.view.PieItem;
 import com.android.browser.view.PieListView;
 import com.android.browser.view.PieMenu;
+import com.android.browser.view.PieMenu.PieView.OnLayoutListener;
+import com.android.browser.view.PieStackView;
+import com.android.browser.view.PieStackView.OnCurrentListener;
 
 import android.app.Activity;
 import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+import android.os.Handler;
 import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuItem;
@@ -33,6 +39,7 @@
 import android.widget.BaseAdapter;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
+import android.widget.ImageView.ScaleType;
 import android.widget.TextView;
 
 import java.util.ArrayList;
@@ -56,6 +63,8 @@
     private PieItem mNewTab;
     private PieItem mClose;
     private MenuAdapter mMenuAdapter;
+    private PieItem mShowTabs;
+    private TabAdapter mTabAdapter;
 
     public PieControl(Activity activity, UiController controller, XLargeUi ui) {
         mActivity = activity;
@@ -76,13 +85,32 @@
             mForward = makeItem(R.drawable.ic_forward_holo_dark, 2);
             mNewTab = makeItem(R.drawable.ic_new_window_holo_dark, 2);
             mClose = makeItem(R.drawable.ic_close_window_holo_dark, 2);
+            mShowTabs = makeItem(R.drawable.ic_windows_holo_dark, 2);
             mOptions = makeItem(
                     com.android.internal.R.drawable.ic_menu_moreoverflow_normal_holo_dark,
                     2);
             mMenuAdapter = new MenuAdapter(mActivity, mUiController);
-            PieMenuView menusym = new PieMenuView(mActivity);
-            mOptions.setPieView(menusym);
-            menusym.setAdapter(mMenuAdapter);
+            mTabAdapter = new TabAdapter(mActivity, mUiController);
+            PieStackView stack = new PieStackView(mActivity);
+            stack.setLayoutListener(new OnLayoutListener() {
+                @Override
+                public void onLayout(int ax, int ay, boolean left) {
+                    buildTabs();
+                }
+            });
+            stack.setOnCurrentListener(mTabAdapter);
+            stack.setAdapter(mTabAdapter);
+            mShowTabs.setPieView(stack);
+            PieListView menuview = new PieListView(mActivity);
+            menuview.setLayoutListener(new OnLayoutListener() {
+                @Override
+                public void onLayout(int ax, int ay, boolean left) {
+                    mActivity.openOptionsMenu();
+                }
+            });
+
+            mOptions.setPieView(menuview);
+            menuview.setAdapter(mMenuAdapter);
             setClickListener(mBack,
                     mRefresh,
                     mForward,
@@ -98,6 +126,7 @@
             // level 2
             mPie.addItem(mForward);
             mPie.addItem(mRefresh);
+            mPie.addItem(mShowTabs);
             mPie.addItem(mNewTab);
             mPie.addItem(mClose);
             mPie.addItem(mOptions);
@@ -106,6 +135,15 @@
         container.addView(mPie);
     }
 
+    private void buildTabs() {
+        final List<Tab> tabs = mUiController.getTabs();
+        mUi.captureTab(mUi.getActiveTab());
+        mTabAdapter.setTabs(tabs);
+        PieStackView sym = (PieStackView) mShowTabs.getPieView();
+        sym.setCurrent(mUiController.getTabControl().getCurrentIndex());
+
+    }
+
     protected void onMenuOpened(Menu menu) {
         mMenuAdapter.setMenu(menu);
     }
@@ -169,19 +207,72 @@
         return false;
     }
 
-    private class PieMenuView extends PieListView {
+    private static class TabAdapter extends BaseAdapter implements OnCurrentListener {
 
-        /**
-         * @param ctx
-         */
-        public PieMenuView(Context ctx) {
-            super(ctx);
+        LayoutInflater mInflater;
+        UiController mUiController;
+        private List<Tab> mTabs;
+        private int mCurrent;
+
+        public TabAdapter(Context ctx, UiController ctl) {
+            mInflater = LayoutInflater.from(ctx);
+            mUiController = ctl;
+            mTabs = new ArrayList<Tab>();
+            mCurrent = -1;
+        }
+
+        public void setTabs(List<Tab> tabs) {
+            mTabs = tabs;
+            notifyDataSetChanged();
         }
 
         @Override
-        public void layout(int anchorX, int anchorY, boolean left) {
-            mActivity.openOptionsMenu();
-            super.layout(anchorX, anchorY, left);
+        public int getCount() {
+            return mTabs.size();
+        }
+
+        @Override
+        public Tab getItem(int position) {
+            return mTabs.get(position);
+        }
+
+        @Override
+        public long getItemId(int position) {
+            return position;
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            final Tab tab = mTabs.get(position);
+            View view = mInflater.inflate(R.layout.qc_tab,
+                    null);
+            ImageView thumb = (ImageView) view.findViewById(R.id.thumb);
+            TextView title1 = (TextView) view.findViewById(R.id.title1);
+            TextView title2 = (TextView) view.findViewById(R.id.title2);
+            Bitmap b = tab.getScreenshot();
+            if (b != null) {
+                thumb.setImageBitmap(b);
+            }
+            if (position > mCurrent) {
+                title1.setVisibility(View.GONE);
+                title2.setText(tab.getTitle());
+            } else {
+                title2.setVisibility(View.GONE);
+                title1.setText(tab.getTitle());
+            }
+            view.setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    mUiController.switchToTab(mUiController.getTabControl()
+                            .getTabIndex(tab));
+                }
+            });
+            return view;
+        }
+
+        @Override
+        public void onSetCurrent(int index) {
+            mCurrent = index;
         }
 
     }
diff --git a/src/com/android/browser/Tab.java b/src/com/android/browser/Tab.java
index 70028ea..bab3458 100644
--- a/src/com/android/browser/Tab.java
+++ b/src/com/android/browser/Tab.java
@@ -136,6 +136,8 @@
     // AsyncTask for downloading touch icons
     DownloadTouchIcon mTouchIconLoader;
 
+    private Bitmap mScreenshot;
+
     // All the state needed for a page
     private static class PageState {
         String mUrl;
@@ -191,6 +193,7 @@
     static final String APPID = "appid";
     static final String ORIGINALURL = "originalUrl";
     static final String INCOGNITO = "privateBrowsingEnabled";
+    static final String SCREENSHOT = "screenshot";
 
     // -------------------------------------------------------------------------
 
@@ -1720,6 +1723,9 @@
             mSavedState.putInt(PARENTTAB, mWebViewController.getTabControl().getTabIndex(
                     mParentTab));
         }
+        if (mScreenshot != null) {
+            mSavedState.putParcelable(SCREENSHOT, mScreenshot);
+        }
         return true;
     }
 
@@ -1735,6 +1741,7 @@
         mSavedState = null;
         mCloseOnExit = b.getBoolean(CLOSEONEXIT);
         mAppId = b.getString(APPID);
+        mScreenshot = b.getParcelable(SCREENSHOT);
 
         final WebBackForwardList list = mMainView.restoreState(b);
         if (list == null) {
@@ -1758,4 +1765,12 @@
         }
     };
 
+    public void setScreenshot(Bitmap screenshot) {
+        mScreenshot = screenshot;
+    }
+
+    public Bitmap getScreenshot() {
+        return mScreenshot;
+    }
+
 }
diff --git a/src/com/android/browser/XLargeUi.java b/src/com/android/browser/XLargeUi.java
index 0712f37..a9a55e8 100644
--- a/src/com/android/browser/XLargeUi.java
+++ b/src/com/android/browser/XLargeUi.java
@@ -21,6 +21,7 @@
 import android.app.ActionBar;
 import android.app.Activity;
 import android.content.pm.PackageManager;
+import android.graphics.Bitmap;
 import android.os.Bundle;
 import android.os.Handler;
 import android.util.Log;
@@ -118,15 +119,11 @@
 
     private void checkTabCount() {
         if (mUseQuickControls) {
-            if (mTabControl.getTabCount() == 1) {
-                mHandler.post(new Runnable() {
-                    public void run() {
-                        mActionBar.hide();
-                    }
-                });
-            } else {
-                mActionBar.show();
-            }
+            mHandler.post(new Runnable() {
+                public void run() {
+                    mActionBar.hide();
+                }
+            });
         }
     }
 
@@ -223,6 +220,11 @@
 
     @Override
     public void setActiveTab(final Tab tab) {
+        if (mUseQuickControls) {
+            if (mActiveTab != null) {
+                captureTab(mActiveTab);
+            }
+        }
         super.setActiveTab(tab, true);
         setActiveTab(tab, true);
     }
@@ -258,6 +260,15 @@
         tab.getTopWindow().requestFocus();
     }
 
+    public void captureTab(final Tab tab) {
+        Bitmap sshot = Controller.createScreenshot(tab,
+                (int) mActivity.getResources()
+                        .getDimension(R.dimen.qc_thumb_width),
+                (int) mActivity.getResources()
+                        .getDimension(R.dimen.qc_thumb_height));
+        tab.setScreenshot(sshot);
+    }
+
     @Override
     public void updateTabs(List<Tab> tabs) {
         mTabBar.updateTabs(tabs);
diff --git a/src/com/android/browser/view/BasePieView.java b/src/com/android/browser/view/BasePieView.java
index 515545a..2120215 100644
--- a/src/com/android/browser/view/BasePieView.java
+++ b/src/com/android/browser/view/BasePieView.java
@@ -33,6 +33,8 @@
     private DataSetObserver mObserver;
     protected ArrayList<View> mViews;
 
+    protected OnLayoutListener mListener;
+
     protected int mCurrent;
     protected int mChildWidth;
     protected int mChildHeight;
@@ -44,6 +46,10 @@
     public BasePieView() {
     }
 
+    public void setLayoutListener(OnLayoutListener l) {
+        mListener = l;
+    }
+
     public void setAdapter(Adapter adapter) {
         mAdapter = adapter;
         if (adapter == null) {
@@ -103,7 +109,12 @@
      * needs to set top, left, width, height
      */
     @Override
-    public abstract void layout(int anchorX, int anchorY, boolean left);
+    public void layout(int anchorX, int anchorY, boolean left) {
+        if (mListener != null) {
+            mListener.onLayout(anchorX, anchorY, left);
+        }
+    }
+
 
     @Override
     public abstract void draw(Canvas canvas);
diff --git a/src/com/android/browser/view/PieListView.java b/src/com/android/browser/view/PieListView.java
index 5fee51d..8cd8a4e 100644
--- a/src/com/android/browser/view/PieListView.java
+++ b/src/com/android/browser/view/PieListView.java
@@ -40,6 +40,7 @@
      */
     @Override
     public void layout(int anchorX, int anchorY, boolean left) {
+        super.layout(anchorX, anchorY, left);
         buildViews();
         mWidth = mChildWidth;
         mHeight = mChildHeight * mAdapter.getCount();
diff --git a/src/com/android/browser/view/PieMenu.java b/src/com/android/browser/view/PieMenu.java
index 22ebd18..e494d19 100644
--- a/src/com/android/browser/view/PieMenu.java
+++ b/src/com/android/browser/view/PieMenu.java
@@ -51,6 +51,12 @@
      */
     public interface PieView {
 
+        public interface OnLayoutListener {
+            public void onLayout(int ax, int ay, boolean left);
+        }
+
+        public void setLayoutListener(OnLayoutListener l);
+
         public void layout(int anchorX, int anchorY, boolean onleft);
 
         public void draw(Canvas c);
diff --git a/src/com/android/browser/view/PieStackView.java b/src/com/android/browser/view/PieStackView.java
new file mode 100644
index 0000000..df387ad
--- /dev/null
+++ b/src/com/android/browser/view/PieStackView.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2011 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.browser.view;
+
+import com.android.browser.R;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.view.View;
+
+/**
+ * shows views in a stack
+ */
+public class PieStackView extends BasePieView {
+
+    private static final int SLOP = 5;
+
+    private OnCurrentListener mCurrentListener;
+    private int mMinHeight;
+
+    public interface OnCurrentListener {
+        public void onSetCurrent(int index);
+    }
+
+    public PieStackView(Context ctx) {
+        mMinHeight = (int) ctx.getResources()
+                .getDimension(R.dimen.qc_tab_title_height);
+    }
+
+    public void setOnCurrentListener(OnCurrentListener l) {
+        mCurrentListener = l;
+    }
+
+    @Override
+    public void setCurrent(int ix) {
+        super.setCurrent(ix);
+        if (mCurrentListener != null) {
+            mCurrentListener.onSetCurrent(ix);
+            buildViews();
+            layoutChildrenLinear();
+        }
+    }
+
+    /**
+     * this will be called before the first draw call
+     */
+    @Override
+    public void layout(int anchorX, int anchorY, boolean left) {
+        super.layout(anchorX, anchorY, left);
+        buildViews();
+        mWidth = mChildWidth;
+        mHeight = mChildHeight + (mViews.size() - 1) * mMinHeight;
+        mLeft = anchorX + (left ? SLOP : -(SLOP + mChildWidth));
+        mTop = anchorY - mHeight / 2;
+        if (mViews != null) {
+            layoutChildrenLinear();
+        }
+    }
+
+    private void layoutChildrenLinear() {
+        final int n = mViews.size();
+        int top = mTop;
+        int dy = (n == 1) ? 0 : (mHeight - mChildHeight) / (n - 1);
+        for (View view : mViews) {
+            view.layout(mLeft, top, mLeft + mChildWidth, top + mChildHeight);
+            top += dy;
+        }
+    }
+
+    @Override
+    public void draw(Canvas canvas) {
+        if (mViews != null) {
+            final int n = mViews.size();
+            for (int i = 0; i < mCurrent; i++) {
+                drawView(mViews.get(i), canvas);
+            }
+            for (int i = n - 1; i > mCurrent; i--) {
+                drawView(mViews.get(i), canvas);
+            }
+            drawView(mViews.get(mCurrent), canvas);
+        }
+    }
+
+    @Override
+    protected int findChildAt(int y) {
+        final int ix = (y - mTop) * mViews.size() / mHeight;
+        return ix;
+    }
+
+}