Skip to content
Snippets Groups Projects
Commit c8dfe17c authored by ruX[Ruslan Zaharov]'s avatar ruX[Ruslan Zaharov]
Browse files

Render new line char in legend items

parent 6b99e929
No related branches found
No related tags found
No related merge requests found
......@@ -200,7 +200,7 @@ public class Axis implements ChartPart {
double chartLegendWidth = 0;
if (getChartPainter().getStyleManager().getLegendPosition() == LegendPosition.OutsideE) {
chartLegendWidth = getChartPainter().getChartLegend().getSizeHint()[0];
chartLegendWidth = getChartPainter().getChartLegend().getSizeHint(g)[0];
}
double width =
......
......@@ -15,15 +15,17 @@
*/
package com.xeiam.xchart.internal.chartpart;
import java.awt.BasicStroke;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.font.FontRenderContext;
import java.awt.font.TextLayout;
import java.awt.*;
import java.awt.font.*;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.text.AttributedCharacterIterator;
import java.text.AttributedString;
import java.util.*;
import java.util.List;
import com.xeiam.xchart.Series;
import com.xeiam.xchart.StyleManager;
import com.xeiam.xchart.StyleManager.ChartType;
import com.xeiam.xchart.internal.markers.Marker;
......@@ -35,15 +37,19 @@ public class Legend implements ChartPart {
private static final int LEGEND_MARGIN = 6;
private static final int BOX_SIZE = 20;
/** parent */
/**
* parent
*/
private final ChartPainter chartPainter;
/** the bounds */
/**
* the bounds
*/
private Rectangle2D bounds;
/**
* Constructor
*
*
* @param chartPainter
*/
public Legend(ChartPainter chartPainter) {
......@@ -53,57 +59,65 @@ public class Legend implements ChartPart {
/**
* get the width of the chart legend
*
*
* @param g
* @return
*/
protected double[] getSizeHint() {
protected double[] getSizeHint(Graphics2D g) {
if (!chartPainter.getStyleManager().isLegendVisible()) {
return new double[]{0, 0};
}
if (chartPainter.getStyleManager().isLegendVisible()) {
StyleManager styleManager = getChartPainter().getStyleManager();
FontMetrics fontMetrics = g.getFontMetrics(chartPainter.getStyleManager().getLegendFont());
boolean isBar = styleManager.getChartType() == ChartType.Bar;
// determine legend text content max width
double legendTextContentMaxWidth = 0;
double legendTextContentMaxHeight = 0;
// determine legend text content max width
double legendTextContentMaxWidth = 0;
double legendTextContentMaxHeight = 0;
for (Series series : chartPainter.getAxisPair().getSeriesMap().values()) {
// determine legend content height
double legendContentHeight = 0;
TextLayout textLayout = new TextLayout(series.getName(), chartPainter.getStyleManager().getLegendFont(), new FontRenderContext(null, true, false));
Rectangle2D rectangle = textLayout.getBounds();
// System.out.println(rectangle);
if (rectangle.getWidth() > legendTextContentMaxWidth) {
legendTextContentMaxWidth = rectangle.getWidth();
}
if (rectangle.getHeight() > legendTextContentMaxHeight) {
legendTextContentMaxHeight = rectangle.getHeight();
}
for (Series series : chartPainter.getAxisPair().getSeriesMap().values()) {
List<Map.Entry<String, Rectangle2D>> seriesBounds = getSeriesBounds(series, g);
double blockHeight = 0;
for (Map.Entry<String, Rectangle2D> entry : seriesBounds) {
blockHeight += entry.getValue().getHeight();
legendTextContentMaxWidth = Math.max(legendTextContentMaxWidth, entry.getValue().getWidth());
}
// determine legend content height
double maxContentHeight = 0;
if (getChartPainter().getStyleManager().getChartType() != ChartType.Bar) {
maxContentHeight = Math.max(legendTextContentMaxHeight, Marker.SIZE);
}
else {
maxContentHeight = Math.max(legendTextContentMaxHeight, BOX_SIZE);
}
double legendContentHeight =
maxContentHeight * getChartPainter().getAxisPair().getSeriesMap().size() + chartPainter.getStyleManager().getLegendPadding() * (getChartPainter().getAxisPair().getSeriesMap().size() - 1);
blockHeight = Math.max(blockHeight, isBar ? BOX_SIZE : Marker.SIZE);
// determine legend content width
double legendContentWidth = 0;
if (getChartPainter().getStyleManager().getChartType() != ChartType.Bar) {
legendContentWidth = getChartPainter().getStyleManager().getLegendSeriesLineLength() + chartPainter.getStyleManager().getLegendPadding() + legendTextContentMaxWidth;
}
else {
legendContentWidth = BOX_SIZE + chartPainter.getStyleManager().getLegendPadding() + legendTextContentMaxWidth;
}
// Legend Box
double legendBoxWidth = legendContentWidth + 2 * chartPainter.getStyleManager().getLegendPadding();
double legendBoxHeight = legendContentHeight + 2 * chartPainter.getStyleManager().getLegendPadding();
return new double[] { legendBoxWidth, legendBoxHeight, maxContentHeight };
legendTextContentMaxHeight = Math.max(legendTextContentMaxHeight, blockHeight);
legendContentHeight += blockHeight;
}
else {
return new double[] { 0, 0, 0 };
// vertical padding between items
double paddingSize = isBar ? styleManager.getLegendPadding() : fontMetrics.getDescent();
legendContentHeight += paddingSize * (chartPainter.getAxisPair().getSeriesMap().size() - 1);
// determine legend content width
double legendContentWidth = 0;
if (!isBar) {
legendContentWidth = styleManager.getLegendSeriesLineLength() + styleManager.getLegendPadding() + legendTextContentMaxWidth;
} else {
legendContentWidth = BOX_SIZE + styleManager.getLegendPadding() + legendTextContentMaxWidth;
}
// Legend Box
double legendBoxWidth = legendContentWidth + 2 * styleManager.getLegendPadding();
double legendBoxHeight = legendContentHeight + 2 * styleManager.getLegendPadding();
return new double[]{legendBoxWidth, legendBoxHeight};
}
private List<Map.Entry<String, Rectangle2D>> getSeriesBounds(Series series, Graphics2D g) {
String lines[] = series.getName().split("\\n");
List<Map.Entry<String, Rectangle2D>> stringBounds = new ArrayList<Map.Entry<String, Rectangle2D>>(lines.length);
for (String line : lines) {
Rectangle2D bounds = g.getFontMetrics().getStringBounds(line, g);
stringBounds.add(new AbstractMap.SimpleEntry<String, Rectangle2D>(line, bounds));
}
return stringBounds;
}
@Override
......@@ -112,18 +126,23 @@ public class Legend implements ChartPart {
bounds = new Rectangle2D.Double();
g.setFont(chartPainter.getStyleManager().getLegendFont());
if (chartPainter.getStyleManager().isLegendVisible()) {
StyleManager styleManager = getChartPainter().getStyleManager();
if (!styleManager.isLegendVisible()) return;
final double[] sizeHint = getSizeHint(g);
double legendBoxWidth = getSizeHint()[0];
double legendBoxHeight = getSizeHint()[1];
double maxContentHeight = getSizeHint()[2];
double legendBoxWidth = sizeHint[0];
double legendBoxHeight = sizeHint[1];
// legend draw position
double xOffset = 0;
double yOffset = 0;
switch (chartPainter.getStyleManager().getLegendPosition()) {
FontMetrics fontMetrics = g.getFontMetrics(styleManager.getLegendFont());
// legend draw position
double xOffset = 0;
double yOffset = 0;
switch (styleManager.getLegendPosition()) {
case OutsideE:
xOffset = chartPainter.getWidth() - legendBoxWidth - chartPainter.getStyleManager().getChartPadding();
xOffset = chartPainter.getWidth() - legendBoxWidth - styleManager.getChartPadding();
yOffset = chartPainter.getPlot().getBounds().getY() + (chartPainter.getPlot().getBounds().getHeight() - legendBoxHeight) / 2.0;
break;
case InsideNW:
......@@ -149,65 +168,80 @@ public class Legend implements ChartPart {
default:
break;
}
g.setStroke(new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
Shape rect = new Rectangle2D.Double(xOffset + 1, yOffset + 1, legendBoxWidth - 2, legendBoxHeight - 2);
g.setColor(chartPainter.getStyleManager().getLegendBackgroundColor());
g.fill(rect);
g.setColor(chartPainter.getStyleManager().getLegendBorderColor());
g.draw(rect);
// Draw legend content inside legend box
double startx = xOffset + chartPainter.getStyleManager().getLegendPadding();
double starty = yOffset + chartPainter.getStyleManager().getLegendPadding();
for (Series series : chartPainter.getAxisPair().getSeriesMap().values()) {
if (getChartPainter().getStyleManager().getChartType() != ChartType.Bar) {
// paint line
if (getChartPainter().getStyleManager().getChartType() != ChartType.Scatter && series.getStroke() != null) {
g.setColor(series.getStrokeColor());
g.setStroke(series.getStroke());
Shape line = new Line2D.Double(startx, starty + maxContentHeight / 2.0, startx + getChartPainter().getStyleManager().getLegendSeriesLineLength(), starty + maxContentHeight / 2.0);
g.draw(line);
}
// paint marker
if (series.getMarker() != null) {
g.setColor(series.getMarkerColor());
series.getMarker().paint(g, startx + getChartPainter().getStyleManager().getLegendSeriesLineLength() / 2.0, starty + maxContentHeight / 2.0);
}
}
g.setStroke(new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
Shape rect = new Rectangle2D.Double(xOffset + 1, yOffset + 1, legendBoxWidth - 2, legendBoxHeight - 2);
g.setColor(styleManager.getLegendBackgroundColor());
g.fill(rect);
g.setColor(styleManager.getLegendBorderColor());
g.draw(rect);
// Draw legend content inside legend box
double startx = xOffset + styleManager.getLegendPadding();
double starty = yOffset + styleManager.getLegendPadding();
for (Series series : chartPainter.getAxisPair().getSeriesMap().values()) {
List<Map.Entry<String, Rectangle2D>> seriesBounds = getSeriesBounds(series, g);
float blockHeight = 0;
for (Map.Entry<String, Rectangle2D> entry : seriesBounds)
blockHeight += entry.getValue().getHeight();
if (styleManager.getChartType() != ChartType.Bar) {
// paint line
if (styleManager.getChartType() != ChartType.Scatter && series.getStroke() != null) {
g.setColor(series.getStrokeColor());
g.setStroke(series.getStroke());
Shape line = new Line2D.Double(startx, starty + blockHeight / 2.0, startx + styleManager.getLegendSeriesLineLength(), starty + blockHeight / 2.0);
g.draw(line);
}
// paint marker
if (series.getMarker() != null) {
g.setColor(series.getMarkerColor());
series.getMarker().paint(g, startx + styleManager.getLegendSeriesLineLength() / 2.0, starty + blockHeight / 2.0);
}
else {
// paint little box
if (series.getStroke() != null) {
g.setColor(series.getStrokeColor());
Shape rectSmall = new Rectangle2D.Double(startx, starty, BOX_SIZE, BOX_SIZE);
g.fill(rectSmall);
}
} else {
// paint little box
if (series.getStroke() != null) {
g.setColor(series.getStrokeColor());
Shape rectSmall = new Rectangle2D.Double(startx, starty, BOX_SIZE, BOX_SIZE);
g.fill(rectSmall);
}
}
// paint series name
// paint series name
g.setColor(chartPainter.getStyleManager().getChartFontColor());
g.setColor(chartPainter.getStyleManager().getChartFontColor());
TextLayout layout = new TextLayout(series.getName(), chartPainter.getStyleManager().getLegendFont(), new FontRenderContext(null, true, false));
if (getChartPainter().getStyleManager().getChartType() != ChartType.Bar) {
layout.draw(g, (float) (startx + getChartPainter().getStyleManager().getLegendSeriesLineLength() + chartPainter.getStyleManager().getLegendPadding()),
(float) (starty + (maxContentHeight - 1 + layout.getBounds().getHeight()) / 2.0));
float itemOffsetY = -fontMetrics.getDescent();
if (styleManager.getChartType() != ChartType.Bar) {
final float x = (float) (startx + styleManager.getLegendSeriesLineLength() + styleManager.getLegendPadding());
for (Map.Entry<String, Rectangle2D> entry : seriesBounds) {
g.drawString(entry.getKey(), x, (float) (starty + entry.getValue().getHeight()) + itemOffsetY);
itemOffsetY += entry.getValue().getHeight();
}
else {
layout.draw(g, (float) (startx + BOX_SIZE + chartPainter.getStyleManager().getLegendPadding()), (float) (starty + (maxContentHeight + layout.getBounds().getHeight()) / 2.0));
itemOffsetY = (float) Math.max(itemOffsetY, Marker.SIZE);
starty += blockHeight + fontMetrics.getDescent();
} else {
final float x = (float) (startx + BOX_SIZE + styleManager.getLegendPadding());
for (Map.Entry<String, Rectangle2D> entry : seriesBounds) {
double height = entry.getValue().getHeight();
double centerOffsetY = (Math.max(BOX_SIZE, height) - height) / 2.0;
g.drawString(entry.getKey(), x, (float)(starty + height + itemOffsetY + centerOffsetY));
itemOffsetY += height;
}
starty = starty + maxContentHeight + chartPainter.getStyleManager().getLegendPadding();
starty += Math.max(BOX_SIZE, blockHeight) + styleManager.getLegendPadding();
}
// bounds
bounds = new Rectangle2D.Double(xOffset, yOffset, legendBoxWidth, legendBoxHeight);
// g.setColor(Color.blue);
// g.draw(bounds);
}
// bounds
bounds = new Rectangle2D.Double(xOffset, yOffset, legendBoxWidth, legendBoxHeight);
// g.setColor(Color.blue);
// g.draw(bounds);
}
@Override
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment