/**
   * Sets the current item. Does nothing when index is wrong.
   *
   * @param index the item index
   * @param animated the animation flag
   */
  public void setCurrentItem(int index, boolean animated) {
    if (adapter == null || adapter.getItemsCount() == 0) {
      return; // throw?
    }
    if (index < 0 || index >= adapter.getItemsCount()) {
      if (isCyclic) {
        while (index < 0) {
          index += adapter.getItemsCount();
        }
        index %= adapter.getItemsCount();
      } else {
        return; // throw?
      }
    }
    if (index != currentItem) {
      if (animated) {
        scroll(index - currentItem, SCROLLING_DURATION);
      } else {
        invalidateLayouts();

        int old = currentItem;
        currentItem = index;

        notifyChangingListeners(old, currentItem);

        invalidate();
      }
    }
  }
  /**
   * Returns the max item length that can be present.
   *
   * @return the max length
   */
  private int getMaxTextLength() {
    AbWheelAdapter adapter = getAdapter();
    if (adapter == null) {
      return 0;
    }

    int adapterLength = adapter.getMaximumLength();
    if (adapterLength > 0) {
      return adapterLength;
    } else {
      return 0;
    }
  }
  /**
   * Returns text item by index.
   *
   * @param index the item index
   * @return the item or null
   */
  private String getTextItem(int index) {
    if (adapter == null || adapter.getItemsCount() == 0) {
      return null;
    }
    int count = adapter.getItemsCount();
    if ((index < 0 || index >= count) && !isCyclic) {
      return null;
    } else {
      while (index < 0) {
        index = count + index;
      }
    }

    index %= count;
    return adapter.getItem(index);
  }
 public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
   lastScrollY = currentItem * getItemHeight() + scrollingOffset;
   int maxY = isCyclic ? 0x7FFFFFFF : adapter.getItemsCount() * getItemHeight();
   int minY = isCyclic ? -maxY : 0;
   scroller.fling(0, lastScrollY, 0, (int) -velocityY / 2, 0, 0, minY, maxY);
   setNextMessage(MESSAGE_SCROLL);
   return true;
 }
  /** Justifies wheel. */
  private void justify() {
    if (adapter == null) {
      return;
    }

    lastScrollY = 0;
    int offset = scrollingOffset;
    int itemHeight = getItemHeight();
    boolean needToIncrease = offset > 0 ? currentItem < adapter.getItemsCount() : currentItem > 0;
    if ((isCyclic || needToIncrease) && Math.abs((float) offset) > (float) itemHeight / 2) {
      if (offset < 0) offset += itemHeight + MIN_DELTA_FOR_SCROLLING;
      else offset -= itemHeight + MIN_DELTA_FOR_SCROLLING;
    }
    if (Math.abs(offset) > MIN_DELTA_FOR_SCROLLING) {
      scroller.startScroll(0, 0, 0, offset, SCROLLING_DURATION);
      setNextMessage(MESSAGE_JUSTIFY);
    } else {
      finishScrolling();
    }
  }
  /**
   * Scrolls the wheel.
   *
   * @param delta the scrolling value
   */
  private void doScroll(int delta) {
    scrollingOffset += delta;

    int count = scrollingOffset / getItemHeight();
    int pos = currentItem - count;
    if (isCyclic && adapter.getItemsCount() > 0) {
      // fix position by rotating
      while (pos < 0) {
        pos += adapter.getItemsCount();
      }
      pos %= adapter.getItemsCount();
    } else if (isScrollingPerformed) {
      //
      if (pos < 0) {
        count = currentItem;
        pos = 0;
      } else if (pos >= adapter.getItemsCount()) {
        count = currentItem - adapter.getItemsCount() + 1;
        pos = adapter.getItemsCount() - 1;
      }
    } else {
      // fix position
      pos = Math.max(pos, 0);
      pos = Math.min(pos, adapter.getItemsCount() - 1);
    }

    int offset = scrollingOffset;
    if (pos != currentItem) {
      setCurrentItem(pos, false);
    } else {
      invalidate();
    }

    // update offset
    scrollingOffset = offset - count * getItemHeight();
    if (scrollingOffset > getHeight()) {
      scrollingOffset = scrollingOffset % getHeight() + getHeight();
    }
  }