diff --git a/.github/workflows/gradle-publish.yml b/.github/workflows/gradle-publish.yml new file mode 100644 index 0000000000..2af46165be --- /dev/null +++ b/.github/workflows/gradle-publish.yml @@ -0,0 +1,44 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. +# This workflow will build a package using Gradle and then publish it to GitHub packages when a release is created +# For more information see: https://github.com/actions/setup-java/blob/main/docs/advanced-usage.md#Publishing-using-gradle + +name: Gradle Package + +on: + release: + types: [created] + +jobs: + build: + + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - uses: actions/checkout@v4 + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + server-id: github # Value of the distributionManagement/repository/id field of the pom.xml + settings-path: ${{ github.workspace }} # location for the settings.xml file + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 + + - name: Build with Gradle + run: ./gradlew build + + # The USERNAME and TOKEN need to correspond to the credentials environment variables used in + # the publishing section of your build.gradle + - name: Publish to GitHub Packages + run: ./gradlew publish + env: + USERNAME: ${{ github.actor }} + TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index dd43b056eb..f411b1c123 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -65,12 +65,11 @@ protected void onCreate(Bundle savedInstanceState) { tvX = findViewById(R.id.tvXMax); tvY = findViewById(R.id.tvYMax); - seekBarX = findViewById(R.id.seekBar1); seekBarX.setOnSeekBarChangeListener(this); seekBarY = findViewById(R.id.seekBar2); - seekBarY.setMax(180); + seekBarY.setMax(40); seekBarY.setOnSeekBarChangeListener(this); @@ -126,12 +125,11 @@ protected void onCreate(Bundle savedInstanceState) { yAxis.enableGridDashedLine(10f, 10f, 0f); // axis range - yAxis.setAxisMaximum(200f); - yAxis.setAxisMinimum(-50f); + yAxis.setAxisMaximum(40f); + yAxis.setAxisMinimum(0f); } - - { // // Create Limit Lines // // + /* { // // Create Limit Lines // // LimitLine llXAxis = new LimitLine(9f, "Index 10"); llXAxis.setLineWidth(4f); llXAxis.enableDashedLine(10f, 10f, 0f); @@ -162,11 +160,11 @@ protected void onCreate(Bundle savedInstanceState) { yAxis.addLimitLine(ll2); //xAxis.addLimitLine(llXAxis); } - +*/ // add data seekBarX.setProgress(45); - seekBarY.setProgress(180); - setData(45, 180); + seekBarY.setProgress(30); + setData(25, 30); // draw points over time chart.animateX(1500); @@ -184,12 +182,13 @@ private void setData(int count, float range) { for (int i = 0; i < count; i++) { - float val = (float) (Math.random() * range) - 30; + float val = (float) (Math.random() * range); values.add(new Entry(i, val, getResources().getDrawable(R.drawable.star))); } LineDataSet set1; + if (chart.getData() != null && chart.getData().getDataSetCount() > 0) { set1 = (LineDataSet) chart.getData().getDataSetByIndex(0); @@ -202,24 +201,26 @@ private void setData(int count, float range) { set1 = new LineDataSet(values, "DataSet 1"); set1.setDrawIcons(false); - + set1.setMode(LineDataSet.Mode.GRADIENT_CUBIC_BEZIER); + set1.setGradientColor(getResources().getColor(android.R.color.holo_green_dark), + getResources().getColor(android.R.color.holo_blue_dark)); // draw dashed line - set1.enableDashedLine(10f, 5f, 0f); + /* set1.enableDashedLine(10f, 5f, 0f);*/ // black lines and points set1.setColor(Color.BLACK); set1.setCircleColor(Color.BLACK); // line thickness and point size - set1.setLineWidth(1f); + set1.setLineWidth(5f); set1.setCircleRadius(3f); // draw points as solid circles - set1.setDrawCircleHole(false); + set1.setDrawCircles(false); // customize legend entry set1.setFormLineWidth(1f); - set1.setFormLineDashEffect(new DashPathEffect(new float[]{10f, 5f}, 0f)); + //set1.setFormLineDashEffect(new DashPathEffect(new float[]{10f, 5f}, 0f)); set1.setFormSize(15.f); // text size of values @@ -229,7 +230,6 @@ private void setData(int count, float range) { set1.enableDashedHighlightLine(10f, 5f, 0f); // set the filled area - set1.setDrawFilled(true); set1.setFillFormatter(new IFillFormatter() { @Override public float getFillLinePosition(ILineDataSet dataSet, LineDataProvider dataProvider) { @@ -237,26 +237,28 @@ public float getFillLinePosition(ILineDataSet dataSet, LineDataProvider dataProv } }); - // set color of filled area + /* // set color of filled area if (Utils.getSDKInt() >= 18) { // drawables only supported on api level 18 and above Drawable drawable = ContextCompat.getDrawable(this, R.drawable.fade_red); set1.setFillDrawable(drawable); } else { set1.setFillColor(Color.BLACK); - } + }*/ ArrayList dataSets = new ArrayList<>(); + /* dataSets.add(ds1);*/ dataSets.add(set1); // add the data sets - // create a data object with the data sets LineData data = new LineData(dataSets); // set data chart.setData(data); } + } + @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.line, menu); @@ -300,7 +302,7 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleHighlight: { - if(chart.getData() != null) { + if (chart.getData() != null) { chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); chart.invalidate(); } @@ -346,7 +348,7 @@ public boolean onOptionsItemSelected(MenuItem item) { LineDataSet set = (LineDataSet) iSet; set.setMode(set.getMode() == LineDataSet.Mode.CUBIC_BEZIER ? LineDataSet.Mode.LINEAR - : LineDataSet.Mode.CUBIC_BEZIER); + : LineDataSet.Mode.CUBIC_BEZIER); } chart.invalidate(); break; @@ -360,7 +362,7 @@ public boolean onOptionsItemSelected(MenuItem item) { LineDataSet set = (LineDataSet) iSet; set.setMode(set.getMode() == LineDataSet.Mode.STEPPED ? LineDataSet.Mode.LINEAR - : LineDataSet.Mode.STEPPED); + : LineDataSet.Mode.STEPPED); } chart.invalidate(); break; @@ -374,7 +376,7 @@ public boolean onOptionsItemSelected(MenuItem item) { LineDataSet set = (LineDataSet) iSet; set.setMode(set.getMode() == LineDataSet.Mode.HORIZONTAL_BEZIER ? LineDataSet.Mode.LINEAR - : LineDataSet.Mode.HORIZONTAL_BEZIER); + : LineDataSet.Mode.HORIZONTAL_BEZIER); } chart.invalidate(); break; @@ -435,10 +437,12 @@ protected void saveToGallery() { } @Override - public void onStartTrackingTouch(SeekBar seekBar) {} + public void onStartTrackingTouch(SeekBar seekBar) { + } @Override - public void onStopTrackingTouch(SeekBar seekBar) {} + public void onStopTrackingTouch(SeekBar seekBar) { + } @Override public void onValueSelected(Entry e, Highlight h) { @@ -451,4 +455,4 @@ public void onValueSelected(Entry e, Highlight h) { public void onNothingSelected() { Log.i("Nothing selected", "Nothing selected."); } -} +} \ No newline at end of file diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java index 0581529308..9b866f27cd 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java @@ -1,4 +1,7 @@ package com.xxmassdeveloper.mpchartexample.fragments; +import android.graphics.LinearGradient; +import android.graphics.Paint; +import android.graphics.Shader; import android.graphics.Typeface; import android.os.Bundle; import androidx.annotation.NonNull; @@ -52,6 +55,22 @@ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, XAxis xAxis = chart.getXAxis(); xAxis.setEnabled(false); + chart.post(this::setupGradient); + return v; } + + private void setupGradient() { + + Paint paint = chart.getRenderer().getPaintRender(); + int height = chart.getHeight(); + + LinearGradient linGrad = new LinearGradient(0, 0, 0, height, + getResources().getColor(android.R.color.holo_blue_dark), + getResources().getColor(android.R.color.holo_green_dark), + Shader.TileMode.REPEAT); + paint.setShader(linGrad); + + chart.invalidate(); + } } diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java index 88e5dc8d8b..0750264644 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java @@ -70,6 +70,7 @@ protected void onCreate(Bundle savedInstanceState) { //// objects.add(0, new ContentItem("Line Charts")); + objects.add(1, new ContentItem("Basic", "Simple line chart.")); objects.add(2, new ContentItem("Multiple", "Show multiple data sets.")); objects.add(3, new ContentItem("Dual Axis", "Line chart with dual y-axes.")); 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 7e7445cac7..6a66e9bbf0 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,6 +9,7 @@ import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.formatter.IValueFormatter; 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; @@ -28,6 +29,8 @@ public abstract class BaseDataSet implements IDataSet { */ protected List mColors = null; + protected GradientColor mGradientColor = null; + /** * List representing all colors that are used for drawing the actual values for this DataSet */ @@ -141,6 +144,11 @@ public int getColor(int index) { return mColors.get(index % mColors.size()); } + @Override + public GradientColor getGradientColor() { + return mGradientColor; + } + /** * ###### ###### COLOR SETTING RELATED METHODS ##### ###### */ @@ -226,6 +234,16 @@ public void setColor(int color, int alpha) { setColor(Color.argb(alpha, Color.red(color), Color.green(color), Color.blue(color))); } + /** + * 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 colors with a specific alpha value. * @@ -495,6 +513,7 @@ protected void copy(BaseDataSet baseDataSet) { baseDataSet.mFormLineDashEffect = mFormLineDashEffect; baseDataSet.mFormLineWidth = mFormLineWidth; baseDataSet.mFormSize = mFormSize; + baseDataSet.mGradientColor = mGradientColor; baseDataSet.mHighlightEnabled = mHighlightEnabled; baseDataSet.mIconsOffset = mIconsOffset; baseDataSet.mValueColors = mValueColors; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java index 10d1837ecd..39b3861c2c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java @@ -412,6 +412,7 @@ public enum Mode { LINEAR, STEPPED, CUBIC_BEZIER, - HORIZONTAL_BEZIER + HORIZONTAL_BEZIER, + GRADIENT_CUBIC_BEZIER } } 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 fd8af7064b..cc8b1091d7 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 @@ -1,7 +1,6 @@ package com.github.mikephil.charting.interfaces.datasets; import android.graphics.DashPathEffect; -import android.graphics.PointF; import android.graphics.Typeface; import com.github.mikephil.charting.components.Legend; @@ -9,6 +8,7 @@ import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.formatter.IValueFormatter; +import com.github.mikephil.charting.model.GradientColor; import com.github.mikephil.charting.utils.MPPointF; import java.util.List; @@ -285,6 +285,13 @@ public interface IDataSet { */ int getColor(); + /** + * Returns the Gradient color model + * + * @return + */ + GradientColor getGradientColor(); + /** * 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 deleted file mode 100644 index b5c8715a08..0000000000 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/model/GradientColor.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.github.mikephil.charting.model; - -import com.github.mikephil.charting.utils.Fill; - -/** - * Deprecated. Use `Fill` - */ -@Deprecated -public class GradientColor extends Fill -{ - /** - * Deprecated. Use `Fill.getGradientColors()` - */ - @Deprecated - public int getStartColor() - { - return getGradientColors()[0]; - } - - /** - * 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; - } - } - - /** - * Deprecated. Use `Fill.getGradientColors()` - */ - @Deprecated - public int getEndColor() - { - return getGradientColors()[1]; - } - - /** - * 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; - } - } - -} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index a86c16f76b..f1de14d04c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -3,8 +3,10 @@ import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.LinearGradient; import android.graphics.Paint; import android.graphics.Path; +import android.graphics.Shader; import android.graphics.drawable.Drawable; import com.github.mikephil.charting.animation.ChartAnimator; @@ -121,6 +123,9 @@ protected void drawDataSet(Canvas c, ILineDataSet dataSet) { case CUBIC_BEZIER: drawCubicBezier(dataSet); break; + case GRADIENT_CUBIC_BEZIER: + drawGradientCubicBezier(dataSet); + break; case HORIZONTAL_BEZIER: drawHorizontalBezier(dataSet); @@ -130,6 +135,89 @@ protected void drawDataSet(Canvas c, ILineDataSet dataSet) { mRenderPaint.setPathEffect(null); } + private void drawGradientCubicBezier(ILineDataSet dataSet) { + + float phaseY = mAnimator.getPhaseY(); + + Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); + + mXBounds.set(mChart, dataSet); + + float intensity = dataSet.getCubicIntensity(); + + cubicPath.reset(); + + if (mXBounds.range >= 1) { + + float prevDx = 0f; + float prevDy = 0f; + float curDx = 0f; + float curDy = 0f; + + // Take an extra point from the left, and an extra from the right. + // That's because we need 4 points for a cubic bezier (cubic=4), otherwise we get lines moving and doing weird stuff on the edges of the chart. + // So in the starting `prev` and `cur`, go -2, -1 + // And in the `lastIndex`, add +1 + + final int firstIndex = mXBounds.min + 1; + final int lastIndex = mXBounds.min + mXBounds.range; + + Entry prevPrev; + Entry prev = dataSet.getEntryForIndex(Math.max(firstIndex - 2, 0)); + Entry cur = dataSet.getEntryForIndex(Math.max(firstIndex - 1, 0)); + Entry next = cur; + int nextIndex = -1; + + if (cur == null) return; + + // let the spline start + cubicPath.moveTo(cur.getX(), cur.getY() * phaseY); + + for (int j = mXBounds.min + 1; j <= mXBounds.range + mXBounds.min; j++) { + + prevPrev = prev; + prev = cur; + cur = nextIndex == j ? next : dataSet.getEntryForIndex(j); + + nextIndex = j + 1 < dataSet.getEntryCount() ? j + 1 : j; + next = dataSet.getEntryForIndex(nextIndex); + + prevDx = (cur.getX() - prevPrev.getX()) * intensity; + prevDy = (cur.getY() - prevPrev.getY()) * intensity; + curDx = (next.getX() - prev.getX()) * intensity; + curDy = (next.getY() - prev.getY()) * intensity; + + cubicPath.cubicTo(prev.getX() + prevDx, (prev.getY() + prevDy) * phaseY, + cur.getX() - curDx, + (cur.getY() - curDy) * phaseY, cur.getX(), cur.getY() * phaseY); + } + } + + // if filled is enabled, close the path + if (dataSet.isDrawFilledEnabled()) { + + cubicFillPath.reset(); + cubicFillPath.addPath(cubicPath); + + drawCubicFill(mBitmapCanvas, dataSet, cubicFillPath, trans, mXBounds); + } + + mRenderPaint.setStyle(Paint.Style.STROKE); + + trans.pathValueToPixel(cubicPath); + + LinearGradient linGrad = new LinearGradient(0, 0, 0, mChart.getHeight(), + dataSet.getGradientColor().getStartColor(), + dataSet.getGradientColor().getEndColor(), + Shader.TileMode.REPEAT); + mRenderPaint.setShader(linGrad); + + mBitmapCanvas.drawPath(cubicPath, mRenderPaint); + + mRenderPaint.setPathEffect(null); + } + + protected void drawHorizontalBezier(ILineDataSet dataSet) { float phaseY = mAnimator.getPhaseY();