package com.github.mikephil.charting.data; import android.content.Context; import android.graphics.Color; import com.github.mikephil.charting.utils.ColorTemplate; import java.util.ArrayList; /** * The DataSet class represents one group or type of entries (Entry) in the * Chart that belong together. It is designed to logically separate different * groups of values inside the Chart (e.g. the values for a specific line in the * LineChart, or the values of a specific group of bars in the BarChart). * * @author Philipp Jahoda */ public abstract class DataSet<T extends Entry> { /** arraylist representing all colors that are used for this DataSet */ protected ArrayList<Integer> mColors = null; /** the entries that this dataset represents / holds together */ protected ArrayList<T> mYVals = null; /** maximum y-value in the y-value array */ protected float mYMax = 0.0f; /** the minimum y-value in the y-value array */ protected float mYMin = 0.0f; /** the total sum of all y-values */ private float mYValueSum = 0f; /** label that describes the DataSet or the data the DataSet represents */ private String mLabel = "DataSet"; /** * Creates a new DataSet object with the given values 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. * * @param yVals * @param label */ public DataSet(ArrayList<T> yVals, String label) { this.mLabel = label; this.mYVals = yVals; if (mYVals == null) mYVals = new ArrayList<T>(); // if (yVals.size() <= 0) { // return; // } mColors = new ArrayList<Integer>(); // default colors // mColors.add(Color.rgb(192, 255, 140)); // mColors.add(Color.rgb(255, 247, 140)); mColors.add(Color.rgb(140, 234, 255)); calcMinMax(); calcYValueSum(); } /** * Use this method to tell the data set that the underlying data has changed */ public void notifyDataSetChanged() { calcMinMax(); calcYValueSum(); } /** * calc minimum and maximum y value */ protected void calcMinMax() { if (mYVals.size() == 0) { return; } mYMin = mYVals.get(0).getVal(); mYMax = mYVals.get(0).getVal(); for (int i = 0; i < mYVals.size(); i++) { Entry e = mYVals.get(i); if (e != null) { if (e.getVal() < mYMin) mYMin = e.getVal(); if (e.getVal() > mYMax) mYMax = e.getVal(); } } } /** * calculates the sum of all y-values */ private void calcYValueSum() { mYValueSum = 0; for (int i = 0; i < mYVals.size(); i++) { Entry e = mYVals.get(i); if (e != null) mYValueSum += Math.abs(e.getVal()); } } /** * returns the number of y-values this DataSet represents * * @return */ public int getEntryCount() { return mYVals.size(); } /** * Returns the value of the Entry object at the given xIndex. Returns * Float.NaN if no value is at the given x-index. INFORMATION: This method * does calculations at runtime. Do not over-use in performance critical * situations. * * @param xIndex * @return */ public float getYValForXIndex(int xIndex) { Entry e = getEntryForXIndex(xIndex); if (e != null) return e.getVal(); else return Float.NaN; } /** * Returns the first Entry object found at the given xIndex with binary * search. Returns null if no Entry object at that index. INFORMATION: This * method does calculations at runtime. Do not over-use in performance * critical situations. * * @param xIndex * @return */ public T getEntryForXIndex(int x) { int low = 0; int high = mYVals.size() - 1; while (low <= high) { int m = (high + low) / 2; if (x == mYVals.get(m).getXIndex()) { return mYVals.get(m); } if (x > mYVals.get(m).getXIndex()) low = m + 1; else high = m - 1; } return null; } /** * Returns all Entry objects at the given xIndex. INFORMATION: This method * does calculations at runtime. Do not over-use in performance critical * situations. * * @param xIndex * @return */ public ArrayList<T> getEntriesForXIndex(int x) { ArrayList<T> entries = new ArrayList<T>(); int low = 0; int high = mYVals.size(); while (low <= high) { int m = (high + low) / 2; if (x == mYVals.get(m).getXIndex()) { entries.add(mYVals.get(m)); } if (x > mYVals.get(m).getXIndex()) low = m + 1; else high = m - 1; } return entries; } /** * returns the DataSets Entry array * * @return */ public ArrayList<T> getYVals() { return mYVals; } /** * gets the sum of all y-values * * @return */ public float getYValueSum() { return mYValueSum; } /** * returns the minimum y-value this DataSet holds * * @return */ public float getYMin() { return mYMin; } /** * returns the maximum y-value this DataSet holds * * @return */ public float getYMax() { return mYMax; } /** * returns the type of the DataSet, specified via constructor * * @return */ // public int getType() { // return mType; // } /** * The xIndex of an Entry object is provided. This method returns the actual * index in the Entry array of the DataSet. IMPORTANT: This method does * calculations at runtime, do not over-use in performance critical * situations. * * @param xIndex * @return */ public int getIndexInEntries(int xIndex) { for (int i = 0; i < mYVals.size(); i++) { if (xIndex == mYVals.get(i).getXIndex()) return i; } return -1; } /** * Provides an exact copy of the DataSet this method is used on. * * @return */ public abstract DataSet<T> copy(); @Override public String toString() { StringBuffer buffer = new StringBuffer(); buffer.append(toSimpleString()); for (int i = 0; i < mYVals.size(); i++) { buffer.append(mYVals.get(i).toString() + " "); } return buffer.toString(); } /** * Returns a simple string representation of the DataSet with the type and * the number of Entries. * * @return */ public String toSimpleString() { StringBuffer buffer = new StringBuffer(); buffer.append("DataSet, label: " + mLabel + ", entries: " + mYVals.size() + "\n"); return buffer.toString(); } /** * Returns the label string that describes the DataSet. * * @return */ public String getLabel() { return mLabel; } /** * Adds an Entry to the DataSet dynamically. This will also recalculate the * current minimum and maximum values of the DataSet and the value-sum. * * @param d */ public void addEntry(Entry e) { if (e == null) return; float val = e.getVal(); if (mYVals == null || mYVals.size() <= 0) { mYVals = new ArrayList<T>(); mYMax = val; mYMin = val; } else { if (mYMax < val) mYMax = val; if (mYMin > val) mYMin = val; } mYValueSum += val; // add the entry mYVals.add((T) e); } /** * Removes an Entry from the DataSets entries array. This will also * recalculate the current minimum and maximum values of the DataSet and the * value-sum. Returns true if an Entry was removed, false if no Entry could * be removed. * * @param e */ public boolean removeEntry(T e) { if (e == null) return false; // remove the entry boolean removed = mYVals.remove(e); if (removed) { float val = e.getVal(); mYValueSum -= val; calcMinMax(); } return removed; } /** * Removes the Entry object that has the given xIndex from the DataSet. * Returns true if an Entry was removed, false if no Entry could be removed. * * @param xIndex */ public boolean removeEntry(int xIndex) { T e = getEntryForXIndex(xIndex); return removeEntry(e); } /** BELOW THIS COLOR HANDLING */ /** * Sets the colors that should be used fore this DataSet. Colors are reused * as soon as the number of Entries the DataSet represents is higher than * the size of the colors array. If you are using colors from the resources, * make sure that the colors are already prepared (by calling * getResources().getColor(...)) before adding them to the DataSet. * * @param colors */ public void setColors(ArrayList<Integer> colors) { this.mColors = colors; } /** * Sets the colors that should be used fore this DataSet. Colors are reused * as soon as the number of Entries the DataSet represents is higher than * the size of the colors array. If you are using colors from the resources, * make sure that the colors are already prepared (by calling * getResources().getColor(...)) before adding them to the DataSet. * * @param colors */ public void setColors(int[] colors) { this.mColors = ColorTemplate.createColors(colors); } /** * Sets the colors that should be used fore 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 int[] { R.color.red, R.color.green, ... }" to provide colors for * this method. Internally, the colors are resolved using * getResources().getColor(...) * * @param colors */ public void setColors(int[] colors, Context c) { ArrayList<Integer> clrs = new ArrayList<Integer>(); for (int color : colors) { clrs.add(c.getResources().getColor(color)); } mColors = clrs; } /** * Adds a new color to the colors array of the DataSet. * * @param color */ public void addColor(int color) { if (mColors == null) mColors = new ArrayList<Integer>(); mColors.add(color); } /** * Sets the one and ONLY color that should be used for this DataSet. * Internally, this recreates the colors array and adds the specified color. * * @param color */ public void setColor(int color) { resetColors(); mColors.add(color); } /** * returns all the colors that are set for this DataSet * * @return */ public ArrayList<Integer> getColors() { return mColors; } /** * Returns the color at the given index of the DataSet's color array. * Performs a IndexOutOfBounds check by modulus. * * @param index * @return */ public int getColor(int index) { return mColors.get(index % mColors.size()); } /** * Returns the first color (index 0) of the colors-array this DataSet * contains. * * @return */ public int getColor() { return mColors.get(0); } /** * Resets all colors of this DataSet and recreates the colors array. */ public void resetColors() { mColors = new ArrayList<Integer>(); } /** * Returns the position of the provided entry in the DataSets Entry array. * Returns -1 if doesnt exist. * * @param e * @return */ public int getEntryPosition(Entry e) { for (int i = 0; i < mYVals.size(); i++) { if (e.equalTo(mYVals.get(i))) return i; } return -1; } // /** // * Convenience method to create multiple DataSets of different types with // * various double value arrays. Each double array represents the data of // one // * DataSet with a type created by this method, starting at 0 (and // * incremented). // * // * @param yValues // * @return // */ // public static ArrayList<DataSet> makeDataSets(ArrayList<Double[]> // yValues) { // // ArrayList<DataSet> dataSets = new ArrayList<DataSet>(); // // for (int i = 0; i < yValues.size(); i++) { // // Double[] curValues = yValues.get(i); // // ArrayList<Entry> entries = new ArrayList<Entry>(); // // for (int j = 0; j < curValues.length; j++) { // entries.add(new Entry(curValues[j].floatValue(), j)); // } // // dataSets.add(new DataSet(entries, "DS " + i)); // } // // return dataSets; // } }