Skip to content
Snippets Groups Projects
Commit e1c455f6 authored by Martin Crawford's avatar Martin Crawford
Browse files

Added text-alignment functionality for axis labels. Added functionality for...

Added text-alignment functionality for axis labels. Added functionality for combining both line & area plots on one chart. Added demo of functionality added.
parent 4d0ea7b8
No related branches found
No related tags found
No related merge requests found
......@@ -47,12 +47,7 @@ import com.xeiam.xchart.demo.charts.date.DateChart04;
import com.xeiam.xchart.demo.charts.date.DateChart05;
import com.xeiam.xchart.demo.charts.date.DateChart06;
import com.xeiam.xchart.demo.charts.date.DateChart07;
import com.xeiam.xchart.demo.charts.line.LineChart01;
import com.xeiam.xchart.demo.charts.line.LineChart02;
import com.xeiam.xchart.demo.charts.line.LineChart03;
import com.xeiam.xchart.demo.charts.line.LineChart04;
import com.xeiam.xchart.demo.charts.line.LineChart05;
import com.xeiam.xchart.demo.charts.line.LineChart06;
import com.xeiam.xchart.demo.charts.line.*;
import com.xeiam.xchart.demo.charts.realtime.RealtimeChart01;
import com.xeiam.xchart.demo.charts.realtime.RealtimeChart02;
import com.xeiam.xchart.demo.charts.scatter.ScatterChart01;
......@@ -216,6 +211,9 @@ public class XChartDemo extends JPanel implements TreeSelectionListener {
defaultMutableTreeNode = new DefaultMutableTreeNode(new ChartInfo("LineChart06 - Logarithmic Y-Axis with Error Bars", new LineChart06().getChart()));
category.add(defaultMutableTreeNode);
defaultMutableTreeNode = new DefaultMutableTreeNode(new ChartInfo("LineAreaChart07 - Line & Area Chart", new LineAreaChart07().getChart()));
category.add(defaultMutableTreeNode);
// Scatter category
category = new DefaultMutableTreeNode("Scatter Charts");
top.add(category);
......
/**
* Copyright 2011 - 2014 Xeiam LLC.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.xeiam.xchart.demo.charts.line;
import com.xeiam.xchart.*;
import com.xeiam.xchart.StyleManager.LegendPosition;
import com.xeiam.xchart.demo.charts.ExampleChart;
import java.awt.*;
/**
* Combination Line & Area Chart
* <p/>
* Demonstrates the following:
* <ul>
* <li>Combination of Line and Area series
* <li>Axis Label Alignment
* <li>Ensuring a chart axis on a tick
*/
public class LineAreaChart07 implements ExampleChart {
public static void main(String[] args) {
ExampleChart exampleChart = new LineAreaChart07();
Chart chart = exampleChart.getChart();
new SwingWrapper(chart).displayChart();
}
@Override
public Chart getChart() {
// Create Chart
Chart chart = new Chart(800, 600);
// Customize Chart
chart.setChartTitle("LineAreaChart07");
chart.setXAxisTitle("Age");
chart.setYAxisTitle("Amount");
chart.getStyleManager().setLegendPosition(LegendPosition.InsideNW);
double[] xAges = new double[]{
60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100};
double[] yLiability = new double[]{
672234,
691729,
711789,
732431,
753671,
775528,
798018,
821160,
844974,
869478,
907735,
887139,
865486,
843023,
819621,
795398,
770426,
744749,
719011,
693176,
667342,
641609,
616078,
590846,
565385,
540002,
514620,
489380,
465149,
441817,
419513,
398465,
377991,
358784,
340920,
323724,
308114,
293097,
279356,
267008,
254873
};
double[] yPercentile75th = new double[]{
800000,
878736,
945583,
1004209,
1083964,
1156332,
1248041,
1340801,
1440138,
1550005,
1647728,
1705046,
1705032,
1710672,
1700847,
1683418,
1686522,
1674901,
1680456,
1679164,
1668514,
1672860,
1673988,
1646597,
1641842,
1653758,
1636317,
1620725,
1589985,
1586451,
1559507,
1544234,
1529700,
1507496,
1474907,
1422169,
1415079,
1346929,
1311689,
1256114,
1221034
};
double[] yPercentile50th = new double[]{
800000,
835286,
873456,
927048,
969305,
1030749,
1101102,
1171396,
1246486,
1329076,
1424666,
1424173,
1421853,
1397093,
1381882,
1364562,
1360050,
1336885,
1340431,
1312217,
1288274,
1271615,
1262682,
1237287,
1211335,
1191953,
1159689,
1117412,
1078875,
1021020,
974933,
910189,
869154,
798476,
744934,
674501,
609237,
524516,
442234,
343960,
257025
};
double[] yPercentile25th = new double[]{
800000,
791439,
809744,
837020,
871166,
914836,
958257,
1002955,
1054094,
1118934,
1194071,
1185041,
1175401,
1156578,
1132121,
1094879,
1066202,
1054411,
1028619,
987730,
944977,
914929,
880687,
809330,
783318,
739751,
696201,
638242,
565197,
496959,
421280,
358113,
276518,
195571,
109514,
13876,
29,
0,
0,
0,
0};
Series seriesLiability = chart.addSeries("Liability", xAges, yLiability);
seriesLiability.setMarker(SeriesMarker.NONE);
seriesLiability.setSeriesType(Series.SeriesType.Area);
Series seriesPercentile75th = chart.addSeries("75th Percentile", xAges, yPercentile75th);
seriesPercentile75th.setMarker(SeriesMarker.NONE);
Series seriesPercentile50th = chart.addSeries("50th Percentile", xAges, yPercentile50th);
seriesPercentile50th.setMarker(SeriesMarker.NONE);
Series seriesPercentile25th = chart.addSeries("25th Percentile", xAges, yPercentile25th);
seriesPercentile25th.setMarker(SeriesMarker.NONE);
chart.getStyleManager().setYAxisLabelAlignment(StyleManager.TextAlignment.Right);
chart.getStyleManager().setDecimalPattern("$ #,###.##"); // TODO need a different patter for y and x axis
chart.getStyleManager().setPlotPadding(0);
chart.getStyleManager().setAxisTickSpaceRatio(1);
chart.getStyleManager().setYAxisMax(1620725 * 1.15); // We want to ensure there is a % of padding on the top of the chart
return chart;
}
}
......@@ -32,6 +32,10 @@ import com.xeiam.xchart.internal.style.SeriesColorMarkerLineStyle;
*/
public class Series {
public enum SeriesType {
Line, Area
}
private String name = "";
private Collection<?> xData;
......@@ -40,6 +44,8 @@ public class Series {
private Collection<? extends Number> yData;
private AxisType yAxisType;
private SeriesType seriesType;
private Collection<? extends Number> errorBars;
/** the minimum value of axis range */
......@@ -60,6 +66,9 @@ public class Series {
/** Line Color */
private Color strokeColor;
/** Fill Colour */
private Color fillColor;
/** Marker Style */
private Marker marker;
......@@ -91,6 +100,7 @@ public class Series {
this.errorBars = errorBars;
strokeColor = seriesColorMarkerLineStyle.getColor();
fillColor = seriesColorMarkerLineStyle.getColor();
markerColor = seriesColorMarkerLineStyle.getColor();
marker = seriesColorMarkerLineStyle.getMarker();
stroke = seriesColorMarkerLineStyle.getStroke();
......@@ -241,6 +251,14 @@ public class Series {
return this;
}
public SeriesType getSeriesType() {
return seriesType;
}
public void setSeriesType(SeriesType seriesType) {
this.seriesType = seriesType;
}
public Collection<?> getXData() {
return xData;
......@@ -296,6 +314,14 @@ public class Series {
return markerColor;
}
public Color getFillColor() {
return fillColor;
}
public void setFillColor(Color fillColor) {
this.fillColor = fillColor;
}
public String getName() {
return name;
......
......@@ -66,6 +66,12 @@ public class StyleManager {
}
}
public enum TextAlignment {
Left,
Centre,
Right;
}
/** the default Theme */
private Theme theme = new XChartTheme();
......@@ -117,6 +123,8 @@ public class StyleManager {
private Double yAxisMin;
private Double yAxisMax;
private double axisTickSpaceRatio;
private TextAlignment xAxisLabelAlignment = TextAlignment.Centre;
private TextAlignment yAxisLabelAlignment = TextAlignment.Left;
// Chart Plot Area ///////////////////////////////
private boolean isPlotGridLinesVisible;
......@@ -872,6 +880,23 @@ public class StyleManager {
return axisTickSpaceRatio;
}
public TextAlignment getXAxisLabelAlignment() {
return xAxisLabelAlignment;
}
public void setXAxisLabelAlignment(TextAlignment xAxisLabelAlignment) {
this.xAxisLabelAlignment = xAxisLabelAlignment;
}
public TextAlignment getYAxisLabelAlignment() {
return yAxisLabelAlignment;
}
public void setYAxisLabelAlignment(TextAlignment yAxisLabelAlignment) {
this.yAxisLabelAlignment = yAxisLabelAlignment;
}
// Chart Plot Area ///////////////////////////////
/**
......
......@@ -15,21 +15,15 @@
*/
package com.xeiam.xchart.internal.chartpart;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import com.xeiam.xchart.Series;
import com.xeiam.xchart.StyleManager.ChartType;
import com.xeiam.xchart.internal.chartpart.Axis.AxisType;
import com.xeiam.xchart.internal.style.SeriesColorMarkerLineStyleCycler;
import java.awt.*;
import java.util.*;
import java.util.List;
/**
* @author timmolter
*/
......@@ -115,6 +109,14 @@ public class AxisPair implements ChartPart {
series = new Series(seriesName, generatedXData, xAxis.getAxisType(), yData, yAxis.getAxisType(), errorBars, seriesColorMarkerLineStyleCycler.getNextSeriesColorMarkerLineStyle());
}
switch (chartPainter.getStyleManager().getChartType()) {
case Area:
series.setSeriesType(Series.SeriesType.Area);
break;
case Line:
series.setSeriesType(Series.SeriesType.Line);
}
// Sanity check
if (xData != null && xData.size() != yData.size()) {
throw new IllegalArgumentException("X and Y-Axis sizes are not the same!!!");
......
......@@ -15,12 +15,13 @@
*/
package com.xeiam.xchart.internal.chartpart;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.font.TextLayout;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.util.HashMap;
import java.util.Map;
/**
* Axis tick labels
......@@ -58,38 +59,58 @@ public class AxisTickLabels implements ChartPart {
if (axisTick.getAxis().getDirection() == Axis.Direction.Y && getChartPainter().getStyleManager().isYAxisTicksVisible()) { // Y-Axis
double xOffset = axisTick.getAxis().getAxisTitle().getBounds().getX() + axisTick.getAxis().getAxisTitle().getBounds().getWidth();
double xWidth = axisTick.getAxis().getAxisTitle().getBounds().getWidth();
double xOffset = axisTick.getAxis().getAxisTitle().getBounds().getX() + xWidth;
double yOffset = axisTick.getAxis().getPaintZone().getY();
double height = axisTick.getAxis().getPaintZone().getHeight();
double maxTickLabelWidth = 0;
Map<Double, TextLayout> axisLabelTextLayouts = new HashMap<Double, TextLayout>();
for (int i = 0; i < axisTick.getTickLabels().size(); i++) {
String tickLabel = axisTick.getTickLabels().get(i);
// System.out.println(tickLabel);
double tickLocation = axisTick.getTickLocations().get(i);
double flippedTickLocation = yOffset + height - tickLocation;
if (tickLabel != null && flippedTickLocation > yOffset && flippedTickLocation < yOffset + height) { // some are null for logarithmic axes
FontRenderContext frc = g.getFontRenderContext();
TextLayout layout = new TextLayout(tickLabel, getChartPainter().getStyleManager().getAxisTickLabelsFont(), frc);
Rectangle2D tickLabelBounds = layout.getBounds();
TextLayout axisLabelTextLayout = new TextLayout(tickLabel, getChartPainter().getStyleManager().getAxisTickLabelsFont(), frc);
Rectangle2D tickLabelBounds = axisLabelTextLayout.getBounds();
double boundWidth = tickLabelBounds.getWidth();
if (boundWidth > maxTickLabelWidth) {
maxTickLabelWidth = boundWidth;
}
axisLabelTextLayouts.put(tickLocation, axisLabelTextLayout);
}
}
Shape shape = layout.getOutline(null);
for (Double tickLocation : axisLabelTextLayouts.keySet()) {
AffineTransform orig = g.getTransform();
AffineTransform at = new AffineTransform();
at.translate(xOffset, flippedTickLocation + tickLabelBounds.getHeight() / 2.0);
g.transform(at);
g.fill(shape);
g.setTransform(orig);
TextLayout axisLabelTextLayout = axisLabelTextLayouts.get(tickLocation);
Rectangle2D tickLabelBounds = axisLabelTextLayout.getBounds();
Shape shape = axisLabelTextLayout.getOutline(null);
if (tickLabelBounds.getWidth() > maxTickLabelWidth) {
maxTickLabelWidth = tickLabelBounds.getWidth();
}
double flippedTickLocation = yOffset + height - tickLocation;
AffineTransform orig = g.getTransform();
AffineTransform at = new AffineTransform();
double boundWidth = tickLabelBounds.getWidth();
double xPos;
switch (getChartPainter().getStyleManager().getYAxisLabelAlignment()) {
case Right:
xPos = xOffset + maxTickLabelWidth - boundWidth;
break;
case Centre:
xPos = xOffset + (maxTickLabelWidth - boundWidth) / 2;
break;
case Left:
default:
xPos = xOffset;
}
at.translate(xPos, flippedTickLocation + tickLabelBounds.getHeight() / 2.0);
g.transform(at);
g.fill(shape);
g.setTransform(orig);
}
// bounds
......@@ -124,7 +145,19 @@ public class AxisTickLabels implements ChartPart {
AffineTransform orig = g.getTransform();
AffineTransform at = new AffineTransform();
at.translate(shiftedTickLocation - tickLabelBounds.getWidth() / 2.0, yOffset);
double xPos;
switch (getChartPainter().getStyleManager().getXAxisLabelAlignment()) {
case Left:
xPos = shiftedTickLocation;
break;
case Right:
xPos = shiftedTickLocation - tickLabelBounds.getWidth();
break;
case Centre:
default:
xPos = shiftedTickLocation - tickLabelBounds.getWidth() / 2.0;
}
at.translate(xPos, yOffset);
g.transform(at);
g.fill(shape);
g.setTransform(orig);
......
......@@ -181,11 +181,11 @@ public class PlotContentLineChart extends PlotContent {
}
// paint area
if (getChartPainter().getStyleManager().getChartType() == ChartType.Area) {
if (getChartPainter().getStyleManager().getChartType() == ChartType.Area || Series.SeriesType.Area.equals(series.getSeriesType())) {
if (previousX != Integer.MIN_VALUE && previousY != Integer.MIN_VALUE) {
g.setColor(series.getStrokeColor());
g.setColor(series.getFillColor());
double yBottomOfArea = bounds.getY() + bounds.getHeight() - yTopMargin;
if (path == null) {
......
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