protected void drawTipsWithArrow(Graphics2D g, Value value, double startAngle, double arcAngle, boolean drawLabels) {
    double xCenter;
    double yCenter;
    double radius;
    double xResult;
    double yResult;
    double arcRadian;
    int x;
    int y;
    int w;
    int h;
    double boxMargin = 2;

    //arrow
    arcAngle = startAngle + arcAngle / 2;
    arcRadian = Math.PI * arcAngle / 180;

    xCenter = (getPieWidth() + (pieMargin + chartMargin) * 2) / 2;
    yCenter = (getPieHeight()+ (pieMargin + chartMargin) * 2) / 2;

    if (getPieWidth() > getPieHeight()) {
      radius = getPieHeight() / 2;
    } else {
      radius = getPieWidth() / 2;
    }
    //the first point of arrow
    radius = radius + TIPS_ARROW_MARGIN;
    if (isRightSide(arcAngle)) {
      xResult = xCenter + Math.cos(arcRadian) * radius;
      yResult = yCenter - Math.sin(arcRadian) * radius;
    } else {
      xResult = xCenter + Math.cos(arcRadian) * radius;
      yResult = yCenter - Math.sin(arcRadian) * radius;
    }
    //the second point of arrow
    radius = radius - TIPS_ARROW_MARGIN * 4;
    if (isRightSide(arcAngle)) {
      xCenter = xCenter + Math.cos(arcRadian) * radius ;
      yCenter = yCenter - Math.sin(arcRadian) * radius;
    } else {
      xCenter = xCenter + Math.cos(arcRadian) * radius;
      yCenter = yCenter - Math.sin(arcRadian) * radius;
    }

    g.setColor(tipsArrowColor);
    x = round(xCenter);
    y = round(yCenter);
    w = round(xResult);
    h = round(yResult);
    g.drawLine(x, y, w, h);

    //box
    StringBuffer label = new StringBuffer();
    label.append(value.getLabel());
    label.append(EQUALS);
    label.append(format(value.getValue()));
    if (!drawLabels) {
      if (isRightSide(arcAngle)) {
        x = round(xResult);
      } else {
        x = round(xResult - getStringWidth(label.toString(), g) - boxMargin * 2);
      }
      if (isTopSide(arcAngle)) {
        y = round(yResult - getStringHeight(label.toString(), g));
      } else {
        y = round(yResult);
      }
      w = round(getStringWidth(label.toString(), g) + boxMargin * 2);
      h = round(getStringHeight(label.toString(), g));
      g.setColor(legendColor);
      g.fillRect(x, y, w, h);
      g.setColor(tipsArrowColor);
      g.drawRect(x, y, w, h);
    } else {
      //label
      if (isRightSide(arcAngle)) {
        x = round(xResult + boxMargin);
      } else {
        x = round(xResult - getStringWidth(label.toString(), g) - boxMargin);
      }
      if (isTopSide(arcAngle)) {
        y = round(yResult - boxMargin * 2);
      } else {
        y = round(yResult + getStringHeight(label.toString(), g) - boxMargin);
      }
      g.setColor(labelsColor);
      g.drawString(label.toString(), x, y);
    }
  }