package com.github.mikephil.charting.data; import android.annotation.SuppressLint; import android.graphics.drawable.Drawable; import com.github.mikephil.charting.highlight.Range; /** * Entry class for the BarChart. (especially stacked bars) * * @author Philipp Jahoda */ @SuppressLint("ParcelCreator") public class BarEntry extends Entry { /** * the values the stacked barchart holds */ private float[] mYVals; /** * the ranges for the individual stack values - automatically calculated */ private Range[] mRanges; /** * the sum of all negative values this entry (if stacked) contains */ private float mNegativeSum; /** * the sum of all positive values this entry (if stacked) contains */ private float mPositiveSum; /** * Constructor for normal bars (not stacked). * * @param x * @param y */ public BarEntry(float x, float y) { super(x, y); } /** * Constructor for normal bars (not stacked). * * @param x * @param y * @param data - Spot for additional data this Entry represents. */ public BarEntry(float x, float y, Object data) { super(x, y, data); } /** * Constructor for normal bars (not stacked). * * @param x * @param y * @param icon - icon image */ public BarEntry(float x, float y, Drawable icon) { super(x, y, icon); } /** * Constructor for normal bars (not stacked). * * @param x * @param y * @param icon - icon image * @param data - Spot for additional data this Entry represents. */ public BarEntry(float x, float y, Drawable icon, Object data) { super(x, y, icon, data); } /** * Constructor for stacked bar entries. One data object for whole stack * * @param x * @param vals - the stack values, use at least 2 */ public BarEntry(float x, float[] vals) { super(x, calcSum(vals)); this.mYVals = vals; calcPosNegSum(); calcRanges(); } /** * Constructor for stacked bar entries. One data object for whole stack * * @param x * @param vals - the stack values, use at least 2 * @param data - Spot for additional data this Entry represents. */ public BarEntry(float x, float[] vals, Object data) { super(x, calcSum(vals), data); this.mYVals = vals; calcPosNegSum(); calcRanges(); } /** * Constructor for stacked bar entries. One data object for whole stack * * @param x * @param vals - the stack values, use at least 2 * @param icon - icon image */ public BarEntry(float x, float[] vals, Drawable icon) { super(x, calcSum(vals), icon); this.mYVals = vals; calcPosNegSum(); calcRanges(); } /** * Constructor for stacked bar entries. One data object for whole stack * * @param x * @param vals - the stack values, use at least 2 * @param icon - icon image * @param data - Spot for additional data this Entry represents. */ public BarEntry(float x, float[] vals, Drawable icon, Object data) { super(x, calcSum(vals), icon, data); this.mYVals = vals; calcPosNegSum(); calcRanges(); } /** * Returns an exact copy of the BarEntry. */ public BarEntry copy() { BarEntry copied = new BarEntry(getX(), getY(), getData()); copied.setVals(mYVals); return copied; } /** * Returns the stacked values this BarEntry represents, or null, if only a single value is represented (then, use * getY()). * * @return */ public float[] getYVals() { return mYVals; } /** * Set the array of values this BarEntry should represent. * * @param vals */ public void setVals(float[] vals) { setY(calcSum(vals)); mYVals = vals; calcPosNegSum(); calcRanges(); } /** * Returns the value of this BarEntry. If the entry is stacked, it returns the positive sum of all values. * * @return */ @Override public float getY() { return super.getY(); } /** * Returns the ranges of the individual stack-entries. Will return null if this entry is not stacked. * * @return */ public Range[] getRanges() { return mRanges; } /** * Returns true if this BarEntry is stacked (has a values array), false if not. * * @return */ public boolean isStacked() { return mYVals != null; } /** * Use `getSumBelow(stackIndex)` instead. */ @Deprecated public float getBelowSum(int stackIndex) { return getSumBelow(stackIndex); } public float getSumBelow(int stackIndex) { if (mYVals == null) return 0; float remainder = 0f; int index = mYVals.length - 1; while (index > stackIndex && index >= 0) { remainder += mYVals[index]; index--; } return remainder; } /** * Reuturns the sum of all positive values this entry (if stacked) contains. * * @return */ public float getPositiveSum() { return mPositiveSum; } /** * Returns the sum of all negative values this entry (if stacked) contains. (this is a positive number) * * @return */ public float getNegativeSum() { return mNegativeSum; } private void calcPosNegSum() { if (mYVals == null) { mNegativeSum = 0; mPositiveSum = 0; return; } float sumNeg = 0f; float sumPos = 0f; for (float f : mYVals) { if (f <= 0f) sumNeg += Math.abs(f); else sumPos += f; } mNegativeSum = sumNeg; mPositiveSum = sumPos; } /** * Calculates the sum across all values of the given stack. * * @param vals * @return */ private static float calcSum(float[] vals) { if (vals == null) return 0f; float sum = 0f; for (float f : vals) sum += f; return sum; } protected void calcRanges() { float[] values = getYVals(); if (values == null || values.length == 0) return; mRanges = new Range[values.length]; float negRemain = -getNegativeSum(); float posRemain = 0f; for (int i = 0; i < mRanges.length; i++) { float value = values[i]; if (value < 0) { mRanges[i] = new Range(negRemain, negRemain - value); negRemain -= value; } else { mRanges[i] = new Range(posRemain, posRemain + value); posRemain += value; } } } }