diff options
author | Daniel Cohen Gindi <danielgindi@gmail.com> | 2020-01-24 11:35:47 +0200 |
---|---|---|
committer | Daniel Cohen Gindi <danielgindi@gmail.com> | 2020-01-24 12:52:27 +0200 |
commit | c0e7f56b5d816c08fd6e238c9e08c6dc1fd6142c (patch) | |
tree | 09cc4e0bc7d45e3bac7052472abedb4d7323a1e5 /MPChartLib/src | |
parent | 351e341ee7498e956c41d307dc2b288223a31821 (diff) | |
download | MPAndroidChart-c0e7f56b5d816c08fd6e238c9e08c6dc1fd6142c.tar.gz |
Implement a more generic Fill class instead of GradientColor
Support HorizontalBarChart too.
Diffstat (limited to 'MPChartLib/src')
9 files changed, 506 insertions, 113 deletions
diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java index 7b7ee5f9..e6563880 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java @@ -4,6 +4,7 @@ package com.github.mikephil.charting.data; import android.graphics.Color; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.utils.Fill; import java.util.ArrayList; import java.util.List; @@ -40,6 +41,8 @@ public class BarDataSet extends BarLineScatterCandleBubbleDataSet<BarEntry> impl */ private String[] mStackLabels = new String[]{}; + protected List<Fill> mFills = null; + public BarDataSet(List<BarEntry> yVals, String label) { super(yVals, label); @@ -69,6 +72,67 @@ public class BarDataSet extends BarLineScatterCandleBubbleDataSet<BarEntry> impl barDataSet.mHighLightAlpha = mHighLightAlpha; } + @Override + public List<Fill> getFills() { + return mFills; + } + + @Override + public Fill getFill(int index) { + return mFills.get(index % mFills.size()); + } + + /** + * This method is deprecated. + * Use getFills() instead. + */ + @Deprecated + public List<Fill> getGradients() { + return mFills; + } + + /** + * This method is deprecated. + * Use getFill(...) instead. + * + * @param index + */ + @Deprecated + public Fill getGradient(int index) { + return getFill(index); + } + + /** + * Sets the start and end color for gradient color, ONLY color that should be used for this DataSet. + * + * @param startColor + * @param endColor + */ + public void setGradientColor(int startColor, int endColor) { + mFills.clear(); + mFills.add(new Fill(startColor, endColor)); + } + + /** + * This method is deprecated. + * Use setFills(...) instead. + * + * @param gradientColors + */ + @Deprecated + public void setGradientColors(List<Fill> gradientColors) { + this.mFills = gradientColors; + } + + /** + * Sets the fills for the bars in this dataset. + * + * @param fills + */ + public void setFills(List<Fill> fills) { + this.mFills = fills; + } + /** * Calculates the total number of entries this DataSet represents, including * stacks. All values belonging to a stack are calculated separately. diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java index 8ca3e68d..a4279629 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java @@ -9,7 +9,6 @@ import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.interfaces.datasets.IDataSet; -import com.github.mikephil.charting.model.GradientColor; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.Utils; @@ -29,10 +28,6 @@ public abstract class BaseDataSet<T extends Entry> implements IDataSet<T> { */ protected List<Integer> mColors = null; - protected GradientColor mGradientColor = null; - - protected List<GradientColor> mGradientColors = null; - /** * List representing all colors that are used for drawing the actual values for this DataSet */ @@ -146,21 +141,6 @@ public abstract class BaseDataSet<T extends Entry> implements IDataSet<T> { return mColors.get(index % mColors.size()); } - @Override - public GradientColor getGradientColor() { - return mGradientColor; - } - - @Override - public List<GradientColor> getGradientColors() { - return mGradientColors; - } - - @Override - public GradientColor getGradientColor(int index) { - return mGradientColors.get(index % mGradientColors.size()); - } - /** * ###### ###### COLOR SETTING RELATED METHODS ##### ###### */ @@ -237,25 +217,6 @@ public abstract class BaseDataSet<T extends Entry> implements IDataSet<T> { } /** - * Sets the start and end color for gradient color, ONLY color that should be used for this DataSet. - * - * @param startColor - * @param endColor - */ - public void setGradientColor(int startColor, int endColor) { - mGradientColor = new GradientColor(startColor, endColor); - } - - /** - * Sets the start and end color for gradient colors, ONLY color that should be used for this DataSet. - * - * @param gradientColors - */ - public void setGradientColors(List<GradientColor> gradientColors) { - this.mGradientColors = gradientColors; - } - - /** * Sets a color with a specific alpha value. * * @param color @@ -534,8 +495,6 @@ public abstract class BaseDataSet<T extends Entry> implements IDataSet<T> { baseDataSet.mFormLineDashEffect = mFormLineDashEffect; baseDataSet.mFormLineWidth = mFormLineWidth; baseDataSet.mFormSize = mFormSize; - baseDataSet.mGradientColor = mGradientColor; - baseDataSet.mGradientColors = mGradientColors; baseDataSet.mHighlightEnabled = mHighlightEnabled; baseDataSet.mIconsOffset = mIconsOffset; baseDataSet.mValueColors = mValueColors; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineRadarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineRadarDataSet.java index 688585cb..b4347e46 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineRadarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineRadarDataSet.java @@ -17,6 +17,7 @@ import java.util.List; */ public abstract class LineRadarDataSet<T extends Entry> extends LineScatterCandleRadarDataSet<T> implements ILineRadarDataSet<T> { + // TODO: Move to using `Fill` class /** * the color that is used for filling the line surface */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IBarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IBarDataSet.java index fbdfd795..5e82a484 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IBarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IBarDataSet.java @@ -1,12 +1,19 @@ package com.github.mikephil.charting.interfaces.datasets; import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.utils.Fill; + +import java.util.List; /** * Created by philipp on 21/10/15. */ public interface IBarDataSet extends IBarLineScatterCandleBubbleDataSet<BarEntry> { + List<Fill> getFills(); + + Fill getFill(int index); + /** * Returns true if this DataSet is stacked (stacksize > 1) or not. * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java index 73a54470..ccd4cb4f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java @@ -9,7 +9,6 @@ import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.utils.MPPointF; -import com.github.mikephil.charting.model.GradientColor; import java.util.List; @@ -286,28 +285,6 @@ public interface IDataSet<T extends Entry> { int getColor(); /** - * Returns the Gradient color model - * - * @return - */ - GradientColor getGradientColor(); - - /** - * Returns the Gradient colors - * - * @return - */ - List<GradientColor> getGradientColors(); - - /** - * Returns the Gradient colors - * - * @param index - * @return - */ - GradientColor getGradientColor(int index); - - /** * Returns the color at the given index of the DataSet's color array. * Performs a IndexOutOfBounds check by modulus. * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/model/GradientColor.java b/MPChartLib/src/main/java/com/github/mikephil/charting/model/GradientColor.java index 1162c011..b5c8715a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/model/GradientColor.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/model/GradientColor.java @@ -1,28 +1,69 @@ package com.github.mikephil.charting.model; -public class GradientColor { +import com.github.mikephil.charting.utils.Fill; - private int startColor; - private int endColor; - - public GradientColor(int startColor, int endColor) { - this.startColor = startColor; - this.endColor = endColor; +/** + * Deprecated. Use `Fill` + */ +@Deprecated +public class GradientColor extends Fill +{ + /** + * Deprecated. Use `Fill.getGradientColors()` + */ + @Deprecated + public int getStartColor() + { + return getGradientColors()[0]; } - public int getStartColor() { - return startColor; + /** + * Deprecated. Use `Fill.setGradientColors(...)` + */ + @Deprecated + public void setStartColor(int startColor) + { + if (getGradientColors() == null || getGradientColors().length != 2) + { + setGradientColors(new int[]{ + startColor, + getGradientColors() != null && getGradientColors().length > 1 + ? getGradientColors()[1] + : 0 + }); + } else + { + getGradientColors()[0] = startColor; + } } - public void setStartColor(int startColor) { - this.startColor = startColor; + /** + * Deprecated. Use `Fill.getGradientColors()` + */ + @Deprecated + public int getEndColor() + { + return getGradientColors()[1]; } - public int getEndColor() { - return endColor; + /** + * Deprecated. Use `Fill.setGradientColors(...)` + */ + @Deprecated + public void setEndColor(int endColor) + { + if (getGradientColors() == null || getGradientColors().length != 2) + { + setGradientColors(new int[]{ + getGradientColors() != null && getGradientColors().length > 0 + ? getGradientColors()[0] + : 0, + endColor + }); + } else + { + getGradientColors()[1] = endColor; + } } - public void setEndColor(int endColor) { - this.endColor = endColor; - } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java index b5de65b0..d6ce3898 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -15,12 +15,11 @@ import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.highlight.Range; import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.utils.Fill; import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; -import android.graphics.LinearGradient; -import com.github.mikephil.charting.model.GradientColor; import java.util.List; @@ -145,13 +144,15 @@ public class BarChartRenderer extends BarLineScatterCandleBubbleRenderer { trans.pointValuesToPixel(buffer.buffer); + final boolean isCustomFill = dataSet.getFills().size() > 0; final boolean isSingleColor = dataSet.getColors().size() == 1; + final boolean isInverted = mChart.isInverted(dataSet.getAxisDependency()); if (isSingleColor) { mRenderPaint.setColor(dataSet.getColor()); } - for (int j = 0; j < buffer.size(); j += 4) { + for (int j = 0, pos = 0; j < buffer.size(); j += 4, pos++) { if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[j + 2])) continue; @@ -162,38 +163,24 @@ public class BarChartRenderer extends BarLineScatterCandleBubbleRenderer { if (!isSingleColor) { // Set the color for the currently drawn value. If the index // is out of bounds, reuse colors. - mRenderPaint.setColor(dataSet.getColor(j / 4)); + mRenderPaint.setColor(dataSet.getColor(pos)); } - if (dataSet.getGradientColor() != null) { - GradientColor gradientColor = dataSet.getGradientColor(); - mRenderPaint.setShader( - new LinearGradient( - buffer.buffer[j], - buffer.buffer[j + 3], - buffer.buffer[j], - buffer.buffer[j + 1], - gradientColor.getStartColor(), - gradientColor.getEndColor(), - android.graphics.Shader.TileMode.MIRROR)); + if (isCustomFill) { + dataSet.getFill(pos) + .fillRect( + c, mRenderPaint, + buffer.buffer[j], + buffer.buffer[j + 1], + buffer.buffer[j + 2], + buffer.buffer[j + 3], + isInverted ? Fill.Direction.DOWN : Fill.Direction.UP); } - - if (dataSet.getGradientColors() != null) { - mRenderPaint.setShader( - new LinearGradient( - buffer.buffer[j], - buffer.buffer[j + 3], - buffer.buffer[j], - buffer.buffer[j + 1], - dataSet.getGradientColor(j / 4).getStartColor(), - dataSet.getGradientColor(j / 4).getEndColor(), - android.graphics.Shader.TileMode.MIRROR)); + else { + c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], + buffer.buffer[j + 3], mRenderPaint); } - - c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], - buffer.buffer[j + 3], mRenderPaint); - if (drawBorder) { c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], buffer.buffer[j + 3], mBarBorderPaint); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index b692a1f9..f9431702 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -15,6 +15,7 @@ import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; import com.github.mikephil.charting.interfaces.dataprovider.ChartInterface; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.utils.Fill; import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; @@ -111,13 +112,15 @@ public class HorizontalBarChartRenderer extends BarChartRenderer { trans.pointValuesToPixel(buffer.buffer); + final boolean isCustomFill = dataSet.getFills().size() > 0; final boolean isSingleColor = dataSet.getColors().size() == 1; + final boolean isInverted = mChart.isInverted(dataSet.getAxisDependency()); if (isSingleColor) { mRenderPaint.setColor(dataSet.getColor()); } - for (int j = 0; j < buffer.size(); j += 4) { + for (int j = 0, pos = 0; j < buffer.size(); j += 4, pos++) { if (!mViewPortHandler.isInBoundsTop(buffer.buffer[j + 3])) break; @@ -131,8 +134,20 @@ public class HorizontalBarChartRenderer extends BarChartRenderer { mRenderPaint.setColor(dataSet.getColor(j / 4)); } - c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], - buffer.buffer[j + 3], mRenderPaint); + if (isCustomFill) { + dataSet.getFill(pos) + .fillRect( + c, mRenderPaint, + buffer.buffer[j], + buffer.buffer[j + 1], + buffer.buffer[j + 2], + buffer.buffer[j + 3], + isInverted ? Fill.Direction.LEFT : Fill.Direction.RIGHT); + } + else { + c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], + buffer.buffer[j + 3], mRenderPaint); + } if (drawBorder) { c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Fill.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Fill.java new file mode 100644 index 00000000..d12e1fb8 --- /dev/null +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Fill.java @@ -0,0 +1,342 @@ +package com.github.mikephil.charting.utils; + +import android.graphics.Canvas; +import android.graphics.LinearGradient; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.RectF; +import android.graphics.drawable.Drawable; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +public class Fill +{ + public enum Type + { + EMPTY, COLOR, LINEAR_GRADIENT, DRAWABLE + } + + public enum Direction + { + DOWN, UP, RIGHT, LEFT + } + + /** + * the type of fill + */ + private Type mType = Type.EMPTY; + + /** + * the color that is used for filling + */ + @Nullable + private Integer mColor = null; + + private Integer mFinalColor = null; + + /** + * the drawable to be used for filling + */ + @Nullable + protected Drawable mDrawable; + + @Nullable + private int[] mGradientColors; + + @Nullable + private float[] mGradientPositions; + + /** + * transparency used for filling + */ + private int mAlpha = 255; + + public Fill() + { + } + + public Fill(int color) + { + this.mType = Type.COLOR; + this.mColor = color; + calculateFinalColor(); + } + + public Fill(int startColor, int endColor) + { + this.mType = Type.LINEAR_GRADIENT; + this.mGradientColors = new int[]{startColor, endColor}; + } + + public Fill(@NonNull int[] gradientColors) + { + this.mType = Type.LINEAR_GRADIENT; + this.mGradientColors = gradientColors; + } + + public Fill(@NonNull int[] gradientColors, @NonNull float[] gradientPositions) + { + this.mType = Type.LINEAR_GRADIENT; + this.mGradientColors = gradientColors; + this.mGradientPositions = gradientPositions; + } + + public Fill(@NonNull Drawable drawable) + { + this.mType = Type.DRAWABLE; + this.mDrawable = drawable; + } + + public Type getType() + { + return mType; + } + + public void setType(Type type) + { + this.mType = type; + } + + @Nullable + public Integer getColor() + { + return mColor; + } + + public void setColor(int color) + { + this.mColor = color; + calculateFinalColor(); + } + + public int[] getGradientColors() + { + return mGradientColors; + } + + public void setGradientColors(int[] colors) + { + this.mGradientColors = colors; + } + + public float[] getGradientPositions() + { + return mGradientPositions; + } + + public void setGradientPositions(float[] positions) + { + this.mGradientPositions = positions; + } + + public void setGradientColors(int startColor, int endColor) + { + this.mGradientColors = new int[]{startColor, endColor}; + } + + public int getAlpha() + { + return mAlpha; + } + + public void setAlpha(int alpha) + { + this.mAlpha = alpha; + calculateFinalColor(); + } + + private void calculateFinalColor() + { + if (mColor == null) + { + mFinalColor = null; + } else + { + int alpha = (int) Math.floor(((mColor >> 24) / 255.0) * (mAlpha / 255.0) * 255.0); + mFinalColor = (alpha << 24) | (mColor & 0xffffff); + } + } + + public void fillRect(Canvas c, Paint paint, + float left, float top, float right, float bottom, + Direction gradientDirection) + { + switch (mType) + { + case EMPTY: + return; + + case COLOR: + { + if (mFinalColor == null) return; + + if (isClipPathSupported()) + { + int save = c.save(); + + c.clipRect(left, top, right, bottom); + c.drawColor(mFinalColor); + + c.restoreToCount(save); + } + else + { + // save + Paint.Style previous = paint.getStyle(); + int previousColor = paint.getColor(); + + // set + paint.setStyle(Paint.Style.FILL); + paint.setColor(mFinalColor); + + c.drawRect(left, top, right, bottom, paint); + + // restore + paint.setColor(previousColor); + paint.setStyle(previous); + } + } + break; + + case LINEAR_GRADIENT: + { + if (mGradientColors == null) return; + + LinearGradient gradient = new LinearGradient( + (int) (gradientDirection == Direction.RIGHT + ? right + : gradientDirection == Direction.LEFT + ? left + : left), + (int) (gradientDirection == Direction.UP + ? bottom + : gradientDirection == Direction.DOWN + ? top + : top), + (int) (gradientDirection == Direction.RIGHT + ? left + : gradientDirection == Direction.LEFT + ? right + : left), + (int) (gradientDirection == Direction.UP + ? top + : gradientDirection == Direction.DOWN + ? bottom + : top), + mGradientColors, + mGradientPositions, + android.graphics.Shader.TileMode.MIRROR); + + paint.setShader(gradient); + + c.drawRect(left, top, right, bottom, paint); + } + break; + + case DRAWABLE: + { + if (mDrawable == null) return; + + mDrawable.setBounds((int) left, (int) top, (int) right, (int) bottom); + mDrawable.draw(c); + } + break; + } + } + + public void fillPath(Canvas c, Path path, Paint paint, + @Nullable RectF clipRect) + { + switch (mType) + { + case EMPTY: + return; + + case COLOR: + { + if (mFinalColor == null) return; + + if (clipRect != null && isClipPathSupported()) + { + int save = c.save(); + + c.clipPath(path); + c.drawColor(mFinalColor); + + c.restoreToCount(save); + } + else + { + // save + Paint.Style previous = paint.getStyle(); + int previousColor = paint.getColor(); + + // set + paint.setStyle(Paint.Style.FILL); + paint.setColor(mFinalColor); + + c.drawPath(path, paint); + + // restore + paint.setColor(previousColor); + paint.setStyle(previous); + } + } + break; + + case LINEAR_GRADIENT: + { + if (mGradientColors == null) return; + + LinearGradient gradient = new LinearGradient( + 0, + 0, + c.getWidth(), + c.getHeight(), + mGradientColors, + mGradientPositions, + android.graphics.Shader.TileMode.MIRROR); + + paint.setShader(gradient); + + c.drawPath(path, paint); + } + break; + + case DRAWABLE: + { + if (mDrawable == null) return; + + ensureClipPathSupported(); + + int save = c.save(); + c.clipPath(path); + + mDrawable.setBounds( + clipRect == null ? 0 : (int) clipRect.left, + clipRect == null ? 0 : (int) clipRect.top, + clipRect == null ? c.getWidth() : (int) clipRect.right, + clipRect == null ? c.getHeight() : (int) clipRect.bottom); + mDrawable.draw(c); + + c.restoreToCount(save); + } + break; + } + } + + private boolean isClipPathSupported() + { + return Utils.getSDKInt() >= 18; + } + + private void ensureClipPathSupported() + { + if (Utils.getSDKInt() < 18) + { + throw new RuntimeException("Fill-drawables not (yet) supported below API level 18, " + + "this code was run on API level " + Utils.getSDKInt() + "."); + } + } +} |