diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java index 6d9e67b109..4213547d12 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java @@ -19,408 +19,406 @@ */ public class YAxis extends AxisBase { - /** - * indicates if the bottom y-label entry is drawn or not - */ - private boolean mDrawBottomYLabelEntry = true; - - /** - * indicates if the top y-label entry is drawn or not - */ - private boolean mDrawTopYLabelEntry = true; - - /** - * flag that indicates if the axis is inverted or not - */ - protected boolean mInverted = false; - - /** - * flag that indicates if the zero-line should be drawn regardless of other grid lines - */ - protected boolean mDrawZeroLine = false; - - /** - * flag indicating that auto scale min restriction should be used - */ - private boolean mUseAutoScaleRestrictionMin = false; - - /** - * flag indicating that auto scale max restriction should be used - */ - private boolean mUseAutoScaleRestrictionMax = false; - - /** - * Color of the zero line - */ - protected int mZeroLineColor = Color.GRAY; - - /** - * Width of the zero line in pixels - */ - protected float mZeroLineWidth = 1f; - - /** - * axis space from the largest value to the top in percent of the total axis range - */ - protected float mSpacePercentTop = 10f; - - /** - * axis space from the smallest value to the bottom in percent of the total axis range - */ - protected float mSpacePercentBottom = 10f; - - /** - * the position of the y-labels relative to the chart - */ - private YAxisLabelPosition mPosition = YAxisLabelPosition.OUTSIDE_CHART; - - /** - * the horizontal offset of the y-label - */ - private float mXLabelOffset = 0.0f; - - /** - * enum for the position of the y-labels relative to the chart - */ - public enum YAxisLabelPosition { - OUTSIDE_CHART, INSIDE_CHART - } - - /** - * the side this axis object represents - */ - private AxisDependency mAxisDependency; - - /** - * the minimum width that the axis should take (in dp). - *

- * default: 0.0 - */ - protected float mMinWidth = 0.f; - - /** - * the maximum width that the axis can take (in dp). - * use Inifinity for disabling the maximum - * default: Float.POSITIVE_INFINITY (no maximum specified) - */ - protected float mMaxWidth = Float.POSITIVE_INFINITY; - - /** - * Enum that specifies the axis a DataSet should be plotted against, either LEFT or RIGHT. - * - * @author Philipp Jahoda - */ - public enum AxisDependency { - LEFT, RIGHT - } - - public YAxis() { - super(); - - // default left - this.mAxisDependency = AxisDependency.LEFT; - this.mYOffset = 0f; - } - - public YAxis(AxisDependency position) { - super(); - this.mAxisDependency = position; - this.mYOffset = 0f; - } - - public AxisDependency getAxisDependency() { - return mAxisDependency; - } - - /** - * @return the minimum width that the axis should take (in dp). - */ - public float getMinWidth() { - return mMinWidth; - } - - /** - * Sets the minimum width that the axis should take (in dp). - */ - public void setMinWidth(float minWidth) { - mMinWidth = minWidth; - } - - /** - * @return the maximum width that the axis can take (in dp). - */ - public float getMaxWidth() { - return mMaxWidth; - } - - /** - * Sets the maximum width that the axis can take (in dp). - */ - public void setMaxWidth(float maxWidth) { - mMaxWidth = maxWidth; - } - - /** - * returns the position of the y-labels - */ - public YAxisLabelPosition getLabelPosition() { - return mPosition; - } - - /** - * sets the position of the y-labels - */ - public void setPosition(YAxisLabelPosition pos) { - mPosition = pos; - } - - /** - * returns the horizontal offset of the y-label - */ - public float getLabelXOffset() { - return mXLabelOffset; - } - - /** - * sets the horizontal offset of the y-label - */ - public void setLabelXOffset(float xOffset) { - mXLabelOffset = xOffset; - } - - /** - * returns true if drawing the top y-axis label entry is enabled - */ - public boolean isDrawTopYLabelEntryEnabled() { - return mDrawTopYLabelEntry; - } - - /** - * returns true if drawing the bottom y-axis label entry is enabled - */ - public boolean isDrawBottomYLabelEntryEnabled() { - return mDrawBottomYLabelEntry; - } - - /** - * set this to true to enable drawing the top y-label entry. Disabling this can be helpful - * when the top y-label and - * left x-label interfere with each other. default: true - */ - public void setDrawTopYLabelEntry(boolean enabled) { - mDrawTopYLabelEntry = enabled; - } - - /** - * If this is set to true, the y-axis is inverted which means that low values are on top of - * the chart, high values - * on bottom. - */ - public void setInverted(boolean enabled) { - mInverted = enabled; - } - - /** - * If this returns true, the y-axis is inverted. - */ - public boolean isInverted() { - return mInverted; - } - - /** - * This method is deprecated. - * Use setAxisMinimum(...) / setAxisMaximum(...) instead. - */ - @Deprecated - public void setStartAtZero(boolean startAtZero) { - if (startAtZero) - setAxisMinimum(0f); - else - resetAxisMinimum(); - } - - /** - * Sets the top axis space in percent of the full range. Default 10f - */ - public void setSpaceTop(float percent) { - mSpacePercentTop = percent; - } - - /** - * Returns the top axis space in percent of the full range. Default 10f - */ - public float getSpaceTop() { - return mSpacePercentTop; - } - - /** - * Sets the bottom axis space in percent of the full range. Default 10f - */ - public void setSpaceBottom(float percent) { - mSpacePercentBottom = percent; - } - - /** - * Returns the bottom axis space in percent of the full range. Default 10f - */ - public float getSpaceBottom() { - return mSpacePercentBottom; - } - - public boolean isDrawZeroLineEnabled() { - return mDrawZeroLine; - } - - /** - * Set this to true to draw the zero-line regardless of weather other - * grid-lines are enabled or not. Default: false - */ - public void setDrawZeroLine(boolean mDrawZeroLine) { - this.mDrawZeroLine = mDrawZeroLine; - } - - public int getZeroLineColor() { - return mZeroLineColor; - } - - /** - * Sets the color of the zero line - */ - public void setZeroLineColor(int color) { - mZeroLineColor = color; - } - - public float getZeroLineWidth() { - return mZeroLineWidth; - } - - /** - * Sets the width of the zero line in dp - */ - public void setZeroLineWidth(float width) { - this.mZeroLineWidth = UtilsKtKt.convertDpToPixel(width); - } - - /** - * This is for normal (not horizontal) charts horizontal spacing. - */ - public float getRequiredWidthSpace(Paint p) { - - p.setTextSize(mTextSize); - - String label = getLongestLabel(p); - float width = (float) Utils.calcTextWidth(p, label) + getXOffset() * 2f; - - float minWidth = getMinWidth(); - float maxWidth = getMaxWidth(); - - if (minWidth > 0.f) - minWidth = UtilsKtKt.convertDpToPixel(minWidth); - - if (maxWidth > 0.f && maxWidth != Float.POSITIVE_INFINITY) - maxWidth = UtilsKtKt.convertDpToPixel(maxWidth); - - width = Math.max(minWidth, Math.min(width, maxWidth > 0.0 ? maxWidth : width)); - - return width; - } - - /** - * This is for HorizontalBarChart vertical spacing. - */ - public float getRequiredHeightSpace(Paint p) { - - p.setTextSize(mTextSize); - - String label = getLongestLabel(p); - return (float) Utils.calcTextHeight(p, label) + getYOffset() * 2f; - } - - /** - * Returns true if this axis needs horizontal offset, false if no offset is needed. - */ - public boolean needsOffset() { - if (isEnabled() && isDrawLabelsEnabled() && getLabelPosition() == YAxisLabelPosition - .OUTSIDE_CHART) - return true; - else - return false; - } - - /** - * Returns true if autoscale restriction for axis min value is enabled - */ - @Deprecated - public boolean isUseAutoScaleMinRestriction( ) { - return mUseAutoScaleRestrictionMin; - } - - /** - * Sets autoscale restriction for axis min value as enabled/disabled - */ - @Deprecated - public void setUseAutoScaleMinRestriction( boolean isEnabled ) { - mUseAutoScaleRestrictionMin = isEnabled; - } - - /** - * Returns true if autoscale restriction for axis max value is enabled - */ - @Deprecated - public boolean isUseAutoScaleMaxRestriction() { - return mUseAutoScaleRestrictionMax; - } - - /** - * Sets autoscale restriction for axis max value as enabled/disabled - */ - @Deprecated - public void setUseAutoScaleMaxRestriction( boolean isEnabled ) { - mUseAutoScaleRestrictionMax = isEnabled; - } - - - @Override - public void calculate(float dataMin, float dataMax) { - - float min = dataMin; - float max = dataMax; - - // Make sure max is greater than min - // Discussion: https://github.com/danielgindi/Charts/pull/3650#discussion_r221409991 - if (min > max) - { - if (mCustomAxisMax && mCustomAxisMin) - { - float t = min; - min = max; - max = t; - } - else if (mCustomAxisMax) - { - min = max < 0f ? max * 1.5f : max * 0.5f; - } - else if (mCustomAxisMin) - { - max = min < 0f ? min * 0.5f : min * 1.5f; - } - } - - float range = Math.abs(max - min); - - // in case all values are equal - if (range == 0f) { - max = max + 1f; - min = min - 1f; - } - - // recalculate - range = Math.abs(max - min); - - // calc extra spacing - this.mAxisMinimum = mCustomAxisMin ? this.mAxisMinimum : min - (range / 100f) * getSpaceBottom(); - this.mAxisMaximum = mCustomAxisMax ? this.mAxisMaximum : max + (range / 100f) * getSpaceTop(); - - this.mAxisRange = Math.abs(this.mAxisMinimum - this.mAxisMaximum); - } + /** + * indicates if the bottom y-label entry is drawn or not + */ + private final boolean mDrawBottomYLabelEntry = true; + + /** + * indicates if the top y-label entry is drawn or not + */ + private boolean mDrawTopYLabelEntry = true; + + /** + * flag that indicates if the axis is inverted or not + */ + protected boolean mInverted = false; + + /** + * flag that indicates if the zero-line should be drawn regardless of other grid lines + */ + protected boolean mDrawZeroLine = false; + + /** + * flag indicating that auto scale min restriction should be used + */ + private boolean mUseAutoScaleRestrictionMin = false; + + /** + * flag indicating that auto scale max restriction should be used + */ + private boolean mUseAutoScaleRestrictionMax = false; + + /** + * Color of the zero line + */ + protected int mZeroLineColor = Color.GRAY; + + /** + * Width of the zero line in pixels + */ + protected float mZeroLineWidth = 1f; + + /** + * axis space from the largest value to the top in percent of the total axis range + */ + protected float mSpacePercentTop = 10f; + + /** + * axis space from the smallest value to the bottom in percent of the total axis range + */ + protected float mSpacePercentBottom = 10f; + + /** + * the position of the y-labels relative to the chart + */ + private YAxisLabelPosition mPosition = YAxisLabelPosition.OUTSIDE_CHART; + + /** + * the horizontal offset of the y-label + */ + private float mXLabelOffset = 0.0f; + + /** + * enum for the position of the y-labels relative to the chart + */ + public enum YAxisLabelPosition { + OUTSIDE_CHART, INSIDE_CHART + } + + /** + * the side this axis object represents + */ + private final AxisDependency mAxisDependency; + + /** + * the minimum width that the axis should take (in dp). + *

+ * default: 0.0 + */ + protected float mMinWidth = 0.f; + + /** + * the maximum width that the axis can take (in dp). + * use Inifinity for disabling the maximum + * default: Float.POSITIVE_INFINITY (no maximum specified) + */ + protected float mMaxWidth = Float.POSITIVE_INFINITY; + + /** + * Enum that specifies the axis a DataSet should be plotted against, either LEFT or RIGHT. + * + * @author Philipp Jahoda + */ + public enum AxisDependency { + LEFT, RIGHT + } + + public YAxis() { + super(); + + // default left + this.mAxisDependency = AxisDependency.LEFT; + this.mYOffset = 0f; + } + + public YAxis(AxisDependency position) { + super(); + this.mAxisDependency = position; + this.mYOffset = 0f; + } + + public AxisDependency getAxisDependency() { + return mAxisDependency; + } + + /** + * @return the minimum width that the axis should take (in dp). + */ + public float getMinWidth() { + return mMinWidth; + } + + /** + * Sets the minimum width that the axis should take (in dp). + */ + public void setMinWidth(float minWidth) { + mMinWidth = minWidth; + } + + /** + * @return the maximum width that the axis can take (in dp). + */ + public float getMaxWidth() { + return mMaxWidth; + } + + /** + * Sets the maximum width that the axis can take (in dp). + */ + public void setMaxWidth(float maxWidth) { + mMaxWidth = maxWidth; + } + + /** + * returns the position of the y-labels + */ + public YAxisLabelPosition getLabelPosition() { + return mPosition; + } + + /** + * sets the position of the y-labels + */ + public void setPosition(YAxisLabelPosition pos) { + mPosition = pos; + } + + /** + * returns the horizontal offset of the y-label + */ + public float getLabelXOffset() { + return mXLabelOffset; + } + + /** + * sets the horizontal offset of the y-label + */ + public void setLabelXOffset(float xOffset) { + mXLabelOffset = xOffset; + } + + /** + * returns true if drawing the top y-axis label entry is enabled + */ + public boolean isDrawTopYLabelEntryEnabled() { + return mDrawTopYLabelEntry; + } + + /** + * returns true if drawing the bottom y-axis label entry is enabled + */ + public boolean isDrawBottomYLabelEntryEnabled() { + return mDrawBottomYLabelEntry; + } + + /** + * set this to true to enable drawing the top y-label entry. Disabling this can be helpful + * when the top y-label and + * left x-label interfere with each other. default: true + */ + public void setDrawTopYLabelEntry(boolean enabled) { + mDrawTopYLabelEntry = enabled; + } + + /** + * If this is set to true, the y-axis is inverted which means that low values are on top of + * the chart, high values + * on bottom. + */ + public void setInverted(boolean enabled) { + mInverted = enabled; + } + + /** + * If this returns true, the y-axis is inverted. + */ + public boolean isInverted() { + return mInverted; + } + + /** + * This method is deprecated. + * Use setAxisMinimum(...) / setAxisMaximum(...) instead. + */ + @Deprecated + public void setStartAtZero(boolean startAtZero) { + if (startAtZero) { + setAxisMinimum(0f); + } else { + resetAxisMinimum(); + } + } + + /** + * Sets the top axis space in percent of the full range. Default 10f + */ + public void setSpaceTop(float percent) { + mSpacePercentTop = percent; + } + + /** + * Returns the top axis space in percent of the full range. Default 10f + */ + public float getSpaceTop() { + return mSpacePercentTop; + } + + /** + * Sets the bottom axis space in percent of the full range. Default 10f + */ + public void setSpaceBottom(float percent) { + mSpacePercentBottom = percent; + } + + /** + * Returns the bottom axis space in percent of the full range. Default 10f + */ + public float getSpaceBottom() { + return mSpacePercentBottom; + } + + public boolean isDrawZeroLineEnabled() { + return mDrawZeroLine; + } + + /** + * Set this to true to draw the zero-line regardless of weather other + * grid-lines are enabled or not. Default: false + */ + public void setDrawZeroLine(boolean mDrawZeroLine) { + this.mDrawZeroLine = mDrawZeroLine; + } + + public int getZeroLineColor() { + return mZeroLineColor; + } + + /** + * Sets the color of the zero line + */ + public void setZeroLineColor(int color) { + mZeroLineColor = color; + } + + public float getZeroLineWidth() { + return mZeroLineWidth; + } + + /** + * Sets the width of the zero line in dp + */ + public void setZeroLineWidth(float width) { + this.mZeroLineWidth = UtilsKtKt.convertDpToPixel(width); + } + + /** + * This is for normal (not horizontal) charts horizontal spacing. + */ + public float getRequiredWidthSpace(Paint p) { + + p.setTextSize(mTextSize); + + String label = getLongestLabel(p); + float width = (float) Utils.calcTextWidth(p, label) + getXOffset() * 2f; + + float minWidth = getMinWidth(); + float maxWidth = getMaxWidth(); + + if (minWidth > 0.f) { + minWidth = UtilsKtKt.convertDpToPixel(minWidth); + } + + if (maxWidth > 0.f && maxWidth != Float.POSITIVE_INFINITY) { + maxWidth = UtilsKtKt.convertDpToPixel(maxWidth); + } + + width = Math.max(minWidth, Math.min(width, maxWidth > 0.0 ? maxWidth : width)); + + return width; + } + + /** + * This is for HorizontalBarChart vertical spacing. + */ + public float getRequiredHeightSpace(Paint p) { + + p.setTextSize(mTextSize); + + String label = getLongestLabel(p); + return (float) Utils.calcTextHeight(p, label) + getYOffset() * 2f; + } + + /** + * Returns true if this axis needs horizontal offset, false if no offset is needed. + */ + public boolean needsOffset() { + if (isEnabled() && isDrawLabelsEnabled() && getLabelPosition() == YAxisLabelPosition + .OUTSIDE_CHART) { + return true; + } else { + return false; + } + } + + /** + * Returns true if autoscale restriction for axis min value is enabled + */ + @Deprecated + public boolean isUseAutoScaleMinRestriction() { + return mUseAutoScaleRestrictionMin; + } + + /** + * Sets autoscale restriction for axis min value as enabled/disabled + */ + @Deprecated + public void setUseAutoScaleMinRestriction(boolean isEnabled) { + mUseAutoScaleRestrictionMin = isEnabled; + } + + /** + * Returns true if autoscale restriction for axis max value is enabled + */ + @Deprecated + public boolean isUseAutoScaleMaxRestriction() { + return mUseAutoScaleRestrictionMax; + } + + /** + * Sets autoscale restriction for axis max value as enabled/disabled + */ + @Deprecated + public void setUseAutoScaleMaxRestriction(boolean isEnabled) { + mUseAutoScaleRestrictionMax = isEnabled; + } + + + @Override + public void calculate(float dataMin, float dataMax) { + + float min = dataMin; + float max = dataMax; + + // Make sure max is greater than min + // Discussion: https://github.com/danielgindi/Charts/pull/3650#discussion_r221409991 + if (min > max) { + if (mCustomAxisMax && mCustomAxisMin) { + float t = min; + min = max; + max = t; + } else if (mCustomAxisMax) { + min = max < 0f ? max * 1.5f : max * 0.5f; + } else if (mCustomAxisMin) { + max = min < 0f ? min * 0.5f : min * 1.5f; + } + } + + float range = Math.abs(max - min); + + // in case all values are equal + if (range == 0f) { + max = max + 1f; + min = min - 1f; + } + + // recalculate + range = Math.abs(max - min); + + // calc extra spacing + this.mAxisMinimum = mCustomAxisMin ? this.mAxisMinimum : min - (range / 100f) * getSpaceBottom(); + this.mAxisMaximum = mCustomAxisMax ? this.mAxisMaximum : max + (range / 100f) * getSpaceTop(); + + this.mAxisRange = Math.abs(this.mAxisMinimum - this.mAxisMaximum); + } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.kt b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.kt index a9cce1f84d..6829bfc2a6 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.kt +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.kt @@ -40,7 +40,7 @@ abstract class BaseDataSet() : IDataSet { protected var mAxisDependency: AxisDependency = AxisDependency.LEFT /** - * if true, value highlightning is enabled + * if true, value highlighting is enabled */ protected var mHighlightEnabled: Boolean = true @@ -85,9 +85,6 @@ abstract class BaseDataSet() : IDataSet { */ protected var mVisible: Boolean = true - /** - * Default constructor. - */ init { mColors = ArrayList() mValueColors = ArrayList() @@ -97,11 +94,6 @@ abstract class BaseDataSet() : IDataSet { mValueColors.add(Color.BLACK) } - /** - * Constructor with label. - * - * @param label - */ constructor(label: String) : this() { this.mLabel = label } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java index 0f5470cc79..58639fb9e2 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java @@ -11,6 +11,7 @@ import java.io.Serializable; import java.util.ArrayList; +import java.util.Collections; import java.util.List; /** @@ -22,713 +23,755 @@ @SuppressWarnings("unused") public abstract class ChartData> implements Serializable { - /** - * maximum y-value in the value array across all axes - */ - protected float mYMax = -Float.MAX_VALUE; - - /** - * the minimum y-value in the value array across all axes - */ - protected float mYMin = Float.MAX_VALUE; - - /** - * maximum x-value in the value array - */ - protected float mXMax = -Float.MAX_VALUE; - - /** - * minimum x-value in the value array - */ - protected float mXMin = Float.MAX_VALUE; - - - protected float mLeftAxisMax = -Float.MAX_VALUE; - - protected float mLeftAxisMin = Float.MAX_VALUE; - - protected float mRightAxisMax = -Float.MAX_VALUE; - - protected float mRightAxisMin = Float.MAX_VALUE; - - /** - * array that holds all DataSets the ChartData object represents - */ - protected List mDataSets; - - /** - * Default constructor. - */ - public ChartData() { - mDataSets = new ArrayList<>(); - } - - /** - * Constructor taking single or multiple DataSet objects. - */ - public ChartData(T... dataSets) { - mDataSets = arrayToList(dataSets); - notifyDataChanged(); - } - - /** - * Created because Arrays.asList(...) does not support modification. - */ - private List arrayToList(T[] array) { - - List list = new ArrayList<>(); - - for (T set : array) { - list.add(set); - } - - return list; - } - - /** - * constructor for chart data - * - * @param sets the dataset array - */ - public ChartData(List sets) { - this.mDataSets = sets; - notifyDataChanged(); - } - - /** - * Call this method to let the ChartData know that the underlying data has - * changed. Calling this performs all necessary recalculations needed when - * the contained data has changed. - */ - public void notifyDataChanged() { - calcMinMax(); - } - - /** - * Calc minimum and maximum y-values over all DataSets. - * Tell DataSets to recalculate their min and max y-values, this is only needed for autoScaleMinMax. - * - * @param fromX the x-value to start the calculation from - * @param toX the x-value to which the calculation should be performed - */ - public void calcMinMaxY(float fromX, float toX) { - - for (T set : mDataSets) { - set.calcMinMaxY(fromX, toX); - } - - // apply the new data - calcMinMax(); - } - - /** - * Calc minimum and maximum values (both x and y) over all DataSets. - */ - protected void calcMinMax() { - - if (mDataSets == null) - return; - - mYMax = -Float.MAX_VALUE; - mYMin = Float.MAX_VALUE; - mXMax = -Float.MAX_VALUE; - mXMin = Float.MAX_VALUE; - - for (T set : mDataSets) { - calcMinMax(set); - } - - mLeftAxisMax = -Float.MAX_VALUE; - mLeftAxisMin = Float.MAX_VALUE; - mRightAxisMax = -Float.MAX_VALUE; - mRightAxisMin = Float.MAX_VALUE; - - // left axis - T firstLeft = getFirstLeft(mDataSets); - - if (firstLeft != null) { - - mLeftAxisMax = firstLeft.getYMax(); - mLeftAxisMin = firstLeft.getYMin(); - - for (T dataSet : mDataSets) { - if (dataSet.getAxisDependency() == AxisDependency.LEFT) { - if (dataSet.getYMin() < mLeftAxisMin) - mLeftAxisMin = dataSet.getYMin(); - - if (dataSet.getYMax() > mLeftAxisMax) - mLeftAxisMax = dataSet.getYMax(); - } - } - } - - // right axis - T firstRight = getFirstRight(mDataSets); - - if (firstRight != null) { - - mRightAxisMax = firstRight.getYMax(); - mRightAxisMin = firstRight.getYMin(); - - for (T dataSet : mDataSets) { - if (dataSet.getAxisDependency() == AxisDependency.RIGHT) { - if (dataSet.getYMin() < mRightAxisMin) - mRightAxisMin = dataSet.getYMin(); - - if (dataSet.getYMax() > mRightAxisMax) - mRightAxisMax = dataSet.getYMax(); - } - } - } - } - - /** - * returns the number of LineDataSets this object contains - */ - public int getDataSetCount() { - if (mDataSets == null) - return 0; - return mDataSets.size(); - } - - /** - * Returns the smallest y-value the data object contains. - */ - public float getYMin() { - return mYMin; - } - - /** - * Returns the minimum y-value for the specified axis. - */ - public float getYMin(AxisDependency axis) { - if (axis == AxisDependency.LEFT) { - - if (mLeftAxisMin == Float.MAX_VALUE) { - return mRightAxisMin; - } else - return mLeftAxisMin; - } else { - if (mRightAxisMin == Float.MAX_VALUE) { - return mLeftAxisMin; - } else - return mRightAxisMin; - } - } - - /** - * Returns the greatest y-value the data object contains. - */ - public float getYMax() { - return mYMax; - } - - /** - * Returns the maximum y-value for the specified axis. - */ - public float getYMax(AxisDependency axis) { - if (axis == AxisDependency.LEFT) { - - if (mLeftAxisMax == -Float.MAX_VALUE) { - return mRightAxisMax; - } else - return mLeftAxisMax; - } else { - if (mRightAxisMax == -Float.MAX_VALUE) { - return mLeftAxisMax; - } else - return mRightAxisMax; - } - } - - /** - * Returns the minimum x-value this data object contains. - */ - public float getXMin() { - return mXMin; - } - - /** - * Returns the maximum x-value this data object contains. - */ - public float getXMax() { - return mXMax; - } - - /** - * Returns all DataSet objects this ChartData object holds. - */ - public List getDataSets() { - return mDataSets; - } - - /** - * Retrieve the index of a DataSet with a specific label from the ChartData. - * Search can be case sensitive or not. IMPORTANT: This method does - * calculations at runtime, do not over-use in performance critical - * situations. - * - * @param dataSets the DataSet array to search - * @param ignorecase if true, the search is not case-sensitive - */ - protected int getDataSetIndexByLabel(List dataSets, String label, - boolean ignorecase) { - - if (ignorecase) { - for (int i = 0; i < dataSets.size(); i++) - if (label.equalsIgnoreCase(dataSets.get(i).getLabel())) - return i; - } else { - for (int i = 0; i < dataSets.size(); i++) - if (label.equals(dataSets.get(i).getLabel())) - return i; - } - - return -1; - } - - /** - * Returns the labels of all DataSets as a string array. - */ - public String[] getDataSetLabels() { - - String[] types = new String[mDataSets.size()]; - - for (int i = 0; i < mDataSets.size(); i++) { - types[i] = mDataSets.get(i).getLabel(); - } - - return types; - } - - /** - * Get the Entry for a corresponding highlight object - * @return the entry that is highlighted - */ - public Entry getEntryForHighlight(Highlight highlight) { - if (highlight.getDataSetIndex() >= mDataSets.size()) - return null; - else { - return mDataSets.get(highlight.getDataSetIndex()).getEntryForXValue(highlight.getX(), highlight.getY()); - } - } - - /** - * Returns the DataSet object with the given label. Search can be case - * sensitive or not. IMPORTANT: This method does calculations at runtime. - * Use with care in performance critical situations. - */ - public T getDataSetByLabel(String label, boolean ignorecase) { - - int index = getDataSetIndexByLabel(mDataSets, label, ignorecase); - - if (index < 0 || index >= mDataSets.size()) - return null; - else - return mDataSets.get(index); - } - - public T getDataSetByIndex(int index) { - - if (mDataSets == null || index < 0 || index >= mDataSets.size()) - return null; - - return mDataSets.get(index); - } - - /** - * Adds a DataSet dynamically. - */ - public void addDataSet(T d) { - - if (d == null) - return; - - calcMinMax(d); - - mDataSets.add(d); - } - - /** - * Removes the given DataSet from this data object. Also recalculates all - * minimum and maximum values. Returns true if a DataSet was removed, false - * if no DataSet could be removed. - */ - public boolean removeDataSet(T d) { - - if (d == null) - return false; - - boolean removed = mDataSets.remove(d); - - // if a DataSet was removed - if (removed) { - notifyDataChanged(); - } - - return removed; - } - - /** - * Removes the DataSet at the given index in the DataSet array from the data - * object. Also recalculates all minimum and maximum values. Returns true if - * a DataSet was removed, false if no DataSet could be removed. - */ - public boolean removeDataSet(int index) { - - if (index >= mDataSets.size() || index < 0) - return false; - - T set = mDataSets.get(index); - return removeDataSet(set); - } - - /** - * Adds an Entry to the DataSet at the specified index. - * Entries are added to the end of the list. - */ - public void addEntry(Entry e, int dataSetIndex) { - - if (mDataSets.size() > dataSetIndex && dataSetIndex >= 0) { - - IDataSet set = mDataSets.get(dataSetIndex); - // add the entry to the dataset - if (!set.addEntry(e)) - return; - - calcMinMax(e, set.getAxisDependency()); - - } else { - Log.e("addEntry", "Cannot add Entry because dataSetIndex too high or too low."); - } - } - - /** - * Adjusts the current minimum and maximum values based on the provided Entry object. - */ - protected void calcMinMax(Entry e, AxisDependency axis) { - - if (mYMax < e.getY()) - mYMax = e.getY(); - if (mYMin > e.getY()) - mYMin = e.getY(); - - if (mXMax < e.getX()) - mXMax = e.getX(); - if (mXMin > e.getX()) - mXMin = e.getX(); - - if (axis == AxisDependency.LEFT) { - - if (mLeftAxisMax < e.getY()) - mLeftAxisMax = e.getY(); - if (mLeftAxisMin > e.getY()) - mLeftAxisMin = e.getY(); - } else { - if (mRightAxisMax < e.getY()) - mRightAxisMax = e.getY(); - if (mRightAxisMin > e.getY()) - mRightAxisMin = e.getY(); - } - } - - /** - * Adjusts the minimum and maximum values based on the given DataSet. - */ - protected void calcMinMax(T d) { - - if (mYMax < d.getYMax()) - mYMax = d.getYMax(); - if (mYMin > d.getYMin()) - mYMin = d.getYMin(); - - if (mXMax < d.getXMax()) - mXMax = d.getXMax(); - if (mXMin > d.getXMin()) - mXMin = d.getXMin(); - - if (d.getAxisDependency() == AxisDependency.LEFT) { - - if (mLeftAxisMax < d.getYMax()) - mLeftAxisMax = d.getYMax(); - if (mLeftAxisMin > d.getYMin()) - mLeftAxisMin = d.getYMin(); - } else { - if (mRightAxisMax < d.getYMax()) - mRightAxisMax = d.getYMax(); - if (mRightAxisMin > d.getYMin()) - mRightAxisMin = d.getYMin(); - } - } - - /** - * Removes the given Entry object from the DataSet at the specified index. - */ - public boolean removeEntry(Entry e, int dataSetIndex) { - - // entry null, outofbounds - if (e == null || dataSetIndex >= mDataSets.size()) - return false; - - IDataSet set = mDataSets.get(dataSetIndex); - - if (set != null) { - // remove the entry from the dataset - boolean removed = set.removeEntry(e); - - if (removed) { - notifyDataChanged(); - } - - return removed; - } else - return false; - } - - /** - * Removes the Entry object closest to the given DataSet at the - * specified index. Returns true if an Entry was removed, false if no Entry - * was found that meets the specified requirements. - */ - public boolean removeEntry(float xValue, int dataSetIndex) { - - if (dataSetIndex >= mDataSets.size()) - return false; - - IDataSet dataSet = mDataSets.get(dataSetIndex); - Entry e = dataSet.getEntryForXValue(xValue, Float.NaN); - - if (e == null) - return false; - - return removeEntry(e, dataSetIndex); - } - - /** - * Returns the DataSet that contains the provided Entry, or null, if no - * DataSet contains this Entry. - */ - public T getDataSetForEntry(Entry e) { - - if (e == null) - return null; - - for (int i = 0; i < mDataSets.size(); i++) { - - T set = mDataSets.get(i); - - for (int j = 0; j < set.getEntryCount(); j++) { - if (e.equalTo(set.getEntryForXValue(e.getX(), e.getY()))) - return set; - } - } - - return null; - } - - /** - * Returns all colors used across all DataSet objects this object - * represents. - */ - public int[] getColors() { - - if (mDataSets == null) - return null; - - int clrcnt = 0; - - for (int i = 0; i < mDataSets.size(); i++) { - clrcnt += mDataSets.get(i).getColors().size(); - } - - int[] colors = new int[clrcnt]; - int cnt = 0; - - for (int i = 0; i < mDataSets.size(); i++) { - - List clrs = mDataSets.get(i).getColors(); - - for (Integer clr : clrs) { - colors[cnt] = clr; - cnt++; - } - } - - return colors; - } - - /** - * Returns the index of the provided DataSet in the DataSet array of this data object, or -1 if it does not exist. - */ - public int getIndexOfDataSet(T dataSet) { - return mDataSets.indexOf(dataSet); - } - - /** - * Returns the first DataSet from the datasets-array that has it's dependency on the left axis. - * Returns null if no DataSet with left dependency could be found. - */ - protected T getFirstLeft(List sets) { - for (T dataSet : sets) { - if (dataSet.getAxisDependency() == AxisDependency.LEFT) - return dataSet; - } - return null; - } - - /** - * Returns the first DataSet from the datasets-array that has it's dependency on the right axis. - * Returns null if no DataSet with right dependency could be found. - */ - public T getFirstRight(List sets) { - for (T dataSet : sets) { - if (dataSet.getAxisDependency() == AxisDependency.RIGHT) - return dataSet; - } - return null; - } - - /** - * Sets a custom IValueFormatter for all DataSets this data object contains. - */ - public void setValueFormatter(IValueFormatter valueFormatter) { - if (valueFormatter == null) - return; - else { - for (IDataSet set : mDataSets) { - set.setValueFormatter(valueFormatter); - } - } - } - - /** - * Sets the color of the value-text (color in which the value-labels are - * drawn) for all DataSets this data object contains. - */ - public void setValueTextColor(int color) { - for (IDataSet set : mDataSets) { - set.setValueTextColor(color); - } - } - - /** - * Sets the same list of value-colors for all DataSets this - * data object contains. - */ - public void setValueTextColors(List colors) { - for (IDataSet set : mDataSets) { - set.setValueTextColors(colors); - } - } - - /** - * Sets the Typeface for all value-labels for all DataSets this data object - * contains. - */ - public void setValueTypeface(Typeface tf) { - for (IDataSet set : mDataSets) { - set.setValueTypeface(tf); - } - } - - /** - * Sets the size (in dp) of the value-text for all DataSets this data object - * contains. - */ - public void setValueTextSize(float size) { - for (IDataSet set : mDataSets) { - set.setValueTextSize(size); - } - } - - /** - * Enables / disables drawing values (value-text) for all DataSets this data - * object contains. - */ - public void setDrawValues(boolean enabled) { - for (IDataSet set : mDataSets) { - set.setDrawValues(enabled); - } - } - - /** - * Enables / disables highlighting values for all DataSets this data object - * contains. If set to true, this means that values can - * be highlighted programmatically or by touch gesture. - */ - public void setHighlightEnabled(boolean enabled) { - for (IDataSet set : mDataSets) { - set.setHighlightEnabled(enabled); - } - } - - /** - * Returns true if highlighting of all underlying values is enabled, false - * if not. - */ - public boolean isHighlightEnabled() { - for (IDataSet set : mDataSets) { - if (!set.isHighlightEnabled()) - return false; - } - return true; - } - - /** - * Clears this data object from all DataSets and removes all Entries. Don't - * forget to invalidate the chart after this. - */ - public void clearValues() { - if (mDataSets != null) { - mDataSets.clear(); - } - notifyDataChanged(); - } - - /** - * Checks if this data object contains the specified DataSet. Returns true - * if so, false if not. - */ - public boolean contains(T dataSet) { - - for (T set : mDataSets) { - if (set.equals(dataSet)) - return true; - } - - return false; - } - - /** - * Returns the total entry count across all DataSet objects this data object contains. - */ - public int getEntryCount() { - - int count = 0; - - for (T set : mDataSets) { - count += set.getEntryCount(); - } - - return count; - } - - /** - * Returns the DataSet object with the maximum number of entries or null if there are no DataSets. - */ - public T getMaxEntryCountSet() { - - if (mDataSets == null || mDataSets.isEmpty()) - return null; - - T max = mDataSets.get(0); - - for (T set : mDataSets) { - - if (set.getEntryCount() > max.getEntryCount()) - max = set; - } - - return max; - } + /** + * maximum y-value in the value array across all axes + */ + protected float mYMax = -Float.MAX_VALUE; + + /** + * the minimum y-value in the value array across all axes + */ + protected float mYMin = Float.MAX_VALUE; + + /** + * maximum x-value in the value array + */ + protected float mXMax = -Float.MAX_VALUE; + + /** + * minimum x-value in the value array + */ + protected float mXMin = Float.MAX_VALUE; + + + protected float mLeftAxisMax = -Float.MAX_VALUE; + + protected float mLeftAxisMin = Float.MAX_VALUE; + + protected float mRightAxisMax = -Float.MAX_VALUE; + + protected float mRightAxisMin = Float.MAX_VALUE; + + /** + * array that holds all DataSets the ChartData object represents + */ + protected List mDataSets; + + /** + * Default constructor. + */ + public ChartData() { + mDataSets = new ArrayList<>(); + } + + /** + * Constructor taking single or multiple DataSet objects. + */ + public ChartData(T... dataSets) { + mDataSets = arrayToList(dataSets); + notifyDataChanged(); + } + + /** + * Created because Arrays.asList(...) does not support modification. + */ + private List arrayToList(T[] array) { + + List list = new ArrayList<>(); + + Collections.addAll(list, array); + + return list; + } + + /** + * constructor for chart data + * + * @param sets the dataset array + */ + public ChartData(List sets) { + this.mDataSets = sets; + notifyDataChanged(); + } + + /** + * Call this method to let the ChartData know that the underlying data has + * changed. Calling this performs all necessary recalculations needed when + * the contained data has changed. + */ + public void notifyDataChanged() { + calcMinMax(); + } + + /** + * Calc minimum and maximum y-values over all DataSets. + * Tell DataSets to recalculate their min and max y-values, this is only needed for autoScaleMinMax. + * + * @param fromX the x-value to start the calculation from + * @param toX the x-value to which the calculation should be performed + */ + public void calcMinMaxY(float fromX, float toX) { + + for (T set : mDataSets) { + set.calcMinMaxY(fromX, toX); + } + + // apply the new data + calcMinMax(); + } + + /** + * Calc minimum and maximum values (both x and y) over all DataSets. + */ + protected void calcMinMax() { + + if (mDataSets == null) { + return; + } + + mYMax = -Float.MAX_VALUE; + mYMin = Float.MAX_VALUE; + mXMax = -Float.MAX_VALUE; + mXMin = Float.MAX_VALUE; + + for (T set : mDataSets) { + calcMinMax(set); + } + + mLeftAxisMax = -Float.MAX_VALUE; + mLeftAxisMin = Float.MAX_VALUE; + mRightAxisMax = -Float.MAX_VALUE; + mRightAxisMin = Float.MAX_VALUE; + + // left axis + T firstLeft = getFirstLeft(mDataSets); + + if (firstLeft != null) { + + mLeftAxisMax = firstLeft.getYMax(); + mLeftAxisMin = firstLeft.getYMin(); + + for (T dataSet : mDataSets) { + if (dataSet.getAxisDependency() == AxisDependency.LEFT) { + if (dataSet.getYMin() < mLeftAxisMin) { + mLeftAxisMin = dataSet.getYMin(); + } + + if (dataSet.getYMax() > mLeftAxisMax) { + mLeftAxisMax = dataSet.getYMax(); + } + } + } + } + + // right axis + T firstRight = getFirstRight(mDataSets); + + if (firstRight != null) { + + mRightAxisMax = firstRight.getYMax(); + mRightAxisMin = firstRight.getYMin(); + + for (T dataSet : mDataSets) { + if (dataSet.getAxisDependency() == AxisDependency.RIGHT) { + if (dataSet.getYMin() < mRightAxisMin) { + mRightAxisMin = dataSet.getYMin(); + } + + if (dataSet.getYMax() > mRightAxisMax) { + mRightAxisMax = dataSet.getYMax(); + } + } + } + } + } + + /** + * returns the number of LineDataSets this object contains + */ + public int getDataSetCount() { + if (mDataSets == null) { + return 0; + } + return mDataSets.size(); + } + + /** + * Returns the smallest y-value the data object contains. + */ + public float getYMin() { + return mYMin; + } + + /** + * Returns the minimum y-value for the specified axis. + */ + public float getYMin(AxisDependency axis) { + if (axis == AxisDependency.LEFT) { + + if (mLeftAxisMin == Float.MAX_VALUE) { + return mRightAxisMin; + } else { + return mLeftAxisMin; + } + } else { + if (mRightAxisMin == Float.MAX_VALUE) { + return mLeftAxisMin; + } else { + return mRightAxisMin; + } + } + } + + /** + * Returns the greatest y-value the data object contains. + */ + public float getYMax() { + return mYMax; + } + + /** + * Returns the maximum y-value for the specified axis. + */ + public float getYMax(AxisDependency axis) { + if (axis == AxisDependency.LEFT) { + + if (mLeftAxisMax == -Float.MAX_VALUE) { + return mRightAxisMax; + } else { + return mLeftAxisMax; + } + } else { + if (mRightAxisMax == -Float.MAX_VALUE) { + return mLeftAxisMax; + } else { + return mRightAxisMax; + } + } + } + + /** + * Returns the minimum x-value this data object contains. + */ + public float getXMin() { + return mXMin; + } + + /** + * Returns the maximum x-value this data object contains. + */ + public float getXMax() { + return mXMax; + } + + /** + * Returns all DataSet objects this ChartData object holds. + */ + public List getDataSets() { + return mDataSets; + } + + /** + * Retrieve the index of a DataSet with a specific label from the ChartData. + * Search can be case sensitive or not. IMPORTANT: This method does + * calculations at runtime, do not over-use in performance critical + * situations. + * + * @param dataSets the DataSet array to search + * @param ignorecase if true, the search is not case-sensitive + */ + protected int getDataSetIndexByLabel(List dataSets, String label, + boolean ignorecase) { + + if (ignorecase) { + for (int i = 0; i < dataSets.size(); i++) { + if (label.equalsIgnoreCase(dataSets.get(i).getLabel())) { + return i; + } + } + } else { + for (int i = 0; i < dataSets.size(); i++) { + if (label.equals(dataSets.get(i).getLabel())) { + return i; + } + } + } + + return -1; + } + + /** + * Returns the labels of all DataSets as a string array. + */ + public String[] getDataSetLabels() { + + String[] types = new String[mDataSets.size()]; + + for (int i = 0; i < mDataSets.size(); i++) { + types[i] = mDataSets.get(i).getLabel(); + } + + return types; + } + + /** + * Get the Entry for a corresponding highlight object + * + * @return the entry that is highlighted + */ + public Entry getEntryForHighlight(Highlight highlight) { + if (highlight.getDataSetIndex() >= mDataSets.size()) { + return null; + } else { + return mDataSets.get(highlight.getDataSetIndex()).getEntryForXValue(highlight.getX(), highlight.getY()); + } + } + + /** + * Returns the DataSet object with the given label. Search can be case + * sensitive or not. IMPORTANT: This method does calculations at runtime. + * Use with care in performance critical situations. + */ + public T getDataSetByLabel(String label, boolean ignorecase) { + + int index = getDataSetIndexByLabel(mDataSets, label, ignorecase); + + if (index < 0 || index >= mDataSets.size()) { + return null; + } else { + return mDataSets.get(index); + } + } + + public T getDataSetByIndex(int index) { + + if (mDataSets == null || index < 0 || index >= mDataSets.size()) { + return null; + } + + return mDataSets.get(index); + } + + /** + * Adds a DataSet dynamically. + */ + public void addDataSet(T d) { + + if (d == null) { + return; + } + + calcMinMax(d); + + mDataSets.add(d); + } + + /** + * Removes the given DataSet from this data object. Also recalculates all + * minimum and maximum values. Returns true if a DataSet was removed, false + * if no DataSet could be removed. + */ + public boolean removeDataSet(T d) { + + if (d == null) { + return false; + } + + boolean removed = mDataSets.remove(d); + + // if a DataSet was removed + if (removed) { + notifyDataChanged(); + } + + return removed; + } + + /** + * Removes the DataSet at the given index in the DataSet array from the data + * object. Also recalculates all minimum and maximum values. Returns true if + * a DataSet was removed, false if no DataSet could be removed. + */ + public boolean removeDataSet(int index) { + + if (index >= mDataSets.size() || index < 0) { + return false; + } + + T set = mDataSets.get(index); + return removeDataSet(set); + } + + /** + * Adds an Entry to the DataSet at the specified index. + * Entries are added to the end of the list. + */ + public void addEntry(Entry e, int dataSetIndex) { + + if (mDataSets.size() > dataSetIndex && dataSetIndex >= 0) { + + IDataSet set = mDataSets.get(dataSetIndex); + // add the entry to the dataset + if (!set.addEntry(e)) { + return; + } + + calcMinMax(e, set.getAxisDependency()); + + } else { + Log.e("addEntry", "Cannot add Entry because dataSetIndex too high or too low."); + } + } + + /** + * Adjusts the current minimum and maximum values based on the provided Entry object. + */ + protected void calcMinMax(Entry e, AxisDependency axis) { + + if (mYMax < e.getY()) { + mYMax = e.getY(); + } + if (mYMin > e.getY()) { + mYMin = e.getY(); + } + + if (mXMax < e.getX()) { + mXMax = e.getX(); + } + if (mXMin > e.getX()) { + mXMin = e.getX(); + } + + if (axis == AxisDependency.LEFT) { + + if (mLeftAxisMax < e.getY()) { + mLeftAxisMax = e.getY(); + } + if (mLeftAxisMin > e.getY()) { + mLeftAxisMin = e.getY(); + } + } else { + if (mRightAxisMax < e.getY()) { + mRightAxisMax = e.getY(); + } + if (mRightAxisMin > e.getY()) { + mRightAxisMin = e.getY(); + } + } + } + + /** + * Adjusts the minimum and maximum values based on the given DataSet. + */ + protected void calcMinMax(T d) { + + if (mYMax < d.getYMax()) { + mYMax = d.getYMax(); + } + if (mYMin > d.getYMin()) { + mYMin = d.getYMin(); + } + + if (mXMax < d.getXMax()) { + mXMax = d.getXMax(); + } + if (mXMin > d.getXMin()) { + mXMin = d.getXMin(); + } + + if (d.getAxisDependency() == AxisDependency.LEFT) { + + if (mLeftAxisMax < d.getYMax()) { + mLeftAxisMax = d.getYMax(); + } + if (mLeftAxisMin > d.getYMin()) { + mLeftAxisMin = d.getYMin(); + } + } else { + if (mRightAxisMax < d.getYMax()) { + mRightAxisMax = d.getYMax(); + } + if (mRightAxisMin > d.getYMin()) { + mRightAxisMin = d.getYMin(); + } + } + } + + /** + * Removes the given Entry object from the DataSet at the specified index. + */ + public boolean removeEntry(Entry e, int dataSetIndex) { + + // entry null, outofbounds + if (e == null || dataSetIndex >= mDataSets.size()) { + return false; + } + + IDataSet set = mDataSets.get(dataSetIndex); + + if (set != null) { + // remove the entry from the dataset + boolean removed = set.removeEntry(e); + + if (removed) { + notifyDataChanged(); + } + + return removed; + } else { + return false; + } + } + + /** + * Removes the Entry object closest to the given DataSet at the + * specified index. Returns true if an Entry was removed, false if no Entry + * was found that meets the specified requirements. + */ + public boolean removeEntry(float xValue, int dataSetIndex) { + + if (dataSetIndex >= mDataSets.size()) { + return false; + } + + IDataSet dataSet = mDataSets.get(dataSetIndex); + Entry e = dataSet.getEntryForXValue(xValue, Float.NaN); + + if (e == null) { + return false; + } + + return removeEntry(e, dataSetIndex); + } + + /** + * Returns the DataSet that contains the provided Entry, or null, if no + * DataSet contains this Entry. + */ + public T getDataSetForEntry(Entry e) { + + if (e == null) { + return null; + } + + for (int i = 0; i < mDataSets.size(); i++) { + + T set = mDataSets.get(i); + + for (int j = 0; j < set.getEntryCount(); j++) { + if (e.equalTo(set.getEntryForXValue(e.getX(), e.getY()))) { + return set; + } + } + } + + return null; + } + + /** + * Returns all colors used across all DataSet objects this object + * represents. + */ + public int[] getColors() { + + if (mDataSets == null) { + return null; + } + + int clrcnt = 0; + + for (int i = 0; i < mDataSets.size(); i++) { + clrcnt += mDataSets.get(i).getColors().size(); + } + + int[] colors = new int[clrcnt]; + int cnt = 0; + + for (int i = 0; i < mDataSets.size(); i++) { + + List clrs = mDataSets.get(i).getColors(); + + for (Integer clr : clrs) { + colors[cnt] = clr; + cnt++; + } + } + + return colors; + } + + /** + * Returns the index of the provided DataSet in the DataSet array of this data object, or -1 if it does not exist. + */ + public int getIndexOfDataSet(T dataSet) { + return mDataSets.indexOf(dataSet); + } + + /** + * Returns the first DataSet from the datasets-array that has it's dependency on the left axis. + * Returns null if no DataSet with left dependency could be found. + */ + protected T getFirstLeft(List sets) { + for (T dataSet : sets) { + if (dataSet.getAxisDependency() == AxisDependency.LEFT) { + return dataSet; + } + } + return null; + } + + /** + * Returns the first DataSet from the datasets-array that has it's dependency on the right axis. + * Returns null if no DataSet with right dependency could be found. + */ + public T getFirstRight(List sets) { + for (T dataSet : sets) { + if (dataSet.getAxisDependency() == AxisDependency.RIGHT) { + return dataSet; + } + } + return null; + } + + /** + * Sets a custom IValueFormatter for all DataSets this data object contains. + */ + public void setValueFormatter(IValueFormatter f) { + for (IDataSet set : mDataSets) { + set.setValueFormatter(f); + } + } + + /** + * Sets the color of the value-text (color in which the value-labels are + * drawn) for all DataSets this data object contains. + */ + public void setValueTextColor(int color) { + for (IDataSet set : mDataSets) { + set.setValueTextColor(color); + } + } + + /** + * Sets the same list of value-colors for all DataSets this + * data object contains. + */ + public void setValueTextColors(List colors) { + for (IDataSet set : mDataSets) { + set.setValueTextColors(colors); + } + } + + /** + * Sets the Typeface for all value-labels for all DataSets this data object + * contains. + */ + public void setValueTypeface(Typeface tf) { + for (IDataSet set : mDataSets) { + set.setValueTypeface(tf); + } + } + + /** + * Sets the size (in dp) of the value-text for all DataSets this data object + * contains. + */ + public void setValueTextSize(float size) { + for (IDataSet set : mDataSets) { + set.setValueTextSize(size); + } + } + + /** + * Enables / disables drawing values (value-text) for all DataSets this data + * object contains. + */ + public void setDrawValues(boolean enabled) { + for (IDataSet set : mDataSets) { + set.setDrawValues(enabled); + } + } + + /** + * Enables / disables highlighting values for all DataSets this data object + * contains. If set to true, this means that values can + * be highlighted programmatically or by touch gesture. + */ + public void setHighlightEnabled(boolean enabled) { + for (IDataSet set : mDataSets) { + set.setHighlightEnabled(enabled); + } + } + + /** + * Returns true if highlighting of all underlying values is enabled, false if not. + */ + public boolean isHighlightEnabled() { + for (IDataSet set : mDataSets) { + if (!set.isHighlightEnabled()) { + return false; + } + } + return true; + } + + /** + * Clears this data object from all DataSets and removes all Entries. Don't + * forget to invalidate the chart after this. + */ + public void clearValues() { + if (mDataSets != null) { + mDataSets.clear(); + } + notifyDataChanged(); + } + + /** + * Checks if this data object contains the specified DataSet. Returns true + * if so, false if not. + */ + public boolean contains(T dataSet) { + + for (T set : mDataSets) { + if (set.equals(dataSet)) { + return true; + } + } + + return false; + } + + /** + * Returns the total entry count across all DataSet objects this data object contains. + */ + public int getEntryCount() { + int count = 0; + + for (T set : mDataSets) { + count += set.getEntryCount(); + } + + return count; + } + + /** + * Returns the DataSet object with the maximum number of entries or null if there are no DataSets. + */ + public T getMaxEntryCountSet() { + + if (mDataSets == null || mDataSets.isEmpty()) { + return null; + } + + T max = mDataSets.get(0); + + for (T set : mDataSets) { + + if (set.getEntryCount() > max.getEntryCount()) { + max = set; + } + } + + return max; + } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java index 4f0d51baa4..6e6821beec 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java @@ -15,224 +15,234 @@ */ public abstract class DataSet extends BaseDataSet implements Serializable { - /** - * the entries that this DataSet represents / holds together - */ - protected List mEntries; + /** + * the entries that this DataSet represents / holds together + */ + protected List mEntries; + + /** + * maximum y-value in the value array + */ + protected float mYMax = -Float.MAX_VALUE; + + /** + * minimum y-value in the value array + */ + protected float mYMin = Float.MAX_VALUE; + + /** + * maximum x-value in the value array + */ + protected float mXMax = -Float.MAX_VALUE; + + /** + * minimum x-value in the value array + */ + protected float mXMin = Float.MAX_VALUE; + + + /** + * Creates a new DataSet object with the given values (entries) it represents. Also, a + * label that describes the DataSet can be specified. The label can also be + * used to retrieve the DataSet from a ChartData object. + */ + public DataSet(List entries, String label) { + super(label); + this.mEntries = entries; + + if (mEntries == null) { + mEntries = new ArrayList<>(); + } + + calcMinMax(); + } - /** - * maximum y-value in the value array - */ - protected float mYMax = -Float.MAX_VALUE; + @Override + public void calcMinMax() { - /** - * minimum y-value in the value array - */ - protected float mYMin = Float.MAX_VALUE; + mYMax = -Float.MAX_VALUE; + mYMin = Float.MAX_VALUE; + mXMax = -Float.MAX_VALUE; + mXMin = Float.MAX_VALUE; - /** - * maximum x-value in the value array - */ - protected float mXMax = -Float.MAX_VALUE; - - /** - * minimum x-value in the value array - */ - protected float mXMin = Float.MAX_VALUE; - - - /** - * Creates a new DataSet object with the given values (entries) it represents. Also, a - * label that describes the DataSet can be specified. The label can also be - * used to retrieve the DataSet from a ChartData object. - */ - public DataSet(List entries, String label) { - super(label); - this.mEntries = entries; - - if (mEntries == null) - mEntries = new ArrayList<>(); - - calcMinMax(); - } - - @Override - public void calcMinMax() { - - mYMax = -Float.MAX_VALUE; - mYMin = Float.MAX_VALUE; - mXMax = -Float.MAX_VALUE; - mXMin = Float.MAX_VALUE; - - if (mEntries == null || mEntries.isEmpty()) - return; - - for (T e : mEntries) { - calcMinMax(e); - } - } - - @Override - public void calcMinMaxY(float fromX, float toX) { - mYMax = -Float.MAX_VALUE; - mYMin = Float.MAX_VALUE; - - if (mEntries == null || mEntries.isEmpty()) - return; - - int indexFrom = getEntryIndex(fromX, Float.NaN, Rounding.DOWN); - int indexTo = getEntryIndex(toX, Float.NaN, Rounding.UP); - - if (indexTo < indexFrom) return; - - for (int i = indexFrom; i <= indexTo; i++) { - - // only recalculate y - calcMinMaxY(mEntries.get(i)); - } - } - - /** - * Updates the min and max x and y value of this DataSet based on the given Entry. - */ - protected void calcMinMax(T entry) { - - if (entry == null) - return; - - calcMinMaxX(entry); - calcMinMaxY(entry); - } - - protected void calcMinMaxX(T entry) { - - if (entry.getX() < mXMin) - mXMin = entry.getX(); - - if (entry.getX() > mXMax) - mXMax = entry.getX(); - } - - protected void calcMinMaxY(T entry) { - - if (entry.getY() < mYMin) - mYMin = entry.getY(); - - if (entry.getY() > mYMax) - mYMax = entry.getY(); - } - - @Override - public int getEntryCount() { - return mEntries.size(); - } - - /** - * This method is deprecated. - * Use getEntries() instead. - */ - @Deprecated - public List getValues() { - return mEntries; - } - - /** - * Returns the array of entries that this DataSet represents. - */ - public List getEntries() { - return mEntries; - } - - /** - * This method is deprecated. - * Use setEntries(...) instead. - */ - @Deprecated - public void setValues(List values) { - setEntries(values); - } - - /** - * Sets the array of entries that this DataSet represents, and calls notifyDataSetChanged() - */ - public void setEntries(List entries) { - mEntries = entries; - notifyDataSetChanged(); - } - - /** - * Provides an exact copy of the DataSet this method is used on. - */ - public abstract DataSet copy(); - - protected void copy(DataSet dataSet) { - super.copy(dataSet); - } + if (mEntries == null || mEntries.isEmpty()) { + return; + } + + for (T e : mEntries) { + calcMinMax(e); + } + } @Override - public String toString() { - StringBuilder buffer = new StringBuilder(); - buffer.append(toSimpleString()); - for (int i = 0; i < mEntries.size(); i++) { - buffer.append(mEntries.get(i).toString()).append(" "); - } - return buffer.toString(); - } - - /** - * Returns a simple string representation of the DataSet with the type and - * the number of Entries. - */ - public String toSimpleString() { - return "DataSet, label: " + + public void calcMinMaxY(float fromX, float toX) { + mYMax = -Float.MAX_VALUE; + mYMin = Float.MAX_VALUE; + + if (mEntries == null || mEntries.isEmpty()) { + return; + } + + int indexFrom = getEntryIndex(fromX, Float.NaN, Rounding.DOWN); + int indexTo = getEntryIndex(toX, Float.NaN, Rounding.UP); + + if (indexTo < indexFrom) { + return; + } + + for (int i = indexFrom; i <= indexTo; i++) { + + // only recalculate y + calcMinMaxY(mEntries.get(i)); + } + } + + /** + * Updates the min and max x and y value of this DataSet based on the given Entry. + */ + protected void calcMinMax(T entry) { + + if (entry == null) { + return; + } + + calcMinMaxX(entry); + calcMinMaxY(entry); + } + + protected void calcMinMaxX(T entry) { + + if (entry.getX() < mXMin) { + mXMin = entry.getX(); + } + + if (entry.getX() > mXMax) { + mXMax = entry.getX(); + } + } + + protected void calcMinMaxY(T entry) { + + if (entry.getY() < mYMin) { + mYMin = entry.getY(); + } + + if (entry.getY() > mYMax) { + mYMax = entry.getY(); + } + } + + @Override + public int getEntryCount() { + return mEntries.size(); + } + + /** + * This method is deprecated. + * Use getEntries() instead. + */ + @Deprecated + public List getValues() { + return mEntries; + } + + /** + * Returns the array of entries that this DataSet represents. + */ + public List getEntries() { + return mEntries; + } + + /** + * This method is deprecated. + * Use setEntries(...) instead. + */ + @Deprecated + public void setValues(List values) { + setEntries(values); + } + + /** + * Sets the array of entries that this DataSet represents, and calls notifyDataSetChanged() + */ + public void setEntries(List entries) { + mEntries = entries; + notifyDataSetChanged(); + } + + /** + * Provides an exact copy of the DataSet this method is used on. + */ + public abstract DataSet copy(); + + protected void copy(DataSet dataSet) { + super.copy(dataSet); + } + + @Override + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append(toSimpleString()); + for (int i = 0; i < mEntries.size(); i++) { + buffer.append(mEntries.get(i).toString()).append(" "); + } + return buffer.toString(); + } + + /** + * Returns a simple string representation of the DataSet with the type and + * the number of Entries. + */ + public String toSimpleString() { + return "DataSet, label: " + (getLabel() == null ? "" : getLabel()) + ", entries: " + mEntries.size() + "\n"; } - @Override - public float getYMin() { - return mYMin; - } + @Override + public float getYMin() { + return mYMin; + } - @Override - public float getYMax() { - return mYMax; - } + @Override + public float getYMax() { + return mYMax; + } - @Override - public float getXMin() { - return mXMin; - } + @Override + public float getXMin() { + return mXMin; + } - @Override - public float getXMax() { - return mXMax; - } + @Override + public float getXMax() { + return mXMax; + } @Override public void addEntryOrdered(T entry) { - if (mEntries == null) { - mEntries = new ArrayList<>(); - } + if (mEntries == null) { + mEntries = new ArrayList<>(); + } - calcMinMax(entry); + calcMinMax(entry); - if (!mEntries.isEmpty() && mEntries.get(mEntries.size() - 1).getX() > entry.getX()) { - int closestIndex = getEntryIndex(entry.getX(), entry.getY(), Rounding.UP); - mEntries.add(closestIndex, entry); - } else { - mEntries.add(entry); - } - } + if (!mEntries.isEmpty() && mEntries.get(mEntries.size() - 1).getX() > entry.getX()) { + int closestIndex = getEntryIndex(entry.getX(), entry.getY(), Rounding.UP); + mEntries.add(closestIndex, entry); + } else { + mEntries.add(entry); + } + } - @Override - public void clear() { - mEntries.clear(); - notifyDataSetChanged(); - } + @Override + public void clear() { + mEntries.clear(); + notifyDataSetChanged(); + } @Override public boolean addEntry(T entry) { @@ -241,205 +251,215 @@ public boolean addEntry(T entry) { values = new ArrayList<>(); } - calcMinMax(entry); + calcMinMax(entry); - // add the entry - return values.add(entry); - } + // add the entry + return values.add(entry); + } @Override public boolean removeEntry(T entry) { - if (mEntries == null) - return false; - - // remove the entry - boolean removed = mEntries.remove(entry); - - if (removed) { - calcMinMax(); - } - - return removed; - } - - @Override - public int getEntryIndex(Entry entry) { - return mEntries.indexOf(entry); - } - - @Override - public T getEntryForXValue(float xValue, float closestToY, Rounding rounding) { - - int index = getEntryIndex(xValue, closestToY, rounding); - if (index > -1) - return mEntries.get(index); - return null; - } - - @Override - public T getEntryForXValue(float xValue, float closestToY) { - return getEntryForXValue(xValue, closestToY, Rounding.CLOSEST); - } - - @Override - public T getEntryForIndex(int index) { - if (index < 0) - return null; - if (index >= mEntries.size()) - return null; - return mEntries.get(index); - } - - @Override - public int getEntryIndex(float xValue, float closestToY, Rounding rounding) { - - if (mEntries == null || mEntries.isEmpty()) - return -1; - - int low = 0; - int high = mEntries.size() - 1; - int closest = high; - - while (low < high) { - int m = low + (high - low) / 2; - - Entry currentEntry = mEntries.get(m); - - if (currentEntry != null) { - Entry nextEntry = mEntries.get(m + 1); - - if (nextEntry != null) { - final float d1 = currentEntry.getX() - xValue, - d2 = nextEntry.getX() - xValue, - ad1 = Math.abs(d1), - ad2 = Math.abs(d2); - - if (ad2 < ad1) { - // [m + 1] is closer to xValue - // Search in an higher place - low = m + 1; - } else if (ad1 < ad2) { - // [m] is closer to xValue - // Search in a lower place - high = m; - } else { - // We have multiple sequential x-value with same distance - - if (d1 >= 0.0) { - // Search in a lower place - high = m; - } else if (d1 < 0.0) { - // Search in an higher place - low = m + 1; - } - } - - closest = high; - } - } - } - - if (closest != -1) { - Entry closestEntry = mEntries.get(closest); - if (closestEntry != null) { - float closestXValue = closestEntry.getX(); - if (rounding == Rounding.UP) { - // If rounding up, and found x-value is lower than specified x, and we can go upper... - if (closestXValue < xValue && closest < mEntries.size() - 1) { - ++closest; - } - } else if (rounding == Rounding.DOWN) { - // If rounding down, and found x-value is upper than specified x, and we can go lower... - if (closestXValue > xValue && closest > 0) { - --closest; - } - } - - // Search by closest to y-value - if (!Float.isNaN(closestToY)) { - while (closest > 0 && mEntries.get(closest - 1).getX() == closestXValue) - closest -= 1; - - float closestYValue = closestEntry.getY(); - int closestYIndex = closest; - - while (true) { - closest += 1; - if (closest >= mEntries.size()) - break; - - final Entry value = mEntries.get(closest); - - if (value == null) { - continue; - } - - if (value.getX() != closestXValue) - break; - - if (Math.abs(value.getY() - closestToY) <= Math.abs(closestYValue - closestToY)) { - closestYValue = closestToY; - closestYIndex = closest; - } - } - - closest = closestYIndex; - } - } - } - return closest; - } - - @Override - public List getEntriesForXValue(float xValue) { - - List entries = new ArrayList<>(); - - int low = 0; - int high = mEntries.size() - 1; - - while (low <= high) { - int m = (high + low) / 2; - T entry = mEntries.get(m); - - // if we have a match - if (xValue == entry.getX()) { - while (m > 0 && mEntries.get(m - 1).getX() == xValue) - m--; - - high = mEntries.size(); - - // loop over all "equal" entries - for (; m < high; m++) { - entry = mEntries.get(m); - if (entry.getX() == xValue) { - entries.add(entry); - } else { - break; - } - } - - break; - } else { - if (xValue > entry.getX()) - low = m + 1; - else - high = m - 1; - } - } - - return entries; - } - - /** - * Determines how to round DataSet index values for - * {@link DataSet#getEntryIndex(float, float, Rounding)} DataSet.getEntryIndex()} - * when an exact x-index is not found. - */ - public enum Rounding { - UP, - DOWN, - CLOSEST, - } + if (mEntries == null) { + return false; + } + + // remove the entry + boolean removed = mEntries.remove(entry); + + if (removed) { + calcMinMax(); + } + + return removed; + } + + @Override + public int getEntryIndex(Entry entry) { + return mEntries.indexOf(entry); + } + + @Override + public T getEntryForXValue(float xValue, float closestToY, Rounding rounding) { + + int index = getEntryIndex(xValue, closestToY, rounding); + if (index > -1) { + return mEntries.get(index); + } + return null; + } + + @Override + public T getEntryForXValue(float xValue, float closestToY) { + return getEntryForXValue(xValue, closestToY, Rounding.CLOSEST); + } + + @Override + public T getEntryForIndex(int index) { + if (index < 0) { + return null; + } + if (index >= mEntries.size()) { + return null; + } + return mEntries.get(index); + } + + @Override + public int getEntryIndex(float xValue, float closestToY, Rounding rounding) { + + if (mEntries == null || mEntries.isEmpty()) { + return -1; + } + + int low = 0; + int high = mEntries.size() - 1; + int closest = high; + + while (low < high) { + int m = low + (high - low) / 2; + + Entry currentEntry = mEntries.get(m); + + if (currentEntry != null) { + Entry nextEntry = mEntries.get(m + 1); + + if (nextEntry != null) { + final float d1 = currentEntry.getX() - xValue, + d2 = nextEntry.getX() - xValue, + ad1 = Math.abs(d1), + ad2 = Math.abs(d2); + + if (ad2 < ad1) { + // [m + 1] is closer to xValue + // Search in an higher place + low = m + 1; + } else if (ad1 < ad2) { + // [m] is closer to xValue + // Search in a lower place + high = m; + } else { + // We have multiple sequential x-value with same distance + + if (d1 >= 0.0) { + // Search in a lower place + high = m; + } else if (d1 < 0.0) { + // Search in an higher place + low = m + 1; + } + } + + closest = high; + } + } + } + + if (closest != -1) { + Entry closestEntry = mEntries.get(closest); + if (closestEntry != null) { + float closestXValue = closestEntry.getX(); + if (rounding == Rounding.UP) { + // If rounding up, and found x-value is lower than specified x, and we can go upper... + if (closestXValue < xValue && closest < mEntries.size() - 1) { + ++closest; + } + } else if (rounding == Rounding.DOWN) { + // If rounding down, and found x-value is upper than specified x, and we can go lower... + if (closestXValue > xValue && closest > 0) { + --closest; + } + } + + // Search by closest to y-value + if (!Float.isNaN(closestToY)) { + while (closest > 0 && mEntries.get(closest - 1).getX() == closestXValue) { + closest -= 1; + } + + float closestYValue = closestEntry.getY(); + int closestYIndex = closest; + + while (true) { + closest += 1; + if (closest >= mEntries.size()) { + break; + } + + final Entry value = mEntries.get(closest); + + if (value == null) { + continue; + } + + if (value.getX() != closestXValue) { + break; + } + + if (Math.abs(value.getY() - closestToY) <= Math.abs(closestYValue - closestToY)) { + closestYValue = closestToY; + closestYIndex = closest; + } + } + + closest = closestYIndex; + } + } + } + return closest; + } + + @Override + public List getEntriesForXValue(float xValue) { + + List entries = new ArrayList<>(); + + int low = 0; + int high = mEntries.size() - 1; + + while (low <= high) { + int m = (high + low) / 2; + T entry = mEntries.get(m); + + // if we have a match + if (xValue == entry.getX()) { + while (m > 0 && mEntries.get(m - 1).getX() == xValue) { + m--; + } + + high = mEntries.size(); + + // loop over all "equal" entries + for (; m < high; m++) { + entry = mEntries.get(m); + if (entry.getX() == xValue) { + entries.add(entry); + } else { + break; + } + } + + break; + } else { + if (xValue > entry.getX()) { + low = m + 1; + } else { + high = m - 1; + } + } + } + + return entries; + } + + /** + * Determines how to round DataSet index values for + * {@link DataSet#getEntryIndex(float, float, Rounding)} DataSet.getEntryIndex()} + * when an exact x-index is not found. + */ + public enum Rounding { + UP, + DOWN, + CLOSEST, + } } \ No newline at end of file diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java index 633eeb4b55..8279aceb1c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java @@ -10,7 +10,6 @@ import com.github.mikephil.charting.formatter.IFillFormatter; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.utils.ColorTemplate; -import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.UtilsKtKt; import java.util.ArrayList; @@ -18,369 +17,372 @@ public class LineDataSet extends LineRadarDataSet implements ILineDataSet { - /** - * Drawing mode for this line dataset - **/ - private LineDataSet.Mode mMode = Mode.LINEAR; - - /** - * List representing all colors that are used for the circles - */ - private List mCircleColors = null; - - /** - * the color of the inner circles - */ - private int mCircleHoleColor = Color.WHITE; - - /** - * the radius of the circle-shaped value indicators - */ - private float mCircleRadius = 8f; - - /** - * the hole radius of the circle-shaped value indicators - */ - private float mCircleHoleRadius = 4f; - - /** - * sets the intensity of the cubic lines - */ - private float mCubicIntensity = 0.2f; - - /** - * the path effect of this DataSet that makes dashed lines possible - */ - private DashPathEffect mDashPathEffect = null; - - /** - * formatter for customizing the position of the fill-line - */ - private IFillFormatter mFillFormatter = new DefaultFillFormatter(); - - /** - * if true, drawing circles is enabled - */ - private boolean mDrawCircles = true; - - private boolean mDrawCircleHole = true; - - - public LineDataSet(List yVals, String label) { - super(yVals, label); - - // mCircleRadius = UtilsKtKt.convertDpToPixel(4f); - // mLineWidth = UtilsKtKt.convertDpToPixel(1f); - - if (mCircleColors == null) { - mCircleColors = new ArrayList<>(); - } - mCircleColors.clear(); - - // default colors - // mColors.add(Color.rgb(192, 255, 140)); - // mColors.add(Color.rgb(255, 247, 140)); - mCircleColors.add(Color.rgb(140, 234, 255)); - } - - @Override - public DataSet copy() { - List entries = new ArrayList<>(); - for (int i = 0; i < mEntries.size(); i++) { - entries.add(mEntries.get(i).copy()); - } - LineDataSet copied = new LineDataSet(entries, getLabel()); - copy(copied); - return copied; - } - - protected void copy(LineDataSet lineDataSet) { - super.copy((BaseDataSet) lineDataSet); - lineDataSet.mCircleColors = mCircleColors; - lineDataSet.mCircleHoleColor = mCircleHoleColor; - lineDataSet.mCircleHoleRadius = mCircleHoleRadius; - lineDataSet.mCircleRadius = mCircleRadius; - lineDataSet.mCubicIntensity = mCubicIntensity; - lineDataSet.mDashPathEffect = mDashPathEffect; - lineDataSet.mDrawCircleHole = mDrawCircleHole; - lineDataSet.mDrawCircles = mDrawCircleHole; - lineDataSet.mFillFormatter = mFillFormatter; - lineDataSet.mMode = mMode; - } - - /** - * Returns the drawing mode for this line dataset - */ - @Override - public LineDataSet.Mode getMode() { - return mMode; - } - - /** - * Returns the drawing mode for this LineDataSet - */ - public void setMode(LineDataSet.Mode mode) { - mMode = mode; - } - - /** - * Sets the intensity for cubic lines (if enabled). Max = 1f = very cubic, - * Min = 0.05f = low cubic effect, Default: 0.2f - */ - public void setCubicIntensity(float intensity) { - - if (intensity > 1f) - intensity = 1f; - if (intensity < 0.05f) - intensity = 0.05f; - - mCubicIntensity = intensity; - } - - @Override - public float getCubicIntensity() { - return mCubicIntensity; - } - - - /** - * Sets the radius of the drawn circles. - * Default radius = 4f, Min = 1f - */ - public void setCircleRadius(float radius) { - - if (radius >= 1f) { - mCircleRadius = UtilsKtKt.convertDpToPixel(radius); - } else { - Log.e("LineDataSet", "Circle radius cannot be < 1"); - } - } - - @Override - public float getCircleRadius() { - return mCircleRadius; - } - - /** - * Sets the hole radius of the drawn circles. - * Default radius = 2f, Min = 0.5f - */ - public void setCircleHoleRadius(float holeRadius) { - - if (holeRadius >= 0.5f) { - mCircleHoleRadius = UtilsKtKt.convertDpToPixel(holeRadius); - } else { - Log.e("LineDataSet", "Circle radius cannot be < 0.5"); - } - } - - @Override - public float getCircleHoleRadius() { - return mCircleHoleRadius; - } - - /** - * sets the size (radius) of the circle shpaed value indicators, - * default size = 4f - *

- * This method is deprecated because of unclarity. Use setCircleRadius instead. - */ - @Deprecated - public void setCircleSize(float size) { - setCircleRadius(size); - } - - /** - * This function is deprecated because of unclarity. Use getCircleRadius instead. - */ - @Deprecated - public float getCircleSize() { - return getCircleRadius(); - } - - /** - * Enables the line to be drawn in dashed mode, e.g. like this - * "- - - - - -". THIS ONLY WORKS IF HARDWARE-ACCELERATION IS TURNED OFF. - * Keep in mind that hardware acceleration boosts performance. - * - * @param lineLength the length of the line pieces - * @param spaceLength the length of space in between the pieces - * @param phase offset, in degrees (normally, use 0) - */ - public void enableDashedLine(float lineLength, float spaceLength, float phase) { - mDashPathEffect = new DashPathEffect(new float[]{ - lineLength, spaceLength - }, phase); - } - - /** - * Disables the line to be drawn in dashed mode. - */ - public void disableDashedLine() { - mDashPathEffect = null; - } - - @Override - public boolean isDashedLineEnabled() { - return mDashPathEffect == null ? false : true; - } - - @Override - public DashPathEffect getDashPathEffect() { - return mDashPathEffect; - } - - /** - * set this to true to enable the drawing of circle indicators for this - * DataSet, default true - */ - public void setDrawCircles(boolean enabled) { - this.mDrawCircles = enabled; - } - - @Override - public boolean isDrawCirclesEnabled() { - return mDrawCircles; - } - - @Deprecated - @Override - public boolean isDrawCubicEnabled() { - return mMode == Mode.CUBIC_BEZIER; - } - - @Deprecated - @Override - public boolean isDrawSteppedEnabled() { - return mMode == Mode.STEPPED; - } - - /** - * returns all colors specified for the circles - */ - public List getCircleColors() { - return mCircleColors; - } - - @Override - public int getCircleColor(int index) { - return mCircleColors.get(index); - } - - @Override - public int getCircleColorCount() { - return mCircleColors.size(); - } - - /** - * Sets the colors that should be used for the circles of this DataSet. - * Colors are reused as soon as the number of Entries the DataSet represents - * is higher than the size of the colors array. Make sure that the colors - * are already prepared (by calling getResources().getColor(...)) before - * adding them to the DataSet. - */ - public void setCircleColors(List colors) { - mCircleColors = colors; - } - - /** - * Sets the colors that should be used for the circles of this DataSet. - * Colors are reused as soon as the number of Entries the DataSet represents - * is higher than the size of the colors array. Make sure that the colors - * are already prepared (by calling getResources().getColor(...)) before - * adding them to the DataSet. - */ - public void setCircleColors(int... colors) { - this.mCircleColors = ColorTemplate.createColors(colors); - } - - /** - * ets the colors that should be used for the circles of this DataSet. - * Colors are reused as soon as the number of Entries the DataSet represents - * is higher than the size of the colors array. You can use - * "new String[] { R.color.red, R.color.green, ... }" to provide colors for - * this method. Internally, the colors are resolved using - * getResources().getColor(...) - */ - public void setCircleColors(int[] colors, Context c) { - - List clrs = mCircleColors; - if (clrs == null) { - clrs = new ArrayList<>(); - } - clrs.clear(); - - for (int color : colors) { - clrs.add(c.getResources().getColor(color)); - } - - mCircleColors = clrs; - } - - /** - * Sets the one and ONLY color that should be used for this DataSet. - * Internally, this recreates the colors array and adds the specified color. - */ - public void setCircleColor(int color) { - resetCircleColors(); - mCircleColors.add(color); - } - - /** - * resets the circle-colors array and creates a new one - */ - public void resetCircleColors() { - if (mCircleColors == null) { - mCircleColors = new ArrayList<>(); - } - mCircleColors.clear(); - } - - /** - * Sets the color of the inner circle of the line-circles. - */ - public void setCircleHoleColor(int color) { - mCircleHoleColor = color; - } - - @Override - public int getCircleHoleColor() { - return mCircleHoleColor; - } - - /** - * Set this to true to allow drawing a hole in each data circle. - */ - public void setDrawCircleHole(boolean enabled) { - mDrawCircleHole = enabled; - } - - @Override - public boolean isDrawCircleHoleEnabled() { - return mDrawCircleHole; - } - - /** - * Sets a custom IFillFormatter to the chart that handles the position of the - * filled-line for each DataSet. Set this to null to use the default logic. - */ - public void setFillFormatter(IFillFormatter formatter) { - - if (formatter == null) - mFillFormatter = new DefaultFillFormatter(); - else - mFillFormatter = formatter; - } - - @Override - public IFillFormatter getFillFormatter() { - return mFillFormatter; - } + /** + * Drawing mode for this line dataset + **/ + private LineDataSet.Mode mMode = Mode.LINEAR; + + /** + * List representing all colors that are used for the circles + */ + private List mCircleColors = null; + + /** + * the color of the inner circles + */ + private int mCircleHoleColor = Color.WHITE; + + /** + * the radius of the circle-shaped value indicators + */ + private float mCircleRadius = 8f; + + /** + * the hole radius of the circle-shaped value indicators + */ + private float mCircleHoleRadius = 4f; + + /** + * sets the intensity of the cubic lines + */ + private float mCubicIntensity = 0.2f; + + /** + * the path effect of this DataSet that makes dashed lines possible + */ + private DashPathEffect mDashPathEffect = null; + + /** + * formatter for customizing the position of the fill-line + */ + private IFillFormatter mFillFormatter = new DefaultFillFormatter(); + + /** + * if true, drawing circles is enabled + */ + private boolean mDrawCircles = true; + + private boolean mDrawCircleHole = true; + + + public LineDataSet(List yVals, String label) { + super(yVals, label); + + // mCircleRadius = UtilsKtKt.convertDpToPixel(4f); + // mLineWidth = UtilsKtKt.convertDpToPixel(1f); + + if (mCircleColors == null) { + mCircleColors = new ArrayList<>(); + } + mCircleColors.clear(); + + // default colors + // mColors.add(Color.rgb(192, 255, 140)); + // mColors.add(Color.rgb(255, 247, 140)); + mCircleColors.add(Color.rgb(140, 234, 255)); + } + + @Override + public DataSet copy() { + List entries = new ArrayList<>(); + for (int i = 0; i < mEntries.size(); i++) { + entries.add(mEntries.get(i).copy()); + } + LineDataSet copied = new LineDataSet(entries, getLabel()); + copy(copied); + return copied; + } + + protected void copy(LineDataSet lineDataSet) { + super.copy((BaseDataSet) lineDataSet); + lineDataSet.mCircleColors = mCircleColors; + lineDataSet.mCircleHoleColor = mCircleHoleColor; + lineDataSet.mCircleHoleRadius = mCircleHoleRadius; + lineDataSet.mCircleRadius = mCircleRadius; + lineDataSet.mCubicIntensity = mCubicIntensity; + lineDataSet.mDashPathEffect = mDashPathEffect; + lineDataSet.mDrawCircleHole = mDrawCircleHole; + lineDataSet.mDrawCircles = mDrawCircleHole; + lineDataSet.mFillFormatter = mFillFormatter; + lineDataSet.mMode = mMode; + } + + /** + * Returns the drawing mode for this line dataset + */ + @Override + public LineDataSet.Mode getMode() { + return mMode; + } + + /** + * Returns the drawing mode for this LineDataSet + */ + public void setMode(LineDataSet.Mode mode) { + mMode = mode; + } + + /** + * Sets the intensity for cubic lines (if enabled). Max = 1f = very cubic, + * Min = 0.05f = low cubic effect, Default: 0.2f + */ + public void setCubicIntensity(float intensity) { + + if (intensity > 1f) { + intensity = 1f; + } + if (intensity < 0.05f) { + intensity = 0.05f; + } + + mCubicIntensity = intensity; + } + + @Override + public float getCubicIntensity() { + return mCubicIntensity; + } + + + /** + * Sets the radius of the drawn circles. + * Default radius = 4f, Min = 1f + */ + public void setCircleRadius(float radius) { + + if (radius >= 1f) { + mCircleRadius = UtilsKtKt.convertDpToPixel(radius); + } else { + Log.e("LineDataSet", "Circle radius cannot be < 1"); + } + } + + @Override + public float getCircleRadius() { + return mCircleRadius; + } + + /** + * Sets the hole radius of the drawn circles. + * Default radius = 2f, Min = 0.5f + */ + public void setCircleHoleRadius(float holeRadius) { + + if (holeRadius >= 0.5f) { + mCircleHoleRadius = UtilsKtKt.convertDpToPixel(holeRadius); + } else { + Log.e("LineDataSet", "Circle radius cannot be < 0.5"); + } + } + + @Override + public float getCircleHoleRadius() { + return mCircleHoleRadius; + } + + /** + * sets the size (radius) of the circle shpaed value indicators, + * default size = 4f + *

+ * This method is deprecated because of unclarity. Use setCircleRadius instead. + */ + @Deprecated + public void setCircleSize(float size) { + setCircleRadius(size); + } + + /** + * This function is deprecated because of unclarity. Use getCircleRadius instead. + */ + @Deprecated + public float getCircleSize() { + return getCircleRadius(); + } + + /** + * Enables the line to be drawn in dashed mode, e.g. like this + * "- - - - - -". THIS ONLY WORKS IF HARDWARE-ACCELERATION IS TURNED OFF. + * Keep in mind that hardware acceleration boosts performance. + * + * @param lineLength the length of the line pieces + * @param spaceLength the length of space in between the pieces + * @param phase offset, in degrees (normally, use 0) + */ + public void enableDashedLine(float lineLength, float spaceLength, float phase) { + mDashPathEffect = new DashPathEffect(new float[]{ + lineLength, spaceLength + }, phase); + } + + /** + * Disables the line to be drawn in dashed mode. + */ + public void disableDashedLine() { + mDashPathEffect = null; + } + + @Override + public boolean isDashedLineEnabled() { + return mDashPathEffect == null ? false : true; + } + + @Override + public DashPathEffect getDashPathEffect() { + return mDashPathEffect; + } + + /** + * set this to true to enable the drawing of circle indicators for this + * DataSet, default true + */ + public void setDrawCircles(boolean enabled) { + this.mDrawCircles = enabled; + } + + @Override + public boolean isDrawCirclesEnabled() { + return mDrawCircles; + } + + @Deprecated + @Override + public boolean isDrawCubicEnabled() { + return mMode == Mode.CUBIC_BEZIER; + } + + @Deprecated + @Override + public boolean isDrawSteppedEnabled() { + return mMode == Mode.STEPPED; + } + + /** + * returns all colors specified for the circles + */ + public List getCircleColors() { + return mCircleColors; + } + + @Override + public int getCircleColor(int index) { + return mCircleColors.get(index); + } + + @Override + public int getCircleColorCount() { + return mCircleColors.size(); + } + + /** + * Sets the colors that should be used for the circles of this DataSet. + * Colors are reused as soon as the number of Entries the DataSet represents + * is higher than the size of the colors array. Make sure that the colors + * are already prepared (by calling getResources().getColor(...)) before + * adding them to the DataSet. + */ + public void setCircleColors(List colors) { + mCircleColors = colors; + } + + /** + * Sets the colors that should be used for the circles of this DataSet. + * Colors are reused as soon as the number of Entries the DataSet represents + * is higher than the size of the colors array. Make sure that the colors + * are already prepared (by calling getResources().getColor(...)) before + * adding them to the DataSet. + */ + public void setCircleColors(int... colors) { + this.mCircleColors = ColorTemplate.createColors(colors); + } + + /** + * ets the colors that should be used for the circles of this DataSet. + * Colors are reused as soon as the number of Entries the DataSet represents + * is higher than the size of the colors array. You can use + * "new String[] { R.color.red, R.color.green, ... }" to provide colors for + * this method. Internally, the colors are resolved using + * getResources().getColor(...) + */ + public void setCircleColors(int[] colors, Context c) { + + List clrs = mCircleColors; + if (clrs == null) { + clrs = new ArrayList<>(); + } + clrs.clear(); + + for (int color : colors) { + clrs.add(c.getResources().getColor(color)); + } + + mCircleColors = clrs; + } + + /** + * Sets the one and ONLY color that should be used for this DataSet. + * Internally, this recreates the colors array and adds the specified color. + */ + public void setCircleColor(int color) { + resetCircleColors(); + mCircleColors.add(color); + } + + /** + * resets the circle-colors array and creates a new one + */ + public void resetCircleColors() { + if (mCircleColors == null) { + mCircleColors = new ArrayList<>(); + } + mCircleColors.clear(); + } + + /** + * Sets the color of the inner circle of the line-circles. + */ + public void setCircleHoleColor(int color) { + mCircleHoleColor = color; + } + + @Override + public int getCircleHoleColor() { + return mCircleHoleColor; + } + + /** + * Set this to true to allow drawing a hole in each data circle. + */ + public void setDrawCircleHole(boolean enabled) { + mDrawCircleHole = enabled; + } + + @Override + public boolean isDrawCircleHoleEnabled() { + return mDrawCircleHole; + } + + /** + * Sets a custom IFillFormatter to the chart that handles the position of the + * filled-line for each DataSet. Set this to null to use the default logic. + */ + public void setFillFormatter(IFillFormatter formatter) { + + if (formatter == null) { + mFillFormatter = new DefaultFillFormatter(); + } else { + mFillFormatter = formatter; + } + } + + @Override + public IFillFormatter getFillFormatter() { + return mFillFormatter; + } public enum Mode { - LINEAR, - STEPPED, - CUBIC_BEZIER, - HORIZONTAL_BEZIER - } + LINEAR, + STEPPED, + CUBIC_BEZIER, + HORIZONTAL_BEZIER + } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IAxisValueFormatter.kt b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IAxisValueFormatter.kt index 023669f909..36c4e53ddb 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IAxisValueFormatter.kt +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IAxisValueFormatter.kt @@ -13,7 +13,6 @@ interface IAxisValueFormatter { * * @param value the value to be formatted * @param axis the axis the value belongs to - * @return */ fun getFormattedValue(value: Float, axis: AxisBase?): String? } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.kt b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.kt index 0b1be39ebb..66a3031905 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.kt +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.kt @@ -43,8 +43,6 @@ open class LargeValueFormatter() : IValueFormatter, IAxisValueFormatter { /** * Set an appendix text to be added at the end of the formatted value. - * - * @param appendix */ fun setAppendix(appendix: String) { text = appendix