forked from PhilJay/MPAndroidChart
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDataSet.java
More file actions
770 lines (641 loc) · 19.2 KB
/
DataSet.java
File metadata and controls
770 lines (641 loc) · 19.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
package com.github.mikephil.charting.data;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Typeface;
import com.github.mikephil.charting.components.YAxis.AxisDependency;
import com.github.mikephil.charting.utils.ColorTemplate;
import com.github.mikephil.charting.utils.DefaultValueFormatter;
import com.github.mikephil.charting.utils.Utils;
import com.github.mikephil.charting.utils.ValueFormatter;
import java.util.ArrayList;
import java.util.List;
/**
* 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> {
/** List representing all colors that are used for this DataSet */
protected List<Integer> mColors = null;
/** the entries that this dataset represents / holds together */
protected List<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;
/** the last start value used for calcMinMax */
protected int mLastStart = 0;
/** the last end value used for calcMinMax */
protected int mLastEnd = 0;
/** label that describes the DataSet or the data the DataSet represents */
private String mLabel = "DataSet";
/** flag that indicates if the DataSet is visible or not */
private boolean mVisible = true;
/** if true, y-values are drawn on the chart */
protected boolean mDrawValues = true;
/** the color used for the value-text */
private int mValueColor = Color.BLACK;
/** the size of the value-text labels */
private float mValueTextSize = 17f;
/** the typeface used for the value text */
private Typeface mValueTypeface;
/** custom formatter that is used instead of the auto-formatter if set */
protected ValueFormatter mValueFormatter;
/** this specifies which axis this DataSet should be plotted against */
protected AxisDependency mAxisDependency = AxisDependency.LEFT;
/** if true, value highlightning is enabled */
protected boolean mHighlightEnabled = true;
/**
* 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(List<T> yVals, String label) {
this.mLabel = label;
this.mYVals = yVals;
if (mYVals == null)
mYVals = new ArrayList<T>();
mColors = new ArrayList<Integer>();
// default color
mColors.add(Color.rgb(140, 234, 255));
calcMinMax(mLastStart, mLastEnd);
calcYValueSum();
}
/**
* Use this method to tell the data set that the underlying data has changed
*/
public void notifyDataSetChanged() {
calcMinMax(mLastStart, mLastEnd);
calcYValueSum();
}
/**
* calc minimum and maximum y value
*/
protected void calcMinMax(int start, int end) {
if (mYVals.size() == 0)
return;
int endValue;
if (end == 0)
endValue = mYVals.size() - 1;
else
endValue = end;
mLastStart = start;
mLastEnd = endValue;
mYMin = Float.MAX_VALUE;
mYMax = Float.MIN_VALUE;
for (int i = start; i <= endValue; i++) {
Entry e = mYVals.get(i);
if (e != null && !Float.isNaN(e.getVal())) {
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 && e.getXIndex() == xIndex)
return e.getVal();
else
return Float.NaN;
}
/**
* Returns the first Entry object found at the given xIndex with binary
* search. If the no Entry at the specifed x-index is found, this method
* returns the Entry at the closest x-index. 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;
T closest = null;
while (low <= high) {
int m = (high + low) / 2;
if (x == mYVals.get(m).getXIndex()) {
while (m > 0 && mYVals.get(m - 1).getXIndex() == x)
m--;
return mYVals.get(m);
}
if (x > mYVals.get(m).getXIndex())
low = m + 1;
else
high = m - 1;
closest = mYVals.get(m);
}
return closest;
}
/**
* 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 List<T> getEntriesForXIndex(int x) {
List<T> entries = new ArrayList<T>();
int low = 0;
int high = mYVals.size() - 1;
while (low <= high) {
int m = (high + low) / 2;
T entry = mYVals.get(m);
if (x == entry.getXIndex()) {
while (m > 0 && mYVals.get(m - 1).getXIndex() == x)
m--;
high = mYVals.size();
for (; m < high; m++)
{
entry = mYVals.get(m);
if (entry.getXIndex() == x)
{
entries.add(entry);
}
else
{
break;
}
}
}
if (x > entry.getXIndex())
low = m + 1;
else
high = m - 1;
}
return entries;
}
/**
* returns the DataSets Entry array
*
* @return
*/
public List<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 number of entries this DataSet holds.
*
* @return
*/
public int getValueCount() {
return mYVals.size();
}
/**
* 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 == null ? "" : mLabel) + ", entries: " + mYVals.size() + "\n");
return buffer.toString();
}
/**
* Sets the label string that describes the DataSet.
*
* @return
*/
public void setLabel(String label) {
mLabel = label;
}
/**
* Returns the label string that describes the DataSet.
*
* @return
*/
public String getLabel() {
return mLabel;
}
/**
* Set the visibility of this DataSet. If not visible, the DataSet will not
* be drawn to the chart upon refreshing it.
*
* @param visible
*/
public void setVisible(boolean visible) {
mVisible = visible;
}
/**
* Returns true if this DataSet is visible inside the chart, or false if it
* is currently hidden.
*
* @return
*/
public boolean isVisible() {
return mVisible;
}
/**
* Returns the axis this DataSet should be plotted against.
*
* @return
*/
public AxisDependency getAxisDependency() {
return mAxisDependency;
}
/**
* Set the y-axis this DataSet should be plotted against (either LEFT or
* RIGHT). Default: LEFT
*
* @param dependency
*/
public void setAxisDependency(AxisDependency dependency) {
mAxisDependency = dependency;
}
/**
* set this to true to draw y-values on the chart NOTE (for bar and
* linechart): if "maxvisiblecount" is reached, no values will be drawn even
* if this is enabled
*
* @param enabled
*/
public void setDrawValues(boolean enabled) {
this.mDrawValues = enabled;
}
/**
* returns true if y-value drawing is enabled, false if not
*
* @return
*/
public boolean isDrawValuesEnabled() {
return mDrawValues;
}
/**
* 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
*/
@SuppressWarnings("unchecked")
public void addEntry(Entry e) {
if (e == null)
return;
float val = e.getVal();
if (mYVals == null) {
mYVals = new ArrayList<T>();
}
if (mYVals.size() == 0) {
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(mLastStart, mLastEnd);
}
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(List<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) {
List<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 List<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>();
}
/**
* If set to true, value highlighting is enabled which means that values can
* be highlighted programmatically or by touch gesture.
*
* @param enabled
*/
public void setHighlightEnabled(boolean enabled) {
mHighlightEnabled = enabled;
}
/**
* returns true if highlighting of values is enabled, false if not
*
* @return
*/
public boolean isHighlightEnabled() {
return mHighlightEnabled;
}
/**
* Returns the position of the provided entry in the DataSets Entry array.
* Returns -1 if doesn't 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;
}
/**
* Sets the formatter to be used for drawing the values inside the chart. If
* no formatter is set, the chart will automatically determine a reasonable
* formatting (concerning decimals) for all the values that are drawn inside
* the chart. Use chart.getDefaultValueFormatter() to use the formatter
* calculated by the chart.
*
* @param f
*/
public void setValueFormatter(ValueFormatter f) {
if (f == null)
return;
else
mValueFormatter = f;
}
/**
* Returns the formatter used for drawing the values inside the chart.
*
* @return
*/
public ValueFormatter getValueFormatter() {
if (mValueFormatter == null)
return new DefaultValueFormatter(1);
return mValueFormatter;
}
/**
* If this component has no ValueFormatter or is only equipped with the
* default one (no custom set), return true.
*
* @return
*/
public boolean needsDefaultFormatter() {
if (mValueFormatter == null)
return true;
if (mValueFormatter instanceof DefaultValueFormatter)
return true;
return false;
}
/**
* Sets the color the value-labels of this DataSet should have.
*
* @param color
*/
public void setValueTextColor(int color) {
mValueColor = color;
}
public int getValueTextColor() {
return mValueColor;
}
/**
* Sets a Typeface for the value-labels of this DataSet.
*
* @param tf
*/
public void setValueTypeface(Typeface tf) {
mValueTypeface = tf;
}
public Typeface getValueTypeface() {
return mValueTypeface;
}
/**
* Sets the text-size of the value-labels of this DataSet in dp.
*
* @param size
*/
public void setValueTextSize(float size) {
mValueTextSize = Utils.convertDpToPixel(size);
}
/**
* Returns the text-size of the labels that are displayed above the values.
*
* @return
*/
public float getValueTextSize() {
return mValueTextSize;
}
/**
* Checks if this DataSet contains the specified Entry. Returns true if so,
* false if not. NOTE: Performance is pretty bad on this one, do not
* over-use in performance critical situations.
*
* @param e
* @return
*/
public boolean contains(Entry e) {
for (Entry entry : mYVals) {
if (entry.equals(e))
return true;
}
return false;
}
/**
* Removes all values from this DataSet and recalculates min and max value.
*/
public void clear() {
mYVals.clear();
mLastStart = 0;
mLastEnd = 0;
notifyDataSetChanged();
}
}