new navscreen ui

Change-Id: Iedbdf5af5d3ee2fbdd6944c1689f6551b3af8d46
diff --git a/src/com/android/browser/BaseUi.java b/src/com/android/browser/BaseUi.java
index b7964dc..43bc7d6 100644
--- a/src/com/android/browser/BaseUi.java
+++ b/src/com/android/browser/BaseUi.java
@@ -76,7 +76,7 @@
 
     private FrameLayout mBrowserFrameLayout;
     protected FrameLayout mContentView;
-    private FrameLayout mCustomViewContainer;
+    protected FrameLayout mCustomViewContainer;
 
     private View mCustomView;
     private WebChromeClient.CustomViewCallback mCustomViewCallback;
diff --git a/src/com/android/browser/Controller.java b/src/com/android/browser/Controller.java
index 2f47cad..f920702 100644
--- a/src/com/android/browser/Controller.java
+++ b/src/com/android/browser/Controller.java
@@ -2128,7 +2128,8 @@
         mTabControl.removeTab(tab);
     }
 
-    protected void setActiveTab(Tab tab) {
+    @Override
+    public void setActiveTab(Tab tab) {
         // monkey protection against delayed start
         if (tab != null) {
             mTabControl.setCurrentTab(tab);
diff --git a/src/com/android/browser/NavScreen.java b/src/com/android/browser/NavScreen.java
new file mode 100644
index 0000000..8b897df
--- /dev/null
+++ b/src/com/android/browser/NavScreen.java
@@ -0,0 +1,382 @@
+/*
+ * 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;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.webkit.WebView;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.AdapterView.OnItemSelectedListener;
+import android.widget.BaseAdapter;
+import android.widget.FrameLayout;
+import android.widget.Gallery;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.ImageView.ScaleType;
+import android.widget.LinearLayout;
+import android.widget.ListPopupWindow;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class NavScreen extends LinearLayout implements OnClickListener {
+
+    UiController mUiController;
+    PhoneUi mUi;
+    Tab mTab;
+    Activity mActivity;
+
+    View mTopPanel;
+    ImageButton mBack;
+    ImageButton mRefresh;
+    ImageButton mForward;
+    ImageButton mTabs;
+    ImageButton mBookmarks;
+    ImageButton mMore;
+    ImageButton mNewTab;
+    ImageButton mNewIncognito;
+    FrameLayout mHolder;
+
+    Gallery mFlipper;
+    int mTabWidth;
+    int mTabHeight;
+    TabAdapter mAdapter;
+    ListPopupWindow mPopup;
+
+    boolean mReady;
+
+    public NavScreen(Activity activity, UiController ctl, PhoneUi ui) {
+        super(activity);
+        mActivity = activity;
+        mUiController = ctl;
+        mUi = ui;
+        init();
+    }
+
+    protected Tab getSelectedTab() {
+        return (Tab) mFlipper.getSelectedItem();
+    }
+
+    protected void setTabDimensions(int w, int h) {
+        mTabWidth = w;
+        mTabHeight = h;
+        requestLayout();
+    }
+
+    protected void showMenu(Menu menu) {
+        MenuAdapter menuAdapter = new MenuAdapter(mContext);
+        menuAdapter.setMenu(menu);
+        ListPopupWindow popup = new ListPopupWindow(mContext);
+        popup.setInputMethodMode(ListPopupWindow.INPUT_METHOD_NOT_NEEDED);
+        popup.setAdapter(menuAdapter);
+        popup.setModal(true);
+        popup.setAnchorView(mMore);
+        popup.setWidth((int) mContext.getResources().getDimension(
+                R.dimen.menu_width));
+        popup.show();
+        mPopup = popup;
+    }
+
+    protected void dismissMenu() {
+        if (mPopup != null) {
+            mPopup.dismiss();
+        }
+    }
+
+    private void init() {
+        LayoutInflater.from(mContext).inflate(R.layout.nav_screen, this);
+        LinearLayout content = (LinearLayout) findViewById(R.id.nav_screen);
+        mTopPanel = findViewById(R.id.navtop);
+        mBack = (ImageButton) findViewById(R.id.back);
+        mForward = (ImageButton) findViewById(R.id.forward);
+        mRefresh = (ImageButton) findViewById(R.id.refresh);
+        mTabs = (ImageButton) findViewById(R.id.tabs);
+        mBookmarks = (ImageButton) findViewById(R.id.bookmarks);
+        mNewTab = (ImageButton) findViewById(R.id.newtab);
+        mNewIncognito = (ImageButton) findViewById(R.id.newincognito);
+        mMore = (ImageButton) findViewById(R.id.more);
+        mBack.setOnClickListener(this);
+        mForward.setOnClickListener(this);
+        mRefresh.setOnClickListener(this);
+        mTabs.setOnClickListener(this);
+        mBookmarks.setOnClickListener(this);
+        mNewTab.setOnClickListener(this);
+        mNewIncognito.setOnClickListener(this);
+        mMore.setOnClickListener(this);
+        mHolder = (FrameLayout) findViewById(R.id.galleryholder);
+        FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
+                LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
+        mFlipper = new TabGallery(mContext);
+        mFlipper.setSpacing((int)(mContext.getResources()
+                .getDimension(R.dimen.nav_tab_spacing)));
+        mFlipper.setLayoutParams(lp);
+        mHolder.addView(mFlipper, 0);
+        mAdapter = new TabAdapter(mContext, mUiController.getTabControl());
+        mFlipper.setAdapter(mAdapter);
+        setTab(mUi.getActiveTab(), true);
+        mFlipper.setOnItemClickListener(new OnItemClickListener() {
+            @Override
+            public void onItemClick(AdapterView<?> parent, View view,
+                    int position, long id) {
+                // post as runnable to prevent bug in gesturedetector
+                // when view is removed in click handler
+                // sends action_cancel before action_up
+                mFlipper.post(new Runnable() {
+                    public void run() {
+                        close();
+                    }
+                });
+            }
+        });
+        mFlipper.setOnItemSelectedListener(new OnItemSelectedListener() {
+            @Override
+            public void onItemSelected(AdapterView<?> parent, View view,
+                    int position, long id) {
+                final Tab tab = mAdapter.getItem(position);
+                setTab(tab, false);
+            }
+
+            @Override
+            public void onNothingSelected(AdapterView<?> parent) {
+            }
+        });
+    }
+
+    private void setTab(Tab tab, boolean updateFlipper) {
+        mTab = tab;
+        // refresh state from tab
+        WebView web = tab.getWebView();
+        if (web != null) {
+            mBack.setImageResource(web.canGoBack()
+                    ? R.drawable.ic_back_holo_dark
+                    : R.drawable.ic_back_disabled_holo_dark);
+            mForward.setImageResource(web.canGoForward()
+                    ? R.drawable.ic_forward_holo_dark
+                    : R.drawable.ic_forward_disabled_holo_dark);
+        }
+        if (updateFlipper) {
+            mFlipper.setSelection(mUiController.getTabControl().getTabIndex(tab));
+        }
+    }
+
+    @Override
+    public void onClick(View v) {
+        WebView web = (mTab != null) ? mTab.getWebView() : null;
+        if (web != null) {
+            if (mBack == v) {
+                mUi.hideNavScreen(true);
+                web.goBack();
+            } else if (mForward == v) {
+                mUi.hideNavScreen(true);
+                web.goForward();
+            } else if (mRefresh == v) {
+                mUi.hideNavScreen(true);
+                web.reload();
+            }
+        }
+        if (mBookmarks == v) {
+            mUi.hideNavScreen(false);
+            mUiController.bookmarksOrHistoryPicker(false);
+        } else if (mTabs == v) {
+            mUi.hideNavScreen(false);
+            mUi.showActiveTabsPage();
+        } else if (mNewTab == v) {
+            mUi.hideNavScreen(true);
+            mUiController.openTabToHomePage();
+        } else if (mMore == v) {
+            mActivity.openOptionsMenu();
+        } else if (mNewIncognito == v) {
+            mUi.hideNavScreen(true);
+            mUiController.openIncognitoTab();
+        }
+    }
+
+    protected void close() {
+        close(true);
+    }
+
+    protected void close(boolean animate) {
+        mUi.hideNavScreen(animate);
+        Tab tab = (Tab) mFlipper.getSelectedItem();
+        if (tab != mUi.getActiveTab()) {
+            mUiController.setActiveTab(tab);
+        }
+    }
+
+    class TabGallery extends Gallery {
+
+        public TabGallery(Context ctx) {
+            super(ctx);
+            setUnselectedAlpha(0.3f);
+        }
+
+       @Override
+       protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
+           return new Gallery.LayoutParams(
+                   LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+       }
+
+       @Override
+       protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) {
+           return generateDefaultLayoutParams();
+       }
+
+    }
+
+    class TabAdapter extends BaseAdapter {
+
+        Context context;
+        TabControl tabControl;
+
+        public TabAdapter(Context ctx, TabControl tc) {
+            context = ctx;
+            tabControl = tc;
+        }
+
+        void onCloseTab(Tab tab) {
+            if (tab != null) {
+                mUiController.closeTab(tab);
+                if (tabControl.getTabCount() == 0) {
+                    mUiController.openTabToHomePage();
+                    mUi.hideNavScreen(false);
+                } else {
+                    notifyDataSetChanged();
+                }
+            }
+        }
+
+        @Override
+        public int getCount() {
+            return tabControl.getTabCount();
+        }
+
+        @Override
+        public Tab getItem(int position) {
+            return tabControl.getTab(position);
+        }
+
+        public long getItemId(int position) {
+            return position;
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            ImageView content = null;
+            if (convertView == null) {
+                convertView = LayoutInflater.from(context).inflate(R.layout.nav_tab_view,
+                        null);
+                content = (ImageView) convertView.findViewById(R.id.content);
+                content.setLayoutParams(new LayoutParams(mTabWidth, mTabHeight));
+            } else {
+                content = (ImageView) convertView.findViewById(R.id.content);
+            }
+            TextView title = (TextView) convertView.findViewById(R.id.title);
+            ImageView icon = (ImageView) convertView.findViewById(R.id.favicon);
+            ImageButton close = (ImageButton) convertView.findViewById(R.id.closetab);
+            final Tab tab = getItem(position);
+            if (tab.getFavicon() != null) {
+                icon.setImageBitmap(tab.getFavicon());
+            }
+            title.setText(tab.getUrl());
+            Bitmap screen = tab.getScreenshot();
+            content.setImageBitmap(screen);
+            close.setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    onCloseTab(tab);
+                }
+            });
+            title.setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    close(false);
+                    mUi.editUrl(false);
+                }
+            });
+            return convertView;
+        }
+    }
+
+    private class MenuAdapter extends BaseAdapter implements OnClickListener {
+
+        List<MenuItem> mItems;
+        LayoutInflater mInflater;
+
+        public MenuAdapter(Context ctx) {
+            mInflater = LayoutInflater.from(ctx);
+            mItems = new ArrayList<MenuItem>();
+        }
+
+        public void setMenu(Menu menu) {
+            mItems.clear();
+            for (int i = 0; i < menu.size(); i++) {
+                MenuItem item = menu.getItem(i);
+                if (item.isEnabled() && item.isVisible()) {
+                    mItems.add(item);
+                }
+            }
+            notifyDataSetChanged();
+        }
+
+        @Override
+        public int getCount() {
+            return mItems.size();
+        }
+
+        @Override
+        public MenuItem getItem(int position) {
+            return mItems.get(position);
+        }
+
+        @Override
+        public long getItemId(int position) {
+            return position;
+        }
+
+        @Override
+        public void onClick(View v) {
+            if (v.getTag() != null) {
+                dismissMenu();
+                mActivity.closeOptionsMenu();
+                mUi.hideNavScreen(false);
+                mUiController.onOptionsItemSelected((MenuItem) v.getTag());
+            }
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            final MenuItem item = mItems.get(position);
+            View view = mInflater.inflate(R.layout.qc_menu_item, null);
+            TextView label = (TextView) view.findViewById(R.id.title);
+            label.setText(item.getTitle());
+            label.setTag(item);
+            label.setOnClickListener(this);
+            return label;
+        }
+
+    }
+
+}
diff --git a/src/com/android/browser/PhoneUi.java b/src/com/android/browser/PhoneUi.java
index 471a9e6..3415e39 100644
--- a/src/com/android/browser/PhoneUi.java
+++ b/src/com/android/browser/PhoneUi.java
@@ -16,17 +16,17 @@
 
 package com.android.browser;
 
+import android.animation.Animator;
+import android.animation.Animator.AnimatorListener;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
 import android.app.Activity;
-import android.content.Context;
-import android.graphics.PixelFormat;
 import android.util.Log;
 import android.view.ActionMode;
 import android.view.Gravity;
 import android.view.KeyEvent;
 import android.view.Menu;
-import android.view.MotionEvent;
 import android.view.View;
-import android.view.WindowManager;
 import android.webkit.WebView;
 import android.widget.FrameLayout;
 
@@ -36,12 +36,13 @@
 public class PhoneUi extends BaseUi {
 
     private static final String LOGTAG = "PhoneUi";
+    private static final float NAV_TAB_SCALE = 0.75f;
 
     private TitleBarPhone mTitleBar;
     private ActiveTabsPage mActiveTabsPage;
-    private TouchProxy mTitleOverlay;
     private boolean mUseQuickControls;
     private PieControl mPieControl;
+    private NavScreen mNavScreen;
 
     boolean mExtendedMenuOpen;
     boolean mOptionsMenuOpen;
@@ -100,11 +101,31 @@
             // if tab page is showing, hide it
             mUiController.removeActiveTabsPage(true);
             return true;
+        } else if (mNavScreen != null) {
+            mNavScreen.close();
+            return true;
         }
         return super.onBackKey();
     }
 
     @Override
+    public boolean dispatchKey(int code, KeyEvent event) {
+        if (!isComboViewShowing()) {
+            switch (code) {
+                case KeyEvent.KEYCODE_MENU:
+                    if (mNavScreen == null) {
+                        showNavScreen();
+                        return true;
+                    } else {
+                        mNavScreen.close();
+                        return true;
+                    }
+            }
+        }
+        return false;
+    }
+
+    @Override
     public void onProgressChanged(Tab tab) {
         if (tab.inForeground()) {
             int progress = tab.getLoadProgress();
@@ -198,46 +219,6 @@
     // menu handling callbacks
 
     @Override
-    public void onOptionsMenuOpened() {
-        if (!mUseQuickControls) {
-            mOptionsMenuOpen = true;
-            // options menu opened, show title bar
-            showTitleBar();
-            if (mTitleOverlay == null) {
-                // This assumes that getTitleBar always returns the same View
-                mTitleOverlay = new TouchProxy(mActivity, getTitleBar());
-            }
-            mActivity.getWindowManager().addView(mTitleOverlay,
-                    mTitleOverlay.getWindowLayoutParams());
-        }
-    }
-
-    @Override
-    public void onExtendedMenuOpened() {
-        // Switching the menu to expanded view, so hide the
-        // title bar.
-        mExtendedMenuOpen = true;
-        hideTitleBar();
-    }
-
-    @Override
-    public void onOptionsMenuClosed(boolean inLoad) {
-        mOptionsMenuOpen = false;
-        mActivity.getWindowManager().removeView(mTitleOverlay);
-        if (!inLoad && !getTitleBar().hasFocus()) {
-            hideTitleBar();
-        }
-    }
-
-    @Override
-    public void onExtendedMenuClosed(boolean inLoad) {
-        mExtendedMenuOpen = false;
-        if (!mUseQuickControls) {
-            showTitleBar();
-        }
-    }
-
-    @Override
     public void onContextMenuCreated(Menu menu) {
         hideTitleBar();
     }
@@ -268,40 +249,6 @@
     }
 
     @Override
-    public boolean dispatchKey(int code, KeyEvent event) {
-        return false;
-    }
-
-    static class TouchProxy extends View {
-
-        View mTarget;
-
-        TouchProxy(Context context, View target) {
-            super(context);
-            mTarget = target;
-        }
-
-        @Override
-        public boolean dispatchTouchEvent(MotionEvent event) {
-            return mTarget.dispatchTouchEvent(event);
-        }
-
-        WindowManager.LayoutParams getWindowLayoutParams() {
-            WindowManager.LayoutParams params =
-                new WindowManager.LayoutParams(
-                        mTarget.getWidth(),
-                        mTarget.getHeight(),
-                        WindowManager.LayoutParams.TYPE_APPLICATION,
-                        WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
-                        PixelFormat.TRANSPARENT);
-            params.gravity = Gravity.TOP | Gravity.LEFT;
-            params.y = mTarget.getTop();
-            params.x = mTarget.getLeft();
-            return params;
-        }
-    }
-
-    @Override
     protected void setTitleGravity(int gravity) {
         if (mUseQuickControls) {
             FrameLayout.LayoutParams lp =
@@ -337,12 +284,15 @@
 
     @Override
     public boolean onPrepareOptionsMenu(Menu menu) {
+        menu.setGroupVisible(R.id.NAV_MENU, false);
         if (mUseQuickControls) {
-            menu.setGroupVisible(R.id.NAV_MENU, false);
             mPieControl.onMenuOpened(menu);
             return false;
         } else {
-            return true;
+            if (mNavScreen != null) {
+                mNavScreen.showMenu(menu);
+            }
+            return false;
         }
     }
 
@@ -353,9 +303,108 @@
         } else {
             captureTab(tab,
                     mActivity.getWindowManager().getDefaultDisplay().getWidth(),
-                    (int) mActivity.getResources()
-                            .getDimension(R.dimen.tab_view_thumbnail_height));
+                    mActivity.getWindowManager().getDefaultDisplay().getHeight());
         }
     }
 
+    void showNavScreen() {
+        captureTab(mActiveTab);
+        mNavScreen = new NavScreen(mActivity, mUiController, this);
+        WebView web = getWebView();
+        if (web != null) {
+            int w = web.getWidth();
+            int h = web.getHeight();
+            mNavScreen.setTabDimensions((int) (w * NAV_TAB_SCALE),
+                    (int) (h * NAV_TAB_SCALE));
+        }
+        // Add the custom view to its container.
+        mCustomViewContainer.addView(mNavScreen, COVER_SCREEN_GRAVITY_CENTER);
+        ObjectAnimator animx = ObjectAnimator.ofFloat(mContentView,
+                "scaleX", 1.0f, 0.85f);
+        ObjectAnimator animy = ObjectAnimator.ofFloat(mContentView,
+                "scaleY", 1.0f, 0.85f);
+        AnimatorSet anims = new AnimatorSet();
+        anims.setDuration(200);
+        anims.addListener(new AnimatorListener() {
+
+            @Override
+            public void onAnimationCancel(Animator animation) {
+                finishShowNavScreen();
+            }
+
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                finishShowNavScreen();
+            }
+
+            @Override
+            public void onAnimationRepeat(Animator animation) {
+            }
+
+            @Override
+            public void onAnimationStart(Animator animation) {
+            }
+        });
+        anims.playTogether(animx, animy);
+        anims.start();
+    }
+
+    private void finishShowNavScreen() {
+        // Hide the content view.
+        mContentView.setVisibility(View.GONE);
+        mContentView.setScaleX(1.0f);
+        mContentView.setScaleY(1.0f);
+        // Finally show the custom view container.
+        mCustomViewContainer.setVisibility(View.VISIBLE);
+        mCustomViewContainer.bringToFront();
+    }
+
+    void hideNavScreen(boolean animateToPage) {
+        if (mNavScreen == null) return;
+        if (animateToPage) {
+            ObjectAnimator animx = ObjectAnimator.ofFloat(mNavScreen, "scaleX",
+                    1.0f, 1.2f);
+            ObjectAnimator animy = ObjectAnimator.ofFloat(mNavScreen, "scaleY",
+                    1.0f, 1.2f);
+            AnimatorSet anims = new AnimatorSet();
+            anims.setDuration(200);
+            anims.addListener(new AnimatorListener() {
+
+                @Override
+                public void onAnimationCancel(Animator animation) {
+                    finishHideNavScreen();
+                }
+
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    finishHideNavScreen();
+                }
+
+                @Override
+                public void onAnimationRepeat(Animator animation) {
+                }
+
+                @Override
+                public void onAnimationStart(Animator animation) {
+                }
+            });
+            anims.playTogether(animx, animy);
+            anims.start();
+        } else {
+            finishHideNavScreen();
+        }
+
+    }
+
+    private void finishHideNavScreen() {
+        // Hide the custom view.
+        mNavScreen.setVisibility(View.GONE);
+        // Remove the custom view from its container.
+        mCustomViewContainer.removeView(mNavScreen);
+        mNavScreen = null;
+        mCustomViewContainer.setVisibility(View.GONE);
+        // Show the content view.
+        mContentView.setVisibility(View.VISIBLE);
+    }
+
 }
diff --git a/src/com/android/browser/TitleBarPhone.java b/src/com/android/browser/TitleBarPhone.java
index 875e4b5..0eb2d1a 100644
--- a/src/com/android/browser/TitleBarPhone.java
+++ b/src/com/android/browser/TitleBarPhone.java
@@ -134,7 +134,7 @@
             }
         }
         super.onFocusChange(v, hasFocus);
-        if (mUseQuickControls && !hasFocus) {
+        if (!hasFocus) {
             mBaseUi.hideTitleBar();
         }
     }
diff --git a/src/com/android/browser/UiController.java b/src/com/android/browser/UiController.java
index ed5fa6a..2b3ee69 100644
--- a/src/com/android/browser/UiController.java
+++ b/src/com/android/browser/UiController.java
@@ -44,6 +44,8 @@
 
     Tab openIncognitoTab();
 
+    void setActiveTab(Tab tab);
+
     boolean switchToTab(int tabIndex);
 
     void closeCurrentTab();