Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ public Highlight getHighlightByTouchPoint(float x, float y) {
// For isHighlightFullBarEnabled, remove stackIndex
return new Highlight(h.getX(), h.getY(),
h.getXPx(), h.getYPx(),
h.getDataIndex(),
h.getDataSetIndex(), -1, h.getAxis());
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,16 @@ public abstract class AxisBase extends ComponentBase {
*/
public float mAxisRange = 0f;

/**
* if true, then labels are displayed using specificLabelPositions instead of computed ones
*/
private boolean showSpecificLabelPositions = false;

/**
* specify to which values labels must be displayed. has no effect if not used showSpecificLabelPositions set to true
*/
private float[] specificLabelPositions = new float[]{};

/**
* default constructor
*/
Expand Down Expand Up @@ -779,4 +789,27 @@ public void setSpaceMax(float mSpaceMax)
{
this.mSpaceMax = mSpaceMax;
}

/**
* if set to true, labels will be displayed at the specific positions passed in via setSpecificLabelPositions
*/
public void setShowSpecificLabelPositions(boolean showSpecificLabelPositions)
{
this.showSpecificLabelPositions = showSpecificLabelPositions;
}

public boolean isShowSpecificLabelPositions()
{
return showSpecificLabelPositions;
}

public void setSpecificLabelPositions(float[] specificLabelPositions)
{
this.specificLabelPositions = specificLabelPositions;
}

public float[] getSpecificLabelPositions()
{
return specificLabelPositions;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,8 @@ public T getEntryForXValue(float xValue, float closestToY) {

@Override
public T getEntryForIndex(int index) {
// Avoid an IndexOutOfBoundsException if we try access an item outside out list
if (index >= mValues.size()) return null;
return mValues.get(index);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public class PieDataSet extends DataSet<PieEntry> implements IPieDataSet {
private float mValueLinePart1Length = 0.3f;
private float mValueLinePart2Length = 0.4f;
private boolean mValueLineVariableLength = true;
private float mDrawValuePercentThreshold = 0.0f;

public PieDataSet(List<PieEntry> yVals, String label) {
super(yVals, label);
Expand Down Expand Up @@ -218,6 +219,16 @@ public void setValueLineVariableLength(boolean valueLineVariableLength) {
this.mValueLineVariableLength = valueLineVariableLength;
}

/** Draw values on chart if the percent value is equal to or exceeds this percent threshold */
@Override public float getDrawValuePercentThreshold() {
return mDrawValuePercentThreshold;
}

public void setDrawValuePercentThreshold(float drawValuePercentThreshold)
{
this.mDrawValuePercentThreshold = drawValuePercentThreshold;
}

public enum ValuePosition {
INSIDE_SLICE,
OUTSIDE_SLICE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,22 @@ public Highlight(float x, float y, float xPx, float yPx, int dataSetIndex, int s
this.mStackIndex = stackIndex;
}

/**
* Constructor, only used for for Combined Chart.
*
* @param x the index of the highlighted value on the x-axis
* @param y the y-value of the highlighted value
* @param dataIndex the index of the highlighted data entry
* @param dataSetIndex the index of the DataSet the highlighted value belongs to
* @param stackIndex references which value of a stacked-bar entry has been
* selected
*/
public Highlight(float x, float y, float xPx, float yPx, int dataIndex, int dataSetIndex, int stackIndex, YAxis.AxisDependency axis) {
this(x, y, xPx, yPx, dataSetIndex, axis);
this.mStackIndex = stackIndex;
this.mDataIndex = dataIndex;
}

/**
* returns the x-value of the highlighted value
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,5 +70,9 @@ public interface IPieDataSet extends IDataSet<PieEntry> {
* */
boolean isValueLineVariableLength();

/**
* Draw values on chart if the percent value is equal to or exceeds this threshold
* */
float getDrawValuePercentThreshold();
}

Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,22 @@ public class LineChartRenderer extends LineRadarRenderer {
protected Path cubicPath = new Path();
protected Path cubicFillPath = new Path();

// Andromeda Additions
private float noDataValue = Float.NaN;
private float noDataTransitionWidth = 0.33f; // As a percent of the normal entry width
public void setNoDataValue(float noDataValue) {
this.noDataValue = noDataValue;
}
public void setNoDataTransitionWidth(float noDataTransitionWidth) {
this.noDataTransitionWidth = noDataTransitionWidth;
}
private float getAdjustedY(Entry entry, float fillMin) {
return (isNoDataValue(entry) ? fillMin : entry.getY());
}
private boolean isNoDataValue(Entry entry) {
return (entry == null || entry.getY() == noDataValue);
}

public LineChartRenderer(LineDataProvider chart, ChartAnimator animator,
ViewPortHandler viewPortHandler) {
super(animator, viewPortHandler);
Expand Down Expand Up @@ -394,24 +410,48 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) {

if (e1 == null || e2 == null) continue;

if (isNoDataValue(e1) || (!isDrawSteppedEnabled && isNoDataValue(e2))) {
// If the previous sample is valid but the current one is not
if(!isNoDataValue(e1) && isNoDataValue(e2)) {
// Draw a no data transition leaving the previous entry
mLineBuffer[j++] = e1.getX();
mLineBuffer[j++] = e1.getY() * phaseY;
mLineBuffer[j++] = e1.getX() + noDataTransitionWidth;
mLineBuffer[j++] = e1.getY() * phaseY;
}
// If the previous sample was not valid and the current one is valid
else if(isNoDataValue(e1) && !isNoDataValue(e2) && !isDrawSteppedEnabled) {
// Draw a no data transition entering the current entry
mLineBuffer[j++] = e2.getX() - noDataTransitionWidth;
mLineBuffer[j++] = e2.getY() * phaseY;
mLineBuffer[j++] = e2.getX();
mLineBuffer[j++] = e2.getY() * phaseY;
}
continue;
}

mLineBuffer[j++] = e1.getX();
mLineBuffer[j++] = e1.getY() * phaseY;

if (isDrawSteppedEnabled) {
mLineBuffer[j++] = e2.getX();
mLineBuffer[j++] = e1.getY() * phaseY;
mLineBuffer[j++] = e2.getX();
mLineBuffer[j++] = e1.getY() * phaseY;
if (!isNoDataValue(e2)) {
mLineBuffer[j++] = e2.getX();
mLineBuffer[j++] = e1.getY() * phaseY;
}
}

mLineBuffer[j++] = e2.getX();
mLineBuffer[j++] = e2.getY() * phaseY;
if (!isNoDataValue(e2)) {
mLineBuffer[j++] = e2.getX();
mLineBuffer[j++] = e2.getY() * phaseY;
}
}

if (j > 0) {
trans.pointValuesToPixel(mLineBuffer);

final int size = Math.max((mXBounds.range + 1) * pointsPerEntryPair, pointsPerEntryPair) * 2;
final int size = j; // Math.max((mXBounds.range + 1) * pointsPerEntryPair, pointsPerEntryPair) * 2;

mRenderPaint.setColor(dataSet.getColor());

Expand Down Expand Up @@ -493,7 +533,7 @@ private void generateFilledPath(final ILineDataSet dataSet, final int startIndex
final Entry entry = dataSet.getEntryForIndex(startIndex);

filled.moveTo(entry.getX(), fillMin);
filled.lineTo(entry.getX(), entry.getY() * phaseY);
filled.lineTo(entry.getX(), getAdjustedY(entry, fillMin) * phaseY);

// create a new path
Entry currentEntry = null;
Expand All @@ -502,12 +542,28 @@ private void generateFilledPath(final ILineDataSet dataSet, final int startIndex

currentEntry = dataSet.getEntryForIndex(x);

// Changes to show gaps for no data. Note: The stepped and non-stepped implementations
// are similar and could be optimized for code size however That will make each code path
// harder to follow.
if (isDrawSteppedEnabled) {
filled.lineTo(currentEntry.getX(), previousEntry.getY() * phaseY);
filled.lineTo(currentEntry.getX(), getAdjustedY(previousEntry, fillMin) * phaseY);
filled.lineTo(currentEntry.getX(), getAdjustedY(currentEntry, fillMin) * phaseY);
} else {
if (isNoDataValue(previousEntry)) {
if (!isNoDataValue(currentEntry)) {
filled.lineTo(currentEntry.getX() - noDataTransitionWidth, getAdjustedY(previousEntry, fillMin) * phaseY);
filled.lineTo(currentEntry.getX() - noDataTransitionWidth, getAdjustedY(currentEntry, fillMin) * phaseY);
}
else {
filled.lineTo(currentEntry.getX(), getAdjustedY(previousEntry, fillMin) * phaseY);
}
} else if (isNoDataValue(currentEntry)) {
filled.lineTo(previousEntry.getX() + noDataTransitionWidth, getAdjustedY(previousEntry, fillMin) * phaseY);
filled.lineTo(previousEntry.getX() + noDataTransitionWidth, fillMin * phaseY);
}
filled.lineTo(currentEntry.getX(), getAdjustedY(currentEntry, fillMin) * phaseY);
}

filled.lineTo(currentEntry.getX(), currentEntry.getY() * phaseY);

previousEntry = currentEntry;
}

Expand Down Expand Up @@ -571,7 +627,7 @@ public void drawValues(Canvas c) {
drawValue(c, formatter.getPointLabel(entry), x, y - valOffset, dataSet.getValueTextColor(j / 2));
}

if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) {
if (entry != null && entry.getIcon() != null && dataSet.isDrawIconsEnabled()) {

Drawable icon = entry.getIcon();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,12 @@ public void drawValues(Canvas c) {
String formattedValue = formatter.getPieLabel(value, entry);
String entryLabel = entry.getLabel();

// Do not draw text if percent value is less than the threshold
if (entry.getY() / yValueSum * 100f < dataSet.getDrawValuePercentThreshold()) {
xIndex++;
continue;
}

final float sliceXBase = (float) Math.cos(transformedAngle * Utils.FDEG2RAD);
final float sliceYBase = (float) Math.sin(transformedAngle * Utils.FDEG2RAD);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,13 +183,20 @@ protected void drawLabels(Canvas c, float pos, MPPointF anchor) {

float[] positions = new float[mXAxis.mEntryCount * 2];

for (int i = 0; i < positions.length; i += 2) {

// only fill x values
if (centeringEnabled) {
positions[i] = mXAxis.mCenteredEntries[i / 2];
} else {
positions[i] = mXAxis.mEntries[i / 2];
if (mXAxis.isShowSpecificLabelPositions()) {
positions = new float[mXAxis.getSpecificLabelPositions().length * 2];
for (int i = 0; i < positions.length; i += 2) {
positions[i] = mXAxis.getSpecificLabelPositions()[i / 2];
}
} else {
for (int i = 0; i < positions.length; i += 2) {

// only fill x values
if (centeringEnabled) {
positions[i] = mXAxis.mCenteredEntries[i / 2];
} else {
positions[i] = mXAxis.mEntries[i / 2];
}
}
}

Expand All @@ -201,7 +208,9 @@ protected void drawLabels(Canvas c, float pos, MPPointF anchor) {

if (mViewPortHandler.isInBoundsX(x)) {

String label = mXAxis.getValueFormatter().getAxisLabel(mXAxis.mEntries[i / 2], mXAxis);
String label = mXAxis.isShowSpecificLabelPositions() ?
mXAxis.getValueFormatter().getAxisLabel(mXAxis.getSpecificLabelPositions()[i / 2], mXAxis)
: mXAxis.getValueFormatter().getAxisLabel(mXAxis.mEntries[i / 2], mXAxis);

if (mXAxis.isAvoidFirstLastClippingEnabled()) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,23 @@ public void renderAxisLine(Canvas c) {
*/
protected void drawYLabels(Canvas c, float fixedPosition, float[] positions, float offset) {

if (mYAxis.isShowSpecificLabelPositions()) {
float[] specificLabelsPositions = new float[mYAxis.getSpecificLabelPositions().length * 2];
for (int i = 0; i < mYAxis.getSpecificLabelPositions().length; i++) {
specificLabelsPositions[i * 2 + 1] = mYAxis.getSpecificLabelPositions()[i];
}
mTrans.pointValuesToPixel(specificLabelsPositions);

for (int i = 0; i < mYAxis.getSpecificLabelPositions().length; i++) {
float y = specificLabelsPositions[i * 2 + 1];
if (mViewPortHandler.isInBoundsY(y)) {
String text = mYAxis.getValueFormatter().getFormattedValue(mYAxis.getSpecificLabelPositions()[i], mYAxis);
c.drawText(text, fixedPosition, y + offset, mAxisLabelPaint);
}
}
return;
}

final int from = mYAxis.isDrawBottomYLabelEntryEnabled() ? 0 : 1;
final int to = mYAxis.isDrawTopYLabelEntryEnabled()
? mYAxis.mEntryCount
Expand Down