blob: bae707b4165d97eca7fd0a7860f22d89fae7c0bb [file] [log] [blame]
package com.github.mikephil.charting.renderer;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import com.github.mikephil.charting.animation.ChartAnimator;
import com.github.mikephil.charting.buffer.CandleBodyBuffer;
import com.github.mikephil.charting.buffer.CandleShadowBuffer;
import com.github.mikephil.charting.data.CandleData;
import com.github.mikephil.charting.data.CandleDataSet;
import com.github.mikephil.charting.data.CandleEntry;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.interfaces.CandleDataProvider;
import com.github.mikephil.charting.utils.ColorTemplate;
import com.github.mikephil.charting.utils.Highlight;
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 DataRenderer {
protected CandleDataProvider mChart;
private CandleShadowBuffer[] mShadowBuffers;
private CandleBodyBuffer[] mBodyBuffers;
public CandleStickChartRenderer(CandleDataProvider chart, ChartAnimator animator,
ViewPortHandler viewPortHandler) {
super(animator, viewPortHandler);
mChart = chart;
}
@Override
public void initBuffers() {
CandleData candleData = mChart.getCandleData();
mShadowBuffers = new CandleShadowBuffer[candleData.getDataSetCount()];
mBodyBuffers = new CandleBodyBuffer[candleData.getDataSetCount()];
for (int i = 0; i < mShadowBuffers.length; i++) {
CandleDataSet set = candleData.getDataSetByIndex(i);
mShadowBuffers[i] = new CandleShadowBuffer(set.getValueCount() * 4);
mBodyBuffers[i] = new CandleBodyBuffer(set.getValueCount() * 4);
}
}
@Override
public void drawData(Canvas c) {
CandleData candleData = mChart.getCandleData();
for (CandleDataSet set : candleData.getDataSets()) {
if (set.isVisible())
drawDataSet(c, set);
}
}
protected void drawDataSet(Canvas c, CandleDataSet dataSet) {
Transformer trans = mChart.getTransformer(dataSet.getAxisDependency());
calcXBounds(trans);
float phaseX = mAnimator.getPhaseX();
float phaseY = mAnimator.getPhaseY();
int dataSetIndex = mChart.getCandleData().getIndexOfDataSet(dataSet);
List<CandleEntry> entries = dataSet.getYVals();
Entry entryFrom = dataSet.getEntryForXIndex(mMinX);
Entry entryTo = dataSet.getEntryForXIndex(mMaxX);
int minx = dataSet.getEntryPosition(entryFrom);
int maxx = Math.min(dataSet.getEntryPosition(entryTo) + 1, entries.size());
int range = (maxx - minx) * 4;
int to = (int)Math.ceil((maxx - minx) * phaseX + minx);
CandleShadowBuffer shadowBuffer = mShadowBuffers[dataSetIndex];
shadowBuffer.setPhases(phaseX, phaseY);
shadowBuffer.limitFrom(minx);
shadowBuffer.limitTo(maxx);
shadowBuffer.feed(entries);
trans.pointValuesToPixel(shadowBuffer.buffer);
mRenderPaint.setStyle(Paint.Style.STROKE);
// If not set, use default functionality for backward compatibility
if (dataSet.getShadowColor() == ColorTemplate.COLOR_NONE) {
mRenderPaint.setColor(dataSet.getColor());
} else {
mRenderPaint.setColor(dataSet.getShadowColor());
}
mRenderPaint.setStrokeWidth(dataSet.getShadowWidth());
// draw the shadow
c.drawLines(shadowBuffer.buffer, 0, range, mRenderPaint);
CandleBodyBuffer bodyBuffer = mBodyBuffers[dataSetIndex];
bodyBuffer.setBodySpace(dataSet.getBodySpace());
bodyBuffer.setPhases(phaseX, phaseY);
bodyBuffer.limitFrom(minx);
bodyBuffer.limitTo(maxx);
bodyBuffer.feed(entries);
trans.pointValuesToPixel(bodyBuffer.buffer);
// draw the body
for (int j = 0; j < range; j += 4) {
// get the entry
CandleEntry e = entries.get(j / 4 + minx);
if (!fitsBounds(e.getXIndex(), mMinX, to))
continue;
float leftBody = bodyBuffer.buffer[j];
float open = bodyBuffer.buffer[j + 1];
float rightBody = bodyBuffer.buffer[j + 2];
float close = bodyBuffer.buffer[j + 3];
// draw body differently for increasing and decreasing entry
if (open > close) { // decreasing
if (dataSet.getDecreasingColor() == ColorTemplate.COLOR_NONE) {
mRenderPaint.setColor(dataSet.getColor(j / 4 + minx));
} else {
mRenderPaint.setColor(dataSet.getDecreasingColor());
}
mRenderPaint.setStyle(dataSet.getDecreasingPaintStyle());
// draw the body
c.drawRect(leftBody, close, rightBody, open, mRenderPaint);
} else if(open < close) {
if (dataSet.getIncreasingColor() == ColorTemplate.COLOR_NONE) {
mRenderPaint.setColor(dataSet.getColor(j / 4 + minx));
} else {
mRenderPaint.setColor(dataSet.getIncreasingColor());
}
mRenderPaint.setStyle(dataSet.getIncreasingPaintStyle());
// draw the body
c.drawRect(leftBody, open, rightBody, close, mRenderPaint);
} else { // equal values
mRenderPaint.setColor(Color.BLACK);
mRenderPaint.setStyle(Paint.Style.STROKE);
c.drawLine(leftBody, open, rightBody, close, mRenderPaint);
}
}
}
// /**
// * Transforms the values of an entry in order to draw the candle-body.
// *
// * @param bodyPoints
// * @param e
// * @param bodySpace
// */
// private void transformBody(float[] bodyPoints, CandleEntry e, float
// bodySpace, Transformer trans) {
//
// float phase = mAnimator.getPhaseY();
//
// bodyPoints[0] = e.getXIndex() - 0.5f + bodySpace;
// bodyPoints[1] = e.getClose() * phase;
// bodyPoints[2] = e.getXIndex() + 0.5f - bodySpace;
// bodyPoints[3] = e.getOpen() * phase;
//
// trans.pointValuesToPixel(bodyPoints);
// }
//
// /**
// * Transforms the values of an entry in order to draw the candle-shadow.
// *
// * @param shadowPoints
// * @param e
// */
// private void transformShadow(float[] shadowPoints, CandleEntry e,
// Transformer trans) {
//
// float phase = mAnimator.getPhaseY();
//
// shadowPoints[0] = e.getXIndex();
// shadowPoints[1] = e.getHigh() * phase;
// shadowPoints[2] = e.getXIndex();
// shadowPoints[3] = e.getLow() * phase;
//
// trans.pointValuesToPixel(shadowPoints);
// }
@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 = dataSet.getEntryPosition(entryFrom);
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);
}
}
}
}
@Override
public void drawExtras(Canvas c) {
}
@Override
public void drawHighlighted(Canvas c, Highlight[] indices) {
for (int i = 0; i < indices.length; i++) {
int xIndex = indices[i].getXIndex(); // get the
// x-position
CandleDataSet set = mChart.getCandleData().getDataSetByIndex(
indices[i].getDataSetIndex());
if (set == null)
continue;
mHighlightPaint.setColor(set.getHighLightColor());
CandleEntry e = set.getEntryForXIndex(xIndex);
if (e == null)
continue;
float low = e.getLow() * mAnimator.getPhaseY();
float high = e.getHigh() * mAnimator.getPhaseY();
float min = mChart.getYChartMin();
float max = mChart.getYChartMax();
float[] vertPts = new float[] {
xIndex - 0.5f, max, xIndex - 0.5f, min, xIndex + 0.5f, max, xIndex + 0.5f,
min
};
float[] horPts = new float[] {
0, low, mChart.getXChartMax(), low, 0, high, mChart.getXChartMax(), high
};
mChart.getTransformer(set.getAxisDependency()).pointValuesToPixel(vertPts);
mChart.getTransformer(set.getAxisDependency()).pointValuesToPixel(horPts);
// draw the vertical highlight lines
c.drawLines(vertPts, mHighlightPaint);
// draw the horizontal highlight lines
c.drawLines(horPts, mHighlightPaint);
}
}
}