blob: 3f3a525c8b5da3c76201c0e7734ff3607be123f2 [file] [log] [blame]
package com.github.mikephil.charting.charts;
import android.content.Context;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import com.github.mikephil.charting.components.Legend.LegendPosition;
import com.github.mikephil.charting.components.XAxis.XAxisPosition;
import com.github.mikephil.charting.components.YAxis.AxisDependency;
import com.github.mikephil.charting.data.BarDataSet;
import com.github.mikephil.charting.data.BarEntry;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.renderer.HorizontalBarChartRenderer;
import com.github.mikephil.charting.renderer.XAxisRendererHorizontalBarChart;
import com.github.mikephil.charting.renderer.YAxisRendererHorizontalBarChart;
import com.github.mikephil.charting.utils.Highlight;
import com.github.mikephil.charting.utils.Utils;
/**
* BarChart with horizontal bar orientation. In this implementation, x- and
* y-axis are switched.
*
* @author Philipp Jahoda
*/
public class HorizontalBarChart extends BarChart {
public HorizontalBarChart(Context context) {
super(context);
}
public HorizontalBarChart(Context context, AttributeSet attrs) {
super(context, attrs);
}
public HorizontalBarChart(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void init() {
super.init();
mRenderer = new HorizontalBarChartRenderer(this, mAnimator, mViewPortHandler);
mAxisRendererLeft = new YAxisRendererHorizontalBarChart(mViewPortHandler, mAxisLeft,
mLeftAxisTransformer);
mAxisRendererRight = new YAxisRendererHorizontalBarChart(mViewPortHandler, mAxisRight,
mRightAxisTransformer);
mXAxisRenderer = new XAxisRendererHorizontalBarChart(mViewPortHandler, mXAxis,
mLeftAxisTransformer, this);
}
@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 += mLegend.mTextWidthMax + mLegend.getXOffset() * 2f;
} else if (mLegend.getPosition() == LegendPosition.LEFT_OF_CHART
|| mLegend.getPosition() == LegendPosition.LEFT_OF_CHART_CENTER) {
offsetLeft += mLegend.mTextWidthMax + mLegend.getXOffset() * 2f;
} else if (mLegend.getPosition() == LegendPosition.BELOW_CHART_LEFT
|| mLegend.getPosition() == LegendPosition.BELOW_CHART_RIGHT
|| mLegend.getPosition() == LegendPosition.BELOW_CHART_CENTER) {
offsetBottom += mLegend.mTextHeightMax * 3f;
}
}
// 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;
}
}
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();
}
@Override
protected void prepareValuePxMatrix() {
mRightAxisTransformer.prepareMatrixValuePx(mAxisRight.mAxisMinimum, mAxisRight.mAxisRange,
mDeltaX,
mXChartMin);
mLeftAxisTransformer.prepareMatrixValuePx(mAxisLeft.mAxisMinimum, mAxisLeft.mAxisRange,
mDeltaX,
mXChartMin);
}
@Override
protected void calcModulus() {
float[] values = new float[9];
mViewPortHandler.getMatrixTouch().getValues(values);
mXAxis.mAxisLabelModulus = (int) Math
.ceil((mData.getXValCount() * mXAxis.mLabelHeight)
/ (mViewPortHandler.contentHeight() * values[Matrix.MSCALE_Y]));
if (mXAxis.mAxisLabelModulus < 1)
mXAxis.mAxisLabelModulus = 1;
}
@Override
public RectF getBarBounds(BarEntry e) {
BarDataSet set = mData.getDataSetForEntry(e);
if (set == null)
return null;
float barspace = set.getBarSpace();
float y = e.getVal();
float x = e.getXIndex();
float spaceHalf = barspace / 2f;
float top = x - 0.5f + spaceHalf;
float bottom = x + 0.5f - spaceHalf;
float left = y >= 0 ? y : 0;
float right = y <= 0 ? y : 0;
RectF bounds = new RectF(left, top, right, bottom);
getTransformer(set.getAxisDependency()).rectValueToPixel(bounds);
return bounds;
}
@Override
public PointF getPosition(Entry e, AxisDependency axis) {
if (e == null)
return null;
float[] vals = new float[] {
e.getVal(), e.getXIndex()
};
getTransformer(axis).pointValuesToPixel(vals);
return new PointF(vals[0], vals[1]);
}
/**
* Returns the Highlight object (contains x-index and DataSet index) of the
* selected value at the given touch point inside the BarChart.
*
* @param x
* @param y
* @return
*/
@Override
public Highlight getHighlightByTouchPoint(float x, float y) {
if (mDataNotSet || mData == null) {
Log.e(LOG_TAG, "Can't select by touch. No data set.");
return null;
}
// create an array of the touch-point
float[] pts = new float[2];
pts[0] = x;
pts[1] = y;
mLeftAxisTransformer.pixelsToValue(pts);
if (pts[1] < mXChartMin || pts[1] > mXChartMax)
return null;
return getHighlight(pts[1], pts[0]);
}
}