package com.github.mikephil.charting.renderer; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Paint.Align; import android.graphics.Path; import com.github.mikephil.charting.components.LimitLine; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; import java.util.List; public class XAxisRenderer extends AxisRenderer { protected XAxis mXAxis; public XAxisRenderer(ViewPortHandler viewPortHandler, XAxis xAxis, Transformer trans) { super(viewPortHandler, trans); this.mXAxis = xAxis; mAxisLabelPaint.setColor(Color.BLACK); mAxisLabelPaint.setTextAlign(Align.CENTER); mAxisLabelPaint.setTextSize(Utils.convertDpToPixel(10f)); } public void computeAxis(float xValAverageLength, List<String> xValues) { mAxisLabelPaint.setTypeface(mXAxis.getTypeface()); mAxisLabelPaint.setTextSize(mXAxis.getTextSize()); StringBuffer a = new StringBuffer(); int max = (int) Math.round(xValAverageLength + mXAxis.getSpaceBetweenLabels()); for (int i = 0; i < max; i++) { a.append("h"); } mXAxis.mLabelWidth = Utils.calcTextWidth(mAxisLabelPaint, a.toString()); mXAxis.mLabelHeight = Utils.calcTextHeight(mAxisLabelPaint, "Q"); mXAxis.setValues(xValues); } @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() + mXAxis.mLabelHeight + yoffset * 1.5f); } 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); } } @Override public void renderAxisLine(Canvas c) { calcXBounds(mTrans); 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(), mViewPortHandler.contentRight(), mViewPortHandler.contentBottom(), mAxisLinePaint); } } /** * draws the x-labels on the specified y-position * * @param pos */ protected void drawLabels(Canvas c, float pos) { // pre allocate to save performance (dont allocate in loop) float[] position = new float[] { 0f, 0f }; int maxx = mMaxX; int minx = mMinX; if (maxx >= mXAxis.getValues().size()) maxx = mXAxis.getValues().size()-1; if (minx < 0) minx = 0; for (int i = minx; i <= maxx; i += mXAxis.mAxisLabelModulus) { position[0] = i; mTrans.pointValuesToPixel(position); if (mViewPortHandler.isInBoundsX(position[0])) { String label = mXAxis.getValues().get(i); if (mXAxis.isAvoidFirstLastClippingEnabled()) { // avoid clipping of the last if (i == mXAxis.getValues().size() - 1 && mXAxis.getValues().size() > 1) { float width = Utils.calcTextWidth(mAxisLabelPaint, label); if (width > mViewPortHandler.offsetRight() * 2 && position[0] + width > mViewPortHandler.getChartWidth()) position[0] -= width / 2; // avoid clipping of the first } else if (i == 0) { float width = Utils.calcTextWidth(mAxisLabelPaint, label); position[0] += width / 2; } } c.drawText(label, position[0], pos, mAxisLabelPaint); } } } @Override public void renderGridLines(Canvas c) { if (!mXAxis.isDrawGridLinesEnabled() || !mXAxis.isEnabled()) return; float[] position = new float[] { 0f, 0f }; mGridPaint.setColor(mXAxis.getGridColor()); mGridPaint.setStrokeWidth(mXAxis.getGridLineWidth()); mGridPaint.setPathEffect(mXAxis.getGridDashPathEffect()); for (int i = mMinX; i <= mMaxX; i += mXAxis.mAxisLabelModulus) { position[0] = i; mTrans.pointValuesToPixel(position); if (position[0] >= mViewPortHandler.offsetLeft() && position[0] <= mViewPortHandler.getChartWidth()) { c.drawLine(position[0], mViewPortHandler.offsetTop(), position[0], mViewPortHandler.contentBottom(), mGridPaint); } } } /** * 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); } } } } }