示例#1
1
 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
   super.onMeasure(widthMeasureSpec, heightMeasureSpec);
   int size = (int) Utils.convertDpToPixel(50f);
   setMeasuredDimension(
       Math.max(getSuggestedMinimumWidth(), resolveSize(size, widthMeasureSpec)),
       Math.max(getSuggestedMinimumHeight(), resolveSize(size, heightMeasureSpec)));
 }
示例#2
0
  @Override
  protected void init() {
    super.init();

    mWebLineWidth = Utils.convertDpToPixel(1.5f);
    mInnerWebLineWidth = Utils.convertDpToPixel(0.75f);

    mWebPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    mWebPaint.setStyle(Paint.Style.STROKE);

    mHighlightPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    mHighlightPaint.setStyle(Paint.Style.STROKE);
    mHighlightPaint.setStrokeWidth(2f);
    mHighlightPaint.setColor(Color.rgb(255, 187, 115));
  }
示例#3
0
  /**
   * sets the size of the description text in pixels, min 6f, max 16f
   *
   * @param size
   */
  public void setDescriptionTextSize(float size) {

    if (size > 16f) size = 16f;
    if (size < 6f) size = 6f;

    mDescPaint.setTextSize(Utils.convertDpToPixel(size));
  }
示例#4
0
 public XAxisRenderer(ViewPortHandler viewPortHandler, XAxis xAxis, Transformer trans) {
   super(viewPortHandler, trans);
   this.mXAxis = xAxis;
   mAxisLabelPaint.setColor(Color.WHITE);
   mAxisLabelPaint.setTextAlign(Align.CENTER);
   mAxisLabelPaint.setTextSize(Utils.convertDpToPixel(10f));
 }
示例#5
0
  /**
   * Draws the LimitLines associated with this axis to the screen.
   *
   * @param c
   */
  @Override
  public void renderLimitLines(Canvas c) {

    List<LimitLine> limitLines = mXAxis.getLimitLines();

    if (limitLines == null || limitLines.size() <= 0) return;

    float[] pts = new float[4];
    Path limitLinePath = new Path();

    for (int i = 0; i < limitLines.size(); i++) {

      LimitLine l = limitLines.get(i);

      pts[0] = l.getLimit();
      pts[2] = l.getLimit();

      mTrans.pointValuesToPixel(pts);

      pts[1] = mViewPortHandler.contentTop();
      pts[3] = mViewPortHandler.contentBottom();

      limitLinePath.moveTo(pts[0], pts[1]);
      limitLinePath.lineTo(pts[2], pts[3]);

      mLimitLinePaint.setStyle(Paint.Style.STROKE);
      mLimitLinePaint.setColor(l.getLineColor());
      mLimitLinePaint.setStrokeWidth(l.getLineWidth());
      mLimitLinePaint.setPathEffect(l.getDashPathEffect());

      c.drawPath(limitLinePath, mLimitLinePaint);
      limitLinePath.reset();

      String label = l.getLabel();

      // if drawing the limit-value label is enabled
      if (label != null && !label.equals("")) {

        float xOffset = l.getLineWidth();
        float add = Utils.convertDpToPixel(4f);

        mLimitLinePaint.setStyle(l.getTextStyle());
        mLimitLinePaint.setPathEffect(null);
        mLimitLinePaint.setColor(l.getTextColor());
        mLimitLinePaint.setStrokeWidth(0.5f);
        mLimitLinePaint.setTextSize(l.getTextSize());

        float yOffset = Utils.calcTextHeight(mLimitLinePaint, label) + add / 2f;

        if (l.getLabelPosition() == LimitLine.LimitLabelPosition.POS_RIGHT) {
          c.drawText(
              label, pts[0] + xOffset, mViewPortHandler.contentBottom() - add, mLimitLinePaint);
        } else {
          c.drawText(
              label, pts[0] + xOffset, mViewPortHandler.contentTop() + yOffset, mLimitLinePaint);
        }
      }
    }
  }
示例#6
0
  /** initialize all paints and stuff */
  protected void init() {

    setWillNotDraw(false);
    // setLayerType(View.LAYER_TYPE_HARDWARE, null);

    if (android.os.Build.VERSION.SDK_INT < 11) mAnimator = new ChartAnimator();
    else
      mAnimator =
          new ChartAnimator(
              new AnimatorUpdateListener() {

                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                  // ViewCompat.postInvalidateOnAnimation(Chart.this);
                  postInvalidate();
                }
              });

    // initialize the utils
    Utils.init(getContext());

    mDefaultFormatter = new DefaultValueFormatter(1);

    mViewPortHandler = new ViewPortHandler();

    mLegend = new Legend();

    mLegendRenderer = new LegendRenderer(mViewPortHandler, mLegend);

    mXAxis = new XAxis();

    mDescPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    mDescPaint.setColor(Color.BLACK);
    mDescPaint.setTextAlign(Align.RIGHT);
    mDescPaint.setTextSize(Utils.convertDpToPixel(9f));

    mInfoPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    mInfoPaint.setColor(Color.rgb(247, 189, 51)); // orange
    mInfoPaint.setTextAlign(Align.CENTER);
    mInfoPaint.setTextSize(Utils.convertDpToPixel(12f));

    mDrawPaint = new Paint(Paint.DITHER_FLAG);

    if (mLogEnabled) Log.i("", "Chart.init()");
  }
示例#7
0
  /** default constructor */
  public Legend() {

    mFormSize = Utils.convertDpToPixel(8f);
    mXEntrySpace = Utils.convertDpToPixel(6f);
    mYEntrySpace = Utils.convertDpToPixel(0f);
    mFormToTextSpace = Utils.convertDpToPixel(5f);
    mTextSize = Utils.convertDpToPixel(10f);
    mStackSpace = Utils.convertDpToPixel(3f);
    this.mXOffset = Utils.convertDpToPixel(5f);
    this.mYOffset = Utils.convertDpToPixel(3f); // 2
  }
  public BubbleChartRenderer(
      BubbleDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler) {
    super(animator, viewPortHandler);
    mChart = chart;

    mRenderPaint.setStyle(Style.FILL);

    mHighlightPaint.setStyle(Style.STROKE);
    mHighlightPaint.setStrokeWidth(Utils.convertDpToPixel(1.5f));
  }
示例#9
0
  public PieChartRenderer(PieChart chart, ChartAnimator animator, ViewPortHandler viewPortHandler) {
    super(animator, viewPortHandler);
    mChart = chart;

    mHolePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    mHolePaint.setColor(Color.WHITE);
    mHolePaint.setStyle(Style.FILL);

    mTransparentCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    mTransparentCirclePaint.setColor(Color.WHITE);
    mTransparentCirclePaint.setStyle(Style.FILL);
    mTransparentCirclePaint.setAlpha(105);

    mCenterTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
    mCenterTextPaint.setColor(Color.BLACK);
    mCenterTextPaint.setTextSize(Utils.convertDpToPixel(12f));
    // mCenterTextPaint.setTextAlign(Align.CENTER);

    mValuePaint.setTextSize(Utils.convertDpToPixel(13f));
    mValuePaint.setColor(Color.WHITE);
    mValuePaint.setTextAlign(Align.CENTER);
  }
  @Override
  public void drawValues(Canvas c) {

    // if values are drawn
    if (mChart.getCandleData().getYValCount()
        < mChart.getMaxVisibleCount() * mViewPortHandler.getScaleX()) {

      List<CandleDataSet> dataSets = mChart.getCandleData().getDataSets();

      for (int i = 0; i < dataSets.size(); i++) {

        CandleDataSet dataSet = dataSets.get(i);

        if (!dataSet.isDrawValuesEnabled()) continue;

        // apply the text-styling defined by the DataSet
        applyValueTextStyle(dataSet);

        Transformer trans = mChart.getTransformer(dataSet.getAxisDependency());

        List<CandleEntry> entries = dataSet.getYVals();

        Entry entryFrom = dataSet.getEntryForXIndex(mMinX);
        Entry entryTo = dataSet.getEntryForXIndex(mMaxX);

        int minx = Math.max(dataSet.getEntryPosition(entryFrom), 0);
        int maxx = Math.min(dataSet.getEntryPosition(entryTo) + 1, entries.size());

        float[] positions =
            trans.generateTransformedValuesCandle(
                entries, mAnimator.getPhaseX(), mAnimator.getPhaseY(), minx, maxx);

        float yOffset = Utils.convertDpToPixel(5f);

        for (int j = 0; j < positions.length; j += 2) {

          float x = positions[j];
          float y = positions[j + 1];

          if (!mViewPortHandler.isInBoundsRight(x)) break;

          if (!mViewPortHandler.isInBoundsLeft(x) || !mViewPortHandler.isInBoundsY(y)) continue;

          float val = entries.get(j / 2 + minx).getHigh();

          c.drawText(
              dataSet.getValueFormatter().getFormattedValue(val), x, y - yOffset, mValuePaint);
        }
      }
    }
  }
示例#11
0
  @Override
  public void renderAxisLine(Canvas c) {

    if (!mXAxis.isDrawAxisLineEnabled() || !mXAxis.isEnabled()) return;

    mAxisLinePaint.setColor(mXAxis.getAxisLineColor());
    mAxisLinePaint.setStrokeWidth(mXAxis.getAxisLineWidth());

    //        if (mXAxis.getPosition() == XAxisPosition.TOP
    //                || mXAxis.getPosition() == XAxisPosition.TOP_INSIDE
    //                || mXAxis.getPosition() == XAxisPosition.BOTH_SIDED) {
    c.drawLine(
        mViewPortHandler.contentLeft(),
        mViewPortHandler.contentTop(),
        mViewPortHandler.contentRight(),
        mViewPortHandler.contentTop(),
        mAxisLinePaint);
    //        }

    //        if (mXAxis.getPosition() == XAxisPosition.BOTTOM
    //                || mXAxis.getPosition() == XAxisPosition.BOTTOM_INSIDE
    //                || mXAxis.getPosition() == XAxisPosition.BOTH_SIDED) {
    c.drawLine(
        mViewPortHandler.contentLeft(),
        mViewPortHandler.contentBottom() * topchartScale,
        mViewPortHandler.contentRight(),
        mViewPortHandler.contentBottom() * topchartScale,
        mAxisLinePaint);

    float yoffset = mViewPortHandler.contentBottom() * 0.08f - Utils.convertDpToPixel(1);
    c.drawLine(
        mViewPortHandler.contentLeft(),
        mViewPortHandler.contentBottom() * topchartScale + yoffset,
        mViewPortHandler.contentRight(),
        mViewPortHandler.contentBottom() * topchartScale + yoffset,
        mAxisLinePaint);
    c.drawLine(
        mViewPortHandler.contentLeft(),
        mViewPortHandler.contentBottom() - 1,
        mViewPortHandler.contentRight(),
        mViewPortHandler.contentBottom() - 1,
        mAxisLinePaint);
    //        }
  }
示例#12
0
  @Override
  protected void drawValues() {

    // if values are drawn
    if (mDrawYValues) {

      float sliceangle = getSliceAngle();

      // calculate the factor that is needed for transforming the value to
      // pixels
      float factor = getFactor();

      PointF c = getCenterOffsets();

      float yoffset = Utils.convertDpToPixel(5f);

      for (int i = 0; i < mCurrentData.getDataSetCount(); i++) {

        RadarDataSet dataSet = mCurrentData.getDataSetByIndex(i);
        ArrayList<Entry> entries = dataSet.getYVals();

        for (int j = 0; j < entries.size(); j++) {

          Entry e = entries.get(j);

          PointF p = getPosition(c, e.getVal() * factor, sliceangle * j + mRotationAngle);

          if (mDrawUnitInChart)
            mDrawCanvas.drawText(
                mValueFormatter.getFormattedValue(e.getVal()) + mUnit,
                p.x,
                p.y - yoffset,
                mValuePaint);
          else
            mDrawCanvas.drawText(
                mValueFormatter.getFormattedValue(e.getVal()), p.x, p.y - yoffset, mValuePaint);
        }
      }
    }
  }
示例#13
0
  @Override
  public void renderAxisLabels(Canvas c) {

    if (!mXAxis.isEnabled() || !mXAxis.isDrawLabelsEnabled()) return;

    float yoffset = Utils.convertDpToPixel(4f);

    mAxisLabelPaint.setTypeface(mXAxis.getTypeface());
    mAxisLabelPaint.setTextSize(mXAxis.getTextSize());
    mAxisLabelPaint.setColor(mXAxis.getTextColor());

    if (mXAxis.getPosition() == XAxisPosition.TOP) {

      drawLabels(c, mViewPortHandler.offsetTop() - yoffset);

    } else if (mXAxis.getPosition() == XAxisPosition.BOTTOM) {

      drawLabels(
          c,
          mViewPortHandler.contentBottom() * topchartScale
              + (mViewPortHandler.contentBottom() * 0.04f)
              + mXAxis.mLabelHeight / 2);

    } else if (mXAxis.getPosition() == XAxisPosition.BOTTOM_INSIDE) {

      drawLabels(c, mViewPortHandler.contentBottom() - yoffset);

    } else if (mXAxis.getPosition() == XAxisPosition.TOP_INSIDE) {

      drawLabels(c, mViewPortHandler.offsetTop() + yoffset + mXAxis.mLabelHeight);

    } else { // BOTH SIDED

      drawLabels(c, mViewPortHandler.offsetTop() - yoffset);
      drawLabels(c, mViewPortHandler.contentBottom() + mXAxis.mLabelHeight + yoffset * 1.6f);
    }
  }
示例#14
0
 /**
  * Sets the size of the center text of the PieChart in dp.
  *
  * @param sizeDp
  */
 public void setCenterTextSize(float sizeDp) {
   ((PieChartRenderer) mRenderer).getPaintCenterText().setTextSize(Utils.convertDpToPixel(sizeDp));
 }
 @Override
 public void setHighlightCircleWidth(float width) {
   mHighlightCircleWidth = Utils.convertDpToPixel(width);
 }
示例#16
0
  @Override
  public void drawValues(Canvas c) {

    PointF center = mChart.getCenterCircleBox();

    // get whole the radius
    float r = mChart.getRadius();
    float rotationAngle = mChart.getRotationAngle();
    float[] drawAngles = mChart.getDrawAngles();
    float[] absoluteAngles = mChart.getAbsoluteAngles();

    float phaseX = mAnimator.getPhaseX();
    float phaseY = mAnimator.getPhaseY();

    float off = r / 10f * 3.6f;

    if (mChart.isDrawHoleEnabled()) {
      off = (r - (r / 100f * mChart.getHoleRadius())) / 2f;
    }

    r -= off; // offset to keep things inside the chart

    PieData data = mChart.getData();
    List<IPieDataSet> dataSets = data.getDataSets();

    float yValueSum = data.getYValueSum();

    boolean drawXVals = mChart.isDrawSliceTextEnabled();

    float angle;
    int xIndex = 0;

    for (int i = 0; i < dataSets.size(); i++) {

      IPieDataSet dataSet = dataSets.get(i);

      if (!dataSet.isDrawValuesEnabled() && !drawXVals) continue;

      // apply the text-styling defined by the DataSet
      applyValueTextStyle(dataSet);

      float lineHeight = Utils.calcTextHeight(mValuePaint, "Q") + Utils.convertDpToPixel(4f);

      int entryCount = dataSet.getEntryCount();

      for (int j = 0, maxEntry = Math.min((int) Math.ceil(entryCount * phaseX), entryCount);
          j < maxEntry;
          j++) {

        Entry entry = dataSet.getEntryForIndex(j);

        if (xIndex == 0) angle = 0.f;
        else angle = absoluteAngles[xIndex - 1] * phaseX;

        final float sliceAngle = drawAngles[xIndex];
        final float sliceSpace = dataSet.getSliceSpace();

        // offset needed to center the drawn text in the slice
        final float offset = (sliceAngle - sliceSpace / 2.f) / 2.f;

        angle = angle + offset;

        // calculate the text position
        float x = (float) (r * Math.cos(Math.toRadians(rotationAngle + angle)) + center.x);
        float y = (float) (r * Math.sin(Math.toRadians(rotationAngle + angle)) + center.y);

        float value =
            mChart.isUsePercentValuesEnabled() ? entry.getVal() / yValueSum * 100f : entry.getVal();

        ValueFormatter formatter = dataSet.getValueFormatter();

        boolean drawYVals = dataSet.isDrawValuesEnabled();

        // draw everything, depending on settings
        if (drawXVals && drawYVals) {

          drawValue(c, formatter, value, entry, 0, x, y);

          if (j < data.getXValCount())
            c.drawText(data.getXVals().get(j), x, y + lineHeight, mValuePaint);

        } else if (drawXVals) {
          if (j < data.getXValCount())
            c.drawText(data.getXVals().get(j), x, y + lineHeight / 2f, mValuePaint);
        } else if (drawYVals) {

          drawValue(c, formatter, value, entry, 0, x, y + lineHeight / 2f);
        }

        xIndex++;
      }
    }
  }
 /**
  * Sets the width of the candle-shadow-line in pixels. Default 3f.
  *
  * @param width
  */
 public void setShadowWidth(float width) {
   mShadowWidth = Utils.convertDpToPixel(width);
 }
示例#18
0
  @Override
  protected void calculateOffsets() {

    float offsetLeft = 0f, offsetRight = 0f, offsetTop = 0f, offsetBottom = 0f;

    // setup offsets for legend
    if (mLegend != null && mLegend.isEnabled()) {

      if (mLegend.getPosition() == LegendPosition.RIGHT_OF_CHART
          || mLegend.getPosition() == LegendPosition.RIGHT_OF_CHART_CENTER) {

        offsetRight +=
            Math.min(
                    mLegend.mNeededWidth,
                    mViewPortHandler.getChartWidth() * mLegend.getMaxSizePercent())
                + mLegend.getXOffset() * 2f;

      } else if (mLegend.getPosition() == LegendPosition.LEFT_OF_CHART
          || mLegend.getPosition() == LegendPosition.LEFT_OF_CHART_CENTER) {

        offsetLeft +=
            Math.min(
                    mLegend.mNeededWidth,
                    mViewPortHandler.getChartWidth() * mLegend.getMaxSizePercent())
                + mLegend.getXOffset() * 2f;

      } else if (mLegend.getPosition() == LegendPosition.BELOW_CHART_LEFT
          || mLegend.getPosition() == LegendPosition.BELOW_CHART_RIGHT
          || mLegend.getPosition() == LegendPosition.BELOW_CHART_CENTER) {

        float yOffset =
            mLegend.mTextHeightMax
                * 2.f; // It's possible that we do not need this offset anymore as it is available
                       // through the extraOffsets
        offsetBottom +=
            Math.min(
                mLegend.mNeededHeight + yOffset,
                mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent());
      }
    }

    // offsets for y-labels
    if (mAxisLeft.needsOffset()) {
      offsetTop += mAxisLeft.getRequiredHeightSpace(mAxisRendererLeft.getPaintAxisLabels());
    }

    if (mAxisRight.needsOffset()) {
      offsetBottom += mAxisRight.getRequiredHeightSpace(mAxisRendererRight.getPaintAxisLabels());
    }

    float xlabelwidth = mXAxis.mLabelWidth;

    if (mXAxis.isEnabled()) {

      // offsets for x-labels
      if (mXAxis.getPosition() == XAxisPosition.BOTTOM) {

        offsetLeft += xlabelwidth;

      } else if (mXAxis.getPosition() == XAxisPosition.TOP) {

        offsetRight += xlabelwidth;

      } else if (mXAxis.getPosition() == XAxisPosition.BOTH_SIDED) {

        offsetLeft += xlabelwidth;
        offsetRight += xlabelwidth;
      }
    }

    offsetTop += getExtraTopOffset();
    offsetRight += getExtraRightOffset();
    offsetBottom += getExtraBottomOffset();
    offsetLeft += getExtraLeftOffset();

    float min = Utils.convertDpToPixel(10f);

    mViewPortHandler.restrainViewPort(
        Math.max(min, offsetLeft),
        Math.max(min, offsetTop),
        Math.max(min, offsetRight),
        Math.max(min, offsetBottom));

    if (mLogEnabled) {
      Log.i(
          LOG_TAG,
          "offsetLeft: "
              + offsetLeft
              + ", offsetTop: "
              + offsetTop
              + ", offsetRight: "
              + offsetRight
              + ", offsetBottom: "
              + offsetBottom);
      Log.i(LOG_TAG, "Content: " + mViewPortHandler.getContentRect().toString());
    }

    prepareOffsetMatrix();
    prepareValuePxMatrix();
  }
示例#19
0
 /**
  * sets the space between the form and the actual label/text, converts to dp internally
  *
  * @param space
  */
 public void setFormToTextSpace(float space) {
   this.mFormToTextSpace = Utils.convertDpToPixel(space);
 }
示例#20
0
 /**
  * sets the size in pixels of the legend forms, this is internally converted in dp, default 8f
  *
  * @param size
  */
 public void setFormSize(float size) {
   mFormSize = Utils.convertDpToPixel(size);
 }
 /**
  * Set an offset in dp that allows the user to drag the chart over it's bounds on the y-axis.
  *
  * @param offset
  */
 public void setDragOffsetY(float offset) {
   mTransOffsetY = Utils.convertDpToPixel(offset);
 }
示例#22
0
 /**
  * Sets the width of the web lines that are in between the lines coming from the center.
  *
  * @param width
  */
 public void setWebLineWidthInner(float width) {
   mInnerWebLineWidth = Utils.convertDpToPixel(width);
 }
示例#23
0
 /**
  * sets the space between the legend entries on a vertical axis in pixels, converts to dp
  * internally
  *
  * @param space
  */
 public void setYEntrySpace(float space) {
   mYEntrySpace = Utils.convertDpToPixel(space);
 }
示例#24
0
 /** Set an extra offset to be appended to the viewport's left */
 public void setExtraLeftOffset(float offset) {
   mExtraLeftOffset = Utils.convertDpToPixel(offset);
 }
  @Override
  protected void calculateOffsets() {

    float legendLeft = 0f, legendRight = 0f, legendBottom = 0f, legendTop = 0f;

    if (mLegend != null && mLegend.isEnabled()) {

      if (mLegend.getPosition() == LegendPosition.RIGHT_OF_CHART_CENTER) {

        // this is the space between the legend and the chart
        float spacing = Utils.convertDpToPixel(13f);

        legendRight = getFullLegendWidth() + spacing;

      } else if (mLegend.getPosition() == LegendPosition.RIGHT_OF_CHART) {

        // this is the space between the legend and the chart
        float spacing = Utils.convertDpToPixel(8f);

        float legendWidth = getFullLegendWidth() + spacing;

        float legendHeight = mLegend.mNeededHeight + mLegend.mTextHeightMax;

        PointF c = getCenter();

        PointF bottomRight = new PointF(getWidth() - legendWidth + 15, legendHeight + 15);
        float distLegend = distanceToCenter(bottomRight.x, bottomRight.y);

        PointF reference =
            getPosition(c, getRadius(), getAngleForPoint(bottomRight.x, bottomRight.y));

        float distReference = distanceToCenter(reference.x, reference.y);
        float min = Utils.convertDpToPixel(5f);

        if (distLegend < distReference) {

          float diff = distReference - distLegend;
          legendRight = min + diff;
        }

        if (bottomRight.y >= c.y && getHeight() - legendWidth > getWidth()) {
          legendRight = legendWidth;
        }

      } else if (mLegend.getPosition() == LegendPosition.LEFT_OF_CHART_CENTER) {

        // this is the space between the legend and the chart
        float spacing = Utils.convertDpToPixel(13f);

        legendLeft = getFullLegendWidth() + spacing;

      } else if (mLegend.getPosition() == LegendPosition.LEFT_OF_CHART) {

        // this is the space between the legend and the chart
        float spacing = Utils.convertDpToPixel(8f);

        float legendWidth = getFullLegendWidth() + spacing;

        float legendHeight = mLegend.mNeededHeight + mLegend.mTextHeightMax;

        PointF c = getCenter();

        PointF bottomLeft = new PointF(legendWidth - 15, legendHeight + 15);
        float distLegend = distanceToCenter(bottomLeft.x, bottomLeft.y);

        PointF reference =
            getPosition(c, getRadius(), getAngleForPoint(bottomLeft.x, bottomLeft.y));

        float distReference = distanceToCenter(reference.x, reference.y);
        float min = Utils.convertDpToPixel(5f);

        if (distLegend < distReference) {

          float diff = distReference - distLegend;
          legendLeft = min + diff;
        }

        if (bottomLeft.y >= c.y && getHeight() - legendWidth > getWidth()) {
          legendLeft = legendWidth;
        }

      } else if (mLegend.getPosition() == LegendPosition.BELOW_CHART_LEFT
          || mLegend.getPosition() == LegendPosition.BELOW_CHART_RIGHT
          || mLegend.getPosition() == LegendPosition.BELOW_CHART_CENTER) {

        legendBottom = getRequiredBottomOffset();
      }

      legendLeft += getRequiredBaseOffset();
      legendRight += getRequiredBaseOffset();
      legendTop += getRequiredBaseOffset();
    }

    float min = Utils.convertDpToPixel(10f);

    float offsetLeft = Math.max(min, legendLeft);
    float offsetTop = Math.max(min, legendTop);
    float offsetRight = Math.max(min, legendRight);
    float offsetBottom = Math.max(min, Math.max(getRequiredBaseOffset(), legendBottom));

    mViewPortHandler.restrainViewPort(offsetLeft, offsetTop, offsetRight, offsetBottom);

    if (mLogEnabled)
      Log.i(
          LOG_TAG,
          "offsetLeft: "
              + offsetLeft
              + ", offsetTop: "
              + offsetTop
              + ", offsetRight: "
              + offsetRight
              + ", offsetBottom: "
              + offsetBottom);
  }
  /**
   * set the line width of the chart (min = 0.2f, max = 10f); default 1f NOTE: thinner line ==
   * better performance, thicker line == worse performance
   *
   * @param width
   */
  public void setLineWidth(float width) {

    if (width < 0.2f) width = 0.2f;
    if (width > 10.0f) width = 10.0f;
    mLineWidth = Utils.convertDpToPixel(width);
  }