/**
  * enter a slice for a view updates model only
  *
  * @param item
  */
 private void onEnter(PieItem item) {
   if (mCurrentItem != null) {
     mCurrentItem.setSelected(false);
   }
   if (item != null && item.isEnabled()) {
     item.setSelected(true);
     mCurrentItem = item;
     if ((mCurrentItem != mOpenItem) && mCurrentItem.hasItems()) {
       openCurrentItem();
     }
   } else {
     mCurrentItem = null;
   }
 }
  private void openCurrentItem() {
    if ((mCurrentItem != null) && mCurrentItem.hasItems()) {
      mCurrentItem.setSelected(false);
      mOpenItem = mCurrentItem;
      mOpening = true;
      mXFade = new LinearAnimation(1, 0);
      mXFade.setDuration(PIE_XFADE_DURATION);
      mXFade.setAnimationListener(
          new AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {}

            @Override
            public void onAnimationEnd(Animation animation) {
              mXFade = null;
            }

            @Override
            public void onAnimationRepeat(Animation animation) {}
          });
      mXFade.startNow();
      mOverlay.startAnimation(mXFade);
    }
  }
 private void layoutItems(List<PieItem> items, float centerAngle, int inner, int outer, int gap) {
   float emptyangle = PIE_SWEEP / 16;
   float sweep = (float) (PIE_SWEEP - 2 * emptyangle) / items.size();
   float angle = centerAngle - PIE_SWEEP / 2 + emptyangle + sweep / 2;
   // check if we have custom geometry
   // first item we find triggers custom sweep for all
   // this allows us to re-use the path
   for (PieItem item : items) {
     if (item.getCenter() >= 0) {
       sweep = item.getSweep();
       break;
     }
   }
   Path path = makeSlice(getDegrees(0) - gap, getDegrees(sweep) + gap, outer, inner, mCenter);
   for (PieItem item : items) {
     // shared between items
     item.setPath(path);
     if (item.getCenter() >= 0) {
       angle = item.getCenter();
     }
     int w = item.getIntrinsicWidth();
     int h = item.getIntrinsicHeight();
     // move views to outer border
     int r = inner + (outer - inner) * 2 / 3;
     int x = (int) (r * Math.cos(angle));
     int y = mCenter.y - (int) (r * Math.sin(angle)) - h / 2;
     x = mCenter.x + x - w / 2;
     item.setBounds(x, y, x + w, y + h);
     float itemstart = angle - sweep / 2;
     item.setGeometry(itemstart, sweep, inner, outer);
     if (item.hasItems()) {
       layoutItems(item.getItems(), angle, inner, outer + mRadiusInc / 2, gap);
     }
     angle += sweep;
   }
 }
 @Override
 public boolean onTouchEvent(MotionEvent evt) {
   float x = evt.getX();
   float y = evt.getY();
   int action = evt.getActionMasked();
   PointF polar = getPolar(x, y, !(mTapMode));
   if (MotionEvent.ACTION_DOWN == action) {
     mDown.x = (int) evt.getX();
     mDown.y = (int) evt.getY();
     mOpening = false;
     if (mTapMode) {
       PieItem item = findItem(polar);
       if ((item != null) && (mCurrentItem != item)) {
         mState = STATE_PIE;
         onEnter(item);
       }
     } else {
       setCenter((int) x, (int) y);
       show(true);
     }
     return true;
   } else if (MotionEvent.ACTION_UP == action) {
     if (isVisible()) {
       PieItem item = mCurrentItem;
       if (mTapMode) {
         item = findItem(polar);
         if (item != null && mOpening) {
           mOpening = false;
           return true;
         }
       }
       if (item == null) {
         mTapMode = false;
         show(false);
       } else if (!mOpening && !item.hasItems()) {
         item.performClick();
         startFadeOut();
         mTapMode = false;
       }
       return true;
     }
   } else if (MotionEvent.ACTION_CANCEL == action) {
     if (isVisible() || mTapMode) {
       show(false);
     }
     deselect();
     return false;
   } else if (MotionEvent.ACTION_MOVE == action) {
     if (polar.y < mRadius) {
       if (mOpenItem != null) {
         mOpenItem = null;
       } else {
         deselect();
       }
       return false;
     }
     PieItem item = findItem(polar);
     boolean moved = hasMoved(evt);
     if ((item != null) && (mCurrentItem != item) && (!mOpening || moved)) {
       // only select if we didn't just open or have moved past slop
       mOpening = false;
       if (moved) {
         // switch back to swipe mode
         mTapMode = false;
       }
       onEnter(item);
     }
   }
   return false;
 }