package com.github.mikephil.charting.highlight;
import com.github.mikephil.charting.data.BarData;
import com.github.mikephil.charting.data.BarEntry;
import com.github.mikephil.charting.data.BarLineScatterCandleBubbleData;
import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider;
import com.github.mikephil.charting.interfaces.datasets.IBarDataSet;
import com.github.mikephil.charting.utils.MPPointD;
/**
* Created by Philipp Jahoda on 22/07/15.
*/
public class BarHighlighter extends ChartHighlighter<BarDataProvider> {
public BarHighlighter(BarDataProvider chart) {
super(chart);
}
@Override
public Highlight getHighlight(float x, float y) {
Highlight high = super.getHighlight(x, y);
if(high == null) {
return null;
}
MPPointD pos = getValsForTouch(x, y);
BarData barData = mChart.getBarData();
IBarDataSet set = barData.getDataSetByIndex(high.getDataSetIndex());
if (set.isStacked()) {
return getStackedHighlight(high,
set,
(float) pos.x,
(float) pos.y);
}
MPPointD.recycleInstance(pos);
return high;
}
/**
* This method creates the Highlight object that also indicates which value of a stacked BarEntry has been
* selected.
*
* @param high the Highlight to work with looking for stacked values
* @param set
* @param xVal
* @param yVal
* @return
*/
public Highlight getStackedHighlight(Highlight high, IBarDataSet set, float xVal, float yVal) {
BarEntry entry = set.getEntryForXValue(xVal, yVal);
if (entry == null)
return null;
// not stacked
if (entry.getYVals() == null) {
return high;
} else {
Range[] ranges = entry.getRanges();
if (ranges.length > 0) {
int stackIndex = getClosestStackIndex(ranges, yVal);
MPPointD pixels = mChart.getTransformer(set.getAxisDependency()).getPixelForValues(high.getX(), ranges[stackIndex].to);
Highlight stackedHigh = new Highlight(
entry.getX(),
entry.getY(),
(float) pixels.x,
(float) pixels.y,
high.getDataSetIndex(),
stackIndex,
high.getAxis()
);
MPPointD.recycleInstance(pixels);
return stackedHigh;
}
}
return null;
}
/**
* Returns the index of the closest value inside the values array / ranges (stacked barchart) to the value
* given as
* a parameter.
*
* @param ranges
* @param value
* @return
*/
protected int getClosestStackIndex(Range[] ranges, float value) {
if (ranges == null || ranges.length == 0)
return 0;
int stackIndex = 0;
for (Range range : ranges) {
if (range.contains(value))
return stackIndex;
else
stackIndex++;
}
int length = Math.max(ranges.length - 1, 0);
return (value > ranges[length].to) ? length : 0;
}
// /**
// * Splits up the stack-values of the given bar-entry into Range objects.
// *
// * @param entry
// * @return
// */
// protected Range[] getRanges(BarEntry entry) {
//
// float[] values = entry.getYVals();
//
// if (values == null || values.length == 0)
// return new Range[0];
//
// Range[] ranges = new Range[values.length];
//
// float negRemain = -entry.getNegativeSum();
// float posRemain = 0f;
//
// for (int i = 0; i < ranges.length; i++) {
//
// float value = values[i];
//
// if (value < 0) {
// ranges[i] = new Range(negRemain, negRemain + Math.abs(value));
// negRemain += Math.abs(value);
// } else {
// ranges[i] = new Range(posRemain, posRemain + value);
// posRemain += value;
// }
// }
//
// return ranges;
// }
@Override
protected float getDistance(float x1, float y1, float x2, float y2) {
return Math.abs(x1 - x2);
}
@Override
protected BarLineScatterCandleBubbleData getData() {
return mChart.getBarData();
}
}