package com.github.mikephil.charting.renderer; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Paint.Align; import android.graphics.Path; import android.graphics.RectF; import com.github.mikephil.charting.charts.BarChart; import com.github.mikephil.charting.components.LimitLine; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.utils.FSize; import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.MPPointD; 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 XAxisRendererHorizontalBarChart extends XAxisRenderer { protected BarChart mChart; public XAxisRendererHorizontalBarChart(ViewPortHandler viewPortHandler, XAxis xAxis, Transformer trans, BarChart chart) { super(viewPortHandler, xAxis, trans); this.mChart = chart; } @Override public void computeAxis(float min, float max, boolean inverted) { // calculate the starting and entry point of the y-labels (depending on // zoom / contentrect bounds) if (mViewPortHandler.contentWidth() > 10 && !mViewPortHandler.isFullyZoomedOutY()) { MPPointD p1 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentBottom()); MPPointD p2 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop()); if (inverted) { min = (float) p2.y; max = (float) p1.y; } else { min = (float) p1.y; max = (float) p2.y; } MPPointD.recycleInstance(p1); MPPointD.recycleInstance(p2); } computeAxisValues(min, max); } @Override protected void computeSize() { mAxisLabelPaint.setTypeface(mXAxis.getTypeface()); mAxisLabelPaint.setTextSize(mXAxis.getTextSize()); String longest = mXAxis.getLongestLabel(); final FSize labelSize = Utils.calcTextSize(mAxisLabelPaint, longest); final float labelWidth = (int)(labelSize.width + mXAxis.getXOffset() * 3.5f); final float labelHeight = labelSize.height; final FSize labelRotatedSize = Utils.getSizeOfRotatedRectangleByDegrees( labelSize.width, labelHeight, mXAxis.getLabelRotationAngle()); mXAxis.mLabelWidth = Math.round(labelWidth); mXAxis.mLabelHeight = Math.round(labelHeight); mXAxis.mLabelRotatedWidth = (int)(labelRotatedSize.width + mXAxis.getXOffset() * 3.5f); mXAxis.mLabelRotatedHeight = Math.round(labelRotatedSize.height); FSize.recycleInstance(labelRotatedSize); } @Override public void renderAxisLabels(Canvas c) { if (!mXAxis.isEnabled() || !mXAxis.isDrawLabelsEnabled()) return; float xoffset = mXAxis.getXOffset(); mAxisLabelPaint.setTypeface(mXAxis.getTypeface()); mAxisLabelPaint.setTextSize(mXAxis.getTextSize()); mAxisLabelPaint.setColor(mXAxis.getTextColor()); MPPointF pointF = MPPointF.getInstance(0,0); if (mXAxis.getPosition() == XAxisPosition.TOP) { pointF.x = 0.0f; pointF.y = 0.5f; drawLabels(c, mViewPortHandler.contentRight() + xoffset, pointF); } else if (mXAxis.getPosition() == XAxisPosition.TOP_INSIDE) { pointF.x = 1.0f; pointF.y = 0.5f; drawLabels(c, mViewPortHandler.contentRight() - xoffset, pointF); } else if (mXAxis.getPosition() == XAxisPosition.BOTTOM) { pointF.x = 1.0f; pointF.y = 0.5f; drawLabels(c, mViewPortHandler.contentLeft() - xoffset, pointF); } else if (mXAxis.getPosition() == XAxisPosition.BOTTOM_INSIDE) { pointF.x = 1.0f; pointF.y = 0.5f; drawLabels(c, mViewPortHandler.contentLeft() + xoffset, pointF); } else { // BOTH SIDED pointF.x = 0.0f; pointF.y = 0.5f; drawLabels(c, mViewPortHandler.contentRight() + xoffset, pointF); pointF.x = 1.0f; pointF.y = 0.5f; drawLabels(c, mViewPortHandler.contentLeft() - xoffset, pointF); } MPPointF.recycleInstance(pointF); } @Override protected void drawLabels(Canvas c, float pos, MPPointF anchor) { final float labelRotationAngleDegrees = mXAxis.getLabelRotationAngle(); boolean centeringEnabled = mXAxis.isCenterAxisLabelsEnabled(); float[] positions = new float[mXAxis.mEntryCount * 2]; for (int i = 0; i < positions.length; i += 2) { // only fill x values if (centeringEnabled) { positions[i + 1] = mXAxis.mCenteredEntries[i / 2]; } else { positions[i + 1] = mXAxis.mEntries[i / 2]; } } mTrans.pointValuesToPixel(positions); for (int i = 0; i < positions.length; i += 2) { float y = positions[i + 1]; if (mViewPortHandler.isInBoundsY(y)) { String label = mXAxis.getValueFormatter().getFormattedValue(mXAxis.mEntries[i / 2], mXAxis); drawLabel(c, label, pos, y, anchor, labelRotationAngleDegrees); } } } @Override public RectF getGridClippingRect() { mGridClippingRect.set(mViewPortHandler.getContentRect()); mGridClippingRect.inset(0.f, -mAxis.getGridLineWidth()); return mGridClippingRect; } @Override protected void drawGridLine(Canvas c, float x, float y, Path gridLinePath) { gridLinePath.moveTo(mViewPortHandler.contentRight(), y); gridLinePath.lineTo(mViewPortHandler.contentLeft(), y); // draw a path because lines don't support dashing on lower android versions c.drawPath(gridLinePath, mGridPaint); gridLinePath.reset(); } @Override public void renderAxisLine(Canvas c) { if (!mXAxis.isDrawAxisLineEnabled() || !mXAxis.isEnabled()) return; mAxisLinePaint.setColor(mXAxis.getAxisLineColor()); mAxisLinePaint.setStrokeWidth(mXAxis.getAxisLineWidth()); if (mXAxis.getPosition() == XAxisPosition.TOP || mXAxis.getPosition() == XAxisPosition.TOP_INSIDE || mXAxis.getPosition() == XAxisPosition.BOTH_SIDED) { c.drawLine(mViewPortHandler.contentRight(), mViewPortHandler.contentTop(), mViewPortHandler.contentRight(), mViewPortHandler.contentBottom(), mAxisLinePaint); } if (mXAxis.getPosition() == XAxisPosition.BOTTOM || mXAxis.getPosition() == XAxisPosition.BOTTOM_INSIDE || mXAxis.getPosition() == XAxisPosition.BOTH_SIDED) { c.drawLine(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), mViewPortHandler.contentLeft(), mViewPortHandler.contentBottom(), mAxisLinePaint); } } protected Path mRenderLimitLinesPathBuffer = new Path(); /** * Draws the LimitLines associated with this axis to the screen. * This is the standard YAxis renderer using the XAxis limit lines. * * @param c */ @Override public void renderLimitLines(Canvas c) { List<LimitLine> limitLines = mXAxis.getLimitLines(); if (limitLines == null || limitLines.size() <= 0) return; float[] pts = mRenderLimitLinesBuffer; pts[0] = 0; pts[1] = 0; Path limitLinePath = mRenderLimitLinesPathBuffer; limitLinePath.reset(); for (int i = 0; i < limitLines.size(); i++) { LimitLine l = limitLines.get(i); if(!l.isEnabled()) continue; int clipRestoreCount = c.save(); mLimitLineClippingRect.set(mViewPortHandler.getContentRect()); mLimitLineClippingRect.inset(0.f, -l.getLineWidth()); c.clipRect(mLimitLineClippingRect); mLimitLinePaint.setStyle(Paint.Style.STROKE); mLimitLinePaint.setColor(l.getLineColor()); mLimitLinePaint.setStrokeWidth(l.getLineWidth()); mLimitLinePaint.setPathEffect(l.getDashPathEffect()); pts[1] = l.getLimit(); mTrans.pointValuesToPixel(pts); limitLinePath.moveTo(mViewPortHandler.contentLeft(), pts[1]); limitLinePath.lineTo(mViewPortHandler.contentRight(), pts[1]); 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("")) { mLimitLinePaint.setStyle(l.getTextStyle()); mLimitLinePaint.setPathEffect(null); mLimitLinePaint.setColor(l.getTextColor()); mLimitLinePaint.setStrokeWidth(0.5f); mLimitLinePaint.setTextSize(l.getTextSize()); final float labelLineHeight = Utils.calcTextHeight(mLimitLinePaint, label); float xOffset = Utils.convertDpToPixel(4f) + l.getXOffset(); float yOffset = l.getLineWidth() + labelLineHeight + l.getYOffset(); final LimitLine.LimitLabelPosition position = l.getLabelPosition(); if (position == LimitLine.LimitLabelPosition.RIGHT_TOP) { mLimitLinePaint.setTextAlign(Align.RIGHT); c.drawText(label, mViewPortHandler.contentRight() - xOffset, pts[1] - yOffset + labelLineHeight, mLimitLinePaint); } else if (position == LimitLine.LimitLabelPosition.RIGHT_BOTTOM) { mLimitLinePaint.setTextAlign(Align.RIGHT); c.drawText(label, mViewPortHandler.contentRight() - xOffset, pts[1] + yOffset, mLimitLinePaint); } else if (position == LimitLine.LimitLabelPosition.LEFT_TOP) { mLimitLinePaint.setTextAlign(Align.LEFT); c.drawText(label, mViewPortHandler.contentLeft() + xOffset, pts[1] - yOffset + labelLineHeight, mLimitLinePaint); } else { mLimitLinePaint.setTextAlign(Align.LEFT); c.drawText(label, mViewPortHandler.offsetLeft() + xOffset, pts[1] + yOffset, mLimitLinePaint); } } c.restoreToCount(clipRestoreCount); } } }