Merge branch 'master' of https://github.com/PhilJay/MPAndroidChart
This commit is contained in:
commit
66ea845e14
12 changed files with 668 additions and 274 deletions
|
@ -2,6 +2,7 @@
|
|||
package com.xxmassdeveloper.mpchartexample;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.graphics.DashPathEffect;
|
||||
import android.graphics.Typeface;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
|
@ -368,6 +369,9 @@ public class LineChartActivity1 extends DemoBase implements OnSeekBarChangeListe
|
|||
set1.setDrawCircleHole(false);
|
||||
set1.setValueTextSize(9f);
|
||||
set1.setDrawFilled(true);
|
||||
set1.setFormLineWidth(1f);
|
||||
set1.setFormLineDashEffect(new DashPathEffect(new float[]{10f, 5f}, 0f));
|
||||
set1.setFormSize(15.f);
|
||||
|
||||
if (Utils.getSDKInt() >= 18) {
|
||||
// fill drawable only supported on api level 18 and above
|
||||
|
|
|
@ -222,11 +222,6 @@ public abstract class BarLineChartBase<T extends BarLineScatterCandleBubbleData<
|
|||
}
|
||||
}
|
||||
|
||||
// make sure the graph values and grid cannot be drawn outside the
|
||||
// content-rect
|
||||
int clipRestoreCount = canvas.save();
|
||||
canvas.clipRect(mViewPortHandler.getContentRect());
|
||||
|
||||
mXAxisRenderer.renderGridLines(canvas);
|
||||
mAxisRendererLeft.renderGridLines(canvas);
|
||||
mAxisRendererRight.renderGridLines(canvas);
|
||||
|
@ -240,6 +235,10 @@ public abstract class BarLineChartBase<T extends BarLineScatterCandleBubbleData<
|
|||
if (mAxisRight.isDrawLimitLinesBehindDataEnabled())
|
||||
mAxisRendererRight.renderLimitLines(canvas);
|
||||
|
||||
// make sure the data cannot be drawn outside the content-rect
|
||||
int clipRestoreCount = canvas.save();
|
||||
canvas.clipRect(mViewPortHandler.getContentRect());
|
||||
|
||||
mRenderer.drawData(canvas);
|
||||
|
||||
// if highlighting is enabled
|
||||
|
@ -251,9 +250,6 @@ public abstract class BarLineChartBase<T extends BarLineScatterCandleBubbleData<
|
|||
|
||||
mRenderer.drawExtras(canvas);
|
||||
|
||||
clipRestoreCount = canvas.save();
|
||||
canvas.clipRect(mViewPortHandler.getContentRect());
|
||||
|
||||
if (!mXAxis.isDrawLimitLinesBehindDataEnabled())
|
||||
mXAxisRenderer.renderLimitLines(canvas);
|
||||
|
||||
|
@ -262,9 +258,7 @@ public abstract class BarLineChartBase<T extends BarLineScatterCandleBubbleData<
|
|||
|
||||
if (!mAxisRight.isDrawLimitLinesBehindDataEnabled())
|
||||
mAxisRendererRight.renderLimitLines(canvas);
|
||||
|
||||
canvas.restoreToCount(clipRestoreCount);
|
||||
|
||||
|
||||
mXAxisRenderer.renderAxisLabels(canvas);
|
||||
mAxisRendererLeft.renderAxisLabels(canvas);
|
||||
mAxisRendererRight.renderAxisLabels(canvas);
|
||||
|
|
|
@ -115,8 +115,7 @@ public abstract class PieRadarChartBase<T extends ChartData<? extends IDataSet<?
|
|||
if (mLegend != null && mLegend.isEnabled() && !mLegend.isDrawInsideEnabled()) {
|
||||
|
||||
float fullLegendWidth = Math.min(mLegend.mNeededWidth,
|
||||
mViewPortHandler.getChartWidth() * mLegend.getMaxSizePercent()) +
|
||||
mLegend.getFormSize() + mLegend.getFormToTextSpace();
|
||||
mViewPortHandler.getChartWidth() * mLegend.getMaxSizePercent());
|
||||
|
||||
switch (mLegend.getOrientation()) {
|
||||
case VERTICAL: {
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
|
||||
package com.github.mikephil.charting.components;
|
||||
|
||||
import android.graphics.DashPathEffect;
|
||||
import android.graphics.Paint;
|
||||
|
||||
import com.github.mikephil.charting.data.Entry;
|
||||
import com.github.mikephil.charting.utils.ColorTemplate;
|
||||
import com.github.mikephil.charting.utils.FSize;
|
||||
import com.github.mikephil.charting.utils.Utils;
|
||||
|
@ -33,7 +35,35 @@ public class Legend extends ComponentBase {
|
|||
}
|
||||
|
||||
public enum LegendForm {
|
||||
SQUARE, CIRCLE, LINE
|
||||
/**
|
||||
* Avoid drawing a form
|
||||
*/
|
||||
NONE,
|
||||
|
||||
/**
|
||||
* Do not draw the a form, but leave space for it
|
||||
*/
|
||||
EMPTY,
|
||||
|
||||
/**
|
||||
* Use default (default dataset's form to the legend's form)
|
||||
*/
|
||||
DEFAULT,
|
||||
|
||||
/**
|
||||
* Draw a square
|
||||
*/
|
||||
SQUARE,
|
||||
|
||||
/**
|
||||
* Draw a circle
|
||||
*/
|
||||
CIRCLE,
|
||||
|
||||
/**
|
||||
* Draw a horizontal line
|
||||
*/
|
||||
LINE
|
||||
}
|
||||
|
||||
public enum LegendHorizontalAlignment {
|
||||
|
@ -53,27 +83,15 @@ public class Legend extends ComponentBase {
|
|||
}
|
||||
|
||||
/**
|
||||
* the legend colors array, each color is for the form drawn at the same
|
||||
* index
|
||||
* The legend entries array
|
||||
*/
|
||||
private int[] mColors;
|
||||
private LegendEntry[] mEntries = new LegendEntry[]{};
|
||||
|
||||
/**
|
||||
* the legend text array. a null label will start a group.
|
||||
* Entries that will be appended to the end of the auto calculated entries after calculating the legend.
|
||||
* (if the legend has already been calculated, you will need to call notifyDataSetChanged() to let the changes take effect)
|
||||
*/
|
||||
private String[] mLabels;
|
||||
|
||||
/**
|
||||
* colors that will be appended to the end of the colors array after
|
||||
* calculating the legend.
|
||||
*/
|
||||
private int[] mExtraColors;
|
||||
|
||||
/**
|
||||
* labels that will be appended to the end of the labels array after
|
||||
* calculating the legend. a null label will start a group.
|
||||
*/
|
||||
private String[] mExtraLabels;
|
||||
private LegendEntry[] mExtraEntries;
|
||||
|
||||
/**
|
||||
* Are the legend labels/colors a custom value or auto calculated? If false,
|
||||
|
@ -101,6 +119,16 @@ public class Legend extends ComponentBase {
|
|||
*/
|
||||
private float mFormSize = 8f;
|
||||
|
||||
/**
|
||||
* the size of the legend forms/shapes
|
||||
*/
|
||||
private float mFormLineWidth = 3f;
|
||||
|
||||
/**
|
||||
* Line dash path effect used for shapes that consist of lines.
|
||||
*/
|
||||
private DashPathEffect mFormLineDashEffect = null;
|
||||
|
||||
/**
|
||||
* the space between the legend entries on a horizontal axis, default 6f
|
||||
*/
|
||||
|
@ -133,22 +161,27 @@ public class Legend extends ComponentBase {
|
|||
*/
|
||||
public Legend() {
|
||||
|
||||
mFormSize = Utils.convertDpToPixel(8f);
|
||||
mXEntrySpace = Utils.convertDpToPixel(6f);
|
||||
mYEntrySpace = Utils.convertDpToPixel(0f);
|
||||
mFormToTextSpace = Utils.convertDpToPixel(5f);
|
||||
mTextSize = Utils.convertDpToPixel(10f);
|
||||
mStackSpace = Utils.convertDpToPixel(3f);
|
||||
this.mTextSize = Utils.convertDpToPixel(10f);
|
||||
this.mXOffset = Utils.convertDpToPixel(5f);
|
||||
this.mYOffset = Utils.convertDpToPixel(3f); // 2
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor. Provide colors and labels for the legend.
|
||||
* Constructor. Provide entries for the legend.
|
||||
*
|
||||
* @param colors
|
||||
* @param labels
|
||||
* @param entries
|
||||
*/
|
||||
public Legend(LegendEntry[] entries) {
|
||||
this();
|
||||
|
||||
if (entries == null) {
|
||||
throw new IllegalArgumentException("entries array is NULL");
|
||||
}
|
||||
|
||||
this.mEntries = entries;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public Legend(int[] colors, String[] labels) {
|
||||
this();
|
||||
|
||||
|
@ -161,56 +194,41 @@ public class Legend extends ComponentBase {
|
|||
"colors array and labels array need to be of same size");
|
||||
}
|
||||
|
||||
this.mColors = colors;
|
||||
this.mLabels = labels;
|
||||
List<LegendEntry> entries = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < Math.min(colors.length, labels.length); i++) {
|
||||
final LegendEntry entry = new LegendEntry();
|
||||
entry.formColor = colors[i];
|
||||
entry.label = labels[i];
|
||||
|
||||
if (entry.formColor == ColorTemplate.COLOR_SKIP)
|
||||
entry.form = LegendForm.NONE;
|
||||
else if (entry.formColor == ColorTemplate.COLOR_NONE ||
|
||||
entry.formColor == 0)
|
||||
entry.form = LegendForm.EMPTY;
|
||||
|
||||
entries.add(entry);
|
||||
}
|
||||
|
||||
mEntries = entries.toArray(new LegendEntry[entries.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor. Provide colors and labels for the legend.
|
||||
*
|
||||
* @param colors
|
||||
* @param labels
|
||||
*/
|
||||
@Deprecated
|
||||
public Legend(List<Integer> colors, List<String> labels) {
|
||||
this();
|
||||
|
||||
if (colors == null || labels == null) {
|
||||
throw new IllegalArgumentException("colors array or labels array is NULL");
|
||||
}
|
||||
|
||||
if (colors.size() != labels.size()) {
|
||||
throw new IllegalArgumentException(
|
||||
"colors array and labels array need to be of same size");
|
||||
}
|
||||
|
||||
this.mColors = Utils.convertIntegers(colors);
|
||||
this.mLabels = Utils.convertStrings(labels);
|
||||
this(Utils.convertIntegers(colors), Utils.convertStrings(labels));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method sets the automatically computed colors for the legend. Use setCustom(...) to set custom colors.
|
||||
*
|
||||
* @param colors
|
||||
* @param entries
|
||||
*/
|
||||
public void setComputedColors(List<Integer> colors) {
|
||||
if (mColors != null && colors.size() == mColors.length) {
|
||||
Utils.copyIntegers(colors, mColors);
|
||||
} else {
|
||||
mColors = Utils.convertIntegers(colors);
|
||||
}
|
||||
public void setEntries(List<LegendEntry> entries) {
|
||||
mEntries = entries.toArray(new LegendEntry[entries.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method sets the automatically computed labels for the legend. Use setCustom(...) to set custom labels.
|
||||
*
|
||||
* @param labels
|
||||
*/
|
||||
public void setComputedLabels(List<String> labels) {
|
||||
if (mLabels != null && mLabels.length == labels.size()) {
|
||||
Utils.copyStrings(labels, mLabels);
|
||||
} else {
|
||||
mLabels = Utils.convertStrings(labels);
|
||||
}
|
||||
public LegendEntry[] getEntries() {
|
||||
return mEntries;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -223,19 +241,26 @@ public class Legend extends ComponentBase {
|
|||
public float getMaximumEntryWidth(Paint p) {
|
||||
|
||||
float max = 0f;
|
||||
float maxFormSize = 0f;
|
||||
float formToTextSpace = Utils.convertDpToPixel(mFormToTextSpace);
|
||||
|
||||
for (int i = 0; i < mLabels.length; i++) {
|
||||
for (LegendEntry entry : mEntries) {
|
||||
final float formSize = Utils.convertDpToPixel(
|
||||
Float.isNaN(entry.formSize)
|
||||
? mFormSize : entry.formSize);
|
||||
if (formSize > maxFormSize)
|
||||
maxFormSize = formSize;
|
||||
|
||||
if (mLabels[i] != null) {
|
||||
String label = entry.label;
|
||||
if (label == null) continue;
|
||||
|
||||
float length = (float) Utils.calcTextWidth(p, mLabels[i]);
|
||||
float length = (float) Utils.calcTextWidth(p, label);
|
||||
|
||||
if (length > max)
|
||||
max = length;
|
||||
}
|
||||
if (length > max)
|
||||
max = length;
|
||||
}
|
||||
|
||||
return max + mFormSize + mFormToTextSpace;
|
||||
return max + maxFormSize + formToTextSpace;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -248,140 +273,141 @@ public class Legend extends ComponentBase {
|
|||
|
||||
float max = 0f;
|
||||
|
||||
for (int i = 0; i < mLabels.length; i++) {
|
||||
for (LegendEntry entry : mEntries) {
|
||||
String label = entry.label;
|
||||
if (label == null) continue;
|
||||
|
||||
if (mLabels[i] != null) {
|
||||
float length = (float) Utils.calcTextHeight(p, label);
|
||||
|
||||
float length = (float) Utils.calcTextHeight(p, mLabels[i]);
|
||||
|
||||
if (length > max)
|
||||
max = length;
|
||||
}
|
||||
if (length > max)
|
||||
max = length;
|
||||
}
|
||||
|
||||
return max;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns all the colors the legend uses
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Deprecated
|
||||
public int[] getColors() {
|
||||
return mColors;
|
||||
|
||||
int[] old = new int[mEntries.length];
|
||||
for (int i = 0; i < mEntries.length; i++) {
|
||||
old[i] = mEntries[i].form == LegendForm.NONE ? ColorTemplate.COLOR_SKIP :
|
||||
(mEntries[i].form == LegendForm.EMPTY ? ColorTemplate.COLOR_NONE :
|
||||
mEntries[i].formColor);
|
||||
}
|
||||
return old;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns all the labels the legend uses
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Deprecated
|
||||
public String[] getLabels() {
|
||||
return mLabels;
|
||||
|
||||
String[] old = new String[mEntries.length];
|
||||
for (int i = 0; i < mEntries.length; i++) {
|
||||
old[i] = mEntries[i].label;
|
||||
}
|
||||
return old;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the legend-label at the given index.
|
||||
*
|
||||
* @param index
|
||||
* @return
|
||||
*/
|
||||
public String getLabel(int index) {
|
||||
return mLabels[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* colors that will be appended to the end of the colors array after
|
||||
* calculating the legend.
|
||||
*/
|
||||
@Deprecated
|
||||
public int[] getExtraColors() {
|
||||
return mExtraColors;
|
||||
|
||||
int[] old = new int[mExtraEntries.length];
|
||||
for (int i = 0; i < mExtraEntries.length; i++) {
|
||||
old[i] = mExtraEntries[i].form == LegendForm.NONE ? ColorTemplate.COLOR_SKIP :
|
||||
(mExtraEntries[i].form == LegendForm.EMPTY ? ColorTemplate.COLOR_NONE :
|
||||
mExtraEntries[i].formColor);
|
||||
}
|
||||
return old;
|
||||
}
|
||||
|
||||
/**
|
||||
* labels that will be appended to the end of the labels array after
|
||||
* calculating the legend. a null label will start a group.
|
||||
*/
|
||||
@Deprecated
|
||||
public String[] getExtraLabels() {
|
||||
return mExtraLabels;
|
||||
|
||||
String[] old = new String[mExtraEntries.length];
|
||||
for (int i = 0; i < mExtraEntries.length; i++) {
|
||||
old[i] = mExtraEntries[i].label;
|
||||
}
|
||||
return old;
|
||||
}
|
||||
|
||||
/**
|
||||
* Colors and labels that will be appended to the end of the auto calculated
|
||||
* colors and labels arrays after calculating the legend. (if the legend has
|
||||
* already been calculated, you will need to call notifyDataSetChanged() to
|
||||
* let the changes take effect)
|
||||
*/
|
||||
public LegendEntry[] getExtraEntries() {
|
||||
|
||||
return mExtraEntries;
|
||||
}
|
||||
|
||||
public void setExtra(List<LegendEntry> entries) {
|
||||
mExtraEntries = entries.toArray(new LegendEntry[entries.size()]);
|
||||
}
|
||||
|
||||
public void setExtra(LegendEntry[] entries) {
|
||||
if (entries == null)
|
||||
entries = new LegendEntry[]{};
|
||||
mExtraEntries = entries;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setExtra(List<Integer> colors, List<String> labels) {
|
||||
if (mExtraColors != null && mExtraColors.length == colors.size()) {
|
||||
Utils.copyIntegers(colors, mExtraColors);
|
||||
} else {
|
||||
this.mExtraColors = Utils.convertIntegers(colors);
|
||||
}
|
||||
|
||||
if (mExtraLabels != null && mExtraLabels.length == labels.size()) {
|
||||
Utils.copyStrings(labels, mExtraLabels);
|
||||
} else {
|
||||
this.mExtraLabels = Utils.convertStrings(labels);
|
||||
}
|
||||
setExtra(Utils.convertIntegers(colors), Utils.convertStrings(labels));
|
||||
}
|
||||
|
||||
/**
|
||||
* Colors and labels that will be appended to the end of the auto calculated
|
||||
* colors and labels arrays after calculating the legend. (if the legend has
|
||||
* already been calculated, you will need to call notifyDataSetChanged() to
|
||||
* let the changes take effect)
|
||||
* Entries that will be appended to the end of the auto calculated
|
||||
* entries after calculating the legend.
|
||||
* (if the legend has already been calculated, you will need to call notifyDataSetChanged()
|
||||
* to let the changes take effect)
|
||||
*/
|
||||
public void setExtra(int[] colors, String[] labels) {
|
||||
this.mExtraColors = colors;
|
||||
this.mExtraLabels = labels;
|
||||
|
||||
List<LegendEntry> entries = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < Math.min(colors.length, labels.length); i++) {
|
||||
final LegendEntry entry = new LegendEntry();
|
||||
entry.formColor = colors[i];
|
||||
entry.label = labels[i];
|
||||
|
||||
if (entry.formColor == ColorTemplate.COLOR_SKIP ||
|
||||
entry.formColor == 0)
|
||||
entry.form = LegendForm.NONE;
|
||||
else if (entry.formColor == ColorTemplate.COLOR_NONE)
|
||||
entry.form = LegendForm.EMPTY;
|
||||
|
||||
entries.add(entry);
|
||||
}
|
||||
|
||||
mExtraEntries = entries.toArray(new LegendEntry[entries.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a custom legend's labels and colors arrays. The colors count should
|
||||
* match the labels count. * Each color is for the form drawn at the same
|
||||
* index. * A null label will start a group. * A ColorTemplate.COLOR_SKIP
|
||||
* color will avoid drawing a form This will disable the feature that
|
||||
* automatically calculates the legend labels and colors from the datasets.
|
||||
* Sets a custom legend's entries array.
|
||||
* * A null label will start a group.
|
||||
* This will disable the feature that automatically calculates the legend
|
||||
* entries from the datasets.
|
||||
* Call resetCustom() to re-enable automatic calculation (and then
|
||||
* notifyDataSetChanged() is needed to auto-calculate the legend again)
|
||||
* notifyDataSetChanged() is needed to auto-calculate the legend again)
|
||||
*/
|
||||
public void setCustom(int[] colors, String[] labels) {
|
||||
public void setCustom(LegendEntry[] entries) {
|
||||
|
||||
if (colors.length != labels.length) {
|
||||
throw new IllegalArgumentException(
|
||||
"colors array and labels array need to be of same size");
|
||||
}
|
||||
|
||||
mLabels = labels;
|
||||
mColors = colors;
|
||||
mEntries = entries;
|
||||
mIsLegendCustom = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a custom legend's labels and colors arrays. The colors count should
|
||||
* match the labels count. * Each color is for the form drawn at the same
|
||||
* index. * A null label will start a group. * A ColorTemplate.COLOR_SKIP
|
||||
* color will avoid drawing a form This will disable the feature that
|
||||
* automatically calculates the legend labels and colors from the datasets.
|
||||
* Sets a custom legend's entries array.
|
||||
* * A null label will start a group.
|
||||
* This will disable the feature that automatically calculates the legend
|
||||
* entries from the datasets.
|
||||
* Call resetCustom() to re-enable automatic calculation (and then
|
||||
* notifyDataSetChanged() is needed to auto-calculate the legend again)
|
||||
* notifyDataSetChanged() is needed to auto-calculate the legend again)
|
||||
*/
|
||||
public void setCustom(List<Integer> colors, List<String> labels) {
|
||||
public void setCustom(List<LegendEntry> entries) {
|
||||
|
||||
if (colors.size() != labels.size()) {
|
||||
throw new IllegalArgumentException(
|
||||
"colors array and labels array need to be of same size");
|
||||
}
|
||||
|
||||
mColors = Utils.convertIntegers(colors);
|
||||
mLabels = Utils.convertStrings(labels);
|
||||
mEntries = entries.toArray(new LegendEntry[entries.size()]);
|
||||
mIsLegendCustom = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calling this will disable the custom legend labels (set by
|
||||
* setCustom(...)). Instead, the labels will again be calculated
|
||||
* Calling this will disable the custom legend entries (set by
|
||||
* setCustom(...)). Instead, the entries will again be calculated
|
||||
* automatically (after notifyDataSetChanged() is called).
|
||||
*/
|
||||
public void resetCustom() {
|
||||
|
@ -389,7 +415,7 @@ public class Legend extends ComponentBase {
|
|||
}
|
||||
|
||||
/**
|
||||
* @return true if a custom legend labels and colors has been set default
|
||||
* @return true if a custom legend entries has been set default
|
||||
* false (automatic legend)
|
||||
*/
|
||||
public boolean isLegendCustom() {
|
||||
|
@ -608,13 +634,12 @@ public class Legend extends ComponentBase {
|
|||
}
|
||||
|
||||
/**
|
||||
* sets the size in pixels of the legend forms, this is internally converted
|
||||
* in dp, default 8f
|
||||
* sets the size in dp of the legend forms, default 8f
|
||||
*
|
||||
* @param size
|
||||
*/
|
||||
public void setFormSize(float size) {
|
||||
mFormSize = Utils.convertDpToPixel(size);
|
||||
mFormSize = size;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -626,6 +651,40 @@ public class Legend extends ComponentBase {
|
|||
return mFormSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the line width in dp for forms that consist of lines, default 3f
|
||||
*
|
||||
* @param size
|
||||
*/
|
||||
public void setFormLineWidth(float size) {
|
||||
mFormLineWidth = size;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the line width in dp for drawing forms that consist of lines
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public float getFormLineWidth() {
|
||||
return mFormLineWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the line dash path effect used for shapes that consist of lines.
|
||||
*
|
||||
* @param dashPathEffect
|
||||
*/
|
||||
public void setFormLineDashEffect(DashPathEffect dashPathEffect) {
|
||||
mFormLineDashEffect = dashPathEffect;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The line dash path effect used for shapes that consist of lines.
|
||||
*/
|
||||
public DashPathEffect getFormLineDashEffect() {
|
||||
return mFormLineDashEffect;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the space between the legend entries on a horizontal axis in
|
||||
* pixels
|
||||
|
@ -643,7 +702,7 @@ public class Legend extends ComponentBase {
|
|||
* @param space
|
||||
*/
|
||||
public void setXEntrySpace(float space) {
|
||||
mXEntrySpace = Utils.convertDpToPixel(space);
|
||||
mXEntrySpace = space;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -662,7 +721,7 @@ public class Legend extends ComponentBase {
|
|||
* @param space
|
||||
*/
|
||||
public void setYEntrySpace(float space) {
|
||||
mYEntrySpace = Utils.convertDpToPixel(space);
|
||||
mYEntrySpace = space;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -681,7 +740,7 @@ public class Legend extends ComponentBase {
|
|||
* @param space
|
||||
*/
|
||||
public void setFormToTextSpace(float space) {
|
||||
this.mFormToTextSpace = Utils.convertDpToPixel(space);
|
||||
this.mFormToTextSpace = space;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -795,6 +854,15 @@ public class Legend extends ComponentBase {
|
|||
*/
|
||||
public void calculateDimensions(Paint labelpaint, ViewPortHandler viewPortHandler) {
|
||||
|
||||
float defaultFormSize = Utils.convertDpToPixel(mFormSize);
|
||||
float stackSpace = Utils.convertDpToPixel(mStackSpace);
|
||||
float formToTextSpace = Utils.convertDpToPixel(mFormToTextSpace);
|
||||
float xEntrySpace = Utils.convertDpToPixel(mXEntrySpace);
|
||||
float yEntrySpace = Utils.convertDpToPixel(mYEntrySpace);
|
||||
boolean wordWrapEnabled = mWordWrapEnabled;
|
||||
LegendEntry[] entries = mEntries;
|
||||
int entryCount = entries.length;
|
||||
|
||||
mTextWidthMax = getMaximumEntryWidth(labelpaint);
|
||||
mTextHeightMax = getMaximumEntryHeight(labelpaint);
|
||||
|
||||
|
@ -803,44 +871,48 @@ public class Legend extends ComponentBase {
|
|||
|
||||
float maxWidth = 0f, maxHeight = 0f, width = 0f;
|
||||
float labelLineHeight = Utils.getLineHeight(labelpaint);
|
||||
final int count = mLabels.length;
|
||||
boolean wasStacked = false;
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
for (int i = 0; i < entryCount; i++) {
|
||||
|
||||
boolean drawingForm = mColors[i] != ColorTemplate.COLOR_SKIP;
|
||||
LegendEntry e = entries[i];
|
||||
boolean drawingForm = e.form != LegendForm.NONE;
|
||||
float formSize = Float.isNaN(e.formSize)
|
||||
? defaultFormSize
|
||||
: Utils.convertDpToPixel(e.formSize);
|
||||
String label = e.label;
|
||||
|
||||
if (!wasStacked)
|
||||
width = 0.f;
|
||||
|
||||
if (drawingForm) {
|
||||
if (wasStacked)
|
||||
width += mStackSpace;
|
||||
width += mFormSize;
|
||||
width += stackSpace;
|
||||
width += formSize;
|
||||
}
|
||||
|
||||
// grouped forms have null labels
|
||||
if (mLabels[i] != null) {
|
||||
if (label != null) {
|
||||
|
||||
// make a step to the left
|
||||
if (drawingForm && !wasStacked)
|
||||
width += mFormToTextSpace;
|
||||
width += formToTextSpace;
|
||||
else if (wasStacked) {
|
||||
maxWidth = Math.max(maxWidth, width);
|
||||
maxHeight += labelLineHeight + mYEntrySpace;
|
||||
maxHeight += labelLineHeight + yEntrySpace;
|
||||
width = 0.f;
|
||||
wasStacked = false;
|
||||
}
|
||||
|
||||
width += Utils.calcTextWidth(labelpaint, mLabels[i]);
|
||||
width += Utils.calcTextWidth(labelpaint, label);
|
||||
|
||||
if (i < count - 1)
|
||||
maxHeight += labelLineHeight + mYEntrySpace;
|
||||
if (i < entryCount - 1)
|
||||
maxHeight += labelLineHeight + yEntrySpace;
|
||||
} else {
|
||||
wasStacked = true;
|
||||
width += mFormSize;
|
||||
if (i < count - 1)
|
||||
width += mStackSpace;
|
||||
width += formSize;
|
||||
if (i < entryCount - 1)
|
||||
width += stackSpace;
|
||||
}
|
||||
|
||||
maxWidth = Math.max(maxWidth, width);
|
||||
|
@ -853,9 +925,8 @@ public class Legend extends ComponentBase {
|
|||
}
|
||||
case HORIZONTAL: {
|
||||
|
||||
int labelCount = mLabels.length;
|
||||
float labelLineHeight = Utils.getLineHeight(labelpaint);
|
||||
float labelLineSpacing = Utils.getLineSpacing(labelpaint) + mYEntrySpace;
|
||||
float labelLineSpacing = Utils.getLineSpacing(labelpaint) + yEntrySpace;
|
||||
float contentWidth = viewPortHandler.contentWidth() * mMaxSizePercent;
|
||||
|
||||
// Start calculating layout
|
||||
|
@ -868,9 +939,14 @@ public class Legend extends ComponentBase {
|
|||
mCalculatedLabelSizes.clear();
|
||||
mCalculatedLineSizes.clear();
|
||||
|
||||
for (int i = 0; i < labelCount; i++) {
|
||||
for (int i = 0; i < entryCount; i++) {
|
||||
|
||||
boolean drawingForm = mColors[i] != ColorTemplate.COLOR_SKIP;
|
||||
LegendEntry e = entries[i];
|
||||
boolean drawingForm = e.form != LegendForm.NONE;
|
||||
float formSize = Float.isNaN(e.formSize)
|
||||
? defaultFormSize
|
||||
: Utils.convertDpToPixel(e.formSize);
|
||||
String label = e.label;
|
||||
|
||||
mCalculatedLabelBreakPoints.add(false);
|
||||
|
||||
|
@ -880,19 +956,19 @@ public class Legend extends ComponentBase {
|
|||
requiredWidth = 0.f;
|
||||
} else {
|
||||
// add the spacing appropriate for stacked labels/forms
|
||||
requiredWidth += mStackSpace;
|
||||
requiredWidth += stackSpace;
|
||||
}
|
||||
|
||||
// grouped forms have null labels
|
||||
if (mLabels[i] != null) {
|
||||
if (label != null) {
|
||||
|
||||
mCalculatedLabelSizes.add(Utils.calcTextSize(labelpaint, mLabels[i]));
|
||||
requiredWidth += drawingForm ? mFormToTextSpace + mFormSize : 0.f;
|
||||
mCalculatedLabelSizes.add(Utils.calcTextSize(labelpaint, label));
|
||||
requiredWidth += drawingForm ? formToTextSpace + formSize : 0.f;
|
||||
requiredWidth += mCalculatedLabelSizes.get(i).width;
|
||||
} else {
|
||||
|
||||
mCalculatedLabelSizes.add(FSize.getInstance(0.f, 0.f));
|
||||
requiredWidth += drawingForm ? mFormSize : 0.f;
|
||||
requiredWidth += drawingForm ? formSize : 0.f;
|
||||
|
||||
if (stackedStartIndex == -1) {
|
||||
// mark this index as we might want to break here later
|
||||
|
@ -900,11 +976,11 @@ public class Legend extends ComponentBase {
|
|||
}
|
||||
}
|
||||
|
||||
if (mLabels[i] != null || i == labelCount - 1) {
|
||||
if (label != null || i == entryCount - 1) {
|
||||
|
||||
float requiredSpacing = currentLineWidth == 0.f ? 0.f : mXEntrySpace;
|
||||
float requiredSpacing = currentLineWidth == 0.f ? 0.f : xEntrySpace;
|
||||
|
||||
if (!mWordWrapEnabled // No word wrapping, it must fit.
|
||||
if (!wordWrapEnabled // No word wrapping, it must fit.
|
||||
// The line is empty, it must fit
|
||||
|| currentLineWidth == 0.f
|
||||
// It simply fits
|
||||
|
@ -925,14 +1001,14 @@ public class Legend extends ComponentBase {
|
|||
currentLineWidth = requiredWidth;
|
||||
}
|
||||
|
||||
if (i == labelCount - 1) {
|
||||
if (i == entryCount - 1) {
|
||||
// Add last line size to array
|
||||
mCalculatedLineSizes.add(FSize.getInstance(currentLineWidth, labelLineHeight));
|
||||
maxLineWidth = Math.max(maxLineWidth, currentLineWidth);
|
||||
}
|
||||
}
|
||||
|
||||
stackedStartIndex = mLabels[i] != null ? -1 : stackedStartIndex;
|
||||
stackedStartIndex = label != null ? -1 : stackedStartIndex;
|
||||
}
|
||||
|
||||
mNeededWidth = maxLineWidth;
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
package com.github.mikephil.charting.components;
|
||||
|
||||
|
||||
import android.graphics.DashPathEffect;
|
||||
|
||||
import com.github.mikephil.charting.utils.ColorTemplate;
|
||||
|
||||
public class LegendEntry {
|
||||
public LegendEntry() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param label The legend entry text. A `null` label will start a group.
|
||||
* @param form The form to draw for this entry.
|
||||
* @param formSize Set to NaN to use the legend's default.
|
||||
* @param formLineWidth Set to NaN to use the legend's default.
|
||||
* @param formLineDashEffect Set to nil to use the legend's default.
|
||||
* @param formColor The color for drawing the form.
|
||||
*/
|
||||
public LegendEntry(String label,
|
||||
Legend.LegendForm form,
|
||||
float formSize,
|
||||
float formLineWidth,
|
||||
DashPathEffect formLineDashEffect,
|
||||
int formColor)
|
||||
{
|
||||
this.label = label;
|
||||
this.form = form;
|
||||
this.formSize = formSize;
|
||||
this.formLineWidth = formLineWidth;
|
||||
this.formLineDashEffect = formLineDashEffect;
|
||||
this.formColor = formColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* The legend entry text.
|
||||
* A `null` label will start a group.
|
||||
*/
|
||||
public String label;
|
||||
|
||||
/**
|
||||
* The form to draw for this entry.
|
||||
*
|
||||
* `NONE` will avoid drawing a form, and any related space.
|
||||
* `EMPTY` will avoid drawing a form, but keep its space.
|
||||
* `DEFAULT` will use the Legend's default.
|
||||
*/
|
||||
public Legend.LegendForm form = Legend.LegendForm.DEFAULT;
|
||||
|
||||
/**
|
||||
* Form size will be considered except for when .None is used
|
||||
*
|
||||
* Set as NaN to use the legend's default
|
||||
*/
|
||||
public float formSize = Float.NaN;
|
||||
|
||||
/**
|
||||
* Line width used for shapes that consist of lines.
|
||||
*
|
||||
* Set as NaN to use the legend's default
|
||||
*/
|
||||
public float formLineWidth = Float.NaN;
|
||||
|
||||
/**
|
||||
* Line dash path effect used for shapes that consist of lines.
|
||||
*
|
||||
* Set to null to use the legend's default
|
||||
*/
|
||||
public DashPathEffect formLineDashEffect = null;
|
||||
|
||||
/**
|
||||
* The color for drawing the form
|
||||
*/
|
||||
public int formColor = ColorTemplate.COLOR_NONE;
|
||||
|
||||
}
|
|
@ -2,8 +2,10 @@ package com.github.mikephil.charting.data;
|
|||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.DashPathEffect;
|
||||
import android.graphics.Typeface;
|
||||
|
||||
import com.github.mikephil.charting.components.Legend;
|
||||
import com.github.mikephil.charting.components.YAxis;
|
||||
import com.github.mikephil.charting.formatter.DefaultValueFormatter;
|
||||
import com.github.mikephil.charting.formatter.IValueFormatter;
|
||||
|
@ -56,6 +58,11 @@ public abstract class BaseDataSet<T extends Entry> implements IDataSet<T> {
|
|||
*/
|
||||
protected Typeface mValueTypeface;
|
||||
|
||||
private Legend.LegendForm mForm = Legend.LegendForm.DEFAULT;
|
||||
private float mFormSize = Float.NaN;
|
||||
private float mFormLineWidth = Float.NaN;
|
||||
private DashPathEffect mFormLineDashEffect = null;
|
||||
|
||||
/**
|
||||
* if true, y-values are drawn on the chart
|
||||
*/
|
||||
|
@ -318,6 +325,42 @@ public abstract class BaseDataSet<T extends Entry> implements IDataSet<T> {
|
|||
return mValueTextSize;
|
||||
}
|
||||
|
||||
public void setForm(Legend.LegendForm form) {
|
||||
mForm = form;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Legend.LegendForm getForm() {
|
||||
return mForm;
|
||||
}
|
||||
|
||||
public void setFormSize(float formSize) {
|
||||
mFormSize = formSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getFormSize() {
|
||||
return mFormSize;
|
||||
}
|
||||
|
||||
public void setFormLineWidth(float formLineWidth) {
|
||||
mFormLineWidth = formLineWidth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getFormLineWidth() {
|
||||
return mFormLineWidth;
|
||||
}
|
||||
|
||||
public void setFormLineDashEffect(DashPathEffect dashPathEffect) {
|
||||
mFormLineDashEffect = dashPathEffect;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DashPathEffect getFormLineDashEffect() {
|
||||
return mFormLineDashEffect;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDrawValues(boolean enabled) {
|
||||
this.mDrawValues = enabled;
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package com.github.mikephil.charting.interfaces.datasets;
|
||||
|
||||
import android.graphics.DashPathEffect;
|
||||
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;
|
||||
|
@ -368,6 +370,34 @@ public interface IDataSet<T extends Entry> {
|
|||
*/
|
||||
float getValueTextSize();
|
||||
|
||||
/**
|
||||
* The form to draw for this dataset in the legend.
|
||||
*
|
||||
* Return `DEFAULT` to use the default legend form.
|
||||
*/
|
||||
Legend.LegendForm getForm();
|
||||
|
||||
/**
|
||||
* The form size to draw for this dataset in the legend.
|
||||
*
|
||||
* Return `Float.NaN` to use the default legend form size.
|
||||
*/
|
||||
float getFormSize();
|
||||
|
||||
/**
|
||||
* The line width for drawing the form of this dataset in the legend
|
||||
*
|
||||
* Return `Float.NaN` to use the default legend form line width.
|
||||
*/
|
||||
float getFormLineWidth();
|
||||
|
||||
/**
|
||||
* The line dash path effect used for shapes that consist of lines.
|
||||
*
|
||||
* Return `null` to use the default legend form line dash effect.
|
||||
*/
|
||||
DashPathEffect getFormLineDashEffect();
|
||||
|
||||
/**
|
||||
* set this to true to draw y-values on the chart NOTE (for bar and
|
||||
* linechart): if "maxvisiblecount" is reached, no values will be drawn even
|
||||
|
|
|
@ -2,11 +2,14 @@
|
|||
package com.github.mikephil.charting.renderer;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.DashPathEffect;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Paint.Align;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.Typeface;
|
||||
|
||||
import com.github.mikephil.charting.components.Legend;
|
||||
import com.github.mikephil.charting.components.LegendEntry;
|
||||
import com.github.mikephil.charting.data.ChartData;
|
||||
import com.github.mikephil.charting.interfaces.datasets.IBarDataSet;
|
||||
import com.github.mikephil.charting.interfaces.datasets.ICandleDataSet;
|
||||
|
@ -49,7 +52,6 @@ public class LegendRenderer extends Renderer {
|
|||
|
||||
mLegendFormPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
mLegendFormPaint.setStyle(Paint.Style.FILL);
|
||||
mLegendFormPaint.setStrokeWidth(3f);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -71,8 +73,7 @@ public class LegendRenderer extends Renderer {
|
|||
}
|
||||
|
||||
|
||||
protected List<String> computedLabels = new ArrayList<>(16);
|
||||
protected List<Integer> computedColors = new ArrayList<>(16);
|
||||
protected List<LegendEntry> computedEntries = new ArrayList<>(16);
|
||||
|
||||
/**
|
||||
* Prepares the legend and calculates all needed forms, labels and colors.
|
||||
|
@ -83,8 +84,7 @@ public class LegendRenderer extends Renderer {
|
|||
|
||||
if (!mLegend.isLegendCustom()) {
|
||||
|
||||
computedLabels.clear();
|
||||
computedColors.clear();
|
||||
computedEntries.clear();
|
||||
|
||||
// loop for building up the colors and labels used in the legend
|
||||
for (int i = 0; i < data.getDataSetCount(); i++) {
|
||||
|
@ -102,14 +102,26 @@ public class LegendRenderer extends Renderer {
|
|||
|
||||
for (int j = 0; j < clrs.size() && j < bds.getStackSize(); j++) {
|
||||
|
||||
computedLabels.add(sLabels[j % sLabels.length]);
|
||||
computedColors.add(clrs.get(j));
|
||||
computedEntries.add(new LegendEntry(
|
||||
sLabels[j % sLabels.length],
|
||||
dataSet.getForm(),
|
||||
dataSet.getFormSize(),
|
||||
dataSet.getFormLineWidth(),
|
||||
dataSet.getFormLineDashEffect(),
|
||||
clrs.get(j)
|
||||
));
|
||||
}
|
||||
|
||||
if (bds.getLabel() != null) {
|
||||
// add the legend description label
|
||||
computedColors.add(ColorTemplate.COLOR_SKIP);
|
||||
computedLabels.add(bds.getLabel());
|
||||
computedEntries.add(new LegendEntry(
|
||||
dataSet.getLabel(),
|
||||
Legend.LegendForm.NONE,
|
||||
Float.NaN,
|
||||
Float.NaN,
|
||||
null,
|
||||
ColorTemplate.COLOR_NONE
|
||||
));
|
||||
}
|
||||
|
||||
} else if (dataSet instanceof IPieDataSet) {
|
||||
|
@ -118,55 +130,82 @@ public class LegendRenderer extends Renderer {
|
|||
|
||||
for (int j = 0; j < clrs.size() && j < entryCount; j++) {
|
||||
|
||||
computedLabels.add(pds.getEntryForIndex(j).getLabel());
|
||||
computedColors.add(clrs.get(j));
|
||||
computedEntries.add(new LegendEntry(
|
||||
pds.getEntryForIndex(j).getLabel(),
|
||||
dataSet.getForm(),
|
||||
dataSet.getFormSize(),
|
||||
dataSet.getFormLineWidth(),
|
||||
dataSet.getFormLineDashEffect(),
|
||||
clrs.get(j)
|
||||
));
|
||||
}
|
||||
|
||||
if (pds.getLabel() != null) {
|
||||
// add the legend description label
|
||||
computedColors.add(ColorTemplate.COLOR_SKIP);
|
||||
computedLabels.add(pds.getLabel());
|
||||
computedEntries.add(new LegendEntry(
|
||||
dataSet.getLabel(),
|
||||
Legend.LegendForm.NONE,
|
||||
Float.NaN,
|
||||
Float.NaN,
|
||||
null,
|
||||
ColorTemplate.COLOR_NONE
|
||||
));
|
||||
}
|
||||
|
||||
} else if (dataSet instanceof ICandleDataSet && ((ICandleDataSet) dataSet).getDecreasingColor() !=
|
||||
ColorTemplate.COLOR_NONE) {
|
||||
|
||||
int decreasingColor = ((ICandleDataSet) dataSet).getDecreasingColor();
|
||||
computedColors.add(decreasingColor);
|
||||
|
||||
int increasingColor = ((ICandleDataSet) dataSet).getIncreasingColor();
|
||||
computedColors.add(increasingColor);
|
||||
|
||||
computedLabels.add(null);
|
||||
computedLabels.add(dataSet.getLabel());
|
||||
computedEntries.add(new LegendEntry(
|
||||
null,
|
||||
dataSet.getForm(),
|
||||
dataSet.getFormSize(),
|
||||
dataSet.getFormLineWidth(),
|
||||
dataSet.getFormLineDashEffect(),
|
||||
decreasingColor
|
||||
));
|
||||
|
||||
computedEntries.add(new LegendEntry(
|
||||
dataSet.getLabel(),
|
||||
dataSet.getForm(),
|
||||
dataSet.getFormSize(),
|
||||
dataSet.getFormLineWidth(),
|
||||
dataSet.getFormLineDashEffect(),
|
||||
increasingColor
|
||||
));
|
||||
|
||||
} else { // all others
|
||||
|
||||
for (int j = 0; j < clrs.size() && j < entryCount; j++) {
|
||||
|
||||
String label;
|
||||
|
||||
// if multiple colors are set for a DataSet, group them
|
||||
if (j < clrs.size() - 1 && j < entryCount - 1) {
|
||||
|
||||
computedLabels.add(null);
|
||||
label = null;
|
||||
} else { // add label to the last entry
|
||||
|
||||
String label = data.getDataSetByIndex(i).getLabel();
|
||||
computedLabels.add(label);
|
||||
label = data.getDataSetByIndex(i).getLabel();
|
||||
}
|
||||
|
||||
computedColors.add(clrs.get(j));
|
||||
computedEntries.add(new LegendEntry(
|
||||
label,
|
||||
dataSet.getForm(),
|
||||
dataSet.getFormSize(),
|
||||
dataSet.getFormLineWidth(),
|
||||
dataSet.getFormLineDashEffect(),
|
||||
clrs.get(j)
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mLegend.getExtraColors() != null && mLegend.getExtraLabels() != null) {
|
||||
for (int color : mLegend.getExtraColors())
|
||||
computedColors.add(color);
|
||||
Collections.addAll(computedLabels, mLegend.getExtraLabels());
|
||||
if (mLegend.getExtraEntries() != null) {
|
||||
Collections.addAll(computedEntries, mLegend.getExtraEntries());
|
||||
}
|
||||
|
||||
mLegend.setComputedColors(computedColors);
|
||||
mLegend.setComputedLabels(computedLabels);
|
||||
mLegend.setEntries(computedEntries);
|
||||
}
|
||||
|
||||
Typeface tf = mLegend.getTypeface();
|
||||
|
@ -197,22 +236,22 @@ public class LegendRenderer extends Renderer {
|
|||
mLegendLabelPaint.setColor(mLegend.getTextColor());
|
||||
|
||||
float labelLineHeight = Utils.getLineHeight(mLegendLabelPaint, legendFontMetrics);
|
||||
float labelLineSpacing = Utils.getLineSpacing(mLegendLabelPaint, legendFontMetrics) + mLegend.getYEntrySpace();
|
||||
float labelLineSpacing = Utils.getLineSpacing(mLegendLabelPaint, legendFontMetrics)
|
||||
+ Utils.convertDpToPixel(mLegend.getYEntrySpace());
|
||||
float formYOffset = labelLineHeight - Utils.calcTextHeight(mLegendLabelPaint, "ABC") / 2.f;
|
||||
|
||||
String[] labels = mLegend.getLabels();
|
||||
int[] colors = mLegend.getColors();
|
||||
LegendEntry[] entries = mLegend.getEntries();
|
||||
|
||||
float formToTextSpace = mLegend.getFormToTextSpace();
|
||||
float xEntrySpace = mLegend.getXEntrySpace();
|
||||
float formToTextSpace = Utils.convertDpToPixel(mLegend.getFormToTextSpace());
|
||||
float xEntrySpace = Utils.convertDpToPixel(mLegend.getXEntrySpace());
|
||||
Legend.LegendOrientation orientation = mLegend.getOrientation();
|
||||
Legend.LegendHorizontalAlignment horizontalAlignment = mLegend.getHorizontalAlignment();
|
||||
Legend.LegendVerticalAlignment verticalAlignment = mLegend.getVerticalAlignment();
|
||||
Legend.LegendDirection direction = mLegend.getDirection();
|
||||
float formSize = mLegend.getFormSize();
|
||||
float defaultFormSize = Utils.convertDpToPixel(mLegend.getFormSize());
|
||||
|
||||
// space between the entries
|
||||
float stackSpace = mLegend.getStackSpace();
|
||||
float stackSpace = Utils.convertDpToPixel(mLegend.getStackSpace());
|
||||
|
||||
float yoffset = mLegend.getYOffset();
|
||||
float xoffset = mLegend.getXOffset();
|
||||
|
@ -292,7 +331,12 @@ public class LegendRenderer extends Renderer {
|
|||
|
||||
int lineIndex = 0;
|
||||
|
||||
for (int i = 0, count = labels.length; i < count; i++) {
|
||||
for (int i = 0, count = entries.length; i < count; i++) {
|
||||
|
||||
LegendEntry e = entries[i];
|
||||
boolean drawingForm = e.form != Legend.LegendForm.NONE;
|
||||
float formSize = Float.isNaN(e.formSize) ? defaultFormSize : Utils.convertDpToPixel(e.formSize);
|
||||
|
||||
if (i < calculatedLabelBreakPoints.size() && calculatedLabelBreakPoints.get(i)) {
|
||||
posX = originPosX;
|
||||
posY += labelLineHeight + labelLineSpacing;
|
||||
|
@ -307,14 +351,13 @@ public class LegendRenderer extends Renderer {
|
|||
lineIndex++;
|
||||
}
|
||||
|
||||
boolean drawingForm = colors[i] != ColorTemplate.COLOR_SKIP;
|
||||
boolean isStacked = labels[i] == null; // grouped forms have null labels
|
||||
boolean isStacked = e.label == null; // grouped forms have null labels
|
||||
|
||||
if (drawingForm) {
|
||||
if (direction == Legend.LegendDirection.RIGHT_TO_LEFT)
|
||||
posX -= formSize;
|
||||
|
||||
drawForm(c, posX, posY + formYOffset, i, mLegend);
|
||||
drawForm(c, posX, posY + formYOffset, e, mLegend);
|
||||
|
||||
if (direction == Legend.LegendDirection.LEFT_TO_RIGHT)
|
||||
posX += formSize;
|
||||
|
@ -328,7 +371,7 @@ public class LegendRenderer extends Renderer {
|
|||
if (direction == Legend.LegendDirection.RIGHT_TO_LEFT)
|
||||
posX -= calculatedLabelSizes.get(i).width;
|
||||
|
||||
drawLabel(c, posX, posY + labelLineHeight, labels[i]);
|
||||
drawLabel(c, posX, posY + labelLineHeight, e.label);
|
||||
|
||||
if (direction == Legend.LegendDirection.LEFT_TO_RIGHT)
|
||||
posX += calculatedLabelSizes.get(i).width;
|
||||
|
@ -369,9 +412,12 @@ public class LegendRenderer extends Renderer {
|
|||
break;
|
||||
}
|
||||
|
||||
for (int i = 0; i < labels.length; i++) {
|
||||
for (int i = 0; i < entries.length; i++) {
|
||||
|
||||
LegendEntry e = entries[i];
|
||||
boolean drawingForm = e.form != Legend.LegendForm.NONE;
|
||||
float formSize = Float.isNaN(e.formSize) ? defaultFormSize : Utils.convertDpToPixel(e.formSize);
|
||||
|
||||
Boolean drawingForm = colors[i] != ColorTemplate.COLOR_SKIP;
|
||||
float posX = originPosX;
|
||||
|
||||
if (drawingForm) {
|
||||
|
@ -380,13 +426,13 @@ public class LegendRenderer extends Renderer {
|
|||
else
|
||||
posX -= formSize - stack;
|
||||
|
||||
drawForm(c, posX, posY + formYOffset, i, mLegend);
|
||||
drawForm(c, posX, posY + formYOffset, e, mLegend);
|
||||
|
||||
if (direction == Legend.LegendDirection.LEFT_TO_RIGHT)
|
||||
posX += formSize;
|
||||
}
|
||||
|
||||
if (labels[i] != null) {
|
||||
if (e.label != null) {
|
||||
|
||||
if (drawingForm && !wasStacked)
|
||||
posX += direction == Legend.LegendDirection.LEFT_TO_RIGHT ? formToTextSpace
|
||||
|
@ -395,13 +441,13 @@ public class LegendRenderer extends Renderer {
|
|||
posX = originPosX;
|
||||
|
||||
if (direction == Legend.LegendDirection.RIGHT_TO_LEFT)
|
||||
posX -= Utils.calcTextWidth(mLegendLabelPaint, labels[i]);
|
||||
posX -= Utils.calcTextWidth(mLegendLabelPaint, e.label);
|
||||
|
||||
if (!wasStacked) {
|
||||
drawLabel(c, posX, posY + labelLineHeight, labels[i]);
|
||||
drawLabel(c, posX, posY + labelLineHeight, e.label);
|
||||
} else {
|
||||
posY += labelLineHeight + labelLineSpacing;
|
||||
drawLabel(c, posX, posY + labelLineHeight, labels[i]);
|
||||
drawLabel(c, posX, posY + labelLineHeight, e.label);
|
||||
}
|
||||
|
||||
// make a step down
|
||||
|
@ -419,36 +465,85 @@ public class LegendRenderer extends Renderer {
|
|||
}
|
||||
}
|
||||
|
||||
private Path mLineFormPath = new Path();
|
||||
|
||||
/**
|
||||
* Draws the Legend-form at the given position with the color at the given
|
||||
* index.
|
||||
*
|
||||
* @param c canvas to draw with
|
||||
* @param x position
|
||||
* @param y position
|
||||
* @param index the index of the color to use (in the colors array)
|
||||
* @param c canvas to draw with
|
||||
* @param x position
|
||||
* @param y position
|
||||
* @param entry the entry to render
|
||||
* @param legend the legend context
|
||||
*/
|
||||
protected void drawForm(Canvas c, float x, float y, int index, Legend legend) {
|
||||
protected void drawForm(
|
||||
Canvas c,
|
||||
float x, float y,
|
||||
LegendEntry entry,
|
||||
Legend legend) {
|
||||
|
||||
if (legend.getColors()[index] == ColorTemplate.COLOR_SKIP)
|
||||
if (entry.formColor == ColorTemplate.COLOR_SKIP ||
|
||||
entry.formColor == ColorTemplate.COLOR_NONE ||
|
||||
entry.formColor == 0)
|
||||
return;
|
||||
|
||||
mLegendFormPaint.setColor(legend.getColors()[index]);
|
||||
int restoreCount = c.save();
|
||||
|
||||
float formsize = legend.getFormSize();
|
||||
float half = formsize / 2f;
|
||||
Legend.LegendForm form = entry.form;
|
||||
if (form == Legend.LegendForm.DEFAULT)
|
||||
form = legend.getForm();
|
||||
|
||||
switch (legend.getForm()) {
|
||||
mLegendFormPaint.setColor(entry.formColor);
|
||||
|
||||
final float formSize = Utils.convertDpToPixel(
|
||||
Float.isNaN(entry.formSize)
|
||||
? legend.getFormSize()
|
||||
: entry.formSize);
|
||||
final float half = formSize / 2f;
|
||||
|
||||
switch (form) {
|
||||
case NONE:
|
||||
// Do nothing
|
||||
break;
|
||||
|
||||
case EMPTY:
|
||||
// Do not draw, but keep space for the form
|
||||
break;
|
||||
|
||||
case DEFAULT:
|
||||
case CIRCLE:
|
||||
mLegendFormPaint.setStyle(Paint.Style.FILL);
|
||||
c.drawCircle(x + half, y, half, mLegendFormPaint);
|
||||
break;
|
||||
|
||||
case SQUARE:
|
||||
c.drawRect(x, y - half, x + formsize, y + half, mLegendFormPaint);
|
||||
mLegendFormPaint.setStyle(Paint.Style.FILL);
|
||||
c.drawRect(x, y - half, x + formSize, y + half, mLegendFormPaint);
|
||||
break;
|
||||
|
||||
case LINE:
|
||||
c.drawLine(x, y, x + formsize, y, mLegendFormPaint);
|
||||
{
|
||||
final float formLineWidth = Utils.convertDpToPixel(
|
||||
Float.isNaN(entry.formLineWidth)
|
||||
? legend.getFormLineWidth()
|
||||
: entry.formLineWidth);
|
||||
final DashPathEffect formLineDashEffect = entry.formLineDashEffect == null
|
||||
? legend.getFormLineDashEffect()
|
||||
: entry.formLineDashEffect;
|
||||
mLegendFormPaint.setStyle(Paint.Style.STROKE);
|
||||
mLegendFormPaint.setStrokeWidth(formLineWidth);
|
||||
mLegendFormPaint.setPathEffect(formLineDashEffect);
|
||||
|
||||
mLineFormPath.reset();
|
||||
mLineFormPath.moveTo(x, y);
|
||||
mLineFormPath.lineTo(x + formSize, y);
|
||||
c.drawPath(mLineFormPath, mLegendFormPaint);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
c.restoreToCount(restoreCount);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -6,6 +6,7 @@ import android.graphics.Color;
|
|||
import android.graphics.Paint;
|
||||
import android.graphics.Paint.Align;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.RectF;
|
||||
|
||||
import com.github.mikephil.charting.components.LimitLine;
|
||||
import com.github.mikephil.charting.components.XAxis;
|
||||
|
@ -236,6 +237,9 @@ public class XAxisRenderer extends AxisRenderer {
|
|||
if (!mXAxis.isDrawGridLinesEnabled() || !mXAxis.isEnabled())
|
||||
return;
|
||||
|
||||
int clipRestoreCount = c.save();
|
||||
c.clipRect(getGridClippingRect());
|
||||
|
||||
if(mRenderGridLinesBuffer.length != mAxis.mEntryCount * 2){
|
||||
mRenderGridLinesBuffer = new float[mXAxis.mEntryCount * 2];
|
||||
}
|
||||
|
@ -257,6 +261,16 @@ public class XAxisRenderer extends AxisRenderer {
|
|||
|
||||
drawGridLine(c, positions[i], positions[i + 1], gridLinePath);
|
||||
}
|
||||
|
||||
c.restoreToCount(clipRestoreCount);
|
||||
}
|
||||
|
||||
protected RectF mGridClippingRect = new RectF();
|
||||
|
||||
public RectF getGridClippingRect() {
|
||||
mGridClippingRect.set(mViewPortHandler.getContentRect());
|
||||
mGridClippingRect.inset(-mAxis.getGridLineWidth() / 2.f, 0.f);
|
||||
return mGridClippingRect;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -279,6 +293,8 @@ public class XAxisRenderer extends AxisRenderer {
|
|||
}
|
||||
|
||||
protected float[] mRenderLimitLinesBuffer = new float[2];
|
||||
protected RectF mLimitLineClippingRect = new RectF();
|
||||
|
||||
/**
|
||||
* Draws the LimitLines associated with this axis to the screen.
|
||||
*
|
||||
|
@ -303,6 +319,11 @@ public class XAxisRenderer extends AxisRenderer {
|
|||
if (!l.isEnabled())
|
||||
continue;
|
||||
|
||||
int clipRestoreCount = c.save();
|
||||
mLimitLineClippingRect.set(mViewPortHandler.getContentRect());
|
||||
mLimitLineClippingRect.inset(-l.getLineWidth() / 2.f, 0.f);
|
||||
c.clipRect(mLimitLineClippingRect);
|
||||
|
||||
position[0] = l.getLimit();
|
||||
position[1] = 0.f;
|
||||
|
||||
|
@ -310,6 +331,8 @@ public class XAxisRenderer extends AxisRenderer {
|
|||
|
||||
renderLimitLineLine(c, l, position);
|
||||
renderLimitLineLabel(c, l, position, 2.f + l.getYOffset());
|
||||
|
||||
c.restoreToCount(clipRestoreCount);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import android.graphics.Canvas;
|
|||
import android.graphics.Paint;
|
||||
import android.graphics.Paint.Align;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.RectF;
|
||||
|
||||
import com.github.mikephil.charting.charts.BarChart;
|
||||
import com.github.mikephil.charting.components.LimitLine;
|
||||
|
@ -161,6 +162,13 @@ public class XAxisRendererHorizontalBarChart extends XAxisRenderer {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public RectF getGridClippingRect() {
|
||||
mGridClippingRect.set(mViewPortHandler.getContentRect());
|
||||
mGridClippingRect.inset(0.f, -mAxis.getGridLineWidth() / 2.f);
|
||||
return mGridClippingRect;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawGridLine(Canvas c, float x, float y, Path gridLinePath) {
|
||||
|
||||
|
@ -228,6 +236,11 @@ public class XAxisRendererHorizontalBarChart extends XAxisRenderer {
|
|||
if(!l.isEnabled())
|
||||
continue;
|
||||
|
||||
int clipRestoreCount = c.save();
|
||||
mLimitLineClippingRect.set(mViewPortHandler.getContentRect());
|
||||
mLimitLineClippingRect.inset(0.f, -l.getLineWidth() / 2.f);
|
||||
c.clipRect(mLimitLineClippingRect);
|
||||
|
||||
mLimitLinePaint.setStyle(Paint.Style.STROKE);
|
||||
mLimitLinePaint.setColor(l.getLineColor());
|
||||
mLimitLinePaint.setStrokeWidth(l.getLineWidth());
|
||||
|
@ -290,6 +303,8 @@ public class XAxisRendererHorizontalBarChart extends XAxisRenderer {
|
|||
pts[1] + yOffset, mLimitLinePaint);
|
||||
}
|
||||
}
|
||||
|
||||
c.restoreToCount(clipRestoreCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import android.graphics.Color;
|
|||
import android.graphics.Paint;
|
||||
import android.graphics.Paint.Align;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.RectF;
|
||||
|
||||
import com.github.mikephil.charting.components.LimitLine;
|
||||
import com.github.mikephil.charting.components.YAxis;
|
||||
|
@ -134,6 +135,9 @@ public class YAxisRenderer extends AxisRenderer {
|
|||
|
||||
if (mYAxis.isDrawGridLinesEnabled()) {
|
||||
|
||||
int clipRestoreCount = c.save();
|
||||
c.clipRect(getGridClippingRect());
|
||||
|
||||
float[] positions = getTransformedPositions();
|
||||
|
||||
mGridPaint.setColor(mYAxis.getGridColor());
|
||||
|
@ -150,6 +154,8 @@ public class YAxisRenderer extends AxisRenderer {
|
|||
c.drawPath(linePath(gridLinePath, i, positions), mGridPaint);
|
||||
gridLinePath.reset();
|
||||
}
|
||||
|
||||
c.restoreToCount(clipRestoreCount);
|
||||
}
|
||||
|
||||
if (mYAxis.isDrawZeroLineEnabled()) {
|
||||
|
@ -157,6 +163,14 @@ public class YAxisRenderer extends AxisRenderer {
|
|||
}
|
||||
}
|
||||
|
||||
protected RectF mGridClippingRect = new RectF();
|
||||
|
||||
public RectF getGridClippingRect() {
|
||||
mGridClippingRect.set(mViewPortHandler.getContentRect());
|
||||
mGridClippingRect.inset(0.f, -mAxis.getGridLineWidth() / 2.f);
|
||||
return mGridClippingRect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the path for a grid line.
|
||||
*
|
||||
|
@ -220,6 +234,7 @@ public class YAxisRenderer extends AxisRenderer {
|
|||
|
||||
protected Path mRenderLimitLines = new Path();
|
||||
protected float[] mRenderLimitLinesBuffer = new float[2];
|
||||
protected RectF mLimitLineClippingRect = new RectF();
|
||||
/**
|
||||
* Draws the LimitLines associated with this axis to the screen.
|
||||
*
|
||||
|
@ -246,6 +261,11 @@ public class YAxisRenderer extends AxisRenderer {
|
|||
if (!l.isEnabled())
|
||||
continue;
|
||||
|
||||
int clipRestoreCount = c.save();
|
||||
mLimitLineClippingRect.set(mViewPortHandler.getContentRect());
|
||||
mLimitLineClippingRect.inset(0.f, -l.getLineWidth() / 2.f);
|
||||
c.clipRect(mLimitLineClippingRect);
|
||||
|
||||
mLimitLinePaint.setStyle(Paint.Style.STROKE);
|
||||
mLimitLinePaint.setColor(l.getLineColor());
|
||||
mLimitLinePaint.setStrokeWidth(l.getLineWidth());
|
||||
|
@ -309,6 +329,8 @@ public class YAxisRenderer extends AxisRenderer {
|
|||
pts[1] + yOffset, mLimitLinePaint);
|
||||
}
|
||||
}
|
||||
|
||||
c.restoreToCount(clipRestoreCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import android.graphics.Canvas;
|
|||
import android.graphics.Paint;
|
||||
import android.graphics.Paint.Align;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.RectF;
|
||||
|
||||
import com.github.mikephil.charting.components.LimitLine;
|
||||
import com.github.mikephil.charting.components.YAxis;
|
||||
|
@ -164,6 +165,13 @@ public class YAxisRendererHorizontalBarChart extends YAxisRenderer {
|
|||
return positions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RectF getGridClippingRect() {
|
||||
mGridClippingRect.set(mViewPortHandler.getContentRect());
|
||||
mGridClippingRect.inset(-mAxis.getGridLineWidth() / 2.f, 0.f);
|
||||
return mGridClippingRect;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Path linePath(Path p, int i, float[] positions) {
|
||||
|
||||
|
@ -225,6 +233,11 @@ public class YAxisRendererHorizontalBarChart extends YAxisRenderer {
|
|||
if (!l.isEnabled())
|
||||
continue;
|
||||
|
||||
int clipRestoreCount = c.save();
|
||||
mLimitLineClippingRect.set(mViewPortHandler.getContentRect());
|
||||
mLimitLineClippingRect.inset(-l.getLineWidth() / 2.f, 0.f);
|
||||
c.clipRect(mLimitLineClippingRect);
|
||||
|
||||
pts[0] = l.getLimit();
|
||||
pts[2] = l.getLimit();
|
||||
|
||||
|
@ -281,6 +294,8 @@ public class YAxisRendererHorizontalBarChart extends YAxisRenderer {
|
|||
c.drawText(label, pts[0] - xOffset, mViewPortHandler.contentBottom() - yOffset, mLimitLinePaint);
|
||||
}
|
||||
}
|
||||
|
||||
c.restoreToCount(clipRestoreCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue