Submenus in QuickControls

Change-Id: I5d4fe7fdac1fb58e2e89afe00c468eed632428db
diff --git a/src/com/android/browser/BaseUi.java b/src/com/android/browser/BaseUi.java
index 9aaceeb..be38928 100644
--- a/src/com/android/browser/BaseUi.java
+++ b/src/com/android/browser/BaseUi.java
@@ -472,6 +472,10 @@
         return mTitleBar.isEditingUrl();
     }
 
+    public void stopEditingUrl() {
+        mTitleBar.getNavigationBar().stopEditingUrl();
+    }
+
     public TitleBar getTitleBar() {
         return mTitleBar;
     }
diff --git a/src/com/android/browser/Controller.java b/src/com/android/browser/Controller.java
index 9861184..78a30d6 100644
--- a/src/com/android/browser/Controller.java
+++ b/src/com/android/browser/Controller.java
@@ -1587,10 +1587,7 @@
                 break;
 
             case R.id.add_bookmark_menu_id:
-                Intent bookmarkIntent = createBookmarkCurrentPageIntent(false);
-                if (bookmarkIntent != null) {
-                    mActivity.startActivity(bookmarkIntent);
-                }
+                bookmarkCurrentPage();
                 break;
 
             case R.id.stop_reload_menu_id:
@@ -1624,14 +1621,10 @@
                 break;
 
             case R.id.preferences_menu_id:
-                Intent intent = new Intent(mActivity, BrowserPreferencesPage.class);
-                intent.putExtra(BrowserPreferencesPage.CURRENT_PAGE,
-                        getCurrentTopWebView().getUrl());
-                mActivity.startActivityForResult(intent, PREFERENCES_PAGE);
+                openPreferences();
                 break;
 
             case R.id.find_menu_id:
-                getCurrentTopWebView().showFindDialog(null, true);
                 break;
 
             case R.id.save_snapshot_menu_id:
@@ -1703,9 +1696,7 @@
                 break;
 
             case R.id.ua_desktop_menu_id:
-                WebView web = getCurrentWebView();
-                mSettings.toggleDesktopUseragent(web);
-                web.loadUrl(web.getOriginalUrl());
+                toggleUserAgent();
                 break;
 
             case R.id.window_one_menu_id:
@@ -1737,6 +1728,34 @@
         return true;
     }
 
+    @Override
+    public void toggleUserAgent() {
+        WebView web = getCurrentWebView();
+        mSettings.toggleDesktopUseragent(web);
+        web.loadUrl(web.getOriginalUrl());
+    }
+
+    @Override
+    public void findOnPage() {
+        getCurrentTopWebView().showFindDialog(null, true);
+    }
+
+    @Override
+    public void openPreferences() {
+        Intent intent = new Intent(mActivity, BrowserPreferencesPage.class);
+        intent.putExtra(BrowserPreferencesPage.CURRENT_PAGE,
+                getCurrentTopWebView().getUrl());
+        mActivity.startActivityForResult(intent, PREFERENCES_PAGE);
+    }
+
+    @Override
+    public void bookmarkCurrentPage() {
+        Intent bookmarkIntent = createBookmarkCurrentPageIntent(false);
+        if (bookmarkIntent != null) {
+            mActivity.startActivity(bookmarkIntent);
+        }
+    }
+
     private void goLive() {
         Tab t = getCurrentTab();
         t.loadUrl(t.getUrl(), null);
diff --git a/src/com/android/browser/PhoneUi.java b/src/com/android/browser/PhoneUi.java
index a1f70da..153533b 100644
--- a/src/com/android/browser/PhoneUi.java
+++ b/src/com/android/browser/PhoneUi.java
@@ -52,7 +52,7 @@
     private static final String LOGTAG = "PhoneUi";
     private static final int MSG_INIT_NAVSCREEN = 100;
 
-    private PieControlPhone mPieControl;
+    private PieControl mPieControl;
     private NavScreen mNavScreen;
     private AnimScreen mAnimScreen;
     private NavigationBarPhone mNavigationBar;
@@ -268,7 +268,7 @@
         mUseQuickControls = useQuickControls;
         mTitleBar.setUseQuickControls(mUseQuickControls);
         if (useQuickControls) {
-            mPieControl = new PieControlPhone(mActivity, mUiController, this);
+            mPieControl = new PieControl(mActivity, mUiController, this);
             mPieControl.attachToContainer(mContentView);
         } else {
             if (mPieControl != null) {
diff --git a/src/com/android/browser/PieControl.java b/src/com/android/browser/PieControl.java
new file mode 100644
index 0000000..68b0c7b
--- /dev/null
+++ b/src/com/android/browser/PieControl.java
@@ -0,0 +1,329 @@
+/*
+ * 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.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
+import android.webkit.WebView;
+import android.widget.BaseAdapter;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.ImageView.ScaleType;
+import android.widget.TextView;
+
+import com.android.browser.UI.ComboViews;
+import com.android.browser.view.PieItem;
+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 java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Controller for Quick Controls pie menu
+ */
+public class PieControl implements PieMenu.PieController, OnClickListener {
+
+    protected Activity mActivity;
+    protected UiController mUiController;
+    protected PieMenu mPie;
+    protected int mItemSize;
+    protected TextView mTabsCount;
+    private BaseUi mUi;
+    private PieItem mBack;
+    private PieItem mForward;
+    private PieItem mRefresh;
+    private PieItem mUrl;
+    private PieItem mOptions;
+    private PieItem mBookmarks;
+    private PieItem mHistory;
+    private PieItem mAddBookmark;
+    private PieItem mNewTab;
+    private PieItem mIncognito;
+    private PieItem mClose;
+    private PieItem mShowTabs;
+    private PieItem mInfo;
+    private PieItem mFind;
+    private PieItem mShare;
+    private PieItem mRDS;
+    private TabAdapter mTabAdapter;
+
+    public PieControl(Activity activity, UiController controller, BaseUi ui) {
+        mActivity = activity;
+        mUiController = controller;
+        mItemSize = (int) activity.getResources().getDimension(R.dimen.qc_item_size);
+        mUi = ui;
+    }
+
+    public void stopEditingUrl() {
+        mUi.stopEditingUrl();
+    }
+
+    protected void attachToContainer(FrameLayout container) {
+        if (mPie == null) {
+            mPie = new PieMenu(mActivity);
+            LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT,
+                    LayoutParams.MATCH_PARENT);
+            mPie.setLayoutParams(lp);
+            populateMenu();
+            mPie.setController(this);
+        }
+        container.addView(mPie);
+    }
+
+    protected void removeFromContainer(FrameLayout container) {
+        container.removeView(mPie);
+    }
+
+    protected void forceToTop(FrameLayout container) {
+        if (mPie.getParent() != null) {
+            container.removeView(mPie);
+            container.addView(mPie);
+        }
+    }
+
+    protected void setClickListener(OnClickListener listener, PieItem... items) {
+        for (PieItem item : items) {
+            item.getView().setOnClickListener(listener);
+        }
+    }
+
+    @Override
+    public boolean onOpen() {
+        int n = mUiController.getTabControl().getTabCount();
+        mTabsCount.setText(Integer.toString(n));
+        Tab tab = mUiController.getCurrentTab();
+        mForward.setEnabled(tab.canGoForward());
+        return true;
+    }
+
+    protected void populateMenu() {
+        mBack = makeItem(R.drawable.ic_back_holo_dark, 1);
+        mUrl = makeItem(R.drawable.ic_web_holo_dark, 1);
+        mBookmarks = makeItem(R.drawable.ic_bookmarks_holo_dark, 1);
+        mHistory = makeItem(R.drawable.ic_history_holo_dark, 1);
+        mAddBookmark = makeItem(R.drawable.ic_bookmark_on_holo_dark, 1);
+        mRefresh = makeItem(R.drawable.ic_refresh_holo_dark, 1);
+        mForward = makeItem(R.drawable.ic_forward_holo_dark, 1);
+        mNewTab = makeItem(R.drawable.ic_new_window_holo_dark, 1);
+        mIncognito = makeItem(R.drawable.ic_new_incognito_holo_dark, 1);
+        mClose = makeItem(R.drawable.ic_close_window_holo_dark, 1);
+        mInfo = makeItem(android.R.drawable.ic_menu_info_details, 1);
+        mFind = makeItem(R.drawable.ic_search_holo_dark, 1);
+        mShare = makeItem(R.drawable.ic_share_holo_dark, 1);
+        View tabs = makeTabsView();
+        mShowTabs = new PieItem(tabs, 1);
+        mOptions = makeItem(R.drawable.ic_settings_holo_dark, 1);
+        mRDS = makeItem(R.drawable.ic_desktop_holo_dark, 1);
+        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);
+        setClickListener(this, mBack, mRefresh, mForward, mUrl, mFind, mInfo,
+                mShare, mBookmarks, mNewTab, mIncognito, mClose, mHistory,
+                mAddBookmark, mOptions, mRDS);
+        // level 1
+        mPie.addItem(mOptions);
+        mOptions.addItem(mRDS);
+        mOptions.addItem(makeFiller());
+        mOptions.addItem(makeFiller());
+        mOptions.addItem(makeFiller());
+        mPie.addItem(mBack);
+        mBack.addItem(mRefresh);
+        mBack.addItem(mForward);
+        mBack.addItem(makeFiller());
+        mBack.addItem(makeFiller());
+        mPie.addItem(mUrl);
+        mUrl.addItem(mFind);
+        mUrl.addItem(mShare);
+        mUrl.addItem(makeFiller());
+        mUrl.addItem(makeFiller());
+        mPie.addItem(mShowTabs);
+        mShowTabs.addItem(mClose);
+        mShowTabs.addItem(mIncognito);
+        mShowTabs.addItem(mNewTab);
+        mShowTabs.addItem(makeFiller());
+        mPie.addItem(mBookmarks);
+        mBookmarks.addItem(makeFiller());
+        mBookmarks.addItem(makeFiller());
+        mBookmarks.addItem(mAddBookmark);
+        mBookmarks.addItem(mHistory);
+    }
+
+    @Override
+    public void onClick(View v) {
+        Tab tab = mUiController.getTabControl().getCurrentTab();
+        WebView web = tab.getWebView();
+        if (mBack.getView() == v) {
+            tab.goBack();
+        } else if (mForward.getView() == v) {
+            tab.goForward();
+        } else if (mRefresh.getView() == v) {
+            if (tab.inPageLoad()) {
+                web.stopLoading();
+            } else {
+                web.reload();
+            }
+        } else if (mUrl.getView() == v) {
+            mUi.editUrl(false);
+        } else if (mBookmarks.getView() == v) {
+            mUiController.bookmarksOrHistoryPicker(ComboViews.Bookmarks);
+        } else if (mHistory.getView() == v) {
+            mUiController.bookmarksOrHistoryPicker(ComboViews.History);
+        } else if (mAddBookmark.getView() == v) {
+            mUiController.bookmarkCurrentPage();
+        } else if (mNewTab.getView() == v) {
+            mUiController.openTabToHomePage();
+            mUi.editUrl(false);
+        } else if (mIncognito.getView() == v) {
+            mUiController.openIncognitoTab();
+            mUi.editUrl(false);
+        } else if (mClose.getView() == v) {
+            mUiController.closeCurrentTab();
+        } else if (mOptions.getView() == v) {
+            mUiController.openPreferences();
+        } else if (mShare.getView() == v) {
+            mUiController.shareCurrentPage();
+        } else if (mInfo.getView() == v) {
+            mUiController.showPageInfo();
+        } else if (mFind.getView() == v) {
+            mUiController.findOnPage();
+        } else if (mRDS.getView() == v) {
+            mUiController.toggleUserAgent();
+        }
+    }
+
+    private void buildTabs() {
+        final List<Tab> tabs = mUiController.getTabs();
+        mUi.getActiveTab().capture();
+        mTabAdapter.setTabs(tabs);
+        PieStackView sym = (PieStackView) mShowTabs.getPieView();
+        sym.setCurrent(mUiController.getTabControl().getCurrentPosition());
+    }
+
+    protected PieItem makeItem(int image, int l) {
+        ImageView view = new ImageView(mActivity);
+        view.setImageResource(image);
+        view.setMinimumWidth(mItemSize);
+        view.setMinimumHeight(mItemSize);
+        view.setScaleType(ScaleType.CENTER);
+        LayoutParams lp = new LayoutParams(mItemSize, mItemSize);
+        view.setLayoutParams(lp);
+        return new PieItem(view, l);
+    }
+
+    protected PieItem makeFiller() {
+        return new PieItem(null, 1);
+    }
+
+    protected View makeTabsView() {
+        View v = mActivity.getLayoutInflater().inflate(R.layout.qc_tabs_view, null);
+        mTabsCount = (TextView) v.findViewById(R.id.label);
+        mTabsCount.setText("1");
+        ImageView image = (ImageView) v.findViewById(R.id.icon);
+        image.setImageResource(R.drawable.ic_windows_holo_dark);
+        image.setScaleType(ScaleType.CENTER);
+        LayoutParams lp = new LayoutParams(mItemSize, mItemSize);
+        v.setLayoutParams(lp);
+        return v;
+    }
+
+    static class TabAdapter extends BaseAdapter implements OnCurrentListener {
+
+        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 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(tab);
+                }
+            });
+            return view;
+        }
+
+        @Override
+        public void onSetCurrent(int index) {
+            mCurrent = index;
+        }
+
+    }
+
+}
diff --git a/src/com/android/browser/PieControlBase.java b/src/com/android/browser/PieControlBase.java
deleted file mode 100644
index 830afea..0000000
--- a/src/com/android/browser/PieControlBase.java
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * 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.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
-import android.widget.BaseAdapter;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-import android.widget.ImageView.ScaleType;
-import android.widget.TextView;
-
-import com.android.browser.view.PieItem;
-import com.android.browser.view.PieMenu;
-import com.android.browser.view.PieStackView.OnCurrentListener;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * base controller for Quick Controls pie menu
- */
-public abstract class PieControlBase implements PieMenu.PieController {
-
-    protected Activity mActivity;
-    protected UiController mUiController;
-    protected PieMenu mPie;
-    protected int mItemSize;
-    protected TextView mTabsCount;
-
-    public PieControlBase(Activity activity, UiController controller) {
-        mActivity = activity;
-        mUiController = controller;
-        mItemSize = (int) activity.getResources().getDimension(R.dimen.qc_item_size);
-    }
-
-    protected void attachToContainer(FrameLayout container) {
-        if (mPie == null) {
-            mPie = new PieMenu(mActivity);
-            LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT,
-                    LayoutParams.MATCH_PARENT);
-            mPie.setLayoutParams(lp);
-            populateMenu();
-            mPie.setController(this);
-        }
-        container.addView(mPie);
-    }
-
-    protected void removeFromContainer(FrameLayout container) {
-        container.removeView(mPie);
-    }
-
-    protected void forceToTop(FrameLayout container) {
-        if (mPie.getParent() != null) {
-            container.removeView(mPie);
-            container.addView(mPie);
-        }
-    }
-
-    protected abstract void populateMenu();
-
-    protected void setClickListener(OnClickListener listener, PieItem... items) {
-        for (PieItem item : items) {
-            item.getView().setOnClickListener(listener);
-        }
-    }
-
-    @Override
-    public boolean onOpen() {
-        int n = mUiController.getTabControl().getTabCount();
-        mTabsCount.setText(Integer.toString(n));
-        return true;
-    }
-
-    protected PieItem makeItem(int image, int l) {
-        ImageView view = new ImageView(mActivity);
-        view.setImageResource(image);
-        view.setMinimumWidth(mItemSize);
-        view.setMinimumHeight(mItemSize);
-        view.setScaleType(ScaleType.CENTER);
-        LayoutParams lp = new LayoutParams(mItemSize, mItemSize);
-        view.setLayoutParams(lp);
-        return new PieItem(view, l);
-    }
-
-    protected View makeTabsView() {
-        View v = mActivity.getLayoutInflater().inflate(R.layout.qc_tabs_view, null);
-        mTabsCount = (TextView) v.findViewById(R.id.label);
-        mTabsCount.setText("1");
-        ImageView image = (ImageView) v.findViewById(R.id.icon);
-        image.setImageResource(R.drawable.ic_windows_holo_dark);
-        image.setScaleType(ScaleType.CENTER);
-        LayoutParams lp = new LayoutParams(mItemSize, mItemSize);
-        v.setLayoutParams(lp);
-        return v;
-    }
-
-    static class TabAdapter extends BaseAdapter implements OnCurrentListener {
-
-        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 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(tab);
-                }
-            });
-            return view;
-        }
-
-        @Override
-        public void onSetCurrent(int index) {
-            mCurrent = index;
-        }
-
-    }
-
-}
diff --git a/src/com/android/browser/PieControlPhone.java b/src/com/android/browser/PieControlPhone.java
deleted file mode 100644
index 2b6a3c5..0000000
--- a/src/com/android/browser/PieControlPhone.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * 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.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.PopupMenu;
-import android.widget.PopupMenu.OnMenuItemClickListener;
-
-import com.android.browser.UI.ComboViews;
-import com.android.browser.view.PieItem;
-import com.android.browser.view.PieMenu.PieView.OnLayoutListener;
-import com.android.browser.view.PieStackView;
-
-import java.util.List;
-
-/**
- * controller for Quick Controls pie menu
- */
-public class PieControlPhone extends PieControlBase implements OnClickListener,
-        OnMenuItemClickListener {
-
-    private PhoneUi mUi;
-    private PieItem mUrl;
-    private PieItem mShowTabs;
-    private PieItem mOptions;
-    private PieItem mNewTab;
-    private PieItem mBookmarks;
-    private TabAdapter mTabAdapter;
-    private PopupMenu mPopup;
-
-    public PieControlPhone(Activity activity, UiController controller, PhoneUi ui) {
-        super(activity, controller);
-        mUi = ui;
-    }
-
-    protected void populateMenu() {
-        mUrl = makeItem(R.drawable.ic_web_holo_dark, 1);
-        View tabs = makeTabsView();
-        mShowTabs = new PieItem(tabs, 1);
-        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);
-        mOptions = makeItem(com.android.internal.R.drawable.ic_menu_moreoverflow_normal_holo_dark,
-                1);
-
-        // level 1
-        mNewTab = makeItem(R.drawable.ic_new_window_holo_dark, 1);
-        mBookmarks = makeItem(R.drawable.ic_bookmarks_holo_dark, 1);
-        mPie.addItem(mNewTab);
-        mPie.addItem(mShowTabs);
-        mPie.addItem(mUrl);
-        mPie.addItem(mBookmarks);
-        mPie.addItem(mOptions);
-        setClickListener(this, mUrl, mShowTabs, mOptions, mNewTab, mBookmarks);
-        mPopup = new PopupMenu(mActivity, mUi.getTitleBar());
-        Menu menu = mPopup.getMenu();
-        mPopup.getMenuInflater().inflate(R.menu.browser, menu);
-        mPopup.setOnMenuItemClickListener(this);
-    }
-
-    protected void showMenu() {
-        mUiController.updateMenuState(mUiController.getCurrentTab(), mPopup.getMenu());
-        mPopup.show();
-    }
-
-    @Override
-    public boolean onMenuItemClick(MenuItem item) {
-        return mUiController.onOptionsItemSelected(item);
-    }
-
-
-    private void buildTabs() {
-        final List<Tab> tabs = mUiController.getTabs();
-        mUi.getActiveTab().capture();
-        mTabAdapter.setTabs(tabs);
-        PieStackView sym = (PieStackView) mShowTabs.getPieView();
-        sym.setCurrent(mUiController.getTabControl().getCurrentPosition());
-
-    }
-
-    @Override
-    public void onClick(View v) {
-        if (mUrl.getView() == v) {
-            mUi.editUrl(false);
-        } else if (mShowTabs.getView() == v) {
-            mUi.showNavScreen();
-        } else if (mOptions.getView() == v) {
-            showMenu();
-        } else if (mNewTab.getView() == v) {
-            mUiController.openTabToHomePage();
-            mUi.editUrl(false);
-        } else if (mBookmarks.getView() == v) {
-            mUiController.bookmarksOrHistoryPicker(ComboViews.Bookmarks);
-        }
-    }
-
-}
diff --git a/src/com/android/browser/PieControlXLarge.java b/src/com/android/browser/PieControlXLarge.java
deleted file mode 100644
index fcc8840..0000000
--- a/src/com/android/browser/PieControlXLarge.java
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * Copyright (C) 2010 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.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.view.ViewGroup.LayoutParams;
-import android.webkit.WebView;
-import android.widget.BaseAdapter;
-import android.widget.FrameLayout;
-import android.widget.TextView;
-
-import com.android.browser.UI.ComboViews;
-import com.android.browser.view.PieItem;
-import com.android.browser.view.PieListView;
-import com.android.browser.view.PieMenu.PieView.OnLayoutListener;
-import com.android.browser.view.PieStackView;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * controller for Quick Controls pie menu
- */
-public class PieControlXLarge extends PieControlBase implements OnClickListener {
-
-    private BaseUi mUi;
-    private PieItem mBack;
-    private PieItem mForward;
-    private PieItem mRefresh;
-    private PieItem mUrl;
-    private PieItem mOptions;
-    private PieItem mBookmarks;
-    private PieItem mNewTab;
-    private PieItem mClose;
-    private MenuAdapter mMenuAdapter;
-    private PieItem mShowTabs;
-    private TabAdapter mTabAdapter;
-
-    public PieControlXLarge(Activity activity, UiController controller, BaseUi ui) {
-        super(activity, controller);
-        mUiController = controller;
-        mUi = ui;
-    }
-
-    @Override
-    protected void attachToContainer(FrameLayout container) {
-        super.attachToContainer(container);
-        mPie.setUseBackground(true);
-    }
-
-    protected void populateMenu() {
-        mBack = makeItem(R.drawable.ic_back_holo_dark, 1);
-        mUrl = makeItem(R.drawable.ic_web_holo_dark, 1);
-        mBookmarks = makeItem(R.drawable.ic_bookmarks_holo_dark, 1);
-        mRefresh = makeItem(R.drawable.ic_refresh_holo_dark, 2);
-        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);
-        View tabs = makeTabsView();
-        mShowTabs = new PieItem(tabs, 2);
-        mOptions = makeItem(com.android.internal.R.drawable.ic_menu_moreoverflow_normal_holo_dark,
-                                        2);
-        mMenuAdapter = new MenuAdapter(mActivity, mUiController);
-        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) {
-                buildMenu();
-            }
-        });
-
-        mOptions.setPieView(menuview);
-        menuview.setAdapter(mMenuAdapter);
-        setClickListener(this, mBack, mRefresh, mForward, mUrl, mBookmarks, mNewTab,
-                mClose);
-        // level 1
-        mPie.addItem(mBack);
-        mPie.addItem(mUrl);
-        mPie.addItem(mBookmarks);
-        // level 2
-        mPie.addItem(mForward);
-        mPie.addItem(mRefresh);
-        mPie.addItem(mOptions);
-        mPie.addItem(mShowTabs);
-        mPie.addItem(mNewTab);
-        mPie.addItem(mClose);
-    }
-
-    private void buildTabs() {
-        final List<Tab> tabs = mUiController.getTabs();
-        mUi.getActiveTab().capture();
-        mTabAdapter.setTabs(tabs);
-        PieStackView sym = (PieStackView) mShowTabs.getPieView();
-        sym.setCurrent(mUiController.getTabControl().getCurrentPosition());
-    }
-
-    private void buildMenu() {
-        Menu menu = mUi.getMenu();
-        menu.setGroupVisible(R.id.NAV_MENU, false);
-        mMenuAdapter.setMenu(menu);
-    }
-
-    @Override
-    public void onClick(View v) {
-        Tab tab = mUiController.getTabControl().getCurrentTab();
-        WebView web = tab.getWebView();
-        if (mBack.getView() == v) {
-            tab.goBack();
-        } else if (mForward.getView() == v) {
-            tab.goForward();
-        } else if (mRefresh.getView() == v) {
-            if (tab.inPageLoad()) {
-                web.stopLoading();
-            } else {
-                web.reload();
-            }
-        } else if (mUrl.getView() == v) {
-            mUi.editUrl(false);
-        } else if (mBookmarks.getView() == v) {
-            mUiController.bookmarksOrHistoryPicker(ComboViews.Bookmarks);
-        } else if (mNewTab.getView() == v) {
-            mUiController.openTabToHomePage();
-            mUi.editUrl(false);
-        } else if (mClose.getView() == v) {
-            mUiController.closeCurrentTab();
-        }
-    }
-
-    private static class MenuAdapter extends BaseAdapter
-            implements OnClickListener {
-
-        List<MenuItem> mItems;
-        UiController mUiController;
-        LayoutInflater mInflater;
-
-        public MenuAdapter(Context ctx, UiController ctl) {
-            mUiController = ctl;
-            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) {
-                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);
-            label.setLayoutParams(new LayoutParams(240, 32));
-            return label;
-        }
-
-    }
-
-}
diff --git a/src/com/android/browser/UiController.java b/src/com/android/browser/UiController.java
index e7a8953..46c0432 100644
--- a/src/com/android/browser/UiController.java
+++ b/src/com/android/browser/UiController.java
@@ -65,6 +65,8 @@
 
     void bookmarksOrHistoryPicker(ComboViews startView);
 
+    void bookmarkCurrentPage();
+
     void startVoiceSearch();
 
     boolean supportsVoiceSearch();
@@ -103,4 +105,10 @@
 
     void showPageInfo();
 
+    void openPreferences();
+
+    void findOnPage();
+
+    void toggleUserAgent();
+
 }
diff --git a/src/com/android/browser/XLargeUi.java b/src/com/android/browser/XLargeUi.java
index b372fab..391b83e 100644
--- a/src/com/android/browser/XLargeUi.java
+++ b/src/com/android/browser/XLargeUi.java
@@ -50,7 +50,7 @@
 
     private NavigationBarTablet mNavBar;
 
-    private PieControlXLarge mPieControl;
+    private PieControl mPieControl;
     private Handler mHandler;
 
     /**
@@ -86,7 +86,7 @@
         mTitleBar.setUseQuickControls(mUseQuickControls);
         if (useQuickControls) {
             checkTabCount();
-            mPieControl = new PieControlXLarge(mActivity, mUiController, this);
+            mPieControl = new PieControl(mActivity, mUiController, this);
             mPieControl.attachToContainer(mContentView);
         } else {
             mActivity.getActionBar().show();
@@ -230,10 +230,6 @@
         super.editUrl(clearInput);
     }
 
-    void stopEditingUrl() {
-        mTitleBar.getNavigationBar().stopEditingUrl();
-    }
-
     @Override
     protected void showTitleBar() {
         if (canShowTitleBar()) {
diff --git a/src/com/android/browser/view/PieItem.java b/src/com/android/browser/view/PieItem.java
index 3674447..9e04ecb 100644
--- a/src/com/android/browser/view/PieItem.java
+++ b/src/com/android/browser/view/PieItem.java
@@ -16,10 +16,12 @@
 
 package com.android.browser.view;
 
+import android.view.View;
+
 import com.android.browser.view.PieMenu.PieView;
 
-import android.graphics.Path;
-import android.view.View;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * Pie menu item
@@ -31,20 +33,66 @@
     private int level;
     private float start;
     private float sweep;
+    private float animate;
     private int inner;
     private int outer;
     private boolean mSelected;
-    private Path mPath;
+    private boolean mEnabled;
+    private List<PieItem> mItems;
 
     public PieItem(View view, int level) {
         mView = view;
         this.level = level;
+        mEnabled = true;
+        setAnimationAngle(getAnimationAngle());
+        setAlpha(getAlpha());
     }
 
     public PieItem(View view, int level, PieView sym) {
         mView = view;
         this.level = level;
         mPieView = sym;
+        mEnabled = false;
+    }
+
+    public boolean hasItems() {
+        return mItems != null;
+    }
+
+    public List<PieItem> getItems() {
+        return mItems;
+    }
+
+    public void addItem(PieItem item) {
+        if (mItems == null) {
+            mItems = new ArrayList<PieItem>();
+        }
+        mItems.add(item);
+    }
+
+    public void setAlpha(float alpha) {
+        if (mView != null) {
+            mView.setAlpha(alpha);
+        }
+    }
+
+    public float getAlpha() {
+        if (mView != null) {
+            return mView.getAlpha();
+        }
+        return 1;
+    }
+
+    public void setAnimationAngle(float a) {
+        animate = a;
+    }
+
+    public float getAnimationAngle() {
+        return animate;
+    }
+
+    public void setEnabled(boolean enabled) {
+        mEnabled = enabled;
     }
 
     public void setSelected(boolean s) {
@@ -62,16 +110,19 @@
         return level;
     }
 
-    public void setGeometry(float st, float sw, int inside, int outside, Path p) {
+    public void setGeometry(float st, float sw, int inside, int outside) {
         start = st;
         sweep = sw;
         inner = inside;
         outer = outside;
-        mPath = p;
+    }
+
+    public float getStart() {
+        return start;
     }
 
     public float getStartAngle() {
-        return start;
+        return start + animate;
     }
 
     public float getSweep() {
@@ -99,11 +150,10 @@
     }
 
     public PieView getPieView() {
-        return mPieView;
-    }
-
-    public Path getPath() {
-        return mPath;
+        if (mEnabled) {
+            return mPieView;
+        }
+        return null;
     }
 
 }
diff --git a/src/com/android/browser/view/PieMenu.java b/src/com/android/browser/view/PieMenu.java
index 7f8dd6b..1fd0e99 100644
--- a/src/com/android/browser/view/PieMenu.java
+++ b/src/com/android/browser/view/PieMenu.java
@@ -16,8 +16,11 @@
 
 package com.android.browser.view;
 
-import com.android.browser.R;
-
+import android.animation.Animator;
+import android.animation.Animator.AnimatorListener;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Canvas;
@@ -34,12 +37,15 @@
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
 
+import com.android.browser.R;
+
 import java.util.ArrayList;
 import java.util.List;
 
 public class PieMenu extends FrameLayout {
 
     private static final int MAX_LEVELS = 5;
+    private static final long ANIMATION = 80;
 
     public interface PieController {
         /**
@@ -47,6 +53,8 @@
          * returns if pie state has been changed
          */
         public boolean onOpen();
+        public void stopEditingUrl();
+
     }
 
     /**
@@ -74,6 +82,7 @@
     private int mRadiusInc;
     private int mSlop;
     private int mTouchOffset;
+    private Path mPath;
 
     private boolean mOpen;
     private PieController mController;
@@ -83,14 +92,20 @@
     private int[] mCounts;
     private PieView mPieView = null;
 
+    // sub menus
+    private List<PieItem> mCurrentItems;
+    private PieItem mOpenItem;
+
     private Drawable mBackground;
     private Paint mNormalPaint;
     private Paint mSelectedPaint;
+    private Paint mSubPaint;
 
     // touch handling
-    PieItem mCurrentItem;
+    private PieItem mCurrentItem;
 
     private boolean mUseBackground;
+    private boolean mAnimating;
 
     /**
      * @param context
@@ -139,6 +154,9 @@
         mSelectedPaint = new Paint();
         mSelectedPaint.setColor(res.getColor(R.color.qc_selected));
         mSelectedPaint.setAntiAlias(true);
+        mSubPaint = new Paint();
+        mSubPaint.setAntiAlias(true);
+        mSubPaint.setColor(res.getColor(R.color.qc_sub));
     }
 
     public void setController(PieController ctl) {
@@ -176,18 +194,39 @@
     private void show(boolean show) {
         mOpen = show;
         if (mOpen) {
+            mController.stopEditingUrl();
+            mCurrentItems = mItems;
             if (mController != null) {
                 boolean changed = mController.onOpen();
             }
             layoutPie();
+            animateOpen();
         }
         if (!show) {
+            mAnimating = false;
             mCurrentItem = null;
+            mOpenItem = null;
             mPieView = null;
         }
         invalidate();
     }
 
+    private void animateOpen() {
+        ValueAnimator anim = ValueAnimator.ofFloat(0, 1);
+        anim.addUpdateListener(new AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                for (PieItem item : mCurrentItems) {
+                    item.setAnimationAngle((1 - animation.getAnimatedFraction()) * (- item.getStart()));
+                }
+                invalidate();
+            }
+
+        });
+        anim.setDuration(2*ANIMATION);
+        anim.start();
+    }
+
     private void setCenter(int x, int y) {
         if (x < mSlop) {
             mCenter.x = 0;
@@ -202,33 +241,32 @@
         int rgap = 2;
         int inner = mRadius + rgap;
         int outer = mRadius + mRadiusInc - rgap;
-        int radius = mRadius;
         int gap = 1;
         for (int i = 0; i < mLevels; i++) {
             int level = i + 1;
             float sweep = (float) (Math.PI - 2 * emptyangle) / mCounts[level];
             float angle = emptyangle + sweep / 2;
-            for (PieItem item : mItems) {
+            mPath = makeSlice(getDegrees(0) - gap, getDegrees(sweep) + gap, outer, inner, mCenter);
+            for (PieItem item : mCurrentItems) {
                 if (item.getLevel() == level) {
                     View view = item.getView();
-                    view.measure(view.getLayoutParams().width,
-                            view.getLayoutParams().height);
-                    int w = view.getMeasuredWidth();
-                    int h = view.getMeasuredHeight();
-                    int r = inner + (outer - inner) * 2 / 3;
-                    int x = (int) (r * Math.sin(angle));
-                    int y = mCenter.y - (int) (r * Math.cos(angle)) - h / 2;
-                    if (onTheLeft()) {
-                        x = mCenter.x + x - w / 2;
-                    } else {
-                        x = mCenter.x - x - w / 2;
+                    if (view != null) {
+                        view.measure(view.getLayoutParams().width,
+                                view.getLayoutParams().height);
+                        int w = view.getMeasuredWidth();
+                        int h = view.getMeasuredHeight();
+                        int r = inner + (outer - inner) * 2 / 3;
+                        int x = (int) (r * Math.sin(angle));
+                        int y = mCenter.y - (int) (r * Math.cos(angle)) - h / 2;
+                        if (onTheLeft()) {
+                            x = mCenter.x + x - w / 2;
+                        } else {
+                            x = mCenter.x - x - w / 2;
+                        }
+                        view.layout(x, y, x + w, y + h);
                     }
-                    view.layout(x, y, x + w, y + h);
                     float itemstart = angle - sweep / 2;
-                    Path slice = makeSlice(getDegrees(itemstart) - gap,
-                            getDegrees(itemstart + sweep) + gap,
-                            outer, inner, mCenter);
-                    item.setGeometry(itemstart, sweep, inner, outer, slice);
+                    item.setGeometry(itemstart, sweep, inner, outer);
                     angle += sweep;
                 }
             }
@@ -266,15 +304,18 @@
                 mBackground.draw(canvas);
                 canvas.restoreToCount(state);
             }
-            for (PieItem item : mItems) {
-                Paint p = item.isSelected() ? mSelectedPaint : mNormalPaint;
-                state = canvas.save();
-                if (onTheLeft()) {
-                    canvas.scale(-1, 1);
+            // draw base menu
+            PieItem last = mCurrentItem;
+            if (mOpenItem != null) {
+                last = mOpenItem;
+            }
+            for (PieItem item : mCurrentItems) {
+                if (item != last) {
+                    drawItem(canvas, item);
                 }
-                drawPath(canvas, item.getPath(), p);
-                canvas.restoreToCount(state);
-                drawItem(canvas, item);
+            }
+            if (last != null) {
+                drawItem(canvas, last);
             }
             if (mPieView != null) {
                 mPieView.draw(canvas);
@@ -283,19 +324,26 @@
     }
 
     private void drawItem(Canvas canvas, PieItem item) {
-        int outer = item.getOuterRadius();
-        int left = mCenter.x - outer;
-        int top = mCenter.y - outer;
-        // draw the item view
-        View view = item.getView();
-        int state = canvas.save();
-        canvas.translate(view.getX(), view.getY());
-        view.draw(canvas);
-        canvas.restoreToCount(state);
-    }
-
-    private void drawPath(Canvas canvas, Path path, Paint paint) {
-        canvas.drawPath(path, paint);
+        if (item.getView() != null) {
+            Paint p = item.isSelected() ? mSelectedPaint : mNormalPaint;
+            if (!mItems.contains(item)) {
+                p = item.isSelected() ? mSelectedPaint : mSubPaint;
+            }
+            int state = canvas.save();
+            if (onTheLeft()) {
+                canvas.scale(-1, 1);
+            }
+            float r = getDegrees(item.getStartAngle()) - 270; // degrees(0)
+            canvas.rotate(r, mCenter.x, mCenter.y);
+            canvas.drawPath(mPath, p);
+            canvas.restoreToCount(state);
+            // draw the item view
+            View view = item.getView();
+            state = canvas.save();
+            canvas.translate(view.getX(), view.getY());
+            view.draw(canvas);
+            canvas.restoreToCount(state);
+        }
     }
 
     private Path makeSlice(float start, float end, int outer, int inner, Point center) {
@@ -332,9 +380,11 @@
                     handled = mPieView.onTouchEvent(evt);
                 }
                 PieItem item = mCurrentItem;
-                deselect();
+                if (!mAnimating) {
+                    deselect();
+                }
                 show(false);
-                if (!handled && (item != null)) {
+                if (!mAnimating && !handled && (item != null) && (item.getView() != null)) {
                     item.getView().performClick();
                 }
                 return true;
@@ -343,9 +393,13 @@
             if (mOpen) {
                 show(false);
             }
-            deselect();
+            if (!mAnimating) {
+                deselect();
+                invalidate();
+            }
             return false;
         } else if (MotionEvent.ACTION_MOVE == action) {
+            if (mAnimating) return false;
             boolean handled = false;
             PointF polar = getPolar(x, y);
             int maxr = mRadius + mLevels * mRadiusInc + 50;
@@ -356,6 +410,15 @@
                 invalidate();
                 return false;
             }
+            if (polar.y < mRadius) {
+                if (mOpenItem != null) {
+                    closeSub();
+                } else if (!mAnimating) {
+                    deselect();
+                    invalidate();
+                }
+                return false;
+            }
             if (polar.y > maxr) {
                 deselect();
                 show(false);
@@ -366,9 +429,10 @@
                 return false;
             }
             PieItem item = findItem(polar);
-            if (mCurrentItem != item) {
+            if (item == null) {
+            } else if (mCurrentItem != item) {
                 onEnter(item);
-                if ((item != null) && item.isPieView()) {
+                if ((item != null) && item.isPieView() && (item.getView() != null)) {
                     int cx = item.getView().getLeft() + (onTheLeft()
                             ? item.getView().getWidth() : 0);
                     int cy = item.getView().getTop();
@@ -402,14 +466,125 @@
             playSoundEffect(SoundEffectConstants.CLICK);
             item.setSelected(true);
             mPieView = null;
+            mCurrentItem = item;
+            if ((mCurrentItem != mOpenItem) && mCurrentItem.hasItems()) {
+                openSub(mCurrentItem);
+                mOpenItem = item;
+            }
+        } else {
+            mCurrentItem = null;
         }
-        mCurrentItem = item;
+
+    }
+
+    private void animateOut(final PieItem fixed, AnimatorListener listener) {
+        if ((mCurrentItems == null) || (fixed == null)) return;
+        final float target = fixed.getStartAngle();
+        ValueAnimator anim = ValueAnimator.ofFloat(0, 1);
+        anim.addUpdateListener(new AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                for (PieItem item : mCurrentItems) {
+                    if (item != fixed) {
+                        item.setAnimationAngle(animation.getAnimatedFraction()
+                                * (target - item.getStart()));
+                    }
+                }
+                invalidate();
+            }
+        });
+        anim.setDuration(ANIMATION);
+        anim.addListener(listener);
+        anim.start();
+    }
+
+    private void animateIn(final PieItem fixed, AnimatorListener listener) {
+        if ((mCurrentItems == null) || (fixed == null)) return;
+        final float target = fixed.getStartAngle();
+        ValueAnimator anim = ValueAnimator.ofFloat(0, 1);
+        anim.addUpdateListener(new AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                for (PieItem item : mCurrentItems) {
+                    if (item != fixed) {
+                        item.setAnimationAngle((1 - animation.getAnimatedFraction())
+                                * (target - item.getStart()));
+                    }
+                }
+                invalidate();
+
+            }
+
+        });
+        anim.setDuration(ANIMATION);
+        anim.addListener(listener);
+        anim.start();
+    }
+
+    private void openSub(final PieItem item) {
+        mAnimating = true;
+        animateOut(item, new AnimatorListenerAdapter() {
+            public void onAnimationEnd(Animator a) {
+                for (PieItem item : mCurrentItems) {
+                    item.setAnimationAngle(0);
+                }
+                mCurrentItems = new ArrayList<PieItem>(mItems.size());
+                int i = 0, j = 0;
+                while (i < mItems.size()) {
+                    if (mItems.get(i) == item) {
+                        mCurrentItems.add(item);
+                    } else {
+                        mCurrentItems.add(item.getItems().get(j++));
+                    }
+                    i++;
+                }
+                layoutPie();
+                animateIn(item, new AnimatorListenerAdapter() {
+                    public void onAnimationEnd(Animator a) {
+                        for (PieItem item : mCurrentItems) {
+                            item.setAnimationAngle(0);
+                        }
+                        mAnimating = false;
+                    }
+                });
+            }
+        });
+    }
+
+    private void closeSub() {
+        mAnimating = true;
+        if (mCurrentItem != null) {
+            mCurrentItem.setSelected(false);
+        }
+        animateOut(mOpenItem, new AnimatorListenerAdapter() {
+            public void onAnimationEnd(Animator a) {
+                for (PieItem item : mCurrentItems) {
+                    item.setAnimationAngle(0);
+                }
+                mCurrentItems = mItems;
+                mPieView = null;
+                animateIn(mOpenItem, new AnimatorListenerAdapter() {
+                    public void onAnimationEnd(Animator a) {
+                        for (PieItem item : mCurrentItems) {
+                            item.setAnimationAngle(0);
+                        }
+                        mAnimating = false;
+                        mOpenItem = null;
+                        mCurrentItem = null;
+                    }
+                });
+            }
+        });
     }
 
     private void deselect() {
         if (mCurrentItem != null) {
             mCurrentItem.setSelected(false);
         }
+        if (mOpenItem != null) {
+            mOpenItem = null;
+            mCurrentItems = mItems;
+        }
         mCurrentItem = null;
         mPieView = null;
     }
@@ -439,15 +614,19 @@
      */
     private PieItem findItem(PointF polar) {
         // find the matching item:
-        for (PieItem item : mItems) {
-            if ((item.getInnerRadius() - mTouchOffset < polar.y)
-                    && (item.getOuterRadius() - mTouchOffset > polar.y)
-                    && (item.getStartAngle() < polar.x)
-                    && (item.getStartAngle() + item.getSweep() > polar.x)) {
+        for (PieItem item : mCurrentItems) {
+            if (inside(polar, mTouchOffset, item)) {
                 return item;
             }
         }
         return null;
     }
 
+    private boolean inside(PointF polar, float offset, PieItem item) {
+        return (item.getInnerRadius() - offset < polar.y)
+        && (item.getOuterRadius() - offset > polar.y)
+        && (item.getStartAngle() < polar.x)
+        && (item.getStartAngle() + item.getSweep() > polar.x);
+    }
+
 }
diff --git a/src/com/android/browser/view/PieStackView.java b/src/com/android/browser/view/PieStackView.java
index 16d42cb..e1f41bd 100644
--- a/src/com/android/browser/view/PieStackView.java
+++ b/src/com/android/browser/view/PieStackView.java
@@ -50,8 +50,6 @@
         super.setCurrent(ix);
         if (mCurrentListener != null) {
             mCurrentListener.onSetCurrent(ix);
-            buildViews();
-            layoutChildrenLinear();
         }
     }