Skip to content

Commit e106289

Browse files
committed
Improved highlight for scatter/bubble, and fixes highlightValueWithX
1 parent 8d65596 commit e106289

19 files changed

Lines changed: 242 additions & 137 deletions

File tree

MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ private void removeLastEntry() {
8787

8888
if (set != null) {
8989

90-
Entry e = set.getEntryForXValue(set.getEntryCount() - 1);
90+
Entry e = set.getEntryForXValue(set.getEntryCount() - 1, Float.NaN);
9191

9292
data.removeEntry(e, 0);
9393
// or remove by index

MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -535,8 +535,8 @@ protected void setLastHighlighted(Highlight[] highs) {
535535
/**
536536
* Highlights the values at the given indices in the given DataSets. Provide
537537
* null or an empty array to undo all highlighting. This should be used to
538-
* programmatically highlight values. This DOES NOT generate a callback to
539-
* the OnChartValueSelectedListener.
538+
* programmatically highlight values.
539+
* This method *will not* call the listener.
540540
*
541541
* @param highs
542542
*/
@@ -552,35 +552,59 @@ public void highlightValues(Highlight[] highs) {
552552
}
553553

554554
/**
555-
* Highlights the value at the given x-value in the given DataSet. Provide
556-
* -1 as the dataSetIndex to undo all highlighting. This will trigger a callback to the OnChartValueSelectedListener.
557-
*
558-
* @param x
559-
* @param dataSetIndex
555+
* Highlights any y-value at the given x-value in the given DataSet.
556+
* Provide -1 as the dataSetIndex to undo all highlighting.
557+
* This method will call the listener.
558+
* @param x The x-value to highlight
559+
* @param dataSetIndex The dataset index to search in
560560
*/
561561
public void highlightValue(float x, int dataSetIndex) {
562562
highlightValue(x, dataSetIndex, true);
563563
}
564564

565565
/**
566-
* Highlights the value at the given x-value in the given DataSet. Provide
567-
* -1 as the dataSetIndex to undo all highlighting.
568-
*
569-
* @param x
570-
* @param dataSetIndex
566+
* Highlights the value at the given x-value and y-value in the given DataSet.
567+
* Provide -1 as the dataSetIndex to undo all highlighting.
568+
* This method will call the listener.
569+
* @param x The x-value to highlight
570+
* @param y The y-value to highlight. Supply `NaN` for "any"
571+
* @param dataSetIndex The dataset index to search in
572+
*/
573+
public void highlightValue(float x, float y, int dataSetIndex) {
574+
highlightValue(x, y, dataSetIndex, true);
575+
}
576+
577+
/**
578+
* Highlights any y-value at the given x-value in the given DataSet.
579+
* Provide -1 as the dataSetIndex to undo all highlighting.
580+
* @param x The x-value to highlight
581+
* @param dataSetIndex The dataset index to search in
582+
* @param callListener Should the listener be called for this change
571583
*/
572584
public void highlightValue(float x, int dataSetIndex, boolean callListener) {
585+
highlightValue(x, Float.NaN, dataSetIndex, callListener);
586+
}
587+
588+
/**
589+
* Highlights any y-value at the given x-value in the given DataSet.
590+
* Provide -1 as the dataSetIndex to undo all highlighting.
591+
* @param x The x-value to highlight
592+
* @param y The y-value to highlight. Supply `NaN` for "any"
593+
* @param dataSetIndex The dataset index to search in
594+
* @param callListener Should the listener be called for this change
595+
*/
596+
public void highlightValue(float x, float y, int dataSetIndex, boolean callListener) {
573597

574598
if (dataSetIndex < 0 || dataSetIndex >= mData.getDataSetCount()) {
575599
highlightValue(null, callListener);
576600
} else {
577-
highlightValue(new Highlight(x, dataSetIndex), callListener);
601+
highlightValue(new Highlight(x, y, dataSetIndex), callListener);
578602
}
579603
}
580604

581605
/**
582606
* Highlights the values represented by the provided Highlight object
583-
* This DOES NOT generate a callback to the OnChartValueSelectedListener.
607+
* This method *will not* call the listener.
584608
*
585609
* @param highlight contains information about which entry should be highlighted
586610
*/

MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ public int getDataSetIndexForIndex(int xIndex) {
328328
List<IPieDataSet> dataSets = mData.getDataSets();
329329

330330
for (int i = 0; i < dataSets.size(); i++) {
331-
if (dataSets.get(i).getEntryForXValue(xIndex) != null)
331+
if (dataSets.get(i).getEntryForXValue(xIndex, Float.NaN) != null)
332332
return i;
333333
}
334334

MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,7 @@ public boolean removeLast() {
432432
@Override
433433
public boolean removeEntryByXValue(float xValue) {
434434

435-
T e = getEntryForXValue(xValue);
435+
T e = getEntryForXValue(xValue, Float.NaN);
436436
return removeEntry(e);
437437
}
438438

MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ public Entry getEntryForHighlight(Highlight highlight) {
338338
if (highlight.getDataSetIndex() >= mDataSets.size())
339339
return null;
340340
else {
341-
return mDataSets.get(highlight.getDataSetIndex()).getEntryForXValue(highlight.getX());
341+
return mDataSets.get(highlight.getDataSetIndex()).getEntryForXValue(highlight.getX(), highlight.getY());
342342
}
343343
}
344344

@@ -550,7 +550,7 @@ public boolean removeEntry(float xValue, int dataSetIndex) {
550550
return false;
551551

552552
IDataSet dataSet = mDataSets.get(dataSetIndex);
553-
Entry e = dataSet.getEntryForXValue(xValue);
553+
Entry e = dataSet.getEntryForXValue(xValue, Float.NaN);
554554

555555
if (e == null)
556556
return false;
@@ -575,7 +575,7 @@ public T getDataSetForEntry(Entry e) {
575575
T set = mDataSets.get(i);
576576

577577
for (int j = 0; j < set.getEntryCount(); j++) {
578-
if (e.equalTo(set.getEntryForXValue(e.getX())))
578+
if (e.equalTo(set.getEntryForXValue(e.getX(), e.getY())))
579579
return set;
580580
}
581581
}

MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java

Lines changed: 48 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,8 @@ public void calcMinMaxY(float fromX, float toX) {
8383
mYMax = -Float.MAX_VALUE;
8484
mYMin = Float.MAX_VALUE;
8585

86-
int indexFrom = getEntryIndex(fromX, Rounding.DOWN);
87-
int indexTo = getEntryIndex(toX, Rounding.UP);
86+
int indexFrom = getEntryIndex(fromX, Float.NaN, Rounding.DOWN);
87+
int indexTo = getEntryIndex(toX, Float.NaN, Rounding.UP);
8888

8989
for (int i = indexFrom; i <= indexTo; i++) {
9090

@@ -213,7 +213,7 @@ public void addEntryOrdered(T e) {
213213
calcMinMax(e);
214214

215215
if (mValues.size() > 0 && mValues.get(mValues.size() - 1).getX() > e.getX()) {
216-
int closestIndex = getEntryIndex(e.getX(), Rounding.UP);
216+
int closestIndex = getEntryIndex(e.getX(), e.getY(), Rounding.UP);
217217
mValues.add(closestIndex, e);
218218
} else {
219219
mValues.add(e);
@@ -268,17 +268,17 @@ public int getEntryIndex(Entry e) {
268268
}
269269

270270
@Override
271-
public T getEntryForXValue(float xValue, Rounding rounding) {
271+
public T getEntryForXValue(float xValue, float closestToY, Rounding rounding) {
272272

273-
int index = getEntryIndex(xValue, rounding);
273+
int index = getEntryIndex(xValue, closestToY, rounding);
274274
if (index > -1)
275275
return mValues.get(index);
276276
return null;
277277
}
278278

279279
@Override
280-
public T getEntryForXValue(float xValue) {
281-
return getEntryForXValue(xValue, Rounding.CLOSEST);
280+
public T getEntryForXValue(float xValue, float closestToY) {
281+
return getEntryForXValue(xValue, closestToY, Rounding.CLOSEST);
282282
}
283283

284284
@Override
@@ -287,13 +287,14 @@ public T getEntryForIndex(int index) {
287287
}
288288

289289
@Override
290-
public int getEntryIndex(float xValue, Rounding rounding) {
290+
public int getEntryIndex(float xValue, float closestToY, Rounding rounding) {
291291

292292
if (mValues == null || mValues.isEmpty())
293293
return -1;
294294

295295
int low = 0;
296296
int high = mValues.size() - 1;
297+
int closest = high;
297298

298299
while (low < high) {
299300
int m = (low + high) / 2;
@@ -321,22 +322,53 @@ public int getEntryIndex(float xValue, Rounding rounding) {
321322
low = m + 1;
322323
}
323324
}
325+
326+
closest = high;
324327
}
325328

326-
if (high != -1) {
327-
float closestXValue = mValues.get(high).getX();
329+
if (closest != -1) {
330+
float closestXValue = mValues.get(closest).getX();
328331
if (rounding == Rounding.UP) {
329-
if (closestXValue < xValue && high < mValues.size() - 1) {
330-
++high;
332+
// If rounding up, and found x-value is lower than specified x, and we can go upper...
333+
if (closestXValue < xValue && closest < mValues.size() - 1) {
334+
++closest;
331335
}
332336
} else if (rounding == Rounding.DOWN) {
333-
if (closestXValue > xValue && high > 0) {
334-
--high;
337+
// If rounding down, and found x-value is upper than specified x, and we can go lower...
338+
if (closestXValue > xValue && closest > 0) {
339+
--closest;
335340
}
336341
}
342+
343+
// Search by closest to y-value
344+
if (!Float.isNaN(closestToY)) {
345+
while (closest > 0 && mValues.get(closest - 1).getX() == closestXValue)
346+
closest -= 1;
347+
348+
float closestYValue = mValues.get(closest).getY();
349+
int closestYIndex = closest;
350+
351+
while (true) {
352+
closest += 1;
353+
if (closest >= mValues.size())
354+
break;
355+
356+
final Entry value = mValues.get(closest);
357+
358+
if (value.getX() != closestXValue)
359+
break;
360+
361+
if (Math.abs(value.getY() - closestToY) < Math.abs(closestYValue - closestToY)) {
362+
closestYValue = closestToY;
363+
closestYIndex = closest;
364+
}
365+
}
366+
367+
closest = closestYIndex;
368+
}
337369
}
338370

339-
return high;
371+
return closest;
340372
}
341373

342374
@Override
@@ -382,7 +414,7 @@ public List<T> getEntriesForXValue(float xValue) {
382414

383415
/**
384416
* Determines how to round DataSet index values for
385-
* {@link DataSet#getEntryIndex(float, Rounding)} DataSet.getEntryIndex()}
417+
* {@link DataSet#getEntryIndex(float, float, Rounding)} DataSet.getEntryIndex()}
386418
* when an exact x-index is not found.
387419
*/
388420
public enum Rounding {

MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public Highlight getHighlight(float x, float y) {
5454
*/
5555
public Highlight getStackedHighlight(Highlight high, IBarDataSet set, float xVal, float yVal) {
5656

57-
BarEntry entry = set.getEntryForXValue(xVal);
57+
BarEntry entry = set.getEntryForXValue(xVal, yVal);
5858

5959
if (entry == null)
6060
return null;

MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -142,35 +142,51 @@ protected List<Highlight> getHighlightsAtXValue(float xVal, float x, float y) {
142142
if (!dataSet.isHighlightEnabled())
143143
continue;
144144

145-
Highlight high = buildHighlight(dataSet, i, xVal, DataSet.Rounding.CLOSEST);
146-
147-
if(high != null)
148-
mHighlightBuffer.add(high);
149-
//vals.add(buildHighlight(dataSet, i, xVal, DataSet.Rounding.DOWN));
145+
mHighlightBuffer.addAll(buildHighlights(dataSet, i, xVal, DataSet.Rounding.CLOSEST));
150146
}
151147

152148
return mHighlightBuffer;
153149
}
154150

155151
/**
156-
* Returns the Highlight object corresponding to the selected xValue and dataSetIndex.
152+
* An array of `Highlight` objects corresponding to the selected xValue and dataSetIndex.
157153
*
158154
* @param set
159155
* @param dataSetIndex
160156
* @param xVal
161157
* @param rounding
162158
* @return
163159
*/
164-
protected Highlight buildHighlight(IDataSet set, int dataSetIndex, float xVal, DataSet.Rounding rounding) {
160+
protected List<Highlight> buildHighlights(IDataSet set, int dataSetIndex, float xVal, DataSet.Rounding rounding) {
161+
162+
ArrayList<Highlight> highlights = new ArrayList<>();
163+
164+
//noinspection unchecked
165+
List<Entry> entries = set.getEntriesForXValue(xVal);
166+
if (entries.size() == 0) {
167+
// Try to find closest x-value and take all entries for that x-value
168+
final Entry closest = set.getEntryForXValue(xVal, Float.NaN, rounding);
169+
if (closest != null)
170+
{
171+
//noinspection unchecked
172+
entries = set.getEntriesForXValue(closest.getX());
173+
}
174+
}
165175

166-
final Entry e = set.getEntryForXValue(xVal, rounding);
176+
if (entries.size() == 0)
177+
return highlights;
167178

168-
if (e == null)
169-
return null;
179+
for (Entry e : entries) {
180+
MPPointD pixels = mChart.getTransformer(
181+
set.getAxisDependency()).getPixelForValues(e.getX(), e.getY());
170182

171-
MPPointD pixels = mChart.getTransformer(set.getAxisDependency()).getPixelForValues(e.getX(), e.getY());
183+
highlights.add(new Highlight(
184+
e.getX(), e.getY(),
185+
(float) pixels.x, (float) pixels.y,
186+
dataSetIndex, set.getAxisDependency()));
187+
}
172188

173-
return new Highlight(e.getX(), e.getY(), (float) pixels.x, (float) pixels.y, dataSetIndex, set.getAxisDependency());
189+
return highlights;
174190
}
175191

176192
/**

MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,12 @@ protected List<Highlight> getHighlightsAtXValue(float xVal, float x, float y) {
5757
if (!dataSet.isHighlightEnabled())
5858
continue;
5959

60-
Highlight s1 = buildHighlight(dataSet, j, xVal, DataSet.Rounding.CLOSEST);
61-
s1.setDataIndex(i);
62-
mHighlightBuffer.add(s1);
63-
64-
// Highlight s2 = buildHighlight(dataSet, j, xVal, DataSet.Rounding.DOWN);
65-
// s2.setDataIndex(i);
66-
// vals.add(s2);
60+
List<Highlight> highs = buildHighlights(dataSet, j, xVal, DataSet.Rounding.CLOSEST);
61+
for (Highlight high : highs)
62+
{
63+
high.setDataIndex(i);
64+
mHighlightBuffer.add(high);
65+
}
6766
}
6867
}
6968
}

MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,14 @@ public class Highlight {
6060
*/
6161
private float mDrawY;
6262

63-
public Highlight(float x, int dataSetIndex) {
63+
public Highlight(float x, float y, int dataSetIndex) {
6464
this.mX = x;
65+
this.mY = y;
6566
this.mDataSetIndex = dataSetIndex;
6667
}
6768

6869
public Highlight(float x, int dataSetIndex, int stackIndex) {
69-
this(x, dataSetIndex);
70+
this(x, Float.NaN, dataSetIndex);
7071
this.mStackIndex = stackIndex;
7172
}
7273

0 commit comments

Comments
 (0)