qc refactor part1

   Bug: 4052266
   change QuickControl rendering (removes all path calculations)
   change pie to allow several levels of items

Change-Id: I52254745eadf956da83d963e23c1ba07946f53a7
diff --git a/res/drawable-mdpi/pie_bg_selected.png b/res/drawable-mdpi/pie_bg_selected.png
new file mode 100644
index 0000000..787984a
--- /dev/null
+++ b/res/drawable-mdpi/pie_bg_selected.png
Binary files differ
diff --git a/res/drawable-mdpi/qc_background_normal.png b/res/drawable-mdpi/qc_background_normal.png
index 539b45d..947722d 100644
--- a/res/drawable-mdpi/qc_background_normal.png
+++ b/res/drawable-mdpi/qc_background_normal.png
Binary files differ
diff --git a/res/drawable/qc_item_selector.xml b/res/drawable/qc_item_selector.xml
new file mode 100644
index 0000000..77f8023
--- /dev/null
+++ b/res/drawable/qc_item_selector.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_selected="true"
+        android:drawable="@drawable/pie_bg_selected" />
+    <item android:state_selected="false" android:drawable="@drawable/clear" />
+</selector>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 6fa0840..73daa07 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -29,10 +29,9 @@
     <color name="bookmarkWidgetDivider">#383847</color>
     <color name="bookmarkWidgetItemBackground">#2b2b3c</color>
     <color name="bookmarkWidgetFolderBackground">#A0383847</color>
-    <color name="qc_slice_normal">#E0A0A0A0</color>
-    <color name="qc_slice_active">#E02090FF</color>
     <color name="bookmarkWidgetFaviconBackground">#23ffffff</color>
     <color name="bookmarkListFaviconBackground">#23ffffff</color>
     <color name="tabFaviconBackground">#FF555555</color>
     <color name="tabFocusHighlight">#FF99CC00</color>
+    <color name="qcMenuBackground">#C0000000</color>
 </resources>
diff --git a/res/values/dimensions.xml b/res/values/dimensions.xml
index 5054254..67acc0a 100644
--- a/res/values/dimensions.xml
+++ b/res/values/dimensions.xml
@@ -30,9 +30,10 @@
     <dimen name="widgetItemMinHeight">48dip</dimen>
     <dimen name="favicon_size">16dip</dimen>
     <dimen name="favicon_padded_size">20dip</dimen>
-    <dimen name="qc_radius">130dip</dimen>
-    <dimen name="qc_radius_inc">100dip</dimen>
+    <dimen name="qc_radius_start">30dip</dimen>
+    <dimen name="qc_radius_increment">70dip</dimen>
     <dimen name="qc_slop">15dip</dimen>
+    <dimen name="qc_tab_title_height">20dip</dimen>
     <dimen name="bookmark_widget_thumb_size">32dip</dimen>
     <dimen name="bookmark_widget_favicon_size">26dip</dimen>
     <!-- For the most visited page -->
diff --git a/src/com/android/browser/PieControl.java b/src/com/android/browser/PieControl.java
index 2e2eba4..ad47c72 100644
--- a/src/com/android/browser/PieControl.java
+++ b/src/com/android/browser/PieControl.java
@@ -16,6 +16,7 @@
 
 package com.android.browser;
 
+import com.android.browser.view.PieItem;
 import com.android.browser.view.PieMenu;
 
 import android.app.Activity;
@@ -26,9 +27,6 @@
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 
-import java.util.HashMap;
-import java.util.Map;
-
 /**
  * controller for Quick Controls pie menu
  */
@@ -38,24 +36,19 @@
     private UiController mUiController;
     private XLargeUi mUi;
     private PieMenu mPie;
-    private ImageView mBack;
-    private ImageView mForward;
-    private ImageView mRefresh;
-    private ImageView mUrl;
-    private ImageView mOptions;
-    private ImageView mBookmarks;
-    private ImageView mNewTab;
-    private ImageView mClose;
-
-    private Map<View,Tab> mTabItems;
-
-    boolean mNewTabMode = true;
+    private PieItem mBack;
+    private PieItem mForward;
+    private PieItem mRefresh;
+    private PieItem mUrl;
+    private PieItem mOptions;
+    private PieItem mBookmarks;
+    private PieItem mNewTab;
+    private PieItem mClose;
 
     public PieControl(Activity activity, UiController controller, XLargeUi ui) {
         mActivity = activity;
         mUiController = controller;
         mUi = ui;
-        mTabItems = new HashMap<View, Tab>();
     }
 
     protected void attachToContainer(FrameLayout container) {
@@ -64,22 +57,35 @@
             LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT,
                     LayoutParams.MATCH_PARENT);
             mPie.setLayoutParams(lp);
-            mNewTab = makeMenuView(R.drawable.ic_pie_new_tab);
-            mPie.addItem(mNewTab);
-            mBack = makeMenuView(R.drawable.ic_pie_back);
-            mPie.addItem(mBack);
-            mUrl = makeMenuView(R.drawable.ic_pie_web);
-            mPie.addItem(mUrl);
-            mBookmarks = makeMenuView(R.drawable.ic_pie_bookmarks);
-            mPie.addItem(mBookmarks);
-            mOptions = makeMenuView(R.drawable.ic_pie_more);
-            mPie.addItem(mOptions);
+            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);
+            mOptions = makeItem(
+                    com.android.internal.R.drawable.ic_menu_moreoverflow_normal_holo_dark,
+                    2);
             setClickListener(mBack,
+                    mRefresh,
+                    mForward,
                     mUrl,
                     mOptions,
                     mBookmarks,
-                    mNewTab
+                    mNewTab,
+                    mClose
                     );
+            // level 1
+            mPie.addItem(mBack);
+            mPie.addItem(mUrl);
+            mPie.addItem(mBookmarks);
+            // level 2
+            mPie.addItem(mForward);
+            mPie.addItem(mRefresh);
+            mPie.addItem(mNewTab);
+            mPie.addItem(mClose);
+            mPie.addItem(mOptions);
             mPie.setController(this);
         }
         container.addView(mPie);
@@ -89,17 +95,20 @@
         container.removeView(mPie);
     }
 
-    private ImageView makeMenuView(int image) {
-        ImageView item = new ImageView(mActivity);
-        item.setImageResource(image);
+    private PieItem makeItem(int image, int l) {
+        ImageView view = new ImageView(mActivity);
+        view.setImageResource(image);
+        view.setMinimumWidth(48);
+        view.setMinimumHeight(48);
         LayoutParams lp = new LayoutParams(48, 48);
-        item.setLayoutParams(lp);
-        return item;
+        view.setLayoutParams(lp);
+        view.setBackgroundResource(R.drawable.qc_item_selector);
+        return new PieItem(view, l);
     }
 
-    private void setClickListener(View... views) {
-        for (View view : views) {
-            view.setOnClickListener(this);
+    private void setClickListener(PieItem... items) {
+        for (PieItem item : items) {
+            item.getView().setOnClickListener(this);
         }
     }
 
@@ -112,41 +121,35 @@
 
     @Override
     public void onClick(View v) {
-        mPie.show(false);
         Tab tab = mUiController.getTabControl().getCurrentTab();
         WebView web = tab.getWebView();
-        if (mBack == v) {
+        if (mBack.getView() == v) {
             web.goBack();
-        } else if (mForward == v) {
+        } else if (mForward.getView() == v) {
             web.goForward();
-        } else if (mRefresh == v) {
+        } else if (mRefresh.getView() == v) {
             if (tab.inPageLoad()) {
                 web.stopLoading();
             } else {
                 web.reload();
             }
-        } else if (mUrl == v) {
+        } else if (mUrl.getView() == v) {
             mUi.showTitleBarAndEdit();
-        } else if (mOptions == v) {
+        } else if (mOptions.getView() == v) {
             mActivity.openOptionsMenu();
-        } else if (mBookmarks == v) {
+        } else if (mBookmarks.getView() == v) {
             mUiController.bookmarksOrHistoryPicker(false);
-        } else if (mNewTab == v) {
+        } else if (mNewTab.getView() == v) {
             mUiController.openTabToHomePage();
             mUi.showTitleBarAndEdit();
-        } else if (mClose == v) {
+        } else if (mClose.getView() == v) {
             mUiController.closeCurrentTab();
-        } else {
-            Tab ntab = mTabItems.get(v);
-            if (ntab != null) {
-                mUiController.switchToTab(mUiController.getTabControl().getTabIndex(ntab));
-            }
         }
     }
 
     @Override
     public boolean onOpen() {
-        return true;
+        return false;
     }
 
 }
diff --git a/src/com/android/browser/XLargeUi.java b/src/com/android/browser/XLargeUi.java
index 6225ad4..fdb72e5 100644
--- a/src/com/android/browser/XLargeUi.java
+++ b/src/com/android/browser/XLargeUi.java
@@ -501,4 +501,5 @@
     public void registerDropdownChangeListener(DropdownChangeListener d) {
         mTitleBar.registerDropdownChangeListener(d);
     }
+
 }
diff --git a/src/com/android/browser/view/PieItem.java b/src/com/android/browser/view/PieItem.java
new file mode 100644
index 0000000..c09dba2
--- /dev/null
+++ b/src/com/android/browser/view/PieItem.java
@@ -0,0 +1,81 @@
+/*
+ * 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 android.view.View;
+
+/**
+ * Pie menu item
+ */
+public class PieItem {
+
+    private View mView;
+    private int level;
+    private float start;
+    private float sweep;
+    private int inner;
+    private int outer;
+    private boolean mSelected;
+
+    public PieItem(View view, int level) {
+        mView = view;
+        this.level = level;
+    }
+
+    public void setSelected(boolean s) {
+        mSelected = s;
+        if (mView != null) {
+            mView.setSelected(s);
+        }
+    }
+
+    public boolean isSelected() {
+        return mSelected;
+    }
+
+    public int getLevel() {
+        return level;
+    }
+
+    public void setGeometry(float st, float sw, int inside, int outside) {
+        start = st;
+        sweep = sw;
+        inner = inside;
+        outer = outside;
+    }
+
+    public float getStartAngle() {
+        return start;
+    }
+
+    public float getSweep() {
+        return sweep;
+    }
+
+    public int getInnerRadius() {
+        return inner;
+    }
+
+    public int getOuterRadius() {
+        return outer;
+    }
+
+    public View getView() {
+        return mView;
+    }
+
+}
diff --git a/src/com/android/browser/view/PieMenu.java b/src/com/android/browser/view/PieMenu.java
index 080c257..98c0f59 100644
--- a/src/com/android/browser/view/PieMenu.java
+++ b/src/com/android/browser/view/PieMenu.java
@@ -20,17 +20,9 @@
 
 import android.content.Context;
 import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.BitmapShader;
 import android.graphics.Canvas;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.Path;
 import android.graphics.Point;
 import android.graphics.PointF;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.graphics.Shader;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.view.MotionEvent;
@@ -40,13 +32,11 @@
 import android.widget.FrameLayout;
 
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 
 public class PieMenu extends FrameLayout {
 
-    private static final int RADIUS_GAP = 10;
+    private static final int MAX_LEVELS = 5;
 
     public interface PieController {
         /**
@@ -55,31 +45,23 @@
          */
         public boolean onOpen();
     }
+
     private Point mCenter;
     private int mRadius;
     private int mRadiusInc;
     private int mSlop;
 
     private boolean mOpen;
-    private Paint mPaint;
-    private Paint mSelectedPaint;
     private PieController mController;
 
-    private Map<View, List<View>> mMenu;
-    private List<View> mStack;
+    private List<PieItem> mItems;
+    private int mLevels;
+    private int[] mCounts;
 
-    private boolean mDirty;
+    private Drawable mBackground;
 
-    private Drawable mActiveDrawable;
-    private Drawable mInactiveDrawable;
-    private final Paint mActiveShaderPaint = new Paint();
-    private final Paint mInactiveShaderPaint = new Paint();
-    private final Matrix mActiveMatrix = new Matrix();
-    private final Matrix mInactiveMatrix = new Matrix();
-
-    private BitmapShader mActiveShader;
-    private BitmapShader mInactiveShader;
-
+    // touch handling
+    PieItem mCurrentItem;
 
     /**
      * @param context
@@ -109,130 +91,58 @@
     }
 
     private void init(Context ctx) {
-        this.setTag(new MenuTag(0));
-        mStack = new ArrayList<View>();
-        mStack.add(this);
+        mItems = new ArrayList<PieItem>();
+        mLevels = 0;
+        mCounts = new int[MAX_LEVELS];
         Resources res = ctx.getResources();
-        mRadius = (int) res.getDimension(R.dimen.qc_radius);
-        mRadiusInc = (int) res.getDimension(R.dimen.qc_radius_inc);
+        mRadius = (int) res.getDimension(R.dimen.qc_radius_start);
+        mRadiusInc = (int) res.getDimension(R.dimen.qc_radius_increment);
         mSlop = (int) res.getDimension(R.dimen.qc_slop);
-        mPaint = new Paint();
-        mPaint.setAntiAlias(true);
-        mPaint.setColor(res.getColor(R.color.qc_slice_normal));
-        mSelectedPaint = new Paint();
-        mSelectedPaint.setAntiAlias(true);
-        mSelectedPaint.setColor(res.getColor(R.color.qc_slice_active));
         mOpen = false;
-        mMenu = new HashMap<View, List<View>>();
         setWillNotDraw(false);
         setDrawingCacheEnabled(false);
         mCenter = new Point(0,0);
-        mDirty = true;
-        mActiveShaderPaint.setStyle(Paint.Style.FILL);
-        mActiveShaderPaint.setAntiAlias(true);
-
-        mInactiveShaderPaint.setStyle(Paint.Style.FILL);
-        mInactiveShaderPaint.setAntiAlias(true);
-        mActiveDrawable = res.getDrawable(R.drawable.qc_background_selected);
-        mInactiveDrawable = res.getDrawable(R.drawable.qc_background_normal);
-
-        Bitmap activeTexture = getDrawableAsBitmap(mActiveDrawable,
-                mActiveDrawable.getIntrinsicWidth(),
-                mActiveDrawable.getIntrinsicHeight());
-        Bitmap inactiveTexture = getDrawableAsBitmap(mInactiveDrawable,
-                mInactiveDrawable.getIntrinsicWidth(),
-                mInactiveDrawable.getIntrinsicHeight());
-
-        mActiveShader = new BitmapShader(activeTexture,
-                Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
-        mActiveShaderPaint.setShader(mActiveShader);
-
-        mInactiveShader = new BitmapShader(inactiveTexture,
-                Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
-        mInactiveShaderPaint.setShader(mInactiveShader);
-
-    }
-
-    private static Bitmap getDrawableAsBitmap(Drawable drawable, int width, int height) {
-        Bitmap b = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
-        Canvas c = new Canvas(b);
-        drawable.setBounds(0, 0, width, height);
-        drawable.draw(c);
-        return b;
+        mBackground = res.getDrawable(R.drawable.qc_background_normal);
     }
 
     public void setController(PieController ctl) {
         mController = ctl;
     }
 
-    public void setRadius(int r) {
-        mRadius = r;
-        requestLayout();
-    }
-
-    public void setRadiusIncrement(int ri) {
-        mRadiusInc = ri;
-        requestLayout();
-    }
-
-    /**
-     * add a menu item to another item as a submenu
-     * @param item
-     * @param parent
-     */
-    public void addItem(View item, View parent) {
-        List<View> subs = mMenu.get(parent);
-        if (subs == null) {
-            subs = new ArrayList<View>();
-            mMenu.put(parent, subs);
-        }
-        subs.add(item);
-        MenuTag tag = new MenuTag(((MenuTag) parent.getTag()).level + 1);
-        item.setTag(tag);
-    }
-
-    public void addItem(View view) {
+    public void addItem(PieItem item) {
         // add the item to the pie itself
-        addItem(view, this);
+        mItems.add(item);
+        int l = item.getLevel();
+        mLevels = Math.max(mLevels, l);
+        mCounts[l]++;
     }
 
-    public void removeItem(View view) {
-        List<View> subs = mMenu.get(view);
-        mMenu.remove(view);
-        for (View p : mMenu.keySet()) {
-            List<View> sl = mMenu.get(p);
-            if (sl != null) {
-                sl.remove(view);
-            }
-        }
-    }
-
-    public void clearItems(View parent) {
-        List<View> subs = mMenu.remove(parent);
-        if (subs != null) {
-            for (View sub: subs) {
-                clearItems(sub);
-            }
-        }
+    public void removeItem(PieItem item) {
+        mItems.remove(item);
     }
 
     public void clearItems() {
-        mMenu.clear();
+        mItems.clear();
     }
 
+    private boolean onTheLeft() {
+        return mCenter.x < mSlop;
+    }
 
-    public void show(boolean show) {
+    /**
+     * guaranteed has center set
+     * @param show
+     */
+    private void show(boolean show) {
         mOpen = show;
         if (mOpen) {
             if (mController != null) {
                 boolean changed = mController.onOpen();
             }
-            mDirty = true;
+            layoutPie();
         }
         if (!show) {
-            // hide sub items
-            mStack.clear();
-            mStack.add(this);
+            mCurrentItem = null;
         }
         invalidate();
     }
@@ -246,151 +156,72 @@
         mCenter.y = y;
     }
 
-    private boolean onTheLeft() {
-        return mCenter.x < mSlop;
+    private void layoutPie() {
+        int inner = mRadius;
+        int outer = mRadius + mRadiusInc;
+        for (int i = 0; i < mLevels; i++) {
+            int level = i + 1;
+            float sweep = (float) Math.PI / (mCounts[level] + 1);
+            float angle = sweep;
+            for (PieItem item : mItems) {
+                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 x = (int) (outer * Math.sin(angle));
+                    int y = mCenter.y - (int) (outer * Math.cos(angle)) - h / 2;
+                    if (onTheLeft()) {
+                        x = mCenter.x + x - w;
+                    } else {
+                        x = mCenter.x - x;
+                    }
+                    view.layout(x, y, x + w, y + h);
+                    float itemstart = angle - sweep / 2;
+                    item.setGeometry(itemstart, sweep, inner, outer);
+                    angle += sweep;
+                }
+            }
+            inner += mRadiusInc;
+            outer += mRadiusInc;
+        }
     }
 
     @Override
     protected void onDraw(Canvas canvas) {
         if (mOpen) {
-            int radius = mRadius;
-            // start in the center for 0 level menu
-            float anchor = (float) Math.PI / 2;
-            PointF angles = new PointF();
+            int w = mBackground.getIntrinsicWidth();
+            int h = mBackground.getIntrinsicHeight();
+            int left = mCenter.x - w;
+            int top = mCenter.y - h / 2;
+            mBackground.setBounds(left, top, left + w, top + h);
             int state = canvas.save();
             if (onTheLeft()) {
-                // left handed
-                canvas.scale(-1, 1);
-            }
-            for (View parent : mStack) {
-                List<View> subs = mMenu.get(parent);
-                if (subs != null) {
-                    setGeometry(anchor, subs.size(), angles);
-                }
-                anchor = drawSlices(canvas, subs, radius, angles.x, angles.y);
-                radius += mRadiusInc + RADIUS_GAP;
-            }
-            canvas.restoreToCount(state);
-            mDirty = false;
-        }
-    }
-
-    /**
-     * draw the set of slices
-     * @param canvas
-     * @param items
-     * @param radius
-     * @param start
-     * @param sweep
-     * @return the angle of the selected slice
-     */
-    private float drawSlices(Canvas canvas, List<View> items, int radius,
-            float start, float sweep) {
-        float angle = start + sweep / 2;
-        // gap between slices in degrees
-        float gap = 1f;
-        float newanchor = 0f;
-        for (View item : items) {
-            if (mDirty) {
-                item.measure(item.getLayoutParams().width,
-                        item.getLayoutParams().height);
-                int w = item.getMeasuredWidth();
-                int h = item.getMeasuredHeight();
-                int x = (int) (radius * Math.sin(angle));
-                int y =  mCenter.y - (int) (radius * Math.cos(angle)) - h / 2;
-                if (onTheLeft()) {
-                    x = mCenter.x + x - w / 2;
-                } else {
-                    x = mCenter.x - x - w / 2;
-                }
-                item.layout(x, y, x + w, y + h);
-            }
-            float itemstart = angle - sweep / 2;
-            int inner = radius - mRadiusInc / 2;
-            int outer = radius + mRadiusInc / 2;
-            Path slice = makeSlice(getDegrees(itemstart) - gap,
-                    getDegrees(itemstart + sweep) + gap,
-                    outer, inner, mCenter);
-            MenuTag tag = (MenuTag) item.getTag();
-            tag.start = itemstart;
-            tag.sweep = sweep;
-            tag.inner = inner;
-            tag.outer = outer;
-            int state = canvas.save();
-            int[] topLeft = new int[2];
-            getLocationInWindow(topLeft);
-            topLeft[0] = mCenter.x - outer;
-            topLeft[1] = mCenter.y - outer;
-            Paint paint = item.isPressed() ? mActiveShaderPaint : mInactiveShaderPaint;
-            drawClipped(canvas, paint, slice, topLeft, item.isPressed());
-            canvas.restoreToCount(state);
-            state = canvas.save();
-            if (onTheLeft()) {
                 canvas.scale(-1, 1);
             }
-            canvas.translate(item.getX(), item.getY());
-            item.draw(canvas);
+            mBackground.draw(canvas);
             canvas.restoreToCount(state);
-            if (mStack.contains(item)) {
-                // item is anchor for sub menu
-                newanchor = angle;
+            for (PieItem item : mItems) {
+                drawItem(canvas, item);
             }
-            angle += sweep;
         }
-        return newanchor;
     }
 
-    private void drawClipped(Canvas canvas, Paint paint, Path clipPath, int[] pos,
-            boolean selected) {
-        // TODO: We should change the matrix/shader only when needed
-        final Matrix matrix = selected ? mActiveMatrix : mInactiveMatrix;
-        matrix.setTranslate(pos[0], pos[1]);
-        (selected ? mActiveShader : mInactiveShader).setLocalMatrix(matrix);
-        canvas.drawPath(clipPath, paint);
-    }
-
-
-    /**
-     * converts a
-     * @param angle from 0..PI to Android degrees (clockwise starting at 3 o'clock)
-     * @return skia angle
-     */
-    private float getDegrees(double angle) {
-        return (float) (270 - 180 * angle / Math.PI);
-    }
-
-    private Path makeSlice(float startangle, float endangle, int outerradius,
-            int innerradius, Point center) {
-        RectF bb = new RectF(center.x - outerradius, center.y - outerradius,
-                center.x + outerradius, center.y + outerradius);
-        RectF bbi = new RectF(center.x - innerradius, center.y - innerradius,
-                center.x + innerradius, center.y + innerradius);
-        Path path = new Path();
-        path.arcTo(bb, startangle, endangle - startangle, true);
-        path.arcTo(bbi, endangle, startangle - endangle);
-        path.close();
-        return path;
-    }
-
-    /**
-     * all angles are 0 .. MATH.PI where 0 points up, and rotate counterclockwise
-     * set the startangle and slice sweep in result
-     * @param anchorangle : angle at which the menu is anchored
-     * @param nslices
-     * @param result : x : start, y : sweep
-     */
-    private void setGeometry(float anchorangle, int nslices, PointF result) {
-        float span = (float) Math.min(anchorangle, Math.PI - anchorangle);
-        float sweep = 2 * span / (nslices + 1);
-        result.x = anchorangle - span + sweep / 2;
-        result.y = sweep;
+    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);
     }
 
     // touch handling for pie
 
-    View mCurrentView;
-    Rect mHitRect = new Rect();
-
     @Override
     public boolean onTouchEvent(MotionEvent evt) {
         float x = evt.getX();
@@ -405,12 +236,12 @@
             }
         } else if (MotionEvent.ACTION_UP == action) {
             if (mOpen) {
-                View v = mCurrentView;
+                PieItem item = mCurrentItem;
                 deselect();
-                if (v != null) {
-                    v.performClick();
-                }
                 show(false);
+                if (item != null) {
+                    item.getView().performClick();
+                }
                 return true;
             }
         } else if (MotionEvent.ACTION_CANCEL == action) {
@@ -420,19 +251,21 @@
             deselect();
             return false;
         } else if (MotionEvent.ACTION_MOVE == action) {
+            boolean handled = false;
             PointF polar = getPolar(x, y);
-            if (polar.y > mRadius + 2 * mRadiusInc) {
-                show(false);
+            int maxr = mRadius + mLevels * mRadiusInc + 50;
+            if (polar.y > maxr) {
                 deselect();
+                show(false);
                 evt.setAction(MotionEvent.ACTION_DOWN);
                 if (getParent() != null) {
                     ((ViewGroup) getParent()).dispatchTouchEvent(evt);
                 }
                 return false;
             }
-            View v = findView(polar);
-            if (mCurrentView != v) {
-                onEnter(v);
+            PieItem item = findItem(polar);
+            if (mCurrentItem != item) {
+                onEnter(item);
                 invalidate();
             }
         }
@@ -443,50 +276,26 @@
     /**
      * enter a slice for a view
      * updates model only
-     * @param view
+     * @param item
      */
-    private void onEnter(View view) {
+    private void onEnter(PieItem item) {
         // deselect
-        if (mCurrentView != null) {
-            if (getLevel(mCurrentView) >= getLevel(view)) {
-                mCurrentView.setPressed(false);
-            }
+        if (mCurrentItem != null) {
+            mCurrentItem.setSelected(false);
         }
-        if (view != null) {
+        if (item != null) {
             // clear up stack
             playSoundEffect(SoundEffectConstants.CLICK);
-            MenuTag tag = (MenuTag) view.getTag();
-            int i = mStack.size() - 1;
-            while (i > 0) {
-                View v = mStack.get(i);
-                if (((MenuTag) v.getTag()).level >= tag.level) {
-                    v.setPressed(false);
-                    mStack.remove(i);
-                } else {
-                    break;
-                }
-                i--;
-            }
-            List<View> items = mMenu.get(view);
-            if (items != null) {
-                mStack.add(view);
-                mDirty = true;
-            }
-            view.setPressed(true);
+            item.setSelected(true);
         }
-        mCurrentView = view;
+        mCurrentItem = item;
     }
 
     private void deselect() {
-        if (mCurrentView != null) {
-            mCurrentView.setPressed(false);
+        if (mCurrentItem != null) {
+            mCurrentItem.setSelected(false);
         }
-        mCurrentView = null;
-    }
-
-    private int getLevel(View v) {
-        if (v == null) return -1;
-        return ((MenuTag) v.getTag()).level;
+        mCurrentItem = null;
     }
 
     private PointF getPolar(float x, float y) {
@@ -510,39 +319,19 @@
     /**
      *
      * @param polar x: angle, y: dist
-     * @return
+     * @return the item at angle/dist or null
      */
-    private View findView(PointF polar) {
+    private PieItem findItem(PointF polar) {
         // find the matching item:
-        for (View parent : mStack) {
-            List<View> subs = mMenu.get(parent);
-            if (subs != null) {
-                for (View item : subs) {
-                    MenuTag tag = (MenuTag) item.getTag();
-                    if ((tag.inner < polar.y)
-                            && (tag.outer > polar.y)
-                            && (tag.start < polar.x)
-                            && (tag.start + tag.sweep > polar.x)) {
-                        return item;
-                    }
-                }
+        for (PieItem item : mItems) {
+            if ((item.getInnerRadius() < polar.y)
+                    && (item.getOuterRadius() > polar.y)
+                    && (item.getStartAngle() < polar.x)
+                    && (item.getStartAngle() + item.getSweep() > polar.x)) {
+                return item;
             }
         }
         return null;
     }
 
-    class MenuTag {
-
-        int level;
-        float start;
-        float sweep;
-        int inner;
-        int outer;
-
-        public MenuTag(int l) {
-            level = l;
-        }
-
-    }
-
 }