package com.github.mikephil.charting.components;
import android.graphics.Paint;
import com.github.mikephil.charting.utils.Utils;
import java.util.List;
/**
* Class representing the legend of the chart. The legend will contain one entry
* per color and DataSet. Multiple colors in one DataSet are grouped together.
* The legend object is NOT available before setting data to the chart.
*
* @author Philipp Jahoda
*/
public class Legend extends ComponentBase {
public enum LegendPosition {
RIGHT_OF_CHART, RIGHT_OF_CHART_CENTER, RIGHT_OF_CHART_INSIDE,
LEFT_OF_CHART, LEFT_OF_CHART_CENTER, LEFT_OF_CHART_INSIDE,
BELOW_CHART_LEFT, BELOW_CHART_RIGHT, BELOW_CHART_CENTER,
PIECHART_CENTER
}
public enum LegendForm {
SQUARE, CIRCLE, LINE
}
public enum LegendDirection {
LEFT_TO_RIGHT, RIGHT_TO_LEFT
}
/** the legend colors */
private int[] mColors;
/** the legend labels */
private String[] mLabels;
/** the position relative to the chart the legend is drawn on */
private LegendPosition mPosition = LegendPosition.BELOW_CHART_LEFT;
/** the text direction for the legend */
private LegendDirection mDirection = LegendDirection.LEFT_TO_RIGHT;
/** the shape/form the legend colors are drawn in */
private LegendForm mShape = LegendForm.SQUARE;
/** the size of the legend forms/shapes */
private float mFormSize = 8f;
/**
* the space between the legend entries on a horizontal axis, default 6f
*/
private float mXEntrySpace = 6f;
/**
* the space between the legend entries on a vertical axis, default 5f
*/
private float mYEntrySpace = 5f;
/**
* the space between the legend entries on a vertical axis, default 2f
* private float mYEntrySpace = 2f; /** the space between the form and the
* actual label/text
*/
private float mFormToTextSpace = 5f;
/** the space that should be left between stacked forms */
private float mStackSpace = 3f;
/** default constructor */
public Legend() {
mFormSize = Utils.convertDpToPixel(8f);
mXEntrySpace = Utils.convertDpToPixel(6f);
mYEntrySpace = Utils.convertDpToPixel(5f);
mFormToTextSpace = Utils.convertDpToPixel(5f);
mTextSize = Utils.convertDpToPixel(10f);
mStackSpace = Utils.convertDpToPixel(3f);
this.mXOffset = Utils.convertDpToPixel(5f);
this.mYOffset = Utils.convertDpToPixel(6f);
}
/**
* Constructor. Provide colors and labels for the legend.
*
* @param colors
* @param labels
*/
public Legend(int[] colors, String[] labels) {
this();
if (colors == null || labels == null) {
throw new IllegalArgumentException("colors array or labels array is NULL");
}
if (colors.length != labels.length) {
throw new IllegalArgumentException(
"colors array and labels array need to be of same size");
}
this.mColors = colors;
this.mLabels = labels;
}
/**
* Constructor. Provide colors and labels for the legend.
*
* @param colors
* @param labels
*/
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);
}
public void setColors(List<Integer> colors) {
mColors = Utils.convertIntegers(colors);;
}
public void setLabels(List<String> labels) {
mLabels = Utils.convertStrings(labels);;
}
/**
* returns the maximum length in pixels across all legend labels + formsize
* + formtotextspace
*
* @param p the paint object used for rendering the text
* @return
*/
public float getMaximumEntryWidth(Paint p) {
float max = 0f;
for (int i = 0; i < mLabels.length; i++) {
if (mLabels[i] != null) {
float length = (float) Utils.calcTextWidth(p, mLabels[i]);
if (length > max)
max = length;
}
}
return max + mFormSize + mFormToTextSpace;
}
/**
* returns the maximum height in pixels across all legend labels
*
* @param p the paint object used for rendering the text
* @return
*/
public float getMaximumEntryHeight(Paint p) {
float max = 0f;
for (int i = 0; i < mLabels.length; i++) {
if (mLabels[i] != null) {
float length = (float) Utils.calcTextHeight(p, mLabels[i]);
if (length > max)
max = length;
}
}
return max;
}
/**
* returns all the colors the legend uses
*
* @return
*/
public int[] getColors() {
return mColors;
}
/**
* returns all the labels the legend uses
*
* @return
*/
public String[] getLegendLabels() {
return mLabels;
}
/**
* Sets a custom array of labels for the legend. Make sure the labels array
* has the same length as the colors array.
*
* @param labels
*/
public void setLabels(String[] labels) {
this.mLabels = labels;
}
/**
* Returns the legend-label at the given index.
*
* @param index
* @return
*/
public String getLabel(int index) {
return mLabels[index];
}
/**
* returns the position of the legend relative to the chart
*
* @return
*/
public LegendPosition getPosition() {
return mPosition;
}
/**
* sets the position of the legend relative to the whole chart
*
* @param pos
*/
public void setPosition(LegendPosition pos) {
mPosition = pos;
}
/**
* returns the text direction of the legend
*
* @return
*/
public LegendDirection getDirection() {
return mDirection;
}
/**
* sets the text direction of the legend
*
* @param pos
*/
public void setDirection(LegendDirection pos) {
mDirection = pos;
}
/**
* returns the current form/shape that is set for the legend
*
* @return
*/
public LegendForm getForm() {
return mShape;
}
/**
* sets the form/shape of the legend forms
*
* @param shape
*/
public void setForm(LegendForm shape) {
mShape = shape;
}
/**
* sets the size in pixels of the legend forms, this is internally converted
* in dp, default 8f
*
* @param size
*/
public void setFormSize(float size) {
mFormSize = Utils.convertDpToPixel(size);
}
/**
* returns the size in dp of the legend forms
*
* @return
*/
public float getFormSize() {
return mFormSize;
}
/**
* returns the space between the legend entries on a horizontal axis in
* pixels
*
* @return
*/
public float getXEntrySpace() {
return mXEntrySpace;
}
/**
* sets the space between the legend entries on a horizontal axis in pixels,
* converts to dp internally
*
* @param space
*/
public void setXEntrySpace(float space) {
mXEntrySpace = Utils.convertDpToPixel(space);
}
/**
* returns the space between the legend entries on a vertical axis in pixels
*
* @return
*/
public float getYEntrySpace() {
return mYEntrySpace;
}
/**
* sets the space between the legend entries on a vertical axis in pixels,
* converts to dp internally
*
* @param space
*/
public void setYEntrySpace(float space) {
mYEntrySpace = Utils.convertDpToPixel(space);
}
/**
* returns the space between the form and the actual label/text
*
* @return
*/
public float getFormToTextSpace() {
return mFormToTextSpace;
}
/**
* sets the space between the form and the actual label/text, converts to dp
* internally
*
* @param mFormToTextSpace
*/
public void setFormToTextSpace(float space) {
this.mFormToTextSpace = Utils.convertDpToPixel(space);
}
// /**
// * applies the state from the legend in the parameter to this legend (except
// * colors, labels and offsets)
// *
// * @param l
// */
// public void apply(Legend l) {
//
// mPosition = l.mPosition;
// mShape = l.mShape;
// mTypeface = l.mTypeface;
// mFormSize = l.mFormSize;
// mXEntrySpace = l.mXEntrySpace;
// mYEntrySpace = l.mYEntrySpace;
// mFormToTextSpace = l.mFormToTextSpace;
// mTextSize = l.mTextSize;
// mStackSpace = l.mStackSpace;
// mTextColor = l.mTextColor;
// mEnabled = l.mEnabled;
// mXOffset = l.mXOffset;
// mYOffset = l.mYOffset;
// }
/**
* returns the space that is left out between stacked forms (with no label)
*
* @return
*/
public float getStackSpace() {
return mStackSpace;
}
/**
* sets the space that is left out between stacked forms (with no label)
*
* @param space
*/
public void setStackSpace(float space) {
mStackSpace = space;
}
/**
* calculates the full width the fully drawn legend will use in pixels
*
* @return
*/
public float getFullWidth(Paint labelpaint) {
float width = 0f;
for (int i = 0; i < mLabels.length; i++) {
// grouped forms have null labels
if (mLabels[i] != null) {
// make a step to the left
if (mColors[i] != -2)
width += mFormSize + mFormToTextSpace;
width += Utils.calcTextWidth(labelpaint, mLabels[i]);
if (i < mLabels.length - 1)
width += mXEntrySpace;
} else {
width += mFormSize;
if (i < mLabels.length - 1)
width += mStackSpace;
}
}
return width;
}
/**
* Calculates the full height of the drawn legend.
*
* @param mLegendLabelPaint
* @return
*/
public float getFullHeight(Paint labelpaint) {
float height = 0f;
for (int i = 0; i < mLabels.length; i++) {
// grouped forms have null labels
if (mLabels[i] != null) {
height += Utils.calcTextHeight(labelpaint, mLabels[i]);
if (i < mLabels.length - 1)
height += mYEntrySpace;
}
}
return height;
}
/** the total width of the legend (needed width space) */
public float mNeededWidth = 0f;
/** the total height of the legend (needed height space) */
public float mNeededHeight = 0f;
public float mTextHeightMax = 0f;
public float mTextWidthMax = 0f;
/**
* Calculates the dimensions of the Legend. This includes the maximum width
* and height of a single entry, as well as the total width and height of
* the Legend.
*
* @param labelpaint
*/
public void calculateDimensions(Paint labelpaint) {
if (mPosition == LegendPosition.RIGHT_OF_CHART
|| mPosition == LegendPosition.RIGHT_OF_CHART_CENTER
|| mPosition == LegendPosition.LEFT_OF_CHART
|| mPosition == LegendPosition.LEFT_OF_CHART_CENTER
|| mPosition == LegendPosition.PIECHART_CENTER) {
mNeededWidth = getMaximumEntryWidth(labelpaint);
mNeededHeight = getFullHeight(labelpaint);
mTextWidthMax = mNeededWidth;
mTextHeightMax = getMaximumEntryHeight(labelpaint);
} else {
mNeededWidth = getFullWidth(labelpaint);
mNeededHeight = getMaximumEntryHeight(labelpaint);
mTextWidthMax = getMaximumEntryWidth(labelpaint);
mTextHeightMax = mNeededHeight;
}
}
}