| |
| 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]); |
| } |
| } |