From 09b19cba615c136105ec693dd85bfb1ed92ab3ee Mon Sep 17 00:00:00 2001 From: RonakAndroid <48938792+RonakAndroid@users.noreply.github.com> Date: Tue, 27 Oct 2020 22:35:33 +0530 Subject: [PATCH] Get Fork Upstream (#1) * Create FUNDING.yml * Update FUNDING.yml * Update README.md * Safe guards These will be even more important when moving to Kotlin ranges * Added highlightColor parameter for pie charts https://github.com/danielgindi/Charts/pull/2961 * Consider axis dependency in Combined chart https://github.com/danielgindi/Charts/pull/2874 * Added an implementation of Douglas Peucker with resultCount input https://github.com/danielgindi/Charts/pull/2848 * Fixed axis label disappearing when zooming in https://github.com/danielgindi/Charts/pull/3132 * Make min/max axis labels configurable https://github.com/danielgindi/Charts/pull/2894 * Avoid race condition for interval/intervalMagnitude https://github.com/danielgindi/Charts/pull/2377 * Custom text alignment for no-data https://github.com/danielgindi/Charts/pull/3199 * Select correct axis for legend distance calculation in horz bar chart https://github.com/danielgindi/Charts/pull/2214 * Use correct color index for bubble chart https://github.com/danielgindi/Charts/pull/3202 * Added dataIndex param for highlightValue (combined charts) https://github.com/danielgindi/Charts/pull/2852 * Reset min/max when clearing ChartDataSet https://github.com/danielgindi/Charts/pull/3265 * Call notifyDataChanged for an opportunity for subclasses * Add a warning message if pie chart has more than one data set https://github.com/danielgindi/Charts/pull/3286 * Add option to disable clipping data to contentRect https://github.com/danielgindi/Charts/pull/3360 * Support for labelXOffset for YAxis label * This is for the inline bubble selection https://github.com/danielgindi/Charts/pull/3548 * Fixed index out of bounds issue when using stacked bar chart https://github.com/danielgindi/Charts/commit/b03cf16ec47437c066e17b5b8f77322111695e6a * Improve min/max calculation https://github.com/danielgindi/Charts/pull/3650 * Call onChartScale listener after double-tap-zoom https://github.com/danielgindi/Charts/pull/3770 * Multiple colors for valueline https://github.com/danielgindi/Charts/pull/3709 * Renamed values -> entries for consistency https://github.com/danielgindi/Charts/pull/3847 * Improved negative offset for horz bar chart https://github.com/danielgindi/Charts/pull/3854 * maxHeight didn't account for the last label https://github.com/danielgindi/Charts/pull/3900 * Fixed a bug where a pie slice without highlight enabled is hidden https://github.com/danielgindi/Charts/pull/3969 * Remove unexpected dash line during linear animation https://github.com/danielgindi/Charts/pull/4094 * Corrected check for line in vertical bounds https://github.com/danielgindi/Charts/pull/4100 * Finalized vertical line collision check * Fixed merge residue * Implement a more generic Fill class instead of GradientColor Support HorizontalBarChart too. * Update LICENSE The LICENSE file was not properly filled out. It was missing some templates that were supposed to be filled in at the end of the license. Additionally, the entire Apache 2.0 license is not required on a project that makes use of it. Only this disclaimer is required. See http://www.apache.org/licenses/LICENSE-2.0#apply under the "How to apply the Apache License to your work" for more information. * fix NPE when use solid color with barchart * Update BarChartRenderer.java * Update HorizontalBarChartRenderer.java * Update BarChartRenderer.java * Update README.md * Update README.md * Update README.md * Update LICENSE * Revert: e5b66192 - bring back polymorphism to value formatters If anyone does not know how to add a space or change the format in anyway, please learn how to subclass. Co-authored-by: Philipp Jahoda Co-authored-by: Daniel Cohen Gindi Co-authored-by: Nathan Fiscaletti Co-authored-by: Anirut Teerabut Co-authored-by: Anirut Teerabut --- .github/FUNDING.yml | 12 + .gitignore | 6 +- LICENSE | 192 +--------- MPChartExample/src/main/AndroidManifest.xml | 1 + .../mpchartexample/BarChartActivity.java | 31 +- .../BarChartActivityMultiDataset.java | 8 +- .../BarChartPositiveNegative.java | 19 +- .../mpchartexample/CombinedChartActivity.java | 8 +- .../HorizontalBarNegativeChartActivity.java | 292 +++++++++++++++ .../mpchartexample/LineChartTime.java | 8 +- .../mpchartexample/PieChartActivity.java | 2 +- .../PiePolylineChartActivity.java | 1 - .../mpchartexample/RadarChartActivity.java | 8 +- .../mpchartexample/StackedBarActivity.java | 6 +- .../StackedBarActivityNegative.java | 21 +- .../custom/DayAxisValueFormatter.java | 7 +- .../custom/MyAxisValueFormatter.java | 21 ++ .../custom/MyCustomXAxisValueFormatter.java | 7 +- .../custom/MyValueFormatter.java | 27 +- .../mpchartexample/custom/XYMarkerView.java | 9 +- .../custom/YearXAxisFormatter.java | 6 +- .../notimportant/MainActivity.java | 83 +++-- .../charting/charts/BarLineChartBase.java | 155 ++++---- .../mikephil/charting/charts/Chart.java | 93 ++++- .../charting/charts/HorizontalBarChart.java | 78 ++++ .../mikephil/charting/charts/RadarChart.java | 1 + .../charting/components/AxisBase.java | 52 ++- .../mikephil/charting/components/Legend.java | 3 +- .../mikephil/charting/components/YAxis.java | 41 +++ .../mikephil/charting/data/BarDataSet.java | 72 +++- .../mikephil/charting/data/BaseDataSet.java | 49 +-- .../mikephil/charting/data/BubbleDataSet.java | 4 +- .../mikephil/charting/data/CandleDataSet.java | 4 +- .../mikephil/charting/data/ChartData.java | 9 +- .../mikephil/charting/data/CombinedData.java | 33 +- .../mikephil/charting/data/DataSet.java | 127 ++++--- .../mikephil/charting/data/LineDataSet.java | 4 +- .../charting/data/LineRadarDataSet.java | 1 + .../mikephil/charting/data/PieData.java | 14 + .../mikephil/charting/data/PieDataSet.java | 52 ++- .../mikephil/charting/data/RadarDataSet.java | 4 +- .../charting/data/ScatterDataSet.java | 4 +- .../charting/data/filter/ApproximatorN.java | 146 ++++++++ .../formatter/DefaultAxisValueFormatter.java | 8 +- .../formatter/DefaultValueFormatter.java | 8 +- .../formatter/IAxisValueFormatter.java | 6 - .../charting/formatter/IValueFormatter.java | 10 +- .../formatter/IndexAxisValueFormatter.java | 12 +- .../formatter/LargeValueFormatter.java | 16 +- .../charting/formatter/PercentFormatter.java | 51 ++- .../formatter/StackedValueFormatter.java | 24 +- .../charting/formatter/ValueFormatter.java | 137 ------- .../charting/highlight/Highlight.java | 8 + .../dataprovider/ChartInterface.java | 4 +- .../interfaces/datasets/IBarDataSet.java | 7 + .../interfaces/datasets/IDataSet.java | 30 +- .../interfaces/datasets/IPieDataSet.java | 16 +- .../listener/BarLineChartTouchListener.java | 9 +- .../listener/OnChartGestureListener.java | 2 +- .../charting/model/GradientColor.java | 73 +++- .../charting/renderer/AxisRenderer.java | 14 +- .../charting/renderer/BarChartRenderer.java | 72 ++-- .../renderer/BubbleChartRenderer.java | 15 +- .../renderer/CandleStickChartRenderer.java | 20 +- .../renderer/CombinedChartRenderer.java | 7 +- .../charting/renderer/DataRenderer.java | 21 +- .../renderer/HorizontalBarChartRenderer.java | 41 ++- .../charting/renderer/LegendRenderer.java | 14 +- .../charting/renderer/LineChartRenderer.java | 41 ++- .../charting/renderer/PieChartRenderer.java | 54 +-- .../charting/renderer/RadarChartRenderer.java | 20 +- .../renderer/ScatterChartRenderer.java | 19 +- .../charting/renderer/XAxisRenderer.java | 3 +- .../XAxisRendererHorizontalBarChart.java | 7 +- .../renderer/XAxisRendererRadarChart.java | 4 +- .../charting/renderer/YAxisRenderer.java | 7 +- .../YAxisRendererHorizontalBarChart.java | 7 +- .../renderer/YAxisRendererRadarChart.java | 12 +- .../github/mikephil/charting/utils/Fill.java | 342 ++++++++++++++++++ .../github/mikephil/charting/utils/Utils.java | 24 +- .../test/LargeValueFormatterTest.java | 50 +-- .../charting/test/ObjectPoolTest.java | 2 +- README.md | 24 +- 83 files changed, 1964 insertions(+), 998 deletions(-) create mode 100644 .github/FUNDING.yml create mode 100644 MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/HorizontalBarNegativeChartActivity.java create mode 100644 MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java create mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/data/filter/ApproximatorN.java delete mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/formatter/ValueFormatter.java create mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/utils/Fill.java diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000000..0a213d6792 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,12 @@ +# These are supported funding model platforms + +github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +patreon: mpandroidchart +open_collective: philippjahoda +ko_fi: # Replace with a single Ko-fi username +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/.gitignore b/.gitignore index 1f0e3083c2..feed37b27d 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ bin/ gen/ generated/ +docs/ finalOutput/ projectFilesBackup/ @@ -23,8 +24,6 @@ local.properties # Eclipse project files .classpath .project -.settings/ -.vscode/ # Proguard folder generated by Eclipse proguard/ @@ -33,8 +32,7 @@ proguard/ *.iml *.ipr *.iws -/.idea/* -!/.idea/runConfigurations +.idea/ .directory diff --git a/LICENSE b/LICENSE index 8dada3edaf..c1551a9dce 100644 --- a/LICENSE +++ b/LICENSE @@ -1,195 +1,7 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} + Copyright 2020 Philipp Jahoda Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. + you may not use this software except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 diff --git a/MPChartExample/src/main/AndroidManifest.xml b/MPChartExample/src/main/AndroidManifest.xml index 28c55b89b2..99334e601a 100644 --- a/MPChartExample/src/main/AndroidManifest.xml +++ b/MPChartExample/src/main/AndroidManifest.xml @@ -24,6 +24,7 @@ + diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 4af0441ddb..0d83e3444a 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -1,3 +1,4 @@ + package com.xxmassdeveloper.mpchartexample; import android.Manifest; @@ -27,15 +28,15 @@ import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.formatter.IAxisValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; -import com.github.mikephil.charting.model.GradientColor; +import com.github.mikephil.charting.utils.Fill; import com.github.mikephil.charting.utils.MPPointF; import com.xxmassdeveloper.mpchartexample.custom.DayAxisValueFormatter; -import com.xxmassdeveloper.mpchartexample.custom.MyValueFormatter; +import com.xxmassdeveloper.mpchartexample.custom.MyAxisValueFormatter; import com.xxmassdeveloper.mpchartexample.custom.XYMarkerView; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -85,7 +86,7 @@ protected void onCreate(Bundle savedInstanceState) { chart.setDrawGridBackground(false); // chart.setDrawYLabels(false); - ValueFormatter xAxisFormatter = new DayAxisValueFormatter(chart); + IAxisValueFormatter xAxisFormatter = new DayAxisValueFormatter(chart); XAxis xAxis = chart.getXAxis(); xAxis.setPosition(XAxisPosition.BOTTOM); @@ -95,7 +96,7 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setLabelCount(7); xAxis.setValueFormatter(xAxisFormatter); - ValueFormatter custom = new MyValueFormatter("$"); + IAxisValueFormatter custom = new MyAxisValueFormatter(); YAxis leftAxis = chart.getAxisLeft(); leftAxis.setTypeface(tfLight); @@ -164,12 +165,6 @@ private void setData(int count, float range) { set1.setDrawIcons(false); -// set1.setColors(ColorTemplate.MATERIAL_COLORS); - - /*int startColor = ContextCompat.getColor(this, android.R.color.holo_blue_dark); - int endColor = ContextCompat.getColor(this, android.R.color.holo_blue_bright); - set1.setGradientColor(startColor, endColor);*/ - int startColor1 = ContextCompat.getColor(this, android.R.color.holo_orange_light); int startColor2 = ContextCompat.getColor(this, android.R.color.holo_blue_light); int startColor3 = ContextCompat.getColor(this, android.R.color.holo_orange_light); @@ -181,14 +176,14 @@ private void setData(int count, float range) { int endColor4 = ContextCompat.getColor(this, android.R.color.holo_red_dark); int endColor5 = ContextCompat.getColor(this, android.R.color.holo_orange_dark); - List gradientColors = new ArrayList<>(); - gradientColors.add(new GradientColor(startColor1, endColor1)); - gradientColors.add(new GradientColor(startColor2, endColor2)); - gradientColors.add(new GradientColor(startColor3, endColor3)); - gradientColors.add(new GradientColor(startColor4, endColor4)); - gradientColors.add(new GradientColor(startColor5, endColor5)); + List gradientFills = new ArrayList<>(); + gradientFills.add(new Fill(startColor1, endColor1)); + gradientFills.add(new Fill(startColor2, endColor2)); + gradientFills.add(new Fill(startColor3, endColor3)); + gradientFills.add(new Fill(startColor4, endColor4)); + gradientFills.add(new Fill(startColor5, endColor5)); - set1.setGradientColors(gradientColors); + set1.setFills(gradientFills); ArrayList dataSets = new ArrayList<>(); dataSets.add(set1); diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index 3369dbf6e2..075af0edbc 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -1,3 +1,4 @@ + package com.xxmassdeveloper.mpchartexample; import android.Manifest; @@ -16,6 +17,7 @@ import android.widget.TextView; import com.github.mikephil.charting.charts.BarChart; +import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; @@ -23,8 +25,8 @@ import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.formatter.IAxisValueFormatter; import com.github.mikephil.charting.formatter.LargeValueFormatter; -import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; @@ -98,9 +100,9 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setTypeface(tfLight); xAxis.setGranularity(1f); xAxis.setCenterAxisLabels(true); - xAxis.setValueFormatter(new ValueFormatter() { + xAxis.setValueFormatter(new IAxisValueFormatter() { @Override - public String getFormattedValue(float value) { + public String getFormattedValue(float value, AxisBase axis) { return String.valueOf((int) value); } }); diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java index 8960dc770f..4fec7dd6ab 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java @@ -1,3 +1,4 @@ + package com.xxmassdeveloper.mpchartexample; import android.content.Intent; @@ -9,13 +10,17 @@ import android.view.WindowManager; import com.github.mikephil.charting.charts.BarChart; +import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.formatter.IAxisValueFormatter; +import com.github.mikephil.charting.formatter.IValueFormatter; +import com.github.mikephil.charting.utils.ViewPortHandler; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.text.DecimalFormat; @@ -83,9 +88,9 @@ protected void onCreate(Bundle savedInstanceState) { data.add(new Data(3f, -442.3f, "01-01")); data.add(new Data(4f, -2280.1f, "01-02")); - xAxis.setValueFormatter(new ValueFormatter() { + xAxis.setValueFormatter(new IAxisValueFormatter() { @Override - public String getFormattedValue(float value) { + public String getFormattedValue(float value, AxisBase axis) { return data.get(Math.min(Math.max((int) value, 0), data.size()-1)).xAxisValue; } }); @@ -130,7 +135,7 @@ private void setData(List dataList) { BarData data = new BarData(set); data.setValueTextSize(13f); data.setValueTypeface(tfRegular); - data.setValueFormatter(new Formatter()); + data.setValueFormatter(new ValueFormatter()); data.setBarWidth(0.8f); chart.setData(data); @@ -154,17 +159,17 @@ private class Data { } } - private class Formatter extends ValueFormatter + private class ValueFormatter implements IValueFormatter { private final DecimalFormat mFormat; - Formatter() { + ValueFormatter() { mFormat = new DecimalFormat("######.0"); } @Override - public String getFormattedValue(float value) { + public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { return mFormat.format(value); } } diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index 53dd3806bc..0308b9a891 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -1,3 +1,4 @@ + package com.xxmassdeveloper.mpchartexample; import android.content.Intent; @@ -10,6 +11,7 @@ import com.github.mikephil.charting.charts.CombinedChart; import com.github.mikephil.charting.charts.CombinedChart.DrawOrder; +import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; @@ -29,7 +31,7 @@ import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.data.ScatterData; import com.github.mikephil.charting.data.ScatterDataSet; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.formatter.IAxisValueFormatter; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -81,9 +83,9 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setPosition(XAxisPosition.BOTH_SIDED); xAxis.setAxisMinimum(0f); xAxis.setGranularity(1f); - xAxis.setValueFormatter(new ValueFormatter() { + xAxis.setValueFormatter(new IAxisValueFormatter() { @Override - public String getFormattedValue(float value) { + public String getFormattedValue(float value, AxisBase axis) { return months[(int) value % months.length]; } }); diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/HorizontalBarNegativeChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/HorizontalBarNegativeChartActivity.java new file mode 100644 index 0000000000..86d578cc43 --- /dev/null +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/HorizontalBarNegativeChartActivity.java @@ -0,0 +1,292 @@ + +package com.xxmassdeveloper.mpchartexample; + +import android.Manifest; +import android.annotation.SuppressLint; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.graphics.RectF; +import android.net.Uri; +import android.os.Bundle; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.view.WindowManager; +import android.widget.SeekBar; +import android.widget.SeekBar.OnSeekBarChangeListener; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.core.content.ContextCompat; + +import com.github.mikephil.charting.charts.HorizontalBarChart; +import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.XAxis.XAxisPosition; +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.BarData; +import com.github.mikephil.charting.data.BarDataSet; +import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.listener.OnChartValueSelectedListener; +import com.github.mikephil.charting.utils.MPPointF; +import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; + +import java.util.ArrayList; +import java.util.List; + +public class HorizontalBarNegativeChartActivity extends DemoBase implements OnSeekBarChangeListener, + OnChartValueSelectedListener { + + private HorizontalBarChart chart; + private SeekBar seekBarX, seekBarY; + private TextView tvX, tvY; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_horizontalbarchart); + + setTitle("HorizontalBarChartActivity"); + + tvX = findViewById(R.id.tvXMax); + tvY = findViewById(R.id.tvYMax); + + seekBarX = findViewById(R.id.seekBar1); + seekBarY = findViewById(R.id.seekBar2); + + seekBarY.setOnSeekBarChangeListener(this); + seekBarX.setOnSeekBarChangeListener(this); + + chart = findViewById(R.id.chart1); + chart.setOnChartValueSelectedListener(this); + // chart.setHighlightEnabled(false); + + chart.setDrawBarShadow(false); + + chart.setDrawValueAboveBar(true); + + chart.getDescription().setEnabled(false); + + // if more than 60 entries are displayed in the chart, no values will be + // drawn + chart.setMaxVisibleValueCount(60); + + // scaling can now only be done on x- and y-axis separately + chart.setPinchZoom(false); + + // draw shadows for each bar that show the maximum value + // chart.setDrawBarShadow(true); + + chart.setDrawGridBackground(false); + + XAxis xl = chart.getXAxis(); + xl.setPosition(XAxisPosition.BOTTOM); + xl.setTypeface(tfLight); + xl.setDrawAxisLine(true); + xl.setDrawGridLines(false); + xl.setGranularity(10f); + + YAxis yl = chart.getAxisLeft(); + yl.setTypeface(tfLight); + yl.setDrawAxisLine(true); + yl.setDrawGridLines(true); +// yl.setInverted(true); + + YAxis yr = chart.getAxisRight(); + yr.setTypeface(tfLight); + yr.setDrawAxisLine(true); + yr.setDrawGridLines(false); +// yr.setInverted(true); + + chart.setFitBars(true); + chart.animateY(2500); + + // setting data + seekBarY.setProgress(50); + seekBarX.setProgress(12); + + Legend l = chart.getLegend(); + l.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM); + l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.LEFT); + l.setOrientation(Legend.LegendOrientation.HORIZONTAL); + l.setDrawInside(false); + l.setFormSize(8f); + l.setXEntrySpace(4f); + } + + private void setData(int count, float range) { + + float barWidth = 9f; + float spaceForBar = 10f; + ArrayList values = new ArrayList<>(); + + for (int i = 0; i < count; i++) { + float val = (float) (Math.random() * range - range / 2); + values.add(new BarEntry(i * spaceForBar, val, + getResources().getDrawable(R.drawable.star))); + } + + BarDataSet set1; + + if (chart.getData() != null && + chart.getData().getDataSetCount() > 0) { + set1 = (BarDataSet) chart.getData().getDataSetByIndex(0); + set1.setValues(values); + chart.getData().notifyDataChanged(); + chart.notifyDataSetChanged(); + } else { + set1 = new BarDataSet(values, "DataSet 1"); + + set1.setDrawIcons(false); + + ArrayList dataSets = new ArrayList<>(); + dataSets.add(set1); + + BarData data = new BarData(dataSets); + data.setValueTextSize(10f); + data.setValueTypeface(tfLight); + data.setBarWidth(barWidth); + chart.setData(data); + } + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.bar, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java")); + startActivity(i); + break; + } + case R.id.actionToggleValues: { + List sets = chart.getData() + .getDataSets(); + + for (IBarDataSet iSet : sets) { + iSet.setDrawValues(!iSet.isDrawValuesEnabled()); + } + + chart.invalidate(); + break; + } + case R.id.actionToggleIcons: { + List sets = chart.getData() + .getDataSets(); + + for (IBarDataSet iSet : sets) { + iSet.setDrawIcons(!iSet.isDrawIconsEnabled()); + } + + chart.invalidate(); + break; + } + case R.id.actionToggleHighlight: { + if(chart.getData() != null) { + chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); + chart.invalidate(); + } + break; + } + case R.id.actionTogglePinch: { + if (chart.isPinchZoomEnabled()) + chart.setPinchZoom(false); + else + chart.setPinchZoom(true); + + chart.invalidate(); + break; + } + case R.id.actionToggleAutoScaleMinMax: { + chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled()); + chart.notifyDataSetChanged(); + break; + } + case R.id.actionToggleBarBorders: { + for (IBarDataSet set : chart.getData().getDataSets()) + ((BarDataSet)set).setBarBorderWidth(set.getBarBorderWidth() == 1.f ? 0.f : 1.f); + + chart.invalidate(); + break; + } + case R.id.animateX: { + chart.animateX(2000); + break; + } + case R.id.animateY: { + chart.animateY(2000); + break; + } + case R.id.animateXY: { + chart.animateXY(2000, 2000); + break; + } + case R.id.actionSave: { + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } + break; + } + } + return true; + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + + tvX.setText(String.valueOf(seekBarX.getProgress())); + tvY.setText(String.valueOf(seekBarY.getProgress())); + + setData(seekBarX.getProgress(), seekBarY.getProgress()); + chart.setFitBars(true); + chart.invalidate(); + } + + @Override + protected void saveToGallery() { + saveToGallery(chart, "HorizontalBarChartActivity"); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) {} + + @Override + public void onStopTrackingTouch(SeekBar seekBar) {} + + private final RectF mOnValueSelectedRectF = new RectF(); + + @Override + public void onValueSelected(Entry e, Highlight h) { + + if (e == null) + return; + + RectF bounds = mOnValueSelectedRectF; + chart.getBarBounds((BarEntry) e, bounds); + + MPPointF position = chart.getPosition(e, chart.getData().getDataSetByIndex(h.getDataSetIndex()) + .getAxisDependency()); + + Log.i("bounds", bounds.toString()); + Log.i("position", position.toString()); + + MPPointF.recycleInstance(position); + } + + @Override + public void onNothingSelected() {} +} diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartTime.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartTime.java index e9ae3c0e43..212b90ff87 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartTime.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartTime.java @@ -1,3 +1,4 @@ + package com.xxmassdeveloper.mpchartexample; import android.Manifest; @@ -15,6 +16,7 @@ import android.widget.TextView; import com.github.mikephil.charting.charts.LineChart; +import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; @@ -22,7 +24,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.formatter.IAxisValueFormatter; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -90,12 +92,12 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setTextColor(Color.rgb(255, 192, 56)); xAxis.setCenterAxisLabels(true); xAxis.setGranularity(1f); // one hour - xAxis.setValueFormatter(new ValueFormatter() { + xAxis.setValueFormatter(new IAxisValueFormatter() { private final SimpleDateFormat mFormat = new SimpleDateFormat("dd MMM HH:mm", Locale.ENGLISH); @Override - public String getFormattedValue(float value) { + public String getFormattedValue(float value, AxisBase axis) { long millis = TimeUnit.HOURS.toMillis((long) value); return mFormat.format(new Date(millis)); diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index 4aeb1b3e9f..830025fbb1 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -160,7 +160,7 @@ private void setData(int count, float range) { //dataSet.setSelectionShift(0f); PieData data = new PieData(dataSet); - data.setValueFormatter(new PercentFormatter(chart)); + data.setValueFormatter(new PercentFormatter()); data.setValueTextSize(11f); data.setValueTextColor(Color.WHITE); data.setValueTypeface(tfLight); diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java index b276806c7d..dd3bd575da 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java @@ -156,7 +156,6 @@ private void setData(int count, float range) { dataSet.setValueLinePart1OffsetPercentage(80.f); dataSet.setValueLinePart1Length(0.2f); dataSet.setValueLinePart2Length(0.4f); - //dataSet.setUsingSliceColorAsValueLineColor(true); //dataSet.setXValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE); dataSet.setYValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE); diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java index 9fdae983d0..883eb7dfc1 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java @@ -1,3 +1,4 @@ + package com.xxmassdeveloper.mpchartexample; import android.Manifest; @@ -13,6 +14,7 @@ import com.github.mikephil.charting.animation.Easing; import com.github.mikephil.charting.charts.RadarChart; +import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.MarkerView; import com.github.mikephil.charting.components.XAxis; @@ -20,7 +22,7 @@ import com.github.mikephil.charting.data.RadarData; import com.github.mikephil.charting.data.RadarDataSet; import com.github.mikephil.charting.data.RadarEntry; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.formatter.IAxisValueFormatter; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.interfaces.datasets.IRadarDataSet; import com.xxmassdeveloper.mpchartexample.custom.RadarMarkerView; @@ -67,12 +69,12 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setTextSize(9f); xAxis.setYOffset(0f); xAxis.setXOffset(0f); - xAxis.setValueFormatter(new ValueFormatter() { + xAxis.setValueFormatter(new IAxisValueFormatter() { private final String[] mActivities = new String[]{"Burger", "Steak", "Salad", "Pasta", "Pizza"}; @Override - public String getFormattedValue(float value) { + public String getFormattedValue(float value, AxisBase axis) { return mActivities[(int) value % mActivities.length]; } }); diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index 1def86e8ef..676e0e62b0 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -24,11 +24,11 @@ import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.formatter.StackedValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; +import com.xxmassdeveloper.mpchartexample.custom.MyAxisValueFormatter; import com.xxmassdeveloper.mpchartexample.custom.MyValueFormatter; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -78,7 +78,7 @@ protected void onCreate(Bundle savedInstanceState) { // change the position of the y-labels YAxis leftAxis = chart.getAxisLeft(); - leftAxis.setValueFormatter(new MyValueFormatter("K")); + leftAxis.setValueFormatter(new MyAxisValueFormatter()); leftAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true) chart.getAxisRight().setEnabled(false); @@ -142,7 +142,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { dataSets.add(set1); BarData data = new BarData(dataSets); - data.setValueFormatter(new StackedValueFormatter(false, "", 1)); + data.setValueFormatter(new MyValueFormatter()); data.setValueTextColor(Color.WHITE); chart.setData(data); diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java index a4e510a20f..7af58c85ca 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java @@ -1,3 +1,4 @@ + package com.xxmassdeveloper.mpchartexample; import android.Manifest; @@ -13,6 +14,7 @@ import android.view.WindowManager; import com.github.mikephil.charting.charts.HorizontalBarChart; +import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; @@ -21,10 +23,12 @@ import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.formatter.IValueFormatter; +import com.github.mikephil.charting.formatter.IAxisValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; +import com.github.mikephil.charting.utils.ViewPortHandler; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.text.DecimalFormat; @@ -76,12 +80,12 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setCenterAxisLabels(true); xAxis.setLabelCount(12); xAxis.setGranularity(10f); - xAxis.setValueFormatter(new ValueFormatter() { + xAxis.setValueFormatter(new IAxisValueFormatter() { private final DecimalFormat format = new DecimalFormat("###"); @Override - public String getFormattedValue(float value) { + public String getFormattedValue(float value, AxisBase axis) { return format.format(value) + "-" + format.format(value + 10); } }); @@ -238,7 +242,7 @@ public void onNothingSelected() { Log.i("NOTING SELECTED", ""); } - private class CustomFormatter extends ValueFormatter { + private class CustomFormatter implements IValueFormatter, IAxisValueFormatter { private final DecimalFormat mFormat; @@ -246,8 +250,15 @@ private class CustomFormatter extends ValueFormatter { mFormat = new DecimalFormat("###"); } + // data + @Override + public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { + return mFormat.format(Math.abs(value)) + "m"; + } + + // YAxis @Override - public String getFormattedValue(float value) { + public String getFormattedValue(float value, AxisBase axis) { return mFormat.format(Math.abs(value)) + "m"; } } diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java index 1fba5cc98e..ba4d860d92 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java @@ -1,12 +1,13 @@ package com.xxmassdeveloper.mpchartexample.custom; import com.github.mikephil.charting.charts.BarLineChartBase; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.components.AxisBase; +import com.github.mikephil.charting.formatter.IAxisValueFormatter; /** * Created by philipp on 02/06/16. */ -public class DayAxisValueFormatter extends ValueFormatter +public class DayAxisValueFormatter implements IAxisValueFormatter { private final String[] mMonths = new String[]{ @@ -20,7 +21,7 @@ public DayAxisValueFormatter(BarLineChartBase chart) { } @Override - public String getFormattedValue(float value) { + public String getFormattedValue(float value, AxisBase axis) { int days = (int) value; diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java new file mode 100644 index 0000000000..e7cdbfcd10 --- /dev/null +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java @@ -0,0 +1,21 @@ +package com.xxmassdeveloper.mpchartexample.custom; + +import com.github.mikephil.charting.components.AxisBase; +import com.github.mikephil.charting.formatter.IAxisValueFormatter; + +import java.text.DecimalFormat; + +public class MyAxisValueFormatter implements IAxisValueFormatter +{ + + private final DecimalFormat mFormat; + + public MyAxisValueFormatter() { + mFormat = new DecimalFormat("###,###,###,##0.0"); + } + + @Override + public String getFormattedValue(float value, AxisBase axis) { + return mFormat.format(value) + " $"; + } +} diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java index 2cf2eab7ba..bea4908ef2 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java @@ -1,6 +1,7 @@ package com.xxmassdeveloper.mpchartexample.custom; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.components.AxisBase; +import com.github.mikephil.charting.formatter.IAxisValueFormatter; import com.github.mikephil.charting.utils.ViewPortHandler; import java.text.DecimalFormat; @@ -11,7 +12,7 @@ * @deprecated The {@link MyAxisValueFormatter} does exactly the same thing and is more functional. */ @Deprecated -public class MyCustomXAxisValueFormatter extends ValueFormatter +public class MyCustomXAxisValueFormatter implements IAxisValueFormatter { private final DecimalFormat mFormat; @@ -24,7 +25,7 @@ public MyCustomXAxisValueFormatter(ViewPortHandler viewPortHandler) { } @Override - public String getFormattedValue(float value) { + public String getFormattedValue(float value, AxisBase axis) { //Log.i("TRANS", "x: " + viewPortHandler.getTransX() + ", y: " + viewPortHandler.getTransY()); diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java index 0b0bf2f2ab..ec1c119818 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java @@ -1,35 +1,22 @@ package com.xxmassdeveloper.mpchartexample.custom; -import com.github.mikephil.charting.components.AxisBase; -import com.github.mikephil.charting.components.XAxis; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.formatter.IValueFormatter; +import com.github.mikephil.charting.utils.ViewPortHandler; import java.text.DecimalFormat; -public class MyValueFormatter extends ValueFormatter +public class MyValueFormatter implements IValueFormatter { private final DecimalFormat mFormat; - private String suffix; - public MyValueFormatter(String suffix) { + public MyValueFormatter() { mFormat = new DecimalFormat("###,###,###,##0.0"); - this.suffix = suffix; } @Override - public String getFormattedValue(float value) { - return mFormat.format(value) + suffix; - } - - @Override - public String getAxisLabel(float value, AxisBase axis) { - if (axis instanceof XAxis) { - return mFormat.format(value); - } else if (value > 0) { - return mFormat.format(value) + suffix; - } else { - return mFormat.format(value); - } + public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { + return mFormat.format(value) + " $"; } } diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java index ed9dcb8a23..51e4247d35 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java @@ -1,3 +1,4 @@ + package com.xxmassdeveloper.mpchartexample.custom; import android.annotation.SuppressLint; @@ -6,7 +7,7 @@ import com.github.mikephil.charting.components.MarkerView; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.formatter.IAxisValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.MPPointF; import com.xxmassdeveloper.mpchartexample.R; @@ -22,11 +23,11 @@ public class XYMarkerView extends MarkerView { private final TextView tvContent; - private final ValueFormatter xAxisValueFormatter; + private final IAxisValueFormatter xAxisValueFormatter; private final DecimalFormat format; - public XYMarkerView(Context context, ValueFormatter xAxisValueFormatter) { + public XYMarkerView(Context context, IAxisValueFormatter xAxisValueFormatter) { super(context, R.layout.custom_marker_view); this.xAxisValueFormatter = xAxisValueFormatter; @@ -39,7 +40,7 @@ public XYMarkerView(Context context, ValueFormatter xAxisValueFormatter) { @Override public void refreshContent(Entry e, Highlight highlight) { - tvContent.setText(String.format("x: %s, y: %s", xAxisValueFormatter.getFormattedValue(e.getX()), format.format(e.getY()))); + tvContent.setText(String.format("x: %s, y: %s", xAxisValueFormatter.getFormattedValue(e.getX(), null), format.format(e.getY()))); super.refreshContent(e, highlight); } diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/YearXAxisFormatter.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/YearXAxisFormatter.java index d45853f8d4..7122e0d80c 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/YearXAxisFormatter.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/YearXAxisFormatter.java @@ -1,13 +1,13 @@ package com.xxmassdeveloper.mpchartexample.custom; import com.github.mikephil.charting.components.AxisBase; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.formatter.IAxisValueFormatter; /** * Created by Philipp Jahoda on 14/09/15. */ @SuppressWarnings("unused") -public class YearXAxisFormatter extends ValueFormatter +public class YearXAxisFormatter implements IAxisValueFormatter { private final String[] mMonths = new String[]{ @@ -19,7 +19,7 @@ public YearXAxisFormatter() { } @Override - public String getAxisLabel(float value, AxisBase axis) { + public String getFormattedValue(float value, AxisBase axis) { float percent = value / axis.mAxisRange; return mMonths[(int) (mMonths.length * percent)]; 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 67749e742f..88e5dc8d8b 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java @@ -26,6 +26,7 @@ import com.xxmassdeveloper.mpchartexample.FilledLineActivity; import com.xxmassdeveloper.mpchartexample.HalfPieChartActivity; import com.xxmassdeveloper.mpchartexample.HorizontalBarChartActivity; +import com.xxmassdeveloper.mpchartexample.HorizontalBarNegativeChartActivity; import com.xxmassdeveloper.mpchartexample.InvertedLineChartActivity; import com.xxmassdeveloper.mpchartexample.LineChartActivity1; import com.xxmassdeveloper.mpchartexample.LineChartActivity2; @@ -87,40 +88,41 @@ protected void onCreate(Bundle savedInstanceState) { objects.add(13, new ContentItem("Horizontal", "Render bar chart horizontally.")); objects.add(14, new ContentItem("Stacked", "Stacked bar chart.")); objects.add(15, new ContentItem("Negative", "Positive and negative values with unique colors.")); - objects.add(16, new ContentItem("Stacked 2", "Stacked bar chart with negative values.")); - objects.add(17, new ContentItem("Sine", "Sine function in bar chart format.")); + objects.add(16, new ContentItem("Negative Horizontal", "demonstrates how to create a HorizontalBarChart with positive and negative values.")); + objects.add(17, new ContentItem("Stacked 2", "Stacked bar chart with negative values.")); + objects.add(18, new ContentItem("Sine", "Sine function in bar chart format.")); //// - objects.add(18, new ContentItem("Pie Charts")); + objects.add(19, new ContentItem("Pie Charts")); - objects.add(19, new ContentItem("Basic", "Simple pie chart.")); - objects.add(20, new ContentItem("Value Lines", "Stylish lines drawn outward from slices.")); - objects.add(21, new ContentItem("Half Pie", "180° (half) pie chart.")); + objects.add(20, new ContentItem("Basic", "Simple pie chart.")); + objects.add(21, new ContentItem("Value Lines", "Stylish lines drawn outward from slices.")); + objects.add(22, new ContentItem("Half Pie", "180° (half) pie chart.")); //// - objects.add(22, new ContentItem("Other Charts")); + objects.add(23, new ContentItem("Other Charts")); - objects.add(23, new ContentItem("Combined Chart", "Bar and line chart together.")); - objects.add(24, new ContentItem("Scatter Plot", "Simple scatter plot.")); - objects.add(25, new ContentItem("Bubble Chart", "Simple bubble chart.")); - objects.add(26, new ContentItem("Candlestick", "Simple financial chart.")); - objects.add(27, new ContentItem("Radar Chart", "Simple web chart.")); + objects.add(24, new ContentItem("Combined Chart", "Bar and line chart together.")); + objects.add(25, new ContentItem("Scatter Plot", "Simple scatter plot.")); + objects.add(26, new ContentItem("Bubble Chart", "Simple bubble chart.")); + objects.add(27, new ContentItem("Candlestick", "Simple financial chart.")); + objects.add(28, new ContentItem("Radar Chart", "Simple web chart.")); //// - objects.add(28, new ContentItem("Scrolling Charts")); + objects.add(29, new ContentItem("Scrolling Charts")); - objects.add(29, new ContentItem("Multiple", "Various types of charts as fragments.")); - objects.add(30, new ContentItem("View Pager", "Swipe through different charts.")); - objects.add(31, new ContentItem("Tall Bar Chart", "Bars bigger than your screen!")); - objects.add(32, new ContentItem("Many Bar Charts", "More bars than your screen can handle!")); + objects.add(30, new ContentItem("Multiple", "Various types of charts as fragments.")); + objects.add(31, new ContentItem("View Pager", "Swipe through different charts.")); + objects.add(32, new ContentItem("Tall Bar Chart", "Bars bigger than your screen!")); + objects.add(33, new ContentItem("Many Bar Charts", "More bars than your screen can handle!")); //// - objects.add(33, new ContentItem("Even More Line Charts")); + objects.add(34, new ContentItem("Even More Line Charts")); - objects.add(34, new ContentItem("Dynamic", "Build a line chart by adding points and sets.")); - objects.add(35, new ContentItem("Realtime", "Add data points in realtime.")); - objects.add(36, new ContentItem("Hourly", "Uses the current time to add a data point for each hour.")); - //objects.add(37, new ContentItem("Realm.io Examples", "See more examples that use Realm.io mobile database.")); + objects.add(35, new ContentItem("Dynamic", "Build a line chart by adding points and sets.")); + objects.add(36, new ContentItem("Realtime", "Add data points in realtime.")); + objects.add(37, new ContentItem("Hourly", "Uses the current time to add a data point for each hour.")); + //objects.add(38, new ContentItem("Realm.io Examples", "See more examples that use Realm.io mobile database.")); MyAdapter adapter = new MyAdapter(this, objects); @@ -179,57 +181,60 @@ public void onItemClick(AdapterView av, View v, int pos, long arg3) { i = new Intent(this, BarChartPositiveNegative.class); break; case 16: - i = new Intent(this, StackedBarActivityNegative.class); + i = new Intent(this, HorizontalBarNegativeChartActivity.class); break; case 17: + i = new Intent(this, StackedBarActivityNegative.class); + break; + case 18: i = new Intent(this, BarChartActivitySinus.class); break; - case 19: + case 20: i = new Intent(this, PieChartActivity.class); break; - case 20: + case 21: i = new Intent(this, PiePolylineChartActivity.class); break; - case 21: + case 22: i = new Intent(this, HalfPieChartActivity.class); break; - case 23: + case 24: i = new Intent(this, CombinedChartActivity.class); break; - case 24: + case 25: i = new Intent(this, ScatterChartActivity.class); break; - case 25: + case 26: i = new Intent(this, BubbleChartActivity.class); break; - case 26: + case 27: i = new Intent(this, CandleStickChartActivity.class); break; - case 27: + case 28: i = new Intent(this, RadarChartActivity.class); break; - case 29: + case 30: i = new Intent(this, ListViewMultiChartActivity.class); break; - case 30: + case 31: i = new Intent(this, SimpleChartDemo.class); break; - case 31: + case 32: i = new Intent(this, ScrollViewActivity.class); break; - case 32: + case 33: i = new Intent(this, ListViewBarChartActivity.class); break; - case 34: + case 35: i = new Intent(this, DynamicalAddingActivity.class); break; - case 35: + case 36: i = new Intent(this, RealtimeLineChartActivity.class); break; - case 36: + case 37: i = new Intent(this, LineChartTime.class); break; - /*case 37: + /*case 38: i = new Intent(this, RealmMainActivity.class); break;*/ } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index 71f8a2d8a8..0926dff244 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -100,6 +100,8 @@ public abstract class BarLineChartBase= mData.getDataSetCount()) { highlightValue(null, callListener); } else { - highlightValue(new Highlight(x, y, dataSetIndex), callListener); + highlightValue(new Highlight(x, y, dataSetIndex, dataIndex), callListener); } } + /** + * Highlights any y-value at the given x-value in the given DataSet. + * Provide -1 as the dataSetIndex to undo all highlighting. + * @param x The x-value to highlight + * @param y The y-value to highlight. Supply `NaN` for "any" + * @param dataSetIndex The dataset index to search in + * @param callListener Should the listener be called for this change + */ + public void highlightValue(float x, float y, int dataSetIndex, boolean callListener) { + highlightValue(x, y, dataSetIndex, -1, callListener); + } + /** * Highlights the values represented by the provided Highlight object * This method *will not* call the listener. @@ -956,7 +1022,7 @@ public XAxis getXAxis() { * * @return */ - public ValueFormatter getDefaultValueFormatter() { + public IValueFormatter getDefaultValueFormatter() { return mDefaultValueFormatter; } @@ -1162,6 +1228,15 @@ public void setNoDataTextTypeface(Typeface tf) { mInfoPaint.setTypeface(tf); } + /** + * alignment of the no data text + * + * @param align + */ + public void setNoDataTextAlignment(Align align) { + mInfoPaint.setTextAlign(align); + } + /** * Set this to false to disable all gestures and touches on the chart, * default: true diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java index e4ec309d9f..9aac1ce97c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -60,6 +60,84 @@ protected void init() { private RectF mOffsetsBuffer = new RectF(); + protected void calculateLegendOffsets(RectF offsets) { + + offsets.left = 0.f; + offsets.right = 0.f; + offsets.top = 0.f; + offsets.bottom = 0.f; + + if (mLegend == null || !mLegend.isEnabled() || mLegend.isDrawInsideEnabled()) + return; + + switch (mLegend.getOrientation()) { + case VERTICAL: + + switch (mLegend.getHorizontalAlignment()) { + case LEFT: + offsets.left += Math.min(mLegend.mNeededWidth, + mViewPortHandler.getChartWidth() * mLegend.getMaxSizePercent()) + + mLegend.getXOffset(); + break; + + case RIGHT: + offsets.right += Math.min(mLegend.mNeededWidth, + mViewPortHandler.getChartWidth() * mLegend.getMaxSizePercent()) + + mLegend.getXOffset(); + break; + + case CENTER: + + switch (mLegend.getVerticalAlignment()) { + case TOP: + offsets.top += Math.min(mLegend.mNeededHeight, + mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()) + + mLegend.getYOffset(); + break; + + case BOTTOM: + offsets.bottom += Math.min(mLegend.mNeededHeight, + mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()) + + mLegend.getYOffset(); + break; + + default: + break; + } + } + + break; + + case HORIZONTAL: + + switch (mLegend.getVerticalAlignment()) { + case TOP: + offsets.top += Math.min(mLegend.mNeededHeight, + mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()) + + mLegend.getYOffset(); + + if (mAxisLeft.isEnabled() && mAxisLeft.isDrawLabelsEnabled()) + offsets.top += mAxisLeft.getRequiredHeightSpace( + mAxisRendererLeft.getPaintAxisLabels()); + break; + + case BOTTOM: + offsets.bottom += Math.min(mLegend.mNeededHeight, + mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()) + + mLegend.getYOffset(); + + if (mAxisRight.isEnabled() && mAxisRight.isDrawLabelsEnabled()) + offsets.bottom += mAxisRight.getRequiredHeightSpace( + mAxisRendererRight.getPaintAxisLabels()); + break; + + default: + break; + } + break; + } + } + @Override public void calculateOffsets() { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java index 3c9aec0dde..8c0885395d 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java @@ -84,6 +84,7 @@ protected void init() { super.init(); mYAxis = new YAxis(AxisDependency.LEFT); + mYAxis.setLabelXOffset(10f); mWebLineWidth = Utils.convertDpToPixel(1.5f); mInnerWebLineWidth = Utils.convertDpToPixel(0.75f); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java index c1f02828be..c90b4fc9b9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java @@ -1,3 +1,4 @@ + package com.github.mikephil.charting.components; import android.graphics.Color; @@ -5,7 +6,7 @@ import android.util.Log; import com.github.mikephil.charting.formatter.DefaultAxisValueFormatter; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.formatter.IAxisValueFormatter; import com.github.mikephil.charting.utils.Utils; import java.util.ArrayList; @@ -21,7 +22,7 @@ public abstract class AxisBase extends ComponentBase { /** * custom formatter that is used instead of the auto-formatter if set */ - protected ValueFormatter mAxisValueFormatter; + protected IAxisValueFormatter mAxisValueFormatter; private int mGridColor = Color.GRAY; @@ -151,6 +152,39 @@ public abstract class AxisBase extends ComponentBase { */ public float mAxisRange = 0f; + private int mAxisMinLabels = 2; + private int mAxisMaxLabels = 25; + + /** + * The minumum number of labels on the axis + */ + public int getAxisMinLabels() { + return mAxisMinLabels; + } + + /** + * The minumum number of labels on the axis + */ + public void setAxisMinLabels(int labels) { + if (labels > 0) + mAxisMinLabels = labels; + } + + /** + * The maximum number of labels on the axis + */ + public int getAxisMaxLabels() { + return mAxisMaxLabels; + } + + /** + * The maximum number of labels on the axis + */ + public void setAxisMaxLabels(int labels) { + if (labels > 0) + mAxisMaxLabels = labels; + } + /** * default constructor */ @@ -314,10 +348,10 @@ public boolean isDrawLabelsEnabled() { */ public void setLabelCount(int count) { - if (count > 25) - count = 25; - if (count < 2) - count = 2; + if (count > getAxisMaxLabels()) + count = getAxisMaxLabels(); + if (count < getAxisMinLabels()) + count = getAxisMinLabels(); mLabelCount = count; mForceLabels = false; @@ -485,7 +519,7 @@ public String getFormattedLabel(int index) { if (index < 0 || index >= mEntries.length) return ""; else - return getValueFormatter().getAxisLabel(mEntries[index], this); + return getValueFormatter().getFormattedValue(mEntries[index], this); } /** @@ -497,7 +531,7 @@ public String getFormattedLabel(int index) { * * @param f */ - public void setValueFormatter(ValueFormatter f) { + public void setValueFormatter(IAxisValueFormatter f) { if (f == null) mAxisValueFormatter = new DefaultAxisValueFormatter(mDecimals); @@ -510,7 +544,7 @@ public void setValueFormatter(ValueFormatter f) { * * @return */ - public ValueFormatter getValueFormatter() { + public IAxisValueFormatter getValueFormatter() { if (mAxisValueFormatter == null || (mAxisValueFormatter instanceof DefaultAxisValueFormatter && diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java index b785098881..708129259b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java @@ -703,8 +703,7 @@ else if (wasStacked) { width += Utils.calcTextWidth(labelpaint, label); - if (i < entryCount - 1) - maxHeight += labelLineHeight + yEntrySpace; + maxHeight += labelLineHeight + yEntrySpace; } else { wasStacked = true; width += formSize; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java index 030603f55a..d2071ec5a8 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java @@ -73,6 +73,11 @@ public class YAxis extends AxisBase { */ private YAxisLabelPosition mPosition = YAxisLabelPosition.OUTSIDE_CHART; + /** + * the horizontal offset of the y-label + */ + private float mXLabelOffset = 0.0f; + /** * enum for the position of the y-labels relative to the chart */ @@ -174,6 +179,22 @@ public void setPosition(YAxisLabelPosition pos) { mPosition = pos; } + /** + * returns the horizontal offset of the y-label + */ + public float getLabelXOffset() { + return mXLabelOffset; + } + + /** + * sets the horizontal offset of the y-label + * + * @param xOffset + */ + public void setLabelXOffset(float xOffset) { + mXLabelOffset = xOffset; + } + /** * returns true if drawing the top y-axis label entry is enabled * @@ -406,6 +427,26 @@ public void calculate(float dataMin, float dataMax) { float min = dataMin; float max = dataMax; + // Make sure max is greater than min + // Discussion: https://github.com/danielgindi/Charts/pull/3650#discussion_r221409991 + if (min > max) + { + if (mCustomAxisMax && mCustomAxisMin) + { + float t = min; + min = max; + max = t; + } + else if (mCustomAxisMax) + { + min = max < 0f ? max * 1.5f : max * 0.5f; + } + else if (mCustomAxisMin) + { + max = min < 0f ? min * 0.5f : min * 1.5f; + } + } + float range = Math.abs(max - min); // in case all values are equal 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 496f4046f8..e65638805b 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 @@ 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; @@ -38,9 +39,9 @@ public class BarDataSet extends BarLineScatterCandleBubbleDataSet impl /** * array of labels used to describe the different values of the stacked bars */ - private String[] mStackLabels = new String[]{ - "Stack" - }; + private String[] mStackLabels = new String[]{}; + + protected List mFills = null; public BarDataSet(List yVals, String label) { super(yVals, label); @@ -54,8 +55,8 @@ public BarDataSet(List yVals, String label) { @Override public DataSet copy() { List entries = new ArrayList(); - for (int i = 0; i < mValues.size(); i++) { - entries.add(mValues.get(i).copy()); + for (int i = 0; i < mEntries.size(); i++) { + entries.add(mEntries.get(i).copy()); } BarDataSet copied = new BarDataSet(entries, getLabel()); copy(copied); @@ -71,6 +72,67 @@ protected void copy(BarDataSet barDataSet) { barDataSet.mHighLightAlpha = mHighLightAlpha; } + @Override + public List 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 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 gradientColors) { + this.mFills = gradientColors; + } + + /** + * Sets the fills for the bars in this dataset. + * + * @param fills + */ + public void setFills(List 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 8ca3e68d42..7e7445cac7 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 @@ -7,9 +7,8 @@ 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.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; @@ -29,10 +28,6 @@ public abstract class BaseDataSet implements IDataSet { */ protected List mColors = null; - protected GradientColor mGradientColor = null; - - protected List mGradientColors = null; - /** * List representing all colors that are used for drawing the actual values for this DataSet */ @@ -56,7 +51,7 @@ public abstract class BaseDataSet implements IDataSet { /** * custom formatter that is used instead of the auto-formatter if set */ - protected transient ValueFormatter mValueFormatter; + protected transient IValueFormatter mValueFormatter; /** * the typeface used for the value text @@ -146,21 +141,6 @@ public int getColor(int index) { return mColors.get(index % mColors.size()); } - @Override - public GradientColor getGradientColor() { - return mGradientColor; - } - - @Override - public List getGradientColors() { - return mGradientColors; - } - - @Override - public GradientColor getGradientColor(int index) { - return mGradientColors.get(index % mGradientColors.size()); - } - /** * ###### ###### COLOR SETTING RELATED METHODS ##### ###### */ @@ -236,25 +216,6 @@ public void setColor(int color) { mColors.add(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 the start and end color for gradient colors, ONLY color that should be used for this DataSet. - * - * @param gradientColors - */ - public void setGradientColors(List gradientColors) { - this.mGradientColors = gradientColors; - } - /** * Sets a color with a specific alpha value. * @@ -313,7 +274,7 @@ public boolean isHighlightEnabled() { } @Override - public void setValueFormatter(ValueFormatter f) { + public void setValueFormatter(IValueFormatter f) { if (f == null) return; @@ -322,7 +283,7 @@ public void setValueFormatter(ValueFormatter f) { } @Override - public ValueFormatter getValueFormatter() { + public IValueFormatter getValueFormatter() { if (needsFormatter()) return Utils.getDefaultValueFormatter(); return mValueFormatter; @@ -534,8 +495,6 @@ protected void copy(BaseDataSet baseDataSet) { 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/BubbleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleDataSet.java index 1f88272dd9..9ef87fb2d5 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleDataSet.java @@ -42,8 +42,8 @@ protected void calcMinMax(BubbleEntry e) { @Override public DataSet copy() { List entries = new ArrayList(); - for (int i = 0; i < mValues.size(); i++) { - entries.add(mValues.get(i).copy()); + for (int i = 0; i < mEntries.size(); i++) { + entries.add(mEntries.get(i).copy()); } BubbleDataSet copied = new BubbleDataSet(entries, getLabel()); copy(copied); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java index c7f8362803..dcd5b76cea 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java @@ -80,8 +80,8 @@ public CandleDataSet(List yVals, String label) { @Override public DataSet copy() { List entries = new ArrayList(); - for (int i = 0; i < mValues.size(); i++) { - entries.add(mValues.get(i).copy()); + for (int i = 0; i < mEntries.size(); i++) { + entries.add(mEntries.get(i).copy()); } CandleDataSet copied = new CandleDataSet(entries, getLabel()); copy(copied); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java index 9bd460290d..bfc5ed7016 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java @@ -1,10 +1,11 @@ + package com.github.mikephil.charting.data; import android.graphics.Typeface; import android.util.Log; import com.github.mikephil.charting.components.YAxis.AxisDependency; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.formatter.IValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IDataSet; @@ -399,7 +400,7 @@ public boolean removeDataSet(T d) { // if a DataSet was removed if (removed) { - calcMinMax(); + notifyDataChanged(); } return removed; @@ -526,7 +527,7 @@ public boolean removeEntry(Entry e, int dataSetIndex) { boolean removed = set.removeEntry(e); if (removed) { - calcMinMax(); + notifyDataChanged(); } return removed; @@ -658,7 +659,7 @@ public T getFirstRight(List sets) { * * @param f */ - public void setValueFormatter(ValueFormatter f) { + public void setValueFormatter(IValueFormatter f) { if (f == null) return; else { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java index 39625b30f9..0b36aa3bef 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java @@ -3,6 +3,7 @@ import android.util.Log; +import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IBarLineScatterCandleBubbleDataSet; @@ -91,18 +92,26 @@ public void calcMinMax() { if (data.getXMin() < mXMin) mXMin = data.getXMin(); - if (data.mLeftAxisMax > mLeftAxisMax) - mLeftAxisMax = data.mLeftAxisMax; - - if (data.mLeftAxisMin < mLeftAxisMin) - mLeftAxisMin = data.mLeftAxisMin; - - if (data.mRightAxisMax > mRightAxisMax) - mRightAxisMax = data.mRightAxisMax; - - if (data.mRightAxisMin < mRightAxisMin) - mRightAxisMin = data.mRightAxisMin; - + for (IBarLineScatterCandleBubbleDataSet dataset : sets) { + if (dataset.getAxisDependency() == YAxis.AxisDependency.LEFT) { + if (dataset.getYMax() > mLeftAxisMax) { + mLeftAxisMax = dataset.getYMax(); + } + + if (dataset.getYMin() < mLeftAxisMin) { + mLeftAxisMin = dataset.getYMin(); + } + } + else { + if (dataset.getYMax() > mRightAxisMax) { + mRightAxisMax = dataset.getYMax(); + } + + if (dataset.getYMin() < mRightAxisMin) { + mRightAxisMin = dataset.getYMin(); + } + } + } } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java index 3c69d9c58f..fda07efef2 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java @@ -17,7 +17,7 @@ public abstract class DataSet extends BaseDataSet { /** * the entries that this DataSet represents / holds together */ - protected List mValues = null; + protected List mEntries; /** * maximum y-value in the value array @@ -45,15 +45,15 @@ public abstract class DataSet extends BaseDataSet { * label that describes the DataSet can be specified. The label can also be * used to retrieve the DataSet from a ChartData object. * - * @param values + * @param entries * @param label */ - public DataSet(List values, String label) { + public DataSet(List entries, String label) { super(label); - this.mValues = values; + this.mEntries = entries; - if (mValues == null) - mValues = new ArrayList(); + if (mEntries == null) + mEntries = new ArrayList(); calcMinMax(); } @@ -61,35 +61,36 @@ public DataSet(List values, String label) { @Override public void calcMinMax() { - if (mValues == null || mValues.isEmpty()) - return; - mYMax = -Float.MAX_VALUE; mYMin = Float.MAX_VALUE; mXMax = -Float.MAX_VALUE; mXMin = Float.MAX_VALUE; - for (T e : mValues) { + if (mEntries == null || mEntries.isEmpty()) + return; + + for (T e : mEntries) { calcMinMax(e); } } @Override public void calcMinMaxY(float fromX, float toX) { - - if (mValues == null || mValues.isEmpty()) - return; - mYMax = -Float.MAX_VALUE; mYMin = Float.MAX_VALUE; + + if (mEntries == null || mEntries.isEmpty()) + return; int indexFrom = getEntryIndex(fromX, Float.NaN, Rounding.DOWN); int indexTo = getEntryIndex(toX, Float.NaN, Rounding.UP); + if (indexTo < indexFrom) return; + for (int i = indexFrom; i <= indexTo; i++) { // only recalculate y - calcMinMaxY(mValues.get(i)); + calcMinMaxY(mEntries.get(i)); } } @@ -128,25 +129,47 @@ protected void calcMinMaxY(T e) { @Override public int getEntryCount() { - return mValues.size(); + return mEntries.size(); } /** - * Returns the array of entries that this DataSet represents. + * This method is deprecated. + * Use getEntries() instead. * * @return */ + @Deprecated public List getValues() { - return mValues; + return mEntries; } /** - * Sets the array of entries that this DataSet represents, and calls notifyDataSetChanged() + * Returns the array of entries that this DataSet represents. * * @return */ + public List getEntries() { + return mEntries; + } + + /** + * This method is deprecated. + * Use setEntries(...) instead. + * + * @param values + */ + @Deprecated public void setValues(List values) { - mValues = values; + setEntries(values); + } + + /** + * Sets the array of entries that this DataSet represents, and calls notifyDataSetChanged() + * + * @return + */ + public void setEntries(List entries) { + mEntries = entries; notifyDataSetChanged(); } @@ -169,8 +192,8 @@ protected void copy(DataSet dataSet) { public String toString() { StringBuffer buffer = new StringBuffer(); buffer.append(toSimpleString()); - for (int i = 0; i < mValues.size(); i++) { - buffer.append(mValues.get(i).toString() + " "); + for (int i = 0; i < mEntries.size(); i++) { + buffer.append(mEntries.get(i).toString() + " "); } return buffer.toString(); } @@ -183,7 +206,7 @@ public String toString() { */ public String toSimpleString() { StringBuffer buffer = new StringBuffer(); - buffer.append("DataSet, label: " + (getLabel() == null ? "" : getLabel()) + ", entries: " + mValues.size() + + buffer.append("DataSet, label: " + (getLabel() == null ? "" : getLabel()) + ", entries: " + mEntries.size() + "\n"); return buffer.toString(); } @@ -214,23 +237,23 @@ public void addEntryOrdered(T e) { if (e == null) return; - if (mValues == null) { - mValues = new ArrayList(); + if (mEntries == null) { + mEntries = new ArrayList(); } calcMinMax(e); - if (mValues.size() > 0 && mValues.get(mValues.size() - 1).getX() > e.getX()) { + if (mEntries.size() > 0 && mEntries.get(mEntries.size() - 1).getX() > e.getX()) { int closestIndex = getEntryIndex(e.getX(), e.getY(), Rounding.UP); - mValues.add(closestIndex, e); + mEntries.add(closestIndex, e); } else { - mValues.add(e); + mEntries.add(e); } } @Override public void clear() { - mValues.clear(); + mEntries.clear(); notifyDataSetChanged(); } @@ -240,9 +263,9 @@ public boolean addEntry(T e) { if (e == null) return false; - List values = getValues(); + List values = getEntries(); if (values == null) { - values = new ArrayList(); + values = new ArrayList<>(); } calcMinMax(e); @@ -257,11 +280,11 @@ public boolean removeEntry(T e) { if (e == null) return false; - if (mValues == null) + if (mEntries == null) return false; // remove the entry - boolean removed = mValues.remove(e); + boolean removed = mEntries.remove(e); if (removed) { calcMinMax(); @@ -272,7 +295,7 @@ public boolean removeEntry(T e) { @Override public int getEntryIndex(Entry e) { - return mValues.indexOf(e); + return mEntries.indexOf(e); } @Override @@ -280,7 +303,7 @@ public T getEntryForXValue(float xValue, float closestToY, Rounding rounding) { int index = getEntryIndex(xValue, closestToY, rounding); if (index > -1) - return mValues.get(index); + return mEntries.get(index); return null; } @@ -291,24 +314,24 @@ public T getEntryForXValue(float xValue, float closestToY) { @Override public T getEntryForIndex(int index) { - return mValues.get(index); + return mEntries.get(index); } @Override public int getEntryIndex(float xValue, float closestToY, Rounding rounding) { - if (mValues == null || mValues.isEmpty()) + if (mEntries == null || mEntries.isEmpty()) return -1; int low = 0; - int high = mValues.size() - 1; + int high = mEntries.size() - 1; int closest = high; while (low < high) { int m = (low + high) / 2; - final float d1 = mValues.get(m).getX() - xValue, - d2 = mValues.get(m + 1).getX() - xValue, + final float d1 = mEntries.get(m).getX() - xValue, + d2 = mEntries.get(m + 1).getX() - xValue, ad1 = Math.abs(d1), ad2 = Math.abs(d2); if (ad2 < ad1) { @@ -335,10 +358,10 @@ public int getEntryIndex(float xValue, float closestToY, Rounding rounding) { } if (closest != -1) { - float closestXValue = mValues.get(closest).getX(); + float closestXValue = mEntries.get(closest).getX(); if (rounding == Rounding.UP) { // If rounding up, and found x-value is lower than specified x, and we can go upper... - if (closestXValue < xValue && closest < mValues.size() - 1) { + if (closestXValue < xValue && closest < mEntries.size() - 1) { ++closest; } } else if (rounding == Rounding.DOWN) { @@ -350,23 +373,23 @@ public int getEntryIndex(float xValue, float closestToY, Rounding rounding) { // Search by closest to y-value if (!Float.isNaN(closestToY)) { - while (closest > 0 && mValues.get(closest - 1).getX() == closestXValue) + while (closest > 0 && mEntries.get(closest - 1).getX() == closestXValue) closest -= 1; - float closestYValue = mValues.get(closest).getY(); + float closestYValue = mEntries.get(closest).getY(); int closestYIndex = closest; while (true) { closest += 1; - if (closest >= mValues.size()) + if (closest >= mEntries.size()) break; - final Entry value = mValues.get(closest); + final Entry value = mEntries.get(closest); if (value.getX() != closestXValue) break; - if (Math.abs(value.getY() - closestToY) < Math.abs(closestYValue - closestToY)) { + if (Math.abs(value.getY() - closestToY) <= Math.abs(closestYValue - closestToY)) { closestYValue = closestToY; closestYIndex = closest; } @@ -385,22 +408,22 @@ public List getEntriesForXValue(float xValue) { List entries = new ArrayList(); int low = 0; - int high = mValues.size() - 1; + int high = mEntries.size() - 1; while (low <= high) { int m = (high + low) / 2; - T entry = mValues.get(m); + T entry = mEntries.get(m); // if we have a match if (xValue == entry.getX()) { - while (m > 0 && mValues.get(m - 1).getX() == xValue) + while (m > 0 && mEntries.get(m - 1).getX() == xValue) m--; - high = mValues.size(); + high = mEntries.size(); // loop over all "equal" entries for (; m < high; m++) { - entry = mValues.get(m); + entry = mEntries.get(m); if (entry.getX() == xValue) { entries.add(entry); } else { 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 c1018d1fb4..10d1837ecd 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 @@ -85,8 +85,8 @@ public LineDataSet(List yVals, String label) { @Override public DataSet copy() { List entries = new ArrayList(); - for (int i = 0; i < mValues.size(); i++) { - entries.add(mValues.get(i).copy()); + for (int i = 0; i < mEntries.size(); i++) { + entries.add(mEntries.get(i).copy()); } LineDataSet copied = new LineDataSet(entries, getLabel()); copy(copied); 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 688585cbdd..b4347e4647 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 @@ */ public abstract class LineRadarDataSet extends LineScatterCandleRadarDataSet implements ILineRadarDataSet { + // 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/data/PieData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieData.java index db7972a3fb..423ce19b16 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieData.java @@ -1,6 +1,8 @@ package com.github.mikephil.charting.data; +import android.util.Log; + import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IPieDataSet; @@ -46,6 +48,18 @@ public IPieDataSet getDataSet() { return mDataSets.get(0); } + @Override + public List getDataSets() { + List dataSets = super.getDataSets(); + + if (dataSets.size() < 1) { + Log.e("MPAndroidChart", + "Found multiple data sets while pie chart only allows one"); + } + + return dataSets; + } + /** * The PieData object can only have one DataSet. Use getDataSet() method instead. * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java index e592399513..c83b24547b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java @@ -3,6 +3,7 @@ import com.github.mikephil.charting.interfaces.datasets.IPieDataSet; import com.github.mikephil.charting.utils.Utils; +import androidx.annotation.Nullable; import java.util.ArrayList; import java.util.List; @@ -22,13 +23,14 @@ public class PieDataSet extends DataSet implements IPieDataSet { private ValuePosition mXValuePosition = ValuePosition.INSIDE_SLICE; private ValuePosition mYValuePosition = ValuePosition.INSIDE_SLICE; - private boolean mUsingSliceColorAsValueLineColor = false; private int mValueLineColor = 0xff000000; + private boolean mUseValueColorForLine = false; private float mValueLineWidth = 1.0f; private float mValueLinePart1OffsetPercentage = 75.f; private float mValueLinePart1Length = 0.3f; private float mValueLinePart2Length = 0.4f; private boolean mValueLineVariableLength = true; + private Integer mHighlightColor = null; public PieDataSet(List yVals, String label) { super(yVals, label); @@ -38,8 +40,8 @@ public PieDataSet(List yVals, String label) { @Override public DataSet copy() { List entries = new ArrayList<>(); - for (int i = 0; i < mValues.size(); i++) { - entries.add(mValues.get(i).copy()); + for (int i = 0; i < mEntries.size(); i++) { + entries.add(mEntries.get(i).copy()); } PieDataSet copied = new PieDataSet(entries, getLabel()); copy(copied); @@ -135,15 +137,23 @@ public void setYValuePosition(ValuePosition yValuePosition) { } /** - * When valuePosition is OutsideSlice, use slice colors as line color if true + * This method is deprecated. + * Use isUseValueColorForLineEnabled() instead. */ - @Override + @Deprecated public boolean isUsingSliceColorAsValueLineColor() { - return mUsingSliceColorAsValueLineColor; + return isUseValueColorForLineEnabled(); } - public void setUsingSliceColorAsValueLineColor(boolean usingSliceColorAsValueLineColor) { - this.mUsingSliceColorAsValueLineColor = usingSliceColorAsValueLineColor; + /** + * This method is deprecated. + * Use setUseValueColorForLine(...) instead. + * + * @param enabled + */ + @Deprecated + public void setUsingSliceColorAsValueLineColor(boolean enabled) { + setUseValueColorForLine(enabled); } /** @@ -158,6 +168,17 @@ public void setValueLineColor(int valueLineColor) { this.mValueLineColor = valueLineColor; } + @Override + public boolean isUseValueColorForLineEnabled() + { + return mUseValueColorForLine; + } + + public void setUseValueColorForLine(boolean enabled) + { + mUseValueColorForLine = enabled; + } + /** * When valuePosition is OutsideSlice, indicates line width */ @@ -218,6 +239,21 @@ public void setValueLineVariableLength(boolean valueLineVariableLength) { this.mValueLineVariableLength = valueLineVariableLength; } + /** Gets the color for the highlighted sector */ + @Override + @Nullable + public Integer getHighlightColor() + { + return mHighlightColor; + } + + /** Sets the color for the highlighted sector (null for using entry color) */ + public void setHighlightColor(@Nullable Integer color) + { + this.mHighlightColor = color; + } + + public enum ValuePosition { INSIDE_SLICE, OUTSIDE_SLICE diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/RadarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/RadarDataSet.java index 09c94b417d..8a9740b6b5 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/RadarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/RadarDataSet.java @@ -102,8 +102,8 @@ public void setHighlightCircleStrokeWidth(float strokeWidth) { @Override public DataSet copy() { List entries = new ArrayList(); - for (int i = 0; i < mValues.size(); i++) { - entries.add(mValues.get(i).copy()); + for (int i = 0; i < mEntries.size(); i++) { + entries.add(mEntries.get(i).copy()); } RadarDataSet copied = new RadarDataSet(entries, getLabel()); copy(copied); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterDataSet.java index d234c751a0..85ed808160 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterDataSet.java @@ -48,8 +48,8 @@ public ScatterDataSet(List yVals, String label) { @Override public DataSet copy() { List entries = new ArrayList(); - for (int i = 0; i < mValues.size(); i++) { - entries.add(mValues.get(i).copy()); + for (int i = 0; i < mEntries.size(); i++) { + entries.add(mEntries.get(i).copy()); } ScatterDataSet copied = new ScatterDataSet(entries, getLabel()); copy(copied); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/filter/ApproximatorN.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/filter/ApproximatorN.java new file mode 100644 index 0000000000..9351341c76 --- /dev/null +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/filter/ApproximatorN.java @@ -0,0 +1,146 @@ + +package com.github.mikephil.charting.data.filter; + +import java.util.ArrayList; + +/** + * Implemented according to modified Douglas Peucker {@link} + * http://psimpl.sourceforge.net/douglas-peucker.html + */ +public class ApproximatorN +{ + public float[] reduceWithDouglasPeucker(float[] points, float resultCount) { + + int pointCount = points.length / 2; + + // if a shape has 2 or less points it cannot be reduced + if (resultCount <= 2 || resultCount >= pointCount) + return points; + + boolean[] keep = new boolean[pointCount]; + + // first and last always stay + keep[0] = true; + keep[pointCount - 1] = true; + + int currentStoredPoints = 2; + + ArrayList queue = new ArrayList<>(); + Line line = new Line(0, pointCount - 1, points); + queue.add(line); + + do { + line = queue.remove(queue.size() - 1); + + // store the key + keep[line.index] = true; + + // check point count tolerance + currentStoredPoints += 1; + + if (currentStoredPoints == resultCount) + break; + + // split the polyline at the key and recurse + Line left = new Line(line.start, line.index, points); + if (left.index > 0) { + int insertionIndex = insertionIndex(left, queue); + queue.add(insertionIndex, left); + } + + Line right = new Line(line.index, line.end, points); + if (right.index > 0) { + int insertionIndex = insertionIndex(right, queue); + queue.add(insertionIndex, right); + } + } while (queue.isEmpty()); + + float[] reducedEntries = new float[currentStoredPoints * 2]; + + for (int i = 0, i2 = 0, r2 = 0; i < currentStoredPoints; i++, r2 += 2) { + if (keep[i]) { + reducedEntries[i2++] = points[r2]; + reducedEntries[i2++] = points[r2 + 1]; + } + } + + return reducedEntries; + } + + private static float distanceToLine( + float ptX, float ptY, float[] + fromLinePoint1, float[] fromLinePoint2) { + float dx = fromLinePoint2[0] - fromLinePoint1[0]; + float dy = fromLinePoint2[1] - fromLinePoint1[1]; + + float dividend = Math.abs( + dy * ptX - + dx * ptY - + fromLinePoint1[0] * fromLinePoint2[1] + + fromLinePoint2[0] * fromLinePoint1[1]); + double divisor = Math.sqrt(dx * dx + dy * dy); + + return (float)(dividend / divisor); + } + + private static class Line { + int start; + int end; + + float distance = 0; + int index = 0; + + Line(int start, int end, float[] points) { + this.start = start; + this.end = end; + + float[] startPoint = new float[]{points[start * 2], points[start * 2 + 1]}; + float[] endPoint = new float[]{points[end * 2], points[end * 2 + 1]}; + + if (end <= start + 1) return; + + for (int i = start + 1, i2 = i * 2; i < end; i++, i2 += 2) { + float distance = distanceToLine( + points[i2], points[i2 + 1], + startPoint, endPoint); + + if (distance > this.distance) { + this.index = i; + this.distance = distance; + } + } + } + + boolean equals(final Line rhs) { + return (start == rhs.start) && (end == rhs.end) && index == rhs.index; + } + + boolean lessThan(final Line rhs) { + return distance < rhs.distance; + } + } + + private static int insertionIndex(Line line, ArrayList queue) { + int min = 0; + int max = queue.size(); + + while (!queue.isEmpty()) { + int midIndex = min + (max - min) / 2; + Line midLine = queue.get(midIndex); + + if (midLine.equals(line)) { + return midIndex; + } + else if (line.lessThan(midLine)) { + // perform search in left half + max = midIndex; + } + else { + // perform search in right half + min = midIndex + 1; + } + } + + return min; + } +} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java index c8834c3e45..552c150e69 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java @@ -1,11 +1,13 @@ package com.github.mikephil.charting.formatter; +import com.github.mikephil.charting.components.AxisBase; + import java.text.DecimalFormat; /** * Created by philipp on 02/06/16. */ -public class DefaultAxisValueFormatter extends ValueFormatter +public class DefaultAxisValueFormatter implements IAxisValueFormatter { /** @@ -16,7 +18,7 @@ public class DefaultAxisValueFormatter extends ValueFormatter /** * the number of decimal digits this formatter uses */ - protected int digits; + protected int digits = 0; /** * Constructor that specifies to how many digits the value should be @@ -38,7 +40,7 @@ public DefaultAxisValueFormatter(int digits) { } @Override - public String getFormattedValue(float value) { + public String getFormattedValue(float value, AxisBase axis) { // avoid memory allocations here (for performance) return mFormat.format(value); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java index 40668b91ab..e2fea4b079 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java @@ -1,5 +1,9 @@ + package com.github.mikephil.charting.formatter; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.utils.ViewPortHandler; + import java.text.DecimalFormat; /** @@ -8,7 +12,7 @@ * * @author Philipp Jahoda */ -public class DefaultValueFormatter extends ValueFormatter +public class DefaultValueFormatter implements IValueFormatter { /** @@ -48,7 +52,7 @@ public void setup(int digits) { } @Override - public String getFormattedValue(float value) { + public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { // put more logic here ... // avoid memory allocations here (for performance reasons) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IAxisValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IAxisValueFormatter.java index 970ea6fca8..51939b5432 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IAxisValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IAxisValueFormatter.java @@ -6,10 +6,7 @@ * Created by Philipp Jahoda on 20/09/15. * Custom formatter interface that allows formatting of * axis labels before they are being drawn. - * - * @deprecated Extend {@link ValueFormatter} instead */ -@Deprecated public interface IAxisValueFormatter { @@ -21,9 +18,6 @@ public interface IAxisValueFormatter * @param value the value to be formatted * @param axis the axis the value belongs to * @return - * - * @deprecated Extend {@link ValueFormatter} and use {@link ValueFormatter#getAxisLabel(float, AxisBase)} */ - @Deprecated String getFormattedValue(float value, AxisBase axis); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IValueFormatter.java index 0dde7012e3..75d2363f26 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IValueFormatter.java @@ -4,12 +4,13 @@ import com.github.mikephil.charting.utils.ViewPortHandler; /** - * Interface to format all values before they are drawn as labels. + * Interface that allows custom formatting of all values inside the chart before they are + * being drawn to the screen. Simply create your own formatting class and let + * it implement IValueFormatter. Then override the getFormattedValue(...) method + * and return whatever you want. * * @author Philipp Jahoda - * @deprecated Extend {@link ValueFormatter} instead */ -@Deprecated public interface IValueFormatter { @@ -23,9 +24,6 @@ public interface IValueFormatter * @param dataSetIndex the index of the DataSet the entry in focus belongs to * @param viewPortHandler provides information about the current chart state (scale, translation, ...) * @return the formatted label ready for being drawn - * - * @deprecated Extend {@link ValueFormatter} and override an appropriate method */ - @Deprecated String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IndexAxisValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IndexAxisValueFormatter.java index 7ab7bdbe7d..07349a6a0e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IndexAxisValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IndexAxisValueFormatter.java @@ -1,11 +1,18 @@ + package com.github.mikephil.charting.formatter; +import com.github.mikephil.charting.components.AxisBase; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.utils.ViewPortHandler; + +import java.text.DecimalFormat; +import java.util.Arrays; import java.util.Collection; /** * This formatter is used for passing an array of x-axis labels, on whole x steps. */ -public class IndexAxisValueFormatter extends ValueFormatter +public class IndexAxisValueFormatter implements IAxisValueFormatter { private String[] mValues = new String[] {}; private int mValueCount = 0; @@ -37,8 +44,7 @@ public IndexAxisValueFormatter(Collection values) { setValues(values.toArray(new String[values.size()])); } - @Override - public String getFormattedValue(float value) { + public String getFormattedValue(float value, AxisBase axis) { int index = Math.round(value); if (index < 0 || index >= mValueCount || index != (int)value) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java index 4870a4cff4..211401ad8a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java @@ -1,5 +1,10 @@ + package com.github.mikephil.charting.formatter; +import com.github.mikephil.charting.components.AxisBase; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.utils.ViewPortHandler; + import java.text.DecimalFormat; /** @@ -12,7 +17,7 @@ * @author Philipp Jahoda * @author Oleksandr Tyshkovets */ -public class LargeValueFormatter extends ValueFormatter +public class LargeValueFormatter implements IValueFormatter, IAxisValueFormatter { private String[] mSuffix = new String[]{ @@ -36,8 +41,15 @@ public LargeValueFormatter(String appendix) { mText = appendix; } + // IValueFormatter + @Override + public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { + return makePretty(value) + mText; + } + + // IAxisValueFormatter @Override - public String getFormattedValue(float value) { + public String getFormattedValue(float value, AxisBase axis) { return makePretty(value) + mText; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java index 012fab77f9..de8a10255a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java @@ -1,54 +1,49 @@ + package com.github.mikephil.charting.formatter; -import com.github.mikephil.charting.charts.PieChart; -import com.github.mikephil.charting.data.PieEntry; +import com.github.mikephil.charting.components.AxisBase; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.utils.ViewPortHandler; import java.text.DecimalFormat; /** * This IValueFormatter is just for convenience and simply puts a "%" sign after - * each value. (Recommended for PieChart) + * each value. (Recommeded for PieChart) * * @author Philipp Jahoda */ -public class PercentFormatter extends ValueFormatter +public class PercentFormatter implements IValueFormatter, IAxisValueFormatter { - public DecimalFormat mFormat; - private PieChart pieChart; - private boolean percentSignSeparated; + protected DecimalFormat mFormat; public PercentFormatter() { mFormat = new DecimalFormat("###,###,##0.0"); - percentSignSeparated = true; - } - - // Can be used to remove percent signs if the chart isn't in percent mode - public PercentFormatter(PieChart pieChart) { - this(); - this.pieChart = pieChart; } - // Can be used to remove percent signs if the chart isn't in percent mode - public PercentFormatter(PieChart pieChart, boolean percentSignSeparated) { - this(pieChart); - this.percentSignSeparated = percentSignSeparated; + /** + * Allow a custom decimalformat + * + * @param format + */ + public PercentFormatter(DecimalFormat format) { + this.mFormat = format; } + // IValueFormatter @Override - public String getFormattedValue(float value) { - return mFormat.format(value) + (percentSignSeparated ? " %" : "%"); + public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { + return mFormat.format(value) + " %"; } + // IAxisValueFormatter @Override - public String getPieLabel(float value, PieEntry pieEntry) { - if (pieChart != null && pieChart.isUsePercentValuesEnabled()) { - // Converted to percent - return getFormattedValue(value); - } else { - // raw value, skip percent sign - return mFormat.format(value); - } + public String getFormattedValue(float value, AxisBase axis) { + return mFormat.format(value) + " %"; } + public int getDecimalDigits() { + return 1; + } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/StackedValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/StackedValueFormatter.java index 7c69dcf5d6..0e8351634f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/StackedValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/StackedValueFormatter.java @@ -1,6 +1,8 @@ package com.github.mikephil.charting.formatter; import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.utils.ViewPortHandler; import java.text.DecimalFormat; @@ -10,7 +12,7 @@ * A formatter specifically for stacked BarChart that allows to specify whether the all stack values * or just the top value should be drawn. */ -public class StackedValueFormatter extends ValueFormatter +public class StackedValueFormatter implements IValueFormatter { /** @@ -21,7 +23,7 @@ public class StackedValueFormatter extends ValueFormatter /** * a string that should be appended behind the value */ - private String mSuffix; + private String mAppendix; private DecimalFormat mFormat; @@ -29,12 +31,12 @@ public class StackedValueFormatter extends ValueFormatter * Constructor. * * @param drawWholeStack if true, all stack values of the stacked bar entry are drawn, else only top - * @param suffix a string that should be appended behind the value + * @param appendix a string that should be appended behind the value * @param decimals the number of decimal digits to use */ - public StackedValueFormatter(boolean drawWholeStack, String suffix, int decimals) { + public StackedValueFormatter(boolean drawWholeStack, String appendix, int decimals) { this.mDrawWholeStack = drawWholeStack; - this.mSuffix = suffix; + this.mAppendix = appendix; StringBuffer b = new StringBuffer(); for (int i = 0; i < decimals; i++) { @@ -47,10 +49,12 @@ public StackedValueFormatter(boolean drawWholeStack, String suffix, int decimals } @Override - public String getBarStackedLabel(float value, BarEntry entry) { - if (!mDrawWholeStack) { + public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { - float[] vals = entry.getYVals(); + if (!mDrawWholeStack && entry instanceof BarEntry) { + + BarEntry barEntry = (BarEntry) entry; + float[] vals = barEntry.getYVals(); if (vals != null) { @@ -58,7 +62,7 @@ public String getBarStackedLabel(float value, BarEntry entry) { if (vals[vals.length - 1] == value) { // return the "sum" across all stack values - return mFormat.format(entry.getY()) + mSuffix; + return mFormat.format(barEntry.getY()) + mAppendix; } else { return ""; // return empty } @@ -66,6 +70,6 @@ public String getBarStackedLabel(float value, BarEntry entry) { } // return the "proposed" value - return mFormat.format(value) + mSuffix; + return mFormat.format(value) + mAppendix; } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/ValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/ValueFormatter.java deleted file mode 100644 index d2f53cb78b..0000000000 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/ValueFormatter.java +++ /dev/null @@ -1,137 +0,0 @@ -package com.github.mikephil.charting.formatter; - -import com.github.mikephil.charting.components.AxisBase; -import com.github.mikephil.charting.data.BarEntry; -import com.github.mikephil.charting.data.BubbleEntry; -import com.github.mikephil.charting.data.CandleEntry; -import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.data.PieEntry; -import com.github.mikephil.charting.data.RadarEntry; -import com.github.mikephil.charting.utils.ViewPortHandler; - -/** - * Class to format all values before they are drawn as labels. - */ -public abstract class ValueFormatter implements IAxisValueFormatter, IValueFormatter{ - - /** - * DO NOT USE, only for backwards compatibility and will be removed in future versions. - * - * @param value the value to be formatted - * @param axis the axis the value belongs to - * @return formatted string label - */ - @Override - @Deprecated - public String getFormattedValue(float value, AxisBase axis) { - return getFormattedValue(value); - } - - /** - * DO NOT USE, only for backwards compatibility and will be removed in future versions. - * @param value the value to be formatted - * @param entry the entry the value belongs to - in e.g. BarChart, this is of class BarEntry - * @param dataSetIndex the index of the DataSet the entry in focus belongs to - * @param viewPortHandler provides information about the current chart state (scale, translation, ...) - * @return formatted string label - */ - @Override - @Deprecated - public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { - return getFormattedValue(value); - } - - /** - * Called when drawing any label, used to change numbers into formatted strings. - * - * @param value float to be formatted - * @return formatted string label - */ - public String getFormattedValue(float value) { - return String.valueOf(value); - } - - /** - * Used to draw axis labels, calls {@link #getFormattedValue(float)} by default. - * - * @param value float to be formatted - * @param axis axis being labeled - * @return formatted string label - */ - public String getAxisLabel(float value, AxisBase axis) { - return getFormattedValue(value); - } - - /** - * Used to draw bar labels, calls {@link #getFormattedValue(float)} by default. - * - * @param barEntry bar being labeled - * @return formatted string label - */ - public String getBarLabel(BarEntry barEntry) { - return getFormattedValue(barEntry.getY()); - } - - /** - * Used to draw stacked bar labels, calls {@link #getFormattedValue(float)} by default. - * - * @param value current value to be formatted - * @param stackedEntry stacked entry being labeled, contains all Y values - * @return formatted string label - */ - public String getBarStackedLabel(float value, BarEntry stackedEntry) { - return getFormattedValue(value); - } - - /** - * Used to draw line and scatter labels, calls {@link #getFormattedValue(float)} by default. - * - * @param entry point being labeled, contains X value - * @return formatted string label - */ - public String getPointLabel(Entry entry) { - return getFormattedValue(entry.getY()); - } - - /** - * Used to draw pie value labels, calls {@link #getFormattedValue(float)} by default. - * - * @param value float to be formatted, may have been converted to percentage - * @param pieEntry slice being labeled, contains original, non-percentage Y value - * @return formatted string label - */ - public String getPieLabel(float value, PieEntry pieEntry) { - return getFormattedValue(value); - } - - /** - * Used to draw radar value labels, calls {@link #getFormattedValue(float)} by default. - * - * @param radarEntry entry being labeled - * @return formatted string label - */ - public String getRadarLabel(RadarEntry radarEntry) { - return getFormattedValue(radarEntry.getY()); - } - - /** - * Used to draw bubble size labels, calls {@link #getFormattedValue(float)} by default. - * - * @param bubbleEntry bubble being labeled, also contains X and Y values - * @return formatted string label - */ - public String getBubbleLabel(BubbleEntry bubbleEntry) { - return getFormattedValue(bubbleEntry.getSize()); - } - - /** - * Used to draw high labels, calls {@link #getFormattedValue(float)} by default. - * - * @param candleEntry candlestick being labeled - * @return formatted string label - */ - public String getCandleLabel(CandleEntry candleEntry) { - return getFormattedValue(candleEntry.getHigh()); - } - -} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java index 032698d5e5..62307cbeaf 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java @@ -60,10 +60,18 @@ public class Highlight { */ private float mDrawY; + public Highlight(float x, float y, int dataSetIndex, int dataIndex) { + this.mX = x; + this.mY = y; + this.mDataSetIndex = dataSetIndex; + this.mDataIndex = dataIndex; + } + public Highlight(float x, float y, int dataSetIndex) { this.mX = x; this.mY = y; this.mDataSetIndex = dataSetIndex; + this.mDataIndex = -1; } public Highlight(float x, int dataSetIndex, int stackIndex) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java index 182aa28757..219b46bd82 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java @@ -3,7 +3,7 @@ import android.graphics.RectF; import com.github.mikephil.charting.data.ChartData; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.formatter.IValueFormatter; import com.github.mikephil.charting.utils.MPPointF; /** @@ -61,7 +61,7 @@ public interface ChartInterface { RectF getContentRect(); - ValueFormatter getDefaultValueFormatter(); + IValueFormatter getDefaultValueFormatter(); ChartData getData(); 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 fbdfd79531..5e82a48420 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 { + List 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 73a54470c8..fd8af7064b 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,15 +1,15 @@ 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; import com.github.mikephil.charting.components.YAxis; 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.formatter.IValueFormatter; import com.github.mikephil.charting.utils.MPPointF; -import com.github.mikephil.charting.model.GradientColor; import java.util.List; @@ -285,28 +285,6 @@ public interface IDataSet { */ int getColor(); - /** - * Returns the Gradient color model - * - * @return - */ - GradientColor getGradientColor(); - - /** - * Returns the Gradient colors - * - * @return - */ - List 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. @@ -340,14 +318,14 @@ public interface IDataSet { * * @param f */ - void setValueFormatter(ValueFormatter f); + void setValueFormatter(IValueFormatter f); /** * Returns the formatter used for drawing the values inside the chart. * * @return */ - ValueFormatter getValueFormatter(); + IValueFormatter getValueFormatter(); /** * Returns true if the valueFormatter object of this DataSet is null. diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java index 1698ef786b..b228fca0e4 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java @@ -1,5 +1,7 @@ package com.github.mikephil.charting.interfaces.datasets; +import androidx.annotation.Nullable; + import com.github.mikephil.charting.data.PieDataSet; import com.github.mikephil.charting.data.PieEntry; @@ -36,14 +38,14 @@ public interface IPieDataSet extends IDataSet { PieDataSet.ValuePosition getYValuePosition(); /** - * When valuePosition is OutsideSlice, use slice colors as line color if true + * When valuePosition is OutsideSlice, indicates line color * */ - boolean isUsingSliceColorAsValueLineColor(); + int getValueLineColor(); /** - * When valuePosition is OutsideSlice, indicates line color + * When valuePosition is OutsideSlice and enabled, line will have the same color as the slice * */ - int getValueLineColor(); + boolean isUseValueColorForLineEnabled(); /** * When valuePosition is OutsideSlice, indicates line width @@ -70,5 +72,11 @@ public interface IPieDataSet extends IDataSet { * */ boolean isValueLineVariableLength(); + /** + * Gets the color for the highlighted sector + * */ + @Nullable + Integer getHighlightColor(); + } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java index 53ab12a369..5685d32fa0 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java @@ -580,12 +580,19 @@ public boolean onDoubleTap(MotionEvent e) { MPPointF trans = getTrans(e.getX(), e.getY()); - mChart.zoom(mChart.isScaleXEnabled() ? 1.4f : 1f, mChart.isScaleYEnabled() ? 1.4f : 1f, trans.x, trans.y); + float scaleX = mChart.isScaleXEnabled() ? 1.4f : 1f; + float scaleY = mChart.isScaleYEnabled() ? 1.4f : 1f; + + mChart.zoom(scaleX, scaleY, trans.x, trans.y); if (mChart.isLogEnabled()) Log.i("BarlineChartTouch", "Double-Tap, Zooming In, x: " + trans.x + ", y: " + trans.y); + if (l != null) { + l.onChartScale(e, scaleX, scaleY); + } + MPPointF.recycleInstance(trans); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnChartGestureListener.java b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnChartGestureListener.java index a17cdde941..da0c5ed180 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnChartGestureListener.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnChartGestureListener.java @@ -57,7 +57,7 @@ public interface OnChartGestureListener { void onChartFling(MotionEvent me1, MotionEvent me2, float velocityX, float velocityY); /** - * Callbacks when the chart is scaled / zoomed via pinch zoom gesture. + * Callbacks when the chart is scaled / zoomed via pinch zoom / double-tap gesture. * * @param me * @param scaleX scalefactor on the x-axis 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 1162c01198..b5c8715a08 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/AxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java index 90528a1359..72ea2d17c8 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java @@ -174,9 +174,12 @@ protected void computeAxisValues(float min, float max) { double intervalMagnitude = Utils.roundToNextSignificant(Math.pow(10, (int) Math.log10(interval))); int intervalSigDigit = (int) (interval / intervalMagnitude); if (intervalSigDigit > 5) { - // Use one order of magnitude higher, to avoid intervals like 0.9 or - // 90 - interval = Math.floor(10 * intervalMagnitude); + // Use one order of magnitude higher, to avoid intervals like 0.9 or 90 + // if it's 0.0 after floor(), we use the old value + interval = Math.floor(10.0 * intervalMagnitude) == 0.0 + ? interval + : Math.floor(10.0 * intervalMagnitude); + } int n = mAxis.isCenterAxisLabelsEnabled() ? 1 : 0; @@ -214,11 +217,14 @@ protected void computeAxisValues(float min, float max) { double f; int i; - if (interval != 0.0) { + if (interval != 0.0 && last != first) { for (f = first; f <= last; f += interval) { ++n; } } + else if (last == first && n == 0) { + n = 1; + } mAxis.mEntryCount = n; 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 b5de65b02e..1656a3a37f 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 @@ -1,3 +1,4 @@ + package com.github.mikephil.charting.renderer; import android.graphics.Canvas; @@ -10,17 +11,15 @@ import com.github.mikephil.charting.buffer.BarBuffer; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarEntry; -import com.github.mikephil.charting.formatter.ValueFormatter; 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 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { trans.pointValuesToPixel(buffer.buffer); + final boolean isCustomFill = dataSet.getFills() != null && !dataSet.getFills().isEmpty(); 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 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { 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); @@ -254,8 +241,6 @@ public void drawValues(Canvas c) { final float phaseY = mAnimator.getPhaseY(); - ValueFormatter formatter = dataSet.getValueFormatter(); - MPPointF iconsOffset = MPPointF.getInstance(dataSet.getIconsOffset()); iconsOffset.x = Utils.convertDpToPixel(iconsOffset.x); iconsOffset.y = Utils.convertDpToPixel(iconsOffset.y); @@ -278,7 +263,8 @@ public void drawValues(Canvas c) { float val = entry.getY(); if (dataSet.isDrawValuesEnabled()) { - drawValue(c, formatter.getBarLabel(entry), x, val >= 0 ? + drawValue(c, dataSet.getValueFormatter(), val, entry, i, x, + val >= 0 ? (buffer.buffer[j + 1] + posOffset) : (buffer.buffer[j + 3] + negOffset), dataSet.getValueTextColor(j / 4)); @@ -336,7 +322,8 @@ public void drawValues(Canvas c) { continue; if (dataSet.isDrawValuesEnabled()) { - drawValue(c, formatter.getBarLabel(entry), x, buffer.buffer[bufferIndex + 1] + + drawValue(c, dataSet.getValueFormatter(), entry.getY(), entry, i, x, + buffer.buffer[bufferIndex + 1] + (entry.getY() >= 0 ? posOffset : negOffset), color); } @@ -407,7 +394,14 @@ public void drawValues(Canvas c) { continue; if (dataSet.isDrawValuesEnabled()) { - drawValue(c, formatter.getBarStackedLabel(val, entry), x, y, color); + drawValue(c, + dataSet.getValueFormatter(), + vals[k / 2], + entry, + i, + x, + y, + color); } if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) { @@ -435,12 +429,6 @@ public void drawValues(Canvas c) { } } - @Override - public void drawValue(Canvas c, String valueText, float x, float y, int color) { - mValuePaint.setColor(color); - c.drawText(valueText, x, y, mValuePaint); - } - @Override public void drawHighlighted(Canvas c, Highlight[] indices) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index 57b81c1d9c..5ce19c2c9f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -1,3 +1,4 @@ + package com.github.mikephil.charting.renderer; import android.graphics.Canvas; @@ -8,7 +9,6 @@ import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.data.BubbleData; import com.github.mikephil.charting.data.BubbleEntry; -import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.BubbleDataProvider; import com.github.mikephil.charting.interfaces.datasets.IBubbleDataSet; @@ -108,7 +108,7 @@ protected void drawDataSet(Canvas c, IBubbleDataSet dataSet) { if (!mViewPortHandler.isInBoundsRight(pointBuffer[0] - shapeHalf)) break; - final int color = dataSet.getColor((int) entry.getX()); + final int color = dataSet.getColor(j); mRenderPaint.setColor(color); c.drawCircle(pointBuffer[0], pointBuffer[1], shapeHalf, mRenderPaint); @@ -150,8 +150,6 @@ public void drawValues(Canvas c) { final float alpha = phaseX == 1 ? phaseY : phaseX; - ValueFormatter formatter = dataSet.getValueFormatter(); - MPPointF iconsOffset = MPPointF.getInstance(dataSet.getIconsOffset()); iconsOffset.x = Utils.convertDpToPixel(iconsOffset.x); iconsOffset.y = Utils.convertDpToPixel(iconsOffset.y); @@ -174,7 +172,8 @@ public void drawValues(Canvas c) { BubbleEntry entry = dataSet.getEntryForIndex(j / 2 + mXBounds.min); if (dataSet.isDrawValuesEnabled()) { - drawValue(c, formatter.getBubbleLabel(entry), x, y + (0.5f * lineHeight), valueTextColor); + drawValue(c, dataSet.getValueFormatter(), entry.getSize(), entry, i, x, + y + (0.5f * lineHeight), valueTextColor); } if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) { @@ -196,12 +195,6 @@ public void drawValues(Canvas c) { } } - @Override - public void drawValue(Canvas c, String valueText, float x, float y, int color) { - mValuePaint.setColor(color); - c.drawText(valueText, x, y, mValuePaint); - } - @Override public void drawExtras(Canvas c) { } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index 027dda31d8..991b702117 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -1,3 +1,4 @@ + package com.github.mikephil.charting.renderer; import android.graphics.Canvas; @@ -7,7 +8,6 @@ import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.data.CandleData; import com.github.mikephil.charting.data.CandleEntry; -import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.CandleDataProvider; import com.github.mikephil.charting.interfaces.datasets.ICandleDataSet; @@ -279,8 +279,6 @@ public void drawValues(Canvas c) { float yOffset = Utils.convertDpToPixel(5f); - ValueFormatter formatter = dataSet.getValueFormatter(); - MPPointF iconsOffset = MPPointF.getInstance(dataSet.getIconsOffset()); iconsOffset.x = Utils.convertDpToPixel(iconsOffset.x); iconsOffset.y = Utils.convertDpToPixel(iconsOffset.y); @@ -299,7 +297,15 @@ public void drawValues(Canvas c) { CandleEntry entry = dataSet.getEntryForIndex(j / 2 + mXBounds.min); if (dataSet.isDrawValuesEnabled()) { - drawValue(c, formatter.getCandleLabel(entry), x, y - yOffset, dataSet.getValueTextColor(j / 2)); + drawValue(c, + dataSet.getValueFormatter(), + entry.getHigh(), + entry, + i, + x, + y - yOffset, + dataSet + .getValueTextColor(j / 2)); } if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) { @@ -321,12 +327,6 @@ public void drawValues(Canvas c) { } } - @Override - public void drawValue(Canvas c, String valueText, float x, float y, int color) { - mValuePaint.setColor(color); - c.drawText(valueText, x, y, mValuePaint); - } - @Override public void drawExtras(Canvas c) { } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.java index 8f6be3c054..6d0d4d3da0 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.java @@ -1,7 +1,6 @@ package com.github.mikephil.charting.renderer; import android.graphics.Canvas; -import android.util.Log; import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.charts.Chart; @@ -10,6 +9,7 @@ import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.CombinedData; import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.interfaces.dataprovider.BarLineScatterCandleBubbleDataProvider; import com.github.mikephil.charting.utils.ViewPortHandler; import java.lang.ref.WeakReference; @@ -89,11 +89,6 @@ public void drawData(Canvas c) { renderer.drawData(c); } - @Override - public void drawValue(Canvas c, String valueText, float x, float y, int color) { - Log.e("MPAndroidChart", "Erroneous call to drawValue() in CombinedChartRenderer!"); - } - @Override public void drawValues(Canvas c) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/DataRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/DataRenderer.java index da4a26edca..e8e5446f4d 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/DataRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/DataRenderer.java @@ -1,3 +1,4 @@ + package com.github.mikephil.charting.renderer; import android.graphics.Canvas; @@ -5,11 +6,15 @@ import android.graphics.Paint; import android.graphics.Paint.Align; import android.graphics.Paint.Style; +import android.graphics.drawable.Drawable; import com.github.mikephil.charting.animation.ChartAnimator; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.formatter.IValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.ChartInterface; import com.github.mikephil.charting.interfaces.datasets.IDataSet; +import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -133,13 +138,19 @@ protected void applyValueTextStyle(IDataSet set) { /** * Draws the value of the given entry by using the provided IValueFormatter. * - * @param c canvas - * @param valueText label to draw - * @param x position - * @param y position + * @param c canvas + * @param formatter formatter for custom value-formatting + * @param value the value to be drawn + * @param entry the entry the value belongs to + * @param dataSetIndex the index of the DataSet the drawn Entry belongs to + * @param x position + * @param y position * @param color */ - public abstract void drawValue(Canvas c, String valueText, float x, float y, int color); + public void drawValue(Canvas c, IValueFormatter formatter, float value, Entry entry, int dataSetIndex, float x, float y, int color) { + mValuePaint.setColor(color); + c.drawText(formatter.getFormattedValue(value, entry, dataSetIndex, mViewPortHandler), x, y, mValuePaint); + } /** * Draws any kind of additional information (e.g. line-circles). 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 7607abdd92..0cd72345fb 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 @@ -1,3 +1,4 @@ + package com.github.mikephil.charting.renderer; import android.graphics.Canvas; @@ -10,11 +11,12 @@ import com.github.mikephil.charting.buffer.HorizontalBarBuffer; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarEntry; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.formatter.IValueFormatter; 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 +113,15 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { trans.pointValuesToPixel(buffer.buffer); + final boolean isCustomFill = dataSet.getFills() != null && !dataSet.getFills().isEmpty(); 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 +135,20 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { 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], @@ -166,7 +182,7 @@ public void drawValues(Canvas c) { applyValueTextStyle(dataSet); final float halfTextHeight = Utils.calcTextHeight(mValuePaint, "10") / 2f; - ValueFormatter formatter = dataSet.getValueFormatter(); + IValueFormatter formatter = dataSet.getValueFormatter(); // get the buffer BarBuffer buffer = mBarBuffers[i]; @@ -195,12 +211,13 @@ public void drawValues(Canvas c) { BarEntry entry = dataSet.getEntryForIndex(j / 4); float val = entry.getY(); - String formattedValue = formatter.getBarLabel(entry); + String formattedValue = formatter.getFormattedValue(val, entry, i, mViewPortHandler); // calculate the correct offset depending on the draw position of the value float valueTextWidth = Utils.calcTextWidth(mValuePaint, formattedValue); posOffset = (drawValueAboveBar ? valueOffsetPlus : -(valueTextWidth + valueOffsetPlus)); - negOffset = (drawValueAboveBar ? -(valueTextWidth + valueOffsetPlus) : valueOffsetPlus); + negOffset = (drawValueAboveBar ? -(valueTextWidth + valueOffsetPlus) : valueOffsetPlus) + - (buffer.buffer[j + 2] - buffer.buffer[j]); if (isInverted) { posOffset = -posOffset - valueTextWidth; @@ -264,7 +281,9 @@ public void drawValues(Canvas c) { if (!mViewPortHandler.isInBoundsBottom(buffer.buffer[bufferIndex + 1])) continue; - String formattedValue = formatter.getBarLabel(entry); + float val = entry.getY(); + String formattedValue = formatter.getFormattedValue(val, + entry, i, mViewPortHandler); // calculate the correct offset depending on the draw position of the value float valueTextWidth = Utils.calcTextWidth(mValuePaint, formattedValue); @@ -334,7 +353,8 @@ public void drawValues(Canvas c) { for (int k = 0; k < transformed.length; k += 2) { final float val = vals[k / 2]; - String formattedValue = formatter.getBarStackedLabel(val, entry); + String formattedValue = formatter.getFormattedValue(val, + entry, i, mViewPortHandler); // calculate the correct offset depending on the draw position of the value float valueTextWidth = Utils.calcTextWidth(mValuePaint, formattedValue); @@ -392,8 +412,7 @@ public void drawValues(Canvas c) { } } - @Override - public void drawValue(Canvas c, String valueText, float x, float y, int color) { + protected void drawValue(Canvas c, String valueText, float x, float y, int color) { mValuePaint.setColor(color); c.drawText(valueText, x, y, mValuePaint); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java index 85597db6a1..5d49580561 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java @@ -90,6 +90,7 @@ public void computeLegend(ChartData data) { for (int i = 0; i < data.getDataSetCount(); i++) { IDataSet dataSet = data.getDataSetByIndex(i); + if (dataSet == null) continue; List clrs = dataSet.getColors(); int entryCount = dataSet.getEntryCount(); @@ -100,10 +101,19 @@ public void computeLegend(ChartData data) { IBarDataSet bds = (IBarDataSet) dataSet; String[] sLabels = bds.getStackLabels(); - for (int j = 0; j < clrs.size() && j < bds.getStackSize(); j++) { + int minEntries = Math.min(clrs.size(), bds.getStackSize()); + + for (int j = 0; j < minEntries; j++) { + String label; + if (sLabels.length > 0) { + int labelIndex = j % minEntries; + label = labelIndex < sLabels.length ? sLabels[labelIndex] : null; + } else { + label = null; + } computedEntries.add(new LegendEntry( - sLabels[j % sLabels.length], + label, dataSet.getForm(), dataSet.getFormSize(), dataSet.getFormLineWidth(), 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 ead9d6d701..a86c16f76b 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 @@ -12,7 +12,6 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; -import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; import com.github.mikephil.charting.interfaces.datasets.IDataSet; @@ -295,7 +294,7 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { int entryCount = dataSet.getEntryCount(); - final boolean isDrawSteppedEnabled = dataSet.getMode() == LineDataSet.Mode.STEPPED; + final boolean isDrawSteppedEnabled = dataSet.isDrawSteppedEnabled(); final int pointsPerEntryPair = isDrawSteppedEnabled ? 4 : 2; Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); @@ -323,10 +322,14 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { // more than 1 color if (dataSet.getColors().size() > 1) { - if (mLineBuffer.length <= pointsPerEntryPair * 2) - mLineBuffer = new float[pointsPerEntryPair * 4]; + int numberOfFloats = pointsPerEntryPair * 2; + + if (mLineBuffer.length <= numberOfFloats) + mLineBuffer = new float[numberOfFloats * 2]; + + int max = mXBounds.min + mXBounds.range; - for (int j = mXBounds.min; j <= mXBounds.range + mXBounds.min; j++) { + for (int j = mXBounds.min; j < max; j++) { Entry e = dataSet.getEntryForIndex(j); if (e == null) continue; @@ -357,16 +360,26 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { mLineBuffer[3] = mLineBuffer[1]; } + // Determine the start and end coordinates of the line, and make sure they differ. + float firstCoordinateX = mLineBuffer[0]; + float firstCoordinateY = mLineBuffer[1]; + float lastCoordinateX = mLineBuffer[numberOfFloats - 2]; + float lastCoordinateY = mLineBuffer[numberOfFloats - 1]; + + if (firstCoordinateX == lastCoordinateX && + firstCoordinateY == lastCoordinateY) + continue; + trans.pointValuesToPixel(mLineBuffer); - if (!mViewPortHandler.isInBoundsRight(mLineBuffer[0])) + if (!mViewPortHandler.isInBoundsRight(firstCoordinateX)) break; // make sure the lines don't do shitty things outside // bounds - if (!mViewPortHandler.isInBoundsLeft(mLineBuffer[2]) - || (!mViewPortHandler.isInBoundsTop(mLineBuffer[1]) && !mViewPortHandler - .isInBoundsBottom(mLineBuffer[3]))) + if (!mViewPortHandler.isInBoundsLeft(lastCoordinateX) || + !mViewPortHandler.isInBoundsTop(Math.max(firstCoordinateY, lastCoordinateY)) || + !mViewPortHandler.isInBoundsBottom(Math.min(firstCoordinateY, lastCoordinateY))) continue; // get the color that is set for this line-segment @@ -548,7 +561,6 @@ public void drawValues(Canvas c) { float[] positions = trans.generateTransformedValuesLine(dataSet, mAnimator.getPhaseX(), mAnimator .getPhaseY(), mXBounds.min, mXBounds.max); - ValueFormatter formatter = dataSet.getValueFormatter(); MPPointF iconsOffset = MPPointF.getInstance(dataSet.getIconsOffset()); iconsOffset.x = Utils.convertDpToPixel(iconsOffset.x); @@ -568,7 +580,8 @@ public void drawValues(Canvas c) { Entry entry = dataSet.getEntryForIndex(j / 2 + mXBounds.min); if (dataSet.isDrawValuesEnabled()) { - drawValue(c, formatter.getPointLabel(entry), x, y - valOffset, dataSet.getValueTextColor(j / 2)); + drawValue(c, dataSet.getValueFormatter(), entry.getY(), entry, i, x, + y - valOffset, dataSet.getValueTextColor(j / 2)); } if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) { @@ -590,12 +603,6 @@ public void drawValues(Canvas c) { } } - @Override - public void drawValue(Canvas c, String valueText, float x, float y, int color) { - mValuePaint.setColor(color); - c.drawText(valueText, x, y, mValuePaint); - } - @Override public void drawExtras(Canvas c) { drawCircles(c); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java index c9f653e808..f35c775d45 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -1,3 +1,4 @@ + package com.github.mikephil.charting.renderer; import android.graphics.Bitmap; @@ -21,7 +22,7 @@ import com.github.mikephil.charting.data.PieData; import com.github.mikephil.charting.data.PieDataSet; import com.github.mikephil.charting.data.PieEntry; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.formatter.IValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IPieDataSet; import com.github.mikephil.charting.utils.ColorTemplate; @@ -258,7 +259,7 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { } // Don't draw if it's highlighted, unless the chart uses rounded slices - if (mChart.needsHighlight(j) && !drawRoundedSlices) { + if (dataSet.isHighlightEnabled() && mChart.needsHighlight(j) && !drawRoundedSlices) { angle += sliceAngle * phaseX; continue; } @@ -464,11 +465,13 @@ public void drawValues(Canvas c) { float lineHeight = Utils.calcTextHeight(mValuePaint, "Q") + Utils.convertDpToPixel(4f); - ValueFormatter formatter = dataSet.getValueFormatter(); + IValueFormatter formatter = dataSet.getValueFormatter(); int entryCount = dataSet.getEntryCount(); - mValueLinePaint.setColor(dataSet.getValueLineColor()); + boolean isUseValueColorForLineEnabled = dataSet.isUseValueColorForLineEnabled(); + int valueLineColor = dataSet.getValueLineColor(); + mValueLinePaint.setStrokeWidth(Utils.convertDpToPixel(dataSet.getValueLineWidth())); final float sliceSpace = getSliceSpace(dataSet); @@ -498,7 +501,6 @@ public void drawValues(Canvas c) { float value = mChart.isUsePercentValuesEnabled() ? entry.getY() / yValueSum * 100f : entry.getY(); - String formattedValue = formatter.getPieLabel(value, entry); String entryLabel = entry.getLabel(); final float sliceXBase = (float) Math.cos(transformedAngle * Utils.FDEG2RAD); @@ -565,12 +567,15 @@ public void drawValues(Canvas c) { labelPty = pt2y; } - if (dataSet.getValueLineColor() != ColorTemplate.COLOR_NONE) { + int lineColor = ColorTemplate.COLOR_NONE; - if (dataSet.isUsingSliceColorAsValueLineColor()) { - mValueLinePaint.setColor(dataSet.getColor(j)); - } + if (isUseValueColorForLineEnabled) + lineColor = dataSet.getColor(j); + else if (valueLineColor != ColorTemplate.COLOR_NONE) + lineColor = valueLineColor; + if (lineColor != ColorTemplate.COLOR_NONE) { + mValueLinePaint.setColor(lineColor); c.drawLine(pt0x, pt0y, pt1x, pt1y, mValueLinePaint); c.drawLine(pt1x, pt1y, pt2x, pt2y, mValueLinePaint); } @@ -578,7 +583,14 @@ public void drawValues(Canvas c) { // draw everything, depending on settings if (drawXOutside && drawYOutside) { - drawValue(c, formattedValue, labelPtx, labelPty, dataSet.getValueTextColor(j)); + drawValue(c, + formatter, + value, + entry, + 0, + labelPtx, + labelPty, + dataSet.getValueTextColor(j)); if (j < data.getEntryCount() && entryLabel != null) { drawEntryLabel(c, entryLabel, labelPtx, labelPty + lineHeight); @@ -590,7 +602,8 @@ public void drawValues(Canvas c) { } } else if (drawYOutside) { - drawValue(c, formattedValue, labelPtx, labelPty + lineHeight / 2.f, dataSet.getValueTextColor(j)); + drawValue(c, formatter, value, entry, 0, labelPtx, labelPty + lineHeight / 2.f, dataSet + .getValueTextColor(j)); } } @@ -604,7 +617,7 @@ public void drawValues(Canvas c) { // draw everything, depending on settings if (drawXInside && drawYInside) { - drawValue(c, formattedValue, x, y, dataSet.getValueTextColor(j)); + drawValue(c, formatter, value, entry, 0, x, y, dataSet.getValueTextColor(j)); if (j < data.getEntryCount() && entryLabel != null) { drawEntryLabel(c, entryLabel, x, y + lineHeight); @@ -615,7 +628,8 @@ public void drawValues(Canvas c) { drawEntryLabel(c, entryLabel, x, y + lineHeight / 2f); } } else if (drawYInside) { - drawValue(c, formattedValue, x, y + lineHeight / 2f, dataSet.getValueTextColor(j)); + + drawValue(c, formatter, value, entry, 0, x, y + lineHeight / 2f, dataSet.getValueTextColor(j)); } } @@ -645,12 +659,6 @@ public void drawValues(Canvas c) { c.restore(); } - @Override - public void drawValue(Canvas c, String valueText, float x, float y, int color) { - mValuePaint.setColor(color); - c.drawText(valueText, x, y, mValuePaint); - } - /** * Draws an entry label at the specified position. * @@ -825,8 +833,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { continue; IPieDataSet set = mChart.getData() - .getDataSetByIndex(indices[i] - .getDataSetIndex()); + .getDataSetByIndex(indices[i].getDataSetIndex()); if (set == null || !set.isHighlightEnabled()) continue; @@ -857,7 +864,10 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { final boolean accountForSliceSpacing = sliceSpace > 0.f && sliceAngle <= 180.f; - mRenderPaint.setColor(set.getColor(index)); + Integer highlightColor = set.getHighlightColor(); + if (highlightColor == null) + highlightColor = set.getColor(index); + mRenderPaint.setColor(highlightColor); final float sliceSpaceAngleOuter = visibleAngleCount == 1 ? 0.f : diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java index 3f932f8725..dbf0e8f807 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -1,3 +1,4 @@ + package com.github.mikephil.charting.renderer; import android.graphics.Canvas; @@ -10,7 +11,6 @@ import com.github.mikephil.charting.charts.RadarChart; import com.github.mikephil.charting.data.RadarData; import com.github.mikephil.charting.data.RadarEntry; -import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IRadarDataSet; import com.github.mikephil.charting.utils.ColorTemplate; @@ -174,8 +174,6 @@ public void drawValues(Canvas c) { // apply the text-styling defined by the DataSet applyValueTextStyle(dataSet); - ValueFormatter formatter = dataSet.getValueFormatter(); - MPPointF iconsOffset = MPPointF.getInstance(dataSet.getIconsOffset()); iconsOffset.x = Utils.convertDpToPixel(iconsOffset.x); iconsOffset.y = Utils.convertDpToPixel(iconsOffset.y); @@ -191,7 +189,15 @@ public void drawValues(Canvas c) { pOut); if (dataSet.isDrawValuesEnabled()) { - drawValue(c, formatter.getRadarLabel(entry), pOut.x, pOut.y - yoffset, dataSet.getValueTextColor(j)); + drawValue(c, + dataSet.getValueFormatter(), + entry.getY(), + entry, + i, + pOut.x, + pOut.y - yoffset, + dataSet.getValueTextColor + (j)); } if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) { @@ -225,12 +231,6 @@ public void drawValues(Canvas c) { MPPointF.recycleInstance(pIcon); } - @Override - public void drawValue(Canvas c, String valueText, float x, float y, int color) { - mValuePaint.setColor(color); - c.drawText(valueText, x, y, mValuePaint); - } - @Override public void drawExtras(Canvas c) { drawWeb(c); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index 98dddb93f9..ccd077e55c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -1,3 +1,4 @@ + package com.github.mikephil.charting.renderer; import android.graphics.Canvas; @@ -7,7 +8,6 @@ import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.ScatterData; -import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.ScatterDataProvider; import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; @@ -118,8 +118,6 @@ public void drawValues(Canvas c) { float shapeSize = Utils.convertDpToPixel(dataSet.getScatterShapeSize()); - ValueFormatter formatter = dataSet.getValueFormatter(); - MPPointF iconsOffset = MPPointF.getInstance(dataSet.getIconsOffset()); iconsOffset.x = Utils.convertDpToPixel(iconsOffset.x); iconsOffset.y = Utils.convertDpToPixel(iconsOffset.y); @@ -137,7 +135,14 @@ public void drawValues(Canvas c) { Entry entry = dataSet.getEntryForIndex(j / 2 + mXBounds.min); if (dataSet.isDrawValuesEnabled()) { - drawValue(c, formatter.getPointLabel(entry), positions[j], positions[j + 1] - shapeSize, dataSet.getValueTextColor(j / 2 + mXBounds.min)); + drawValue(c, + dataSet.getValueFormatter(), + entry.getY(), + entry, + i, + positions[j], + positions[j + 1] - shapeSize, + dataSet.getValueTextColor(j / 2 + mXBounds.min)); } if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) { @@ -159,12 +164,6 @@ public void drawValues(Canvas c) { } } - @Override - public void drawValue(Canvas c, String valueText, float x, float y, int color) { - mValuePaint.setColor(color); - c.drawText(valueText, x, y, mValuePaint); - } - @Override public void drawExtras(Canvas c) { } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java index 046f3469bc..8adb56c73a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -1,3 +1,4 @@ + package com.github.mikephil.charting.renderer; import android.graphics.Canvas; @@ -201,7 +202,7 @@ 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.getValueFormatter().getFormattedValue(mXAxis.mEntries[i / 2], mXAxis); if (mXAxis.isAvoidFirstLastClippingEnabled()) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java index 9054dcb679..86047cf1b8 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java @@ -1,3 +1,4 @@ + package com.github.mikephil.charting.renderer; import android.graphics.Canvas; @@ -56,10 +57,10 @@ public void computeAxis(float min, float max, boolean inverted) { computeAxisValues(min, max); } - + @Override protected void computeSize() { - + mAxisLabelPaint.setTypeface(mXAxis.getTypeface()); mAxisLabelPaint.setTextSize(mXAxis.getTextSize()); @@ -155,7 +156,7 @@ protected void drawLabels(Canvas c, float pos, MPPointF anchor) { if (mViewPortHandler.isInBoundsY(y)) { - String label = mXAxis.getValueFormatter().getAxisLabel(mXAxis.mEntries[i / 2], mXAxis); + String label = mXAxis.getValueFormatter().getFormattedValue(mXAxis.mEntries[i / 2], mXAxis); drawLabel(c, label, pos, y, anchor, labelRotationAngleDegrees); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java index 6d83cf59e4..956e8c7d5c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java @@ -1,6 +1,8 @@ + package com.github.mikephil.charting.renderer; import android.graphics.Canvas; +import android.graphics.PointF; import com.github.mikephil.charting.charts.RadarChart; import com.github.mikephil.charting.components.XAxis; @@ -41,7 +43,7 @@ public void renderAxisLabels(Canvas c) { MPPointF pOut = MPPointF.getInstance(0,0); for (int i = 0; i < mChart.getData().getMaxEntryCountSet().getEntryCount(); i++) { - String label = mXAxis.getValueFormatter().getAxisLabel(i, mXAxis); + String label = mXAxis.getValueFormatter().getFormattedValue(i, mXAxis); float angle = (sliceangle * i + mChart.getRotationAngle()) % 360f; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java index a2bf679777..53cca7ee03 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -119,12 +119,17 @@ protected void drawYLabels(Canvas c, float fixedPosition, float[] positions, flo ? mYAxis.mEntryCount : (mYAxis.mEntryCount - 1); + float xOffset = mYAxis.getLabelXOffset(); + // draw for (int i = from; i < to; i++) { String text = mYAxis.getFormattedLabel(i); - c.drawText(text, fixedPosition, positions[i * 2 + 1] + offset, mAxisLabelPaint); + c.drawText(text, + fixedPosition + xOffset, + positions[i * 2 + 1] + offset, + mAxisLabelPaint); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java index 71275b03c3..fedf8054a1 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java @@ -142,11 +142,16 @@ protected void drawYLabels(Canvas c, float fixedPosition, float[] positions, flo ? mYAxis.mEntryCount : (mYAxis.mEntryCount - 1); + float xOffset = mYAxis.getLabelXOffset(); + for (int i = from; i < to; i++) { String text = mYAxis.getFormattedLabel(i); - c.drawText(text, positions[i * 2], fixedPosition - offset, mAxisLabelPaint); + c.drawText(text, + positions[i * 2], + fixedPosition - offset + xOffset, + mAxisLabelPaint); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java index ee7392e928..f7b1ad9e87 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java @@ -52,9 +52,11 @@ protected void computeAxisValues(float min, float max) { double intervalMagnitude = Utils.roundToNextSignificant(Math.pow(10, (int) Math.log10(interval))); int intervalSigDigit = (int) (interval / intervalMagnitude); if (intervalSigDigit > 5) { - // Use one order of magnitude higher, to avoid intervals like 0.9 or - // 90 - interval = Math.floor(10 * intervalMagnitude); + // Use one order of magnitude higher, to avoid intervals like 0.9 or 90 + // if it's 0.0 after floor(), we use the old value + interval = Math.floor(10.0 * intervalMagnitude) == 0.0 + ? interval + : Math.floor(10.0 * intervalMagnitude); } boolean centeringEnabled = mAxis.isCenterAxisLabelsEnabled(); @@ -161,6 +163,8 @@ public void renderAxisLabels(Canvas c) { ? mYAxis.mEntryCount : (mYAxis.mEntryCount - 1); + float xOffset = mYAxis.getLabelXOffset(); + for (int j = from; j < to; j++) { float r = (mYAxis.mEntries[j] - mYAxis.mAxisMinimum) * factor; @@ -169,7 +173,7 @@ public void renderAxisLabels(Canvas c) { String label = mYAxis.getFormattedLabel(j); - c.drawText(label, pOut.x + 10, pOut.y, mAxisLabelPaint); + c.drawText(label, pOut.x + xOffset, pOut.y, mAxisLabelPaint); } MPPointF.recycleInstance(center); MPPointF.recycleInstance(pOut); 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 0000000000..d12e1fb8d7 --- /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() + "."); + } + } +} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java index 60ff6ba3da..c302673919 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java @@ -1,3 +1,4 @@ + package com.github.mikephil.charting.utils; import android.annotation.SuppressLint; @@ -6,6 +7,7 @@ import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; +import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Build; import android.text.Layout; @@ -13,13 +15,14 @@ import android.text.TextPaint; import android.util.DisplayMetrics; import android.util.Log; +import android.util.SizeF; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; import android.view.ViewConfiguration; import com.github.mikephil.charting.formatter.DefaultValueFormatter; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.formatter.IValueFormatter; import java.util.List; @@ -226,14 +229,15 @@ public static void calcTextSize(Paint paint, String demoText, FSize outputFSize) 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; - private static ValueFormatter mDefaultValueFormatter = generateDefaultValueFormatter(); + private static IValueFormatter mDefaultValueFormatter = generateDefaultValueFormatter(); - private static ValueFormatter generateDefaultValueFormatter() { - return new DefaultValueFormatter(1); + private static IValueFormatter generateDefaultValueFormatter() { + final DefaultValueFormatter formatter = new DefaultValueFormatter(1); + return formatter; } /// - returns: The default value formatter used for all chart components that needs a default - public static ValueFormatter getDefaultValueFormatter() + public static IValueFormatter getDefaultValueFormatter() { return mDefaultValueFormatter; } @@ -349,11 +353,11 @@ public static String formatNumber(float number, int digitCount, boolean separate * @return */ public static float roundToNextSignificant(double number) { - if (Double.isInfinite(number) || - Double.isNaN(number) || + if (Double.isInfinite(number) || + Double.isNaN(number) || number == 0.0) return 0; - + final float d = (float) Math.ceil((float) Math.log10(number < 0 ? -number : number)); final int pw = 1 - (int) d; final float magnitude = (float) Math.pow(10, pw); @@ -371,10 +375,10 @@ public static float roundToNextSignificant(double number) { public static int getDecimals(float number) { float i = roundToNextSignificant(number); - + if (Float.isInfinite(i)) return 0; - + return (int) Math.ceil(-Math.log10(i)) + 2; } diff --git a/MPChartLib/src/test/java/com/github/mikephil/charting/test/LargeValueFormatterTest.java b/MPChartLib/src/test/java/com/github/mikephil/charting/test/LargeValueFormatterTest.java index fc7eb93e75..f1e1e0279e 100644 --- a/MPChartLib/src/test/java/com/github/mikephil/charting/test/LargeValueFormatterTest.java +++ b/MPChartLib/src/test/java/com/github/mikephil/charting/test/LargeValueFormatterTest.java @@ -16,80 +16,80 @@ public void test() { LargeValueFormatter formatter = new LargeValueFormatter(); - String result = formatter.getFormattedValue(5f); + String result = formatter.getFormattedValue(5f, null); assertEquals("5", result); - result = formatter.getFormattedValue(5.5f); + result = formatter.getFormattedValue(5.5f, null); assertEquals("5.5", result); - result = formatter.getFormattedValue(50f); + result = formatter.getFormattedValue(50f, null); assertEquals("50", result); - result = formatter.getFormattedValue(50.5f); + result = formatter.getFormattedValue(50.5f, null); assertEquals("50.5", result); - result = formatter.getFormattedValue(500f); + result = formatter.getFormattedValue(500f, null); assertEquals("500", result); - result = formatter.getFormattedValue(1100f); + result = formatter.getFormattedValue(1100f, null); assertEquals("1.1k", result); - result = formatter.getFormattedValue(10000f); + result = formatter.getFormattedValue(10000f, null); assertEquals("10k", result); - result = formatter.getFormattedValue(10500f); + result = formatter.getFormattedValue(10500f, null); assertEquals("10.5k", result); - result = formatter.getFormattedValue(100000f); + result = formatter.getFormattedValue(100000f, null); assertEquals("100k", result); - result = formatter.getFormattedValue(1000000f); + result = formatter.getFormattedValue(1000000f, null); assertEquals("1m", result); - result = formatter.getFormattedValue(1500000f); + result = formatter.getFormattedValue(1500000f, null); assertEquals("1.5m", result); - result = formatter.getFormattedValue(9500000f); + result = formatter.getFormattedValue(9500000f, null); assertEquals("9.5m", result); - result = formatter.getFormattedValue(22200000f); + result = formatter.getFormattedValue(22200000f, null); assertEquals("22.2m", result); - result = formatter.getFormattedValue(222000000f); + result = formatter.getFormattedValue(222000000f, null); assertEquals("222m", result); - result = formatter.getFormattedValue(1000000000f); + result = formatter.getFormattedValue(1000000000f, null); assertEquals("1b", result); - result = formatter.getFormattedValue(9900000000f); + result = formatter.getFormattedValue(9900000000f, null); assertEquals("9.9b", result); - result = formatter.getFormattedValue(99000000000f); + result = formatter.getFormattedValue(99000000000f, null); assertEquals("99b", result); - result = formatter.getFormattedValue(99500000000f); + result = formatter.getFormattedValue(99500000000f, null); assertEquals("99.5b", result); - result = formatter.getFormattedValue(999000000000f); + result = formatter.getFormattedValue(999000000000f, null); assertEquals("999b", result); - result = formatter.getFormattedValue(1000000000000f); + result = formatter.getFormattedValue(1000000000000f, null); assertEquals("1t", result); formatter.setSuffix(new String[]{"", "k", "m", "b", "t", "q"}); // quadrillion support - result = formatter.getFormattedValue(1000000000000000f); + result = formatter.getFormattedValue(1000000000000000f, null); assertEquals("1q", result); - result = formatter.getFormattedValue(1100000000000000f); + result = formatter.getFormattedValue(1100000000000000f, null); assertEquals("1.1q", result); - result = formatter.getFormattedValue(10000000000000000f); + result = formatter.getFormattedValue(10000000000000000f, null); assertEquals("10q", result); - result = formatter.getFormattedValue(13300000000000000f); + result = formatter.getFormattedValue(13300000000000000f, null); assertEquals("13.3q", result); - result = formatter.getFormattedValue(100000000000000000f); + result = formatter.getFormattedValue(100000000000000000f, null); assertEquals("100q", result); } } diff --git a/MPChartLib/src/test/java/com/github/mikephil/charting/test/ObjectPoolTest.java b/MPChartLib/src/test/java/com/github/mikephil/charting/test/ObjectPoolTest.java index 44946cf4da..e1dbe81be9 100644 --- a/MPChartLib/src/test/java/com/github/mikephil/charting/test/ObjectPoolTest.java +++ b/MPChartLib/src/test/java/com/github/mikephil/charting/test/ObjectPoolTest.java @@ -2,7 +2,7 @@ import com.github.mikephil.charting.utils.ObjectPool; -import org.junit.Assert; +import junit.framework.Assert; import org.junit.Test; diff --git a/README.md b/README.md index 044a84f9a6..46006a1e06 100644 --- a/README.md +++ b/README.md @@ -23,28 +23,6 @@ 1. [License](#licence) 1. [Creators](#creators) -## [Realtime Graphing Solution | SciChart](https://scichart.com/android-chart-features?source=MPAndroidChart) - - - - -MPAndroidChart is free software, as a result **dynamic & realtime data is not officially supported**. If you are looking for an enterprise-grade chart solution with extreme realtime performance and tech support, we recommend -SciChart Android. - - - -All MPAndroidChart users are entitled to a special **discount of 5%** off the SciChart store, using the following discount code: **MPANDROIDCHART** - -
- -## [Bi-Weekly Coding Newsletter](https://weeklycoding.com) - -Sign up for my [coding newsletter](https://weeklycoding.com) to get quick updates on Kotlin and Android development related topics. - -

Quick Start :chart_with_upwards_trend:

- -Add the library to your Android project, then check out the examples below! - ### Gradle Setup ```gradle @@ -209,7 +187,7 @@ You can follow me on Twitter [**@PhilippJahoda**](https://twitter.com/PhilippJah

License :page_facing_up:

-Copyright 2019 Philipp Jahoda +Copyright 2020 Philipp Jahoda Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.