package com.github.mikephil.charting.renderer;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import com.github.mikephil.charting.animation.ChartAnimator;
import com.github.mikephil.charting.data.CandleData;
import com.github.mikephil.charting.data.CandleEntry;
import com.github.mikephil.charting.highlight.Highlight;
import com.github.mikephil.charting.interfaces.dataprovider.CandleDataProvider;
import com.github.mikephil.charting.interfaces.datasets.ICandleDataSet;
import com.github.mikephil.charting.utils.ColorTemplate;
import com.github.mikephil.charting.utils.MPPointD;
import com.github.mikephil.charting.utils.MPPointF;
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 CandleStickChartRenderer extends LineScatterCandleRadarRenderer {
protected CandleDataProvider mChart;
private float[] mShadowBuffers = new float[8];
private float[] mBodyBuffers = new float[4];
private float[] mRangeBuffers = new float[4];
private float[] mOpenBuffers = new float[4];
private float[] mCloseBuffers = new float[4];
public CandleStickChartRenderer(CandleDataProvider chart, ChartAnimator animator,
ViewPortHandler viewPortHandler) {
super(animator, viewPortHandler);
mChart = chart;
}
@Override
public void initBuffers() {
}
@Override
public void drawData(Canvas c) {
CandleData candleData = mChart.getCandleData();
for (ICandleDataSet set : candleData.getDataSets()) {
if (set.isVisible())
drawDataSet(c, set);
}
}
@SuppressWarnings("ResourceAsColor")
protected void drawDataSet(Canvas c, ICandleDataSet dataSet) {
Transformer trans = mChart.getTransformer(dataSet.getAxisDependency());
float phaseY = mAnimator.getPhaseY();
float barSpace = dataSet.getBarSpace();
boolean showCandleBar = dataSet.getShowCandleBar();
mXBounds.set(mChart, dataSet);
mRenderPaint.setStrokeWidth(dataSet.getShadowWidth());
// draw the body
for (int j = mXBounds.min; j <= mXBounds.range + mXBounds.min; j++) {
// get the entry
CandleEntry e = dataSet.getEntryForIndex(j);
if (e == null)
continue;
final float xPos = e.getX();
final float open = e.getOpen();
final float close = e.getClose();
final float high = e.getHigh();
final float low = e.getLow();
if (showCandleBar) {
// calculate the shadow
mShadowBuffers[0] = xPos;
mShadowBuffers[2] = xPos;
mShadowBuffers[4] = xPos;
mShadowBuffers[6] = xPos;
if (open > close) {
mShadowBuffers[1] = high * phaseY;
mShadowBuffers[3] = open * phaseY;
mShadowBuffers[5] = low * phaseY;
mShadowBuffers[7] = close * phaseY;
} else if (open < close) {
mShadowBuffers[1] = high * phaseY;
mShadowBuffers[3] = close * phaseY;
mShadowBuffers[5] = low * phaseY;
mShadowBuffers[7] = open * phaseY;
} else {
mShadowBuffers[1] = high * phaseY;
mShadowBuffers[3] = open * phaseY;
mShadowBuffers[5] = low * phaseY;
mShadowBuffers[7] = mShadowBuffers[3];
}
trans.pointValuesToPixel(mShadowBuffers);
// draw the shadows
if (dataSet.getShadowColorSameAsCandle()) {
if (open > close)
mRenderPaint.setColor(
dataSet.getDecreasingColor() == ColorTemplate.COLOR_NONE ?
dataSet.getColor(j) :
dataSet.getDecreasingColor()
);
else if (open < close)
mRenderPaint.setColor(
dataSet.getIncreasingColor() == ColorTemplate.COLOR_NONE ?
dataSet.getColor(j) :
dataSet.getIncreasingColor()
);
else
mRenderPaint.setColor(
dataSet.getNeutralColor() == ColorTemplate.COLOR_NONE ?
dataSet.getColor(j) :
dataSet.getNeutralColor()
);
} else {
mRenderPaint.setColor(
dataSet.getShadowColor() == ColorTemplate.COLOR_NONE ?
dataSet.getColor(j) :
dataSet.getShadowColor()
);
}
mRenderPaint.setStyle(Paint.Style.STROKE);
c.drawLines(mShadowBuffers, mRenderPaint);
// calculate the body
mBodyBuffers[0] = xPos - 0.5f + barSpace;
mBodyBuffers[1] = close * phaseY;
mBodyBuffers[2] = (xPos + 0.5f - barSpace);
mBodyBuffers[3] = open * phaseY;
trans.pointValuesToPixel(mBodyBuffers);
// draw body differently for increasing and decreasing entry
if (open > close) { // decreasing
if (dataSet.getDecreasingColor() == ColorTemplate.COLOR_NONE) {
mRenderPaint.setColor(dataSet.getColor(j));
} else {
mRenderPaint.setColor(dataSet.getDecreasingColor());
}
mRenderPaint.setStyle(dataSet.getDecreasingPaintStyle());
c.drawRect(
mBodyBuffers[0], mBodyBuffers[3],
mBodyBuffers[2], mBodyBuffers[1],
mRenderPaint);
} else if (open < close) {
if (dataSet.getIncreasingColor() == ColorTemplate.COLOR_NONE) {
mRenderPaint.setColor(dataSet.getColor(j));
} else {
mRenderPaint.setColor(dataSet.getIncreasingColor());
}
mRenderPaint.setStyle(dataSet.getIncreasingPaintStyle());
c.drawRect(
mBodyBuffers[0], mBodyBuffers[1],
mBodyBuffers[2], mBodyBuffers[3],
mRenderPaint);
} else { // equal values
if (dataSet.getNeutralColor() == ColorTemplate.COLOR_NONE) {
mRenderPaint.setColor(dataSet.getColor(j));
} else {
mRenderPaint.setColor(dataSet.getNeutralColor());
}
c.drawLine(
mBodyBuffers[0], mBodyBuffers[1],
mBodyBuffers[2], mBodyBuffers[3],
mRenderPaint);
}
} else {
mRangeBuffers[0] = xPos;
mRangeBuffers[1] = high * phaseY;
mRangeBuffers[2] = xPos;
mRangeBuffers[3] = low * phaseY;
mOpenBuffers[0] = xPos - 0.5f + barSpace;
mOpenBuffers[1] = open * phaseY;
mOpenBuffers[2] = xPos;
mOpenBuffers[3] = open * phaseY;
mCloseBuffers[0] = xPos + 0.5f - barSpace;
mCloseBuffers[1] = close * phaseY;
mCloseBuffers[2] = xPos;
mCloseBuffers[3] = close * phaseY;
trans.pointValuesToPixel(mRangeBuffers);
trans.pointValuesToPixel(mOpenBuffers);
trans.pointValuesToPixel(mCloseBuffers);
// draw the ranges
int barColor;
if (open > close)
barColor = dataSet.getDecreasingColor() == ColorTemplate.COLOR_NONE
? dataSet.getColor(j)
: dataSet.getDecreasingColor();
else if (open < close)
barColor = dataSet.getIncreasingColor() == ColorTemplate.COLOR_NONE
? dataSet.getColor(j)
: dataSet.getIncreasingColor();
else
barColor = dataSet.getNeutralColor() == ColorTemplate.COLOR_NONE
? dataSet.getColor(j)
: dataSet.getNeutralColor();
mRenderPaint.setColor(barColor);
c.drawLine(
mRangeBuffers[0], mRangeBuffers[1],
mRangeBuffers[2], mRangeBuffers[3],
mRenderPaint);
c.drawLine(
mOpenBuffers[0], mOpenBuffers[1],
mOpenBuffers[2], mOpenBuffers[3],
mRenderPaint);
c.drawLine(
mCloseBuffers[0], mCloseBuffers[1],
mCloseBuffers[2], mCloseBuffers[3],
mRenderPaint);
}
}
}
@Override
public void drawValues(Canvas c) {
// if values are drawn
if (isDrawingValuesAllowed(mChart)) {
List<ICandleDataSet> dataSets = mChart.getCandleData().getDataSets();
for (int i = 0; i < dataSets.size(); i++) {
ICandleDataSet dataSet = dataSets.get(i);
if (!shouldDrawValues(dataSet))
continue;
// apply the text-styling defined by the DataSet
applyValueTextStyle(dataSet);
Transformer trans = mChart.getTransformer(dataSet.getAxisDependency());
mXBounds.set(mChart, dataSet);
float[] positions = trans.generateTransformedValuesCandle(
dataSet, mAnimator.getPhaseX(), mAnimator.getPhaseY(), mXBounds.min, mXBounds.max);
float yOffset = Utils.convertDpToPixel(5f);
MPPointF iconsOffset = MPPointF.getInstance(dataSet.getIconsOffset());
iconsOffset.x = Utils.convertDpToPixel(iconsOffset.x);
iconsOffset.y = Utils.convertDpToPixel(iconsOffset.y);
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;
CandleEntry entry = dataSet.getEntryForIndex(j / 2 + mXBounds.min);
if (dataSet.isDrawValuesEnabled()) {
drawValue(c,
dataSet.getValueFormatter(),
entry.getHigh(),
entry,
i,
x,
y - yOffset,
dataSet
.getValueTextColor(j / 2));
}
if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) {
Drawable icon = entry.getIcon();
Utils.drawImage(
c,
icon,
(int)(x + iconsOffset.x),
(int)(y + iconsOffset.y),
icon.getIntrinsicWidth(),
icon.getIntrinsicHeight());
}
}
MPPointF.recycleInstance(iconsOffset);
}
}
}
@Override
public void drawExtras(Canvas c) {
}
@Override
public void drawHighlighted(Canvas c, Highlight[] indices) {
CandleData candleData = mChart.getCandleData();
for (Highlight high : indices) {
ICandleDataSet set = candleData.getDataSetByIndex(high.getDataSetIndex());
if (set == null || !set.isHighlightEnabled())
continue;
CandleEntry e = set.getEntryForXValue(high.getX(), high.getY());
if (!isInBoundsX(e, set))
continue;
float lowValue = e.getLow() * mAnimator.getPhaseY();
float highValue = e.getHigh() * mAnimator.getPhaseY();
float y = (lowValue + highValue) / 2f;
MPPointD pix = mChart.getTransformer(set.getAxisDependency()).getPixelForValues(e.getX(), y);
high.setDraw((float) pix.x, (float) pix.y);
// draw the lines
drawHighlightLines(c, (float) pix.x, (float) pix.y, set);
}
}
}