blob: dca9275d5c8519fdc4937a5c60539dee5d718050 [file] [log] [blame]
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.LimitLine.LimitLabelPosition;
import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.components.YAxis.AxisDependency;
import com.github.mikephil.charting.components.YAxis.YAxisLabelPosition;
import com.github.mikephil.charting.utils.PointD;
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 YAxisRenderer extends AxisRenderer {
/** paint used for the limit lines */
protected Paint mLimitLinePaint;
protected YAxis mYAxis;
public YAxisRenderer(ViewPortHandler viewPortHandler, YAxis yAxis, Transformer trans) {
super(viewPortHandler, trans);
this.mYAxis = yAxis;
mAxisLabelPaint.setColor(Color.BLACK);
mAxisLabelPaint.setTextSize(Utils.convertDpToPixel(10f));
mLimitLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mLimitLinePaint.setStyle(Paint.Style.FILL_AND_STROKE);
}
/**
* Computes the axis values.
*
* @param yMin - the minimum y-value in the data object for this axis
* @param yMax - the maximum y-value in the data object for this axis
*/
public void computeAxis(float yMin, float yMax) {
// calculate the starting and entry point of the y-labels (depending on
// zoom / contentrect bounds)
if (mViewPortHandler.contentWidth() > 10 && !mViewPortHandler.isFullyZoomedOutY()) {
PointD p1 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(),
mViewPortHandler.contentTop());
PointD p2 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(),
mViewPortHandler.contentBottom());
if (!mYAxis.isInverted()) {
yMin = (float) p2.y;
yMax = (float) p1.y;
} else {
if (!mYAxis.isStartAtZeroEnabled())
yMin = (float) Math.min(p1.y, p2.y);
else
yMin = 0;
yMax = (float) Math.max(p1.y, p2.y);
}
}
computeAxisValues(yMin, yMax);
}
/**
* Sets up the y-axis labels. Computes the desired number of labels between
* the two given extremes. Unlike the papareXLabels() method, this method
* needs to be called upon every refresh of the view.
*
* @return
*/
protected void computeAxisValues(float min, float max) {
float yMin = min;
float yMax = max;
int labelCount = mYAxis.getLabelCount();
double range = Math.abs(yMax - yMin);
if (labelCount == 0 || range <= 0) {
mYAxis.mEntries = new float[] {};
mYAxis.mEntryCount = 0;
return;
}
double rawInterval = range / labelCount;
double interval = Utils.roundToNextSignificant(rawInterval);
double intervalMagnitude = Math.pow(10, (int) Math.log10(interval));
int intervalSigDigit = (int) (interval / intervalMagnitude);
if (intervalSigDigit > 5) {
// Use one order of magnitude higher, to avoid intervals like 0.9 or
// 90
interval = Math.floor(10 * intervalMagnitude);
}
// if the labels should only show min and max
if (mYAxis.isShowOnlyMinMaxEnabled()) {
mYAxis.mEntryCount = 2;
mYAxis.mEntries = new float[2];
mYAxis.mEntries[0] = yMin;
mYAxis.mEntries[1] = yMax;
} else {
double first = Math.ceil(yMin / interval) * interval;
double last = Utils.nextUp(Math.floor(yMax / interval) * interval);
double f;
int i;
int n = 0;
for (f = first; f <= last; f += interval) {
++n;
}
mYAxis.mEntryCount = n;
if (mYAxis.mEntries.length < n) {
// Ensure stops contains at least numStops elements.
mYAxis.mEntries = new float[n];
}
for (f = first, i = 0; i < n; f += interval, ++i) {
mYAxis.mEntries[i] = (float) f;
}
}
if (interval < 1) {
mYAxis.mDecimals = (int) Math.ceil(-Math.log10(interval));
} else {
mYAxis.mDecimals = 0;
}
}
/**
* draws the y-axis labels to the screen
*/
@Override
public void renderAxisLabels(Canvas c) {
if (!mYAxis.isEnabled() || !mYAxis.isDrawLabelsEnabled())
return;
float[] positions = new float[mYAxis.mEntryCount * 2];
for (int i = 0; i < positions.length; i += 2) {
// only fill y values, x values are not needed since the y-labels
// are
// static on the x-axis
positions[i + 1] = mYAxis.mEntries[i / 2];
}
mTrans.pointValuesToPixel(positions);
mAxisLabelPaint.setTypeface(mYAxis.getTypeface());
mAxisLabelPaint.setTextSize(mYAxis.getTextSize());
mAxisLabelPaint.setColor(mYAxis.getTextColor());
float xoffset = mYAxis.getXOffset();
float yoffset = Utils.calcTextHeight(mAxisLabelPaint, "A") / 2.5f;
AxisDependency dependency = mYAxis.getAxisDependency();
YAxisLabelPosition labelPosition = mYAxis.getLabelPosition();
float xPos = 0f;
if (dependency == AxisDependency.LEFT) {
if (labelPosition == YAxisLabelPosition.OUTSIDE_CHART) {
mAxisLabelPaint.setTextAlign(Align.RIGHT);
xPos = mViewPortHandler.offsetLeft() - xoffset;
} else {
mAxisLabelPaint.setTextAlign(Align.LEFT);
xPos = mViewPortHandler.offsetLeft() + xoffset;
}
} else {
if (labelPosition == YAxisLabelPosition.OUTSIDE_CHART) {
mAxisLabelPaint.setTextAlign(Align.LEFT);
xPos = mViewPortHandler.contentRight() + xoffset;
} else {
mAxisLabelPaint.setTextAlign(Align.RIGHT);
xPos = mViewPortHandler.contentRight() - xoffset;
}
}
drawYLabels(c, xPos, positions, yoffset);
}
@Override
public void renderAxisLine(Canvas c) {
if (!mYAxis.isEnabled() || !mYAxis.isDrawAxisLineEnabled())
return;
mAxisLinePaint.setColor(mYAxis.getAxisLineColor());
mAxisLinePaint.setStrokeWidth(mYAxis.getAxisLineWidth());
if (mYAxis.getAxisDependency() == AxisDependency.LEFT) {
c.drawLine(mViewPortHandler.contentLeft(),
mViewPortHandler.contentTop(), mViewPortHandler.contentLeft(),
mViewPortHandler.contentBottom(), mAxisLinePaint);
} else {
c.drawLine(mViewPortHandler.contentRight(),
mViewPortHandler.contentTop(), mViewPortHandler.contentRight(),
mViewPortHandler.contentBottom(), mAxisLinePaint);
}
}
/**
* draws the y-labels on the specified x-position
*
* @param fixedPosition
* @param positions
*/
protected void drawYLabels(Canvas c, float fixedPosition, float[] positions, float offset) {
// draw
for (int i = 0; i < mYAxis.mEntryCount; i++) {
String text = mYAxis.getFormattedLabel(i);
if (!mYAxis.isDrawTopYLabelEntryEnabled() && i >= mYAxis.mEntryCount - 1)
return;
c.drawText(text, fixedPosition, positions[i * 2 + 1] + offset, mAxisLabelPaint);
}
}
@Override
public void renderGridLines(Canvas c) {
if (!mYAxis.isDrawGridLinesEnabled() || !mYAxis.isEnabled())
return;
// pre alloc
float[] position = new float[2];
mGridPaint.setColor(mYAxis.getGridColor());
mGridPaint.setStrokeWidth(mYAxis.getGridLineWidth());
// draw the horizontal grid
for (int i = 0; i < mYAxis.mEntryCount; i++) {
position[1] = mYAxis.mEntries[i];
mTrans.pointValuesToPixel(position);
c.drawLine(mViewPortHandler.offsetLeft(), position[1], mViewPortHandler.contentRight(),
position[1],
mGridPaint);
}
}
/**
* Draws the LimitLines associated with this axis to the screen.
*
* @param c
*/
public void renderLimitLines(Canvas c) {
List<LimitLine> limitLines = mYAxis.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[1] = l.getLimit();
pts[3] = l.getLimit();
mTrans.pointValuesToPixel(pts);
pts[0] = mViewPortHandler.contentLeft();
pts[2] = mViewPortHandler.contentRight();
limitLinePath.moveTo(pts[0], pts[1]);
limitLinePath.lineTo(pts[2], pts[3]);
mLimitLinePaint.setColor(l.getLineColor());
mLimitLinePaint.setPathEffect(l.getDashPathEffect());
mLimitLinePaint.setStrokeWidth(l.getLineWidth());
c.drawPath(limitLinePath, mLimitLinePaint);
limitLinePath.reset();
// c.drawLines(pts, mLimitLinePaint);
String label = l.getLabel();
// if drawing the limit-value label is enabled
if (label != null && !label.equals("")) {
float xOffset = Utils.convertDpToPixel(4f);
float yOffset = l.getLineWidth() + Utils.calcTextHeight(mLimitLinePaint, label)
/ 2f;
mLimitLinePaint.setPathEffect(null);
mLimitLinePaint.setColor(l.getTextColor());
mLimitLinePaint.setStrokeWidth(0.5f);
mLimitLinePaint.setTextSize(l.getTextSize());
if (l.getLabelPosition() == LimitLabelPosition.POS_RIGHT) {
mLimitLinePaint.setTextAlign(Align.RIGHT);
c.drawText(label, mViewPortHandler.contentRight()
- xOffset,
pts[1] - yOffset, mLimitLinePaint);
} else {
mLimitLinePaint.setTextAlign(Align.LEFT);
c.drawText(label, mViewPortHandler.offsetLeft()
+ xOffset,
pts[1] - yOffset, mLimitLinePaint);
}
}
}
}
}