diff --git a/xchart-demo/src/main/java/org/knowm/xchart/demo/charts/bar/BarChart09.java b/xchart-demo/src/main/java/org/knowm/xchart/demo/charts/bar/BarChart09.java new file mode 100644 index 0000000000000000000000000000000000000000..164303e2e56e3a9c075c08ca17110dabd26541d6 --- /dev/null +++ b/xchart-demo/src/main/java/org/knowm/xchart/demo/charts/bar/BarChart09.java @@ -0,0 +1,67 @@ +/** + * Copyright 2015 Knowm Inc. (http://knowm.org) and contributors. + * Copyright 2011-2015 Xeiam LLC (http://xeiam.com) and contributors. + * + * 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 org.knowm.xchart.demo.charts.bar; + +import java.util.ArrayList; +import java.util.Arrays; + +import org.knowm.xchart.Chart; +import org.knowm.xchart.ChartBuilder; +import org.knowm.xchart.Series; +import org.knowm.xchart.Series.SeriesType; +import org.knowm.xchart.StyleManager.ChartTheme; +import org.knowm.xchart.StyleManager.ChartType; +import org.knowm.xchart.StyleManager.LegendPosition; +import org.knowm.xchart.SwingWrapper; +import org.knowm.xchart.demo.charts.ExampleChart; + +/** + * Category chart with Bar and Line Series + * <p> + * Demonstrates the following: + * <ul> + * <li>Mixed series types - Bar and Line + * <li>Bar Chart styles - overlapped, bar width + */ +public class BarChart09 implements ExampleChart { + + public static void main(String[] args) { + + ExampleChart exampleChart = new BarChart09(); + Chart chart = exampleChart.getChart(); + new SwingWrapper(chart).displayChart(); + } + + @Override + public Chart getChart() { + + // Create Chart + Chart chart = new ChartBuilder().chartType(ChartType.Bar).width(800).height(600).title("Value vs. Letter").xAxisTitle("Letter").yAxisTitle("Value").theme(ChartTheme.GGPlot2).build(); + chart.addSeries("China", new ArrayList<String>(Arrays.asList(new String[] { "A", "B", "C", "D", "E" })), new ArrayList<Number>(Arrays.asList(new Number[] { 11, 23, 20, 36, 5 }))); + Series series2 = chart.addSeries("World Ave.", new ArrayList<String>(Arrays.asList(new String[] { "A", "B", "C", "D", "E" })), new ArrayList<Number>(Arrays.asList(new Number[] { 13, 25, 22, 38, + 7 }))); + series2.setSeriesType(SeriesType.Line); + + // Customize Chart + chart.getStyleManager().setLegendPosition(LegendPosition.InsideNW); + chart.getStyleManager().setBarWidthPercentage(.7); + chart.getStyleManager().setBarsOverlapped(true); + + return chart; + } + +} diff --git a/xchart/src/main/java/org/knowm/xchart/internal/chartpart/PlotContentBarChart.java b/xchart/src/main/java/org/knowm/xchart/internal/chartpart/PlotContentBarChart.java index 47ae84174623da9419f03c14b835f9ab12d20f46..155db2fecfe5fe065922cdc973c449148edf0363 100644 --- a/xchart/src/main/java/org/knowm/xchart/internal/chartpart/PlotContentBarChart.java +++ b/xchart/src/main/java/org/knowm/xchart/internal/chartpart/PlotContentBarChart.java @@ -26,6 +26,7 @@ import java.util.Collection; import java.util.Iterator; import org.knowm.xchart.Series; +import org.knowm.xchart.Series.SeriesType; import org.knowm.xchart.StyleManager; import org.knowm.xchart.internal.Utils; @@ -76,8 +77,9 @@ public class PlotContentBarChart extends PlotContent { int seriesCounter = 0; for (Series series : getChartPainter().getAxisPair().getSeriesMap().values()) { - // data points - // Collection<?> xData = series.getXData(); + // for line series + double previousX = Integer.MIN_VALUE; + double previousY = Integer.MIN_VALUE; Collection<? extends Number> yData = series.getYData(); double yMin = getChartPainter().getAxisPair().getYAxis().getMin(); @@ -135,6 +137,7 @@ public class PlotContentBarChart extends PlotContent { while (yItr.hasNext()) { double y = ((Number) yItr.next()).doubleValue(); + // TODO test if this works, make an example chart if (getChartPainter().getStyleManager().isYAxisLogarithmic()) { y = Math.log10(y); } @@ -185,40 +188,66 @@ public class PlotContentBarChart extends PlotContent { double zeroTransform = bounds.getHeight() - (yTopMargin + (yBottom - yMin) / (yMax - yMin) * yTickSpace); double zeroOffset = bounds.getY() + zeroTransform; - - // paint bar - boolean isOverlap = true; double xOffset; double barWidth; + if (getChartPainter().getStyleManager().isBarsOverlapped()) { double barWidthPercentage = getChartPainter().getStyleManager().getBarWidthPercentage(); barWidth = gridStep * barWidthPercentage; double barMargin = gridStep * (1 - barWidthPercentage) / 2; xOffset = bounds.getX() + xLeftMargin + gridStep * barCounter++ + barMargin; - g.setColor(series.getStrokeColor()); } else { double barWidthPercentage = getChartPainter().getStyleManager().getBarWidthPercentage(); barWidth = gridStep / getChartPainter().getAxisPair().getSeriesMap().size() * barWidthPercentage; double barMargin = gridStep * (1 - barWidthPercentage) / 2; xOffset = bounds.getX() + xLeftMargin + gridStep * barCounter++ + seriesCounter * barWidth + barMargin; + } + if (series.getSeriesType() == SeriesType.Bar) { + // paint bar g.setColor(series.getStrokeColor()); + Path2D.Double path = new Path2D.Double(); + path.moveTo(xOffset, yOffset); + path.lineTo(xOffset + barWidth, yOffset); + path.lineTo(xOffset + barWidth, zeroOffset); + path.lineTo(xOffset, zeroOffset); + path.closePath(); + g.setStroke(series.getStroke()); + if (getChartPainter().getStyleManager().isBarFilled()) { + g.fill(path); + } + else { + g.draw(path); + } } - Path2D.Double path = new Path2D.Double(); - path.moveTo(xOffset, yOffset); - path.lineTo(xOffset + barWidth, yOffset); - path.lineTo(xOffset + barWidth, zeroOffset); - path.lineTo(xOffset, zeroOffset); - path.closePath(); - g.setStroke(series.getStroke()); - if (getChartPainter().getStyleManager().isBarFilled()) { - g.fill(path); + else if (series.getSeriesType() == SeriesType.Line) { // line series + + // paint line + if (series.getStroke() != null) { + + if (previousX != Integer.MIN_VALUE && previousY != Integer.MIN_VALUE) { + g.setColor(series.getStrokeColor()); + g.setStroke(series.getStroke()); + Shape line = new Line2D.Double(previousX, previousY, xOffset + barWidth / 2, yOffset); + g.draw(line); + } + } + previousX = xOffset + barWidth / 2; + previousY = yOffset; + + // paint marker + if (series.getMarker() != null) { + g.setColor(series.getMarkerColor()); + series.getMarker().paint(g, previousX, previousY, getChartPainter().getStyleManager().getMarkerSize()); + } + } else { - g.draw(path); + // TODO probably add this earlier as a sanity check when series are added to charts + throw new RuntimeException("Category charts only accept Bar and Line series types!!!"); } - // paint errorbars + // paint error bars if (errorBars != null) {