diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java deleted file mode 100644 index b6f9f49a7..000000000 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java +++ /dev/null @@ -1,293 +0,0 @@ - -package com.github.mikephil.charting.charts; - -import android.content.Context; -import android.graphics.Canvas; -import android.util.AttributeSet; -import android.util.Log; - -import com.github.mikephil.charting.components.IMarker; -import com.github.mikephil.charting.data.BarData; -import com.github.mikephil.charting.data.BubbleData; -import com.github.mikephil.charting.data.CandleData; -import com.github.mikephil.charting.data.CombinedData; -import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.data.LineData; -import com.github.mikephil.charting.data.ScatterData; -import com.github.mikephil.charting.highlight.CombinedHighlighter; -import com.github.mikephil.charting.highlight.Highlight; -import com.github.mikephil.charting.interfaces.dataprovider.CombinedDataProvider; -import com.github.mikephil.charting.interfaces.datasets.IDataSet; -import com.github.mikephil.charting.renderer.CombinedChartRenderer; - -/** - * This chart class allows the combination of lines, bars, scatter and candle - * data all displayed in one chart area. - * - * @author Philipp Jahoda - */ -@SuppressWarnings("unused") -public class CombinedChart extends BarLineChartBase implements CombinedDataProvider { - - /** - * if set to true, all values are drawn above their bars, instead of below - * their top - */ - private boolean mDrawValueAboveBar = true; - - - /** - * flag that indicates whether the highlight should be full-bar oriented, or single-value? - */ - protected boolean mHighlightFullBarEnabled = false; - - /** - * if set to true, a grey area is drawn behind each bar that indicates the - * maximum value - */ - private boolean mDrawBarShadow = false; - - protected DrawOrder[] mDrawOrder; - - /** - * enum that allows to specify the order in which the different data objects - * for the combined-chart are drawn - */ - public enum DrawOrder { - BAR, BUBBLE, LINE, CANDLE, SCATTER - } - - public CombinedChart(Context context) { - super(context); - } - - public CombinedChart(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public CombinedChart(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } - - @Override - protected void init() { - super.init(); - - // Default values are not ready here yet - mDrawOrder = new DrawOrder[]{ - DrawOrder.BAR, DrawOrder.BUBBLE, DrawOrder.LINE, DrawOrder.CANDLE, DrawOrder.SCATTER - }; - - setHighlighter(new CombinedHighlighter(this, this)); - - // Old default behaviour - setHighlightFullBarEnabled(true); - - mRenderer = new CombinedChartRenderer(this, mAnimator, mViewPortHandler); - } - - @Override - public CombinedData getCombinedData() { - return mData; - } - - @Override - public void setData(CombinedData data) { - super.setData(data); - setHighlighter(new CombinedHighlighter(this, this)); - ((CombinedChartRenderer) mRenderer).createRenderers(); - mRenderer.initBuffers(); - } - - /** - * Returns the Highlight object (contains x-index and DataSet index) of the selected value at the given touch - * point - * inside the CombinedChart. - */ - @Override - public Highlight getHighlightByTouchPoint(float x, float y) { - - if (mData == null) { - Log.e(LOG_TAG, "Can't select by touch. No data set."); - return null; - } else { - Highlight highlight = getHighlighter().getHighlight(x, y); - if (highlight == null || !isHighlightFullBarEnabled()) { - return highlight; - } - - // For isHighlightFullBarEnabled, remove stackIndex - return new Highlight( - highlight.getX(), - highlight.getY(), - highlight.getXPx(), - highlight.getYPx(), - highlight.getDataSetIndex(), - -1, - highlight.getAxis()); - } - } - - @Override - public LineData getLineData() { - if (mData == null) { - return null; - } - return mData.getLineData(); - } - - @Override - public BarData getBarData() { - if (mData == null) { - return null; - } - return mData.getBarData(); - } - - @Override - public ScatterData getScatterData() { - if (mData == null) { - return null; - } - return mData.getScatterData(); - } - - @Override - public CandleData getCandleData() { - if (mData == null) { - return null; - } - return mData.getCandleData(); - } - - @Override - public BubbleData getBubbleData() { - if (mData == null) { - return null; - } - return mData.getBubbleData(); - } - - @Override - public boolean isDrawBarShadowEnabled() { - return mDrawBarShadow; - } - - @Override - public boolean isDrawValueAboveBarEnabled() { - return mDrawValueAboveBar; - } - - @Override - public void setDrawBarShadowEnabled(boolean value) { - mDrawBarShadow = value; - } - - @Override - public void setDrawValueAboveBarEnabled(boolean value) { - mDrawValueAboveBar = value; - } - - /** - * If set to true, all values are drawn above their bars, instead of below - * their top. - */ - public void setDrawValueAboveBar(boolean enabled) { - mDrawValueAboveBar = enabled; - } - - - /** - * If set to true, a grey area is drawn behind each bar that indicates the - * maximum value. Enabling his will reduce performance by about 50%. - */ - public void setDrawBarShadow(boolean value) { - mDrawBarShadow = value; - } - - /** - * Set this to true to make the highlight operation full-bar oriented, - * false to make it highlight single values (relevant only for stacked). - */ - public void setHighlightFullBarEnabled(boolean enabled) { - mHighlightFullBarEnabled = enabled; - } - - /** - * @return true the highlight operation is be full-bar oriented, false if single-value - */ - @Override - public boolean isHighlightFullBarEnabled() { - return mHighlightFullBarEnabled; - } - - /** - * Returns the currently set draw order. - */ - public DrawOrder[] getDrawOrder() { - return mDrawOrder; - } - - /** - * Sets the order in which the provided data objects should be drawn. The - * earlier you place them in the provided array, the further they will be in - * the background. e.g. if you provide new DrawOrer[] { DrawOrder.BAR, - * DrawOrder.LINE }, the bars will be drawn behind the lines. - */ - public void setDrawOrder(DrawOrder[] order) { - if (order == null || order.length <= 0) { - return; - } - mDrawOrder = order; - } - - /** - * draws all MarkerViews on the highlighted positions - */ - protected void drawMarkers(Canvas canvas) { - - // if there is no marker view or drawing marker is disabled - if (mMarkers == null || !isDrawMarkersEnabled() || !valuesToHighlight()) { - return; - } - - for (int i = 0; i < mIndicesToHighlight.length; i++) { - - Highlight highlight = mIndicesToHighlight[i]; - IDataSet set = mData.getDataSetByHighlight(highlight); - - Entry e = mData.getEntryForHighlight(highlight); - if (e == null || set == null) { - continue; - } - - int entryIndex = set.getEntryIndex(e); - - // make sure entry not null - if (entryIndex > set.getEntryCount() * mAnimator.getPhaseX()) { - continue; - } - - float[] pos = getMarkerPosition(highlight); - - // check bounds - if (!mViewPortHandler.isInBounds(pos[0], pos[1])) { - continue; - } - - // callbacks to update the content - if (!mMarkers.isEmpty()) { - IMarker markerItem = mMarkers.get(i % mMarkers.size()); - markerItem.refreshContent(e, highlight); - - // draw the marker - markerItem.draw(canvas, pos[0], pos[1]); - } - } - } - - @Override - public String getAccessibilityDescription() { - return "This is a combined chart"; - } -} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.kt b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.kt new file mode 100644 index 000000000..0326b53a8 --- /dev/null +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.kt @@ -0,0 +1,242 @@ +package com.github.mikephil.charting.charts + +import android.content.Context +import android.graphics.Canvas +import android.util.AttributeSet +import android.util.Log +import com.github.mikephil.charting.data.BarData +import com.github.mikephil.charting.data.BubbleData +import com.github.mikephil.charting.data.CandleData +import com.github.mikephil.charting.data.CombinedData +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.LineData +import com.github.mikephil.charting.data.ScatterData +import com.github.mikephil.charting.highlight.CombinedHighlighter +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.interfaces.dataprovider.CombinedDataProvider +import com.github.mikephil.charting.interfaces.datasets.IDataSet +import com.github.mikephil.charting.renderer.CombinedChartRenderer + +/** + * This chart class allows the combination of lines, bars, scatter and candle + * data all displayed in one chart area. + */ +@Suppress("unused") +open class CombinedChart : BarLineChartBase, CombinedDataProvider { + /** + * if set to true, all values are drawn above their bars, instead of below + * their top + */ + override var isDrawValueAboveBarEnabled: Boolean = true + + + /** + * @return true the highlight operation is be full-bar oriented, false if single-value + */ + /** + * Set this to true to make the highlight operation full-bar oriented, + * false to make it highlight single values (relevant only for stacked). + */ + /** + * flag that indicates whether the highlight should be full-bar oriented, or single-value? + */ + override var isHighlightFullBarEnabled: Boolean = false + + /** + * if set to true, a grey area is drawn behind each bar that indicates the + * maximum value + */ + override var isDrawBarShadowEnabled: Boolean = false + + protected var mDrawOrder: MutableList? = null + + /** + * enum that allows to specify the order in which the different data objects + * for the combined-chart are drawn + */ + enum class DrawOrder { + BAR, BUBBLE, LINE, CANDLE, SCATTER + } + + constructor(context: Context?) : super(context) + + constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) + + constructor(context: Context?, attrs: AttributeSet?, defStyle: Int) : super(context, attrs, defStyle) + + protected override fun init() { + super.init() + + // Default values are not ready here yet + mDrawOrder = mutableListOf( + DrawOrder.BAR, DrawOrder.BUBBLE, DrawOrder.LINE, DrawOrder.CANDLE, DrawOrder.SCATTER + ) + + setHighlighter(CombinedHighlighter(this, this)) + + // Old default behaviour + isHighlightFullBarEnabled = true + + mRenderer = CombinedChartRenderer(this, mAnimator, mViewPortHandler) + } + + override val combinedData: CombinedData? + get() = mData + + override fun setData(data: CombinedData?) { + super.setData(data) + setHighlighter(CombinedHighlighter(this, this)) + (mRenderer as CombinedChartRenderer).createRenderers() + mRenderer.initBuffers() + } + + /** + * Returns the Highlight object (contains x-index and DataSet index) of the selected value at the given touch + * point + * inside the CombinedChart. + */ + override fun getHighlightByTouchPoint(x: Float, y: Float): Highlight? { + if (mData == null) { + Log.e(LOG_TAG, "Can't select by touch. No data set.") + return null + } else { + val highlight = highlighter.getHighlight(x, y) + if (highlight == null || !isHighlightFullBarEnabled) { + return highlight + } + + // For isHighlightFullBarEnabled, remove stackIndex + return Highlight( + highlight.x, + highlight.y, + highlight.xPx, + highlight.yPx, + highlight.dataSetIndex, + -1, + highlight.axis + ) + } + } + + override val lineData: LineData? + get() { + if (mData == null) { + return null + } + return mData!!.lineData!! + } + + override val barData: BarData? + get() { + if (mData == null) { + return null + } + return mData!!.barData + } + + override val scatterData: ScatterData? + get() { + if (mData == null) { + return null + } + return mData!!.scatterData + } + + override val candleData: CandleData? + get() { + if (mData == null) { + return null + } + return mData!!.candleData + } + + override val bubbleData: BubbleData? + get() { + if (mData == null) { + return null + } + return mData!!.bubbleData + } + + /** + * If set to true, all values are drawn above their bars, instead of below + * their top. + */ + fun setDrawValueAboveBar(enabled: Boolean) { + this.isDrawValueAboveBarEnabled = enabled + } + + + /** + * If set to true, a grey area is drawn behind each bar that indicates the + * maximum value. Enabling his will reduce performance by about 50%. + */ + fun setDrawBarShadow(value: Boolean) { + this.isDrawBarShadowEnabled = value + } + + var drawOrder: MutableList? + get() = mDrawOrder + /** + * Sets the order in which the provided data objects should be drawn. The + * earlier you place them in the provided array, the further they will be in + * the background. e.g. if you provide new DrawOrer[] { DrawOrder.BAR, + * DrawOrder.LINE }, the bars will be drawn behind the lines. + */ + set(order) { + if (order == null || order.isEmpty()) { + return + } + mDrawOrder = order + } + + /** + * draws all MarkerViews on the highlighted positions + */ + override fun drawMarkers(canvas: Canvas) { + // if there is no marker view or drawing marker is disabled + + if (mMarkers == null || !isDrawMarkersEnabled || !valuesToHighlight()) { + return + } + + for (i in mIndicesToHighlight.indices) { + val highlight = mIndicesToHighlight[i] + val dataset = mData!!.getDataSetByHighlight(highlight) + + val e = mData!!.getEntryForHighlight(highlight) + if (e == null || dataset == null) { + continue + } + + @Suppress("UNCHECKED_CAST") + val set = dataset as IDataSet + val entryIndex = set.getEntryIndex(e) + + // make sure entry not null + if (entryIndex > set.entryCount * mAnimator.phaseX) { + continue + } + + val pos = getMarkerPosition(highlight) + + // check bounds + if (!mViewPortHandler.isInBounds(pos[0], pos[1])) { + continue + } + + // callbacks to update the content + if (!mMarkers.isEmpty()) { + val markerItem = mMarkers[i % mMarkers.size] + markerItem.refreshContent(e, highlight) + + // draw the marker + markerItem.draw(canvas, pos[0], pos[1]) + } + } + } + + override fun getAccessibilityDescription(): String { + return "This is a combined chart" + } +} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.kt b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.kt index fb3bc5751..84e63262b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.kt +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.kt @@ -168,7 +168,7 @@ class CombinedData : BarLineScatterCandleBubbleData= data.dataSetCount) return null - return data.dataSets!!.get(highlight.dataSetIndex) as IBarLineScatterCandleBubbleDataSet? + return data.dataSets!![highlight.dataSetIndex] as IBarLineScatterCandleBubbleDataSet? } fun getDataIndex(data: ChartData<*>?): Int { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultFillFormatter.kt b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultFillFormatter.kt index a6fb0f429..52417b18f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultFillFormatter.kt +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultFillFormatter.kt @@ -12,22 +12,24 @@ open class DefaultFillFormatter : IFillFormatter { val fillMin: Float val chartMaxY = dataProvider.yChartMax val chartMinY = dataProvider.yChartMin - val data = dataProvider.lineData - fillMin = if (dataSet!!.yMax > 0 && dataSet.yMin < 0) { - 0f - } else { - val max: Float = if (data.yMax > 0) 0f - else - chartMaxY - val min: Float = if (data.yMin < 0) + dataProvider.lineData?.let { data -> + fillMin = if (dataSet!!.yMax > 0 && dataSet.yMin < 0) { 0f - else - chartMinY - if (dataSet.yMin >= 0) - min - else - max + } else { + val max: Float = if (data.yMax > 0) 0f + else + chartMaxY + val min: Float = if (data.yMin < 0) + 0f + else + chartMinY + if (dataSet.yMin >= 0) + min + else + max + } + return fillMin } - return fillMin + return 0f } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/LineDataProvider.kt b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/LineDataProvider.kt index 4f6d3e87c..bd44ade84 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/LineDataProvider.kt +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/LineDataProvider.kt @@ -6,6 +6,6 @@ import com.github.mikephil.charting.data.LineData import com.github.mikephil.charting.interfaces.dataprovider.base.BarLineScatterCandleBubbleDataProvider interface LineDataProvider : BarLineScatterCandleBubbleDataProvider { - val lineData: LineData + val lineData: LineData? fun getAxis(dependency: AxisDependency): YAxis? } \ No newline at end of file diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.kt b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.kt index af9f15257..7c6373b29 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.kt +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.kt @@ -34,13 +34,15 @@ open class CombinedChartRenderer(chart: CombinedChart, animator: ChartAnimator, val orders = chart.drawOrder - for (order in orders) { - when (order) { - DrawOrder.BAR -> dataRenderers.add(BarChartRenderer(chart, animator, viewPortHandler)) - DrawOrder.BUBBLE -> if (chart.bubbleData != null) dataRenderers.add(BubbleChartRenderer(chart, animator, viewPortHandler)) - DrawOrder.LINE -> dataRenderers.add(LineChartRenderer(chart, animator, viewPortHandler)) - DrawOrder.CANDLE -> if (chart.candleData != null) dataRenderers.add(CandleStickChartRenderer(chart, animator, viewPortHandler)) - DrawOrder.SCATTER -> if (chart.scatterData != null) dataRenderers.add(ScatterChartRenderer(chart, animator, viewPortHandler)) + orders?.let { + for (order in it) { + when (order) { + DrawOrder.BAR -> dataRenderers.add(BarChartRenderer(chart, animator, viewPortHandler)) + DrawOrder.BUBBLE -> if (chart.bubbleData != null) dataRenderers.add(BubbleChartRenderer(chart, animator, viewPortHandler)) + DrawOrder.LINE -> dataRenderers.add(LineChartRenderer(chart, animator, viewPortHandler)) + DrawOrder.CANDLE -> if (chart.candleData != null) dataRenderers.add(CandleStickChartRenderer(chart, animator, viewPortHandler)) + DrawOrder.SCATTER -> if (chart.scatterData != null) dataRenderers.add(ScatterChartRenderer(chart, animator, viewPortHandler)) + } } } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.kt b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.kt index 57d9c17a8..6612228b2 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.kt +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.kt @@ -75,11 +75,11 @@ open class LineChartRenderer( drawBitmapLocal.eraseColor(Color.TRANSPARENT) - val lineData = dataProvider.lineData - - lineData.dataSets?.forEach { set -> - if (set.isVisible) - drawDataSet(canvas, set) + dataProvider.lineData?.let { lineData -> + lineData.dataSets?.forEach { set -> + if (set.isVisible) + drawDataSet(canvas, set) + } } canvas.drawBitmap(drawBitmapLocal, 0f, 0f, null) } @@ -482,7 +482,7 @@ open class LineChartRenderer( override fun drawValues(canvas: Canvas) { if (isDrawingValuesAllowed(dataProvider)) { - val dataSets = dataProvider.lineData.dataSets + val dataSets = dataProvider.lineData?.dataSets dataSets?.let { for (i in it.indices) { @@ -586,7 +586,7 @@ open class LineChartRenderer( mCirclesBuffer[0] = 0f mCirclesBuffer[1] = 0f - val dataSets = dataProvider.lineData.dataSets + val dataSets = dataProvider.lineData?.dataSets dataSets?.let { for (i in it.indices) { @@ -651,7 +651,7 @@ open class LineChartRenderer( val lineData = dataProvider.lineData for (high in indices) { - val set = lineData.getDataSetByIndex(high.dataSetIndex) + val set = lineData?.getDataSetByIndex(high.dataSetIndex) if (set == null || !set.isHighlightEnabled) continue diff --git a/app/src/main/kotlin/info/appdev/chartexample/CombinedChartActivity.kt b/app/src/main/kotlin/info/appdev/chartexample/CombinedChartActivity.kt index 184d4fce7..9e7dddefa 100644 --- a/app/src/main/kotlin/info/appdev/chartexample/CombinedChartActivity.kt +++ b/app/src/main/kotlin/info/appdev/chartexample/CombinedChartActivity.kt @@ -51,10 +51,8 @@ class CombinedChartActivity : DemoBase() { binding.chart1.isHighlightFullBarEnabled = false // draw bars behind lines - binding.chart1.setDrawOrder( - arrayOf( - DrawOrder.BAR, DrawOrder.BUBBLE, DrawOrder.CANDLE, DrawOrder.LINE, DrawOrder.SCATTER - ) + binding.chart1.drawOrder = mutableListOf( + DrawOrder.BAR, DrawOrder.BUBBLE, DrawOrder.CANDLE, DrawOrder.LINE, DrawOrder.SCATTER ) val l = binding.chart1.legend