* The chart object returned by this method uses a {@link PiePlot} instance * as the plot. * * @param title the chart title ({@code null} permitted). * @param dataset the dataset for the chart ({@code null} permitted). * @param legend a flag specifying whether or not a legend is required. * @param tooltips configure chart to generate tool tips? * @param locale the locale ({@code null} not permitted). * * @return A pie chart. */ public static JFreeChart createPieChart(String title, PieDataset dataset, boolean legend, boolean tooltips, Locale locale) { PiePlot plot = new PiePlot(dataset); plot.setLabelGenerator(new StandardPieSectionLabelGenerator(locale)); plot.setInsets(new RectangleInsets(0.0, 5.0, 5.0, 5.0)); if (tooltips) { plot.setToolTipGenerator(new StandardPieToolTipGenerator(locale)); } JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, legend); currentTheme.apply(chart); return chart; } /** * Creates a pie chart with default settings. *
* The chart object returned by this method uses a {@link PiePlot} instance * as the plot. * * @param title the chart title ({@code null} permitted). * @param dataset the dataset for the chart ({@code null} permitted). * * @return A pie chart. */ public static JFreeChart createPieChart(String title, PieDataset dataset) { return createPieChart(title, dataset, true, true, false); } /** * Creates a pie chart with default settings. *
* The chart object returned by this method uses a {@link PiePlot} instance * as the plot. * * @param title the chart title ({@code null} permitted). * @param dataset the dataset for the chart ({@code null} permitted). * @param legend a flag specifying whether or not a legend is required. * @param tooltips configure chart to generate tool tips? * @param urls configure chart to generate URLs? * * @return A pie chart. */ public static JFreeChart createPieChart(String title, PieDataset dataset, boolean legend, boolean tooltips, boolean urls) { PiePlot plot = new PiePlot(dataset); plot.setLabelGenerator(new StandardPieSectionLabelGenerator()); plot.setInsets(new RectangleInsets(0.0, 5.0, 5.0, 5.0)); if (tooltips) { plot.setToolTipGenerator(new StandardPieToolTipGenerator()); } if (urls) { plot.setURLGenerator(new StandardPieURLGenerator()); } JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, legend); currentTheme.apply(chart); return chart; } /** * Creates a pie chart with default settings that compares 2 datasets. * The colour of each section will be determined by the move from the value * for the same key in {@code previousDataset}. ie if value1 > * value2 then the section will be in green (unless * {@code greenForIncrease} is {@code false}, in which case it * would be {@code red}). Each section can have a shade of red or * green as the difference can be tailored between 0% (black) and * percentDiffForMaxScale% (bright red/green). *
* For instance if {@code percentDiffForMaxScale} is 10 (10%), a * difference of 5% will have a half shade of red/green, a difference of * 10% or more will have a maximum shade/brightness of red/green. *
* The chart object returned by this method uses a {@link PiePlot} instance * as the plot. *
* Written by Benoit * Xhenseval. * * @param title the chart title ({@code null} permitted). * @param dataset the dataset for the chart ({@code null} permitted). * @param previousDataset the dataset for the last run, this will be used * to compare each key in the dataset * @param percentDiffForMaxScale scale goes from bright red/green to black, * percentDiffForMaxScale indicate the change * required to reach top scale. * @param greenForIncrease an increase since previousDataset will be * displayed in green (decrease red) if true. * @param legend a flag specifying whether or not a legend is required. * @param tooltips configure chart to generate tool tips? * @param locale the locale ({@code null} not permitted). * @param subTitle displays a subtitle with colour scheme if true * @param showDifference create a new dataset that will show the % * difference between the two datasets. * * @return A pie chart. */ public static JFreeChart createPieChart(String title, PieDataset dataset, PieDataset previousDataset, int percentDiffForMaxScale, boolean greenForIncrease, boolean legend, boolean tooltips, Locale locale, boolean subTitle, boolean showDifference) { PiePlot plot = new PiePlot(dataset); plot.setLabelGenerator(new StandardPieSectionLabelGenerator(locale)); plot.setInsets(new RectangleInsets(0.0, 5.0, 5.0, 5.0)); if (tooltips) { plot.setToolTipGenerator(new StandardPieToolTipGenerator(locale)); } List keys = dataset.getKeys(); DefaultPieDataset series = null; if (showDifference) { series = new DefaultPieDataset(); } double colorPerPercent = 255.0 / percentDiffForMaxScale; for (Iterator it = keys.iterator(); it.hasNext();) { Comparable key = (Comparable) it.next(); Number newValue = dataset.getValue(key); Number oldValue = previousDataset.getValue(key); if (oldValue == null) { if (greenForIncrease) { plot.setSectionPaint(key, Color.GREEN); } else { plot.setSectionPaint(key, Color.RED); } if (showDifference) { assert series != null; // suppresses compiler warning series.setValue(key + " (+100%)", newValue); } } else { double percentChange = (newValue.doubleValue() / oldValue.doubleValue() - 1.0) * 100.0; double shade = (Math.abs(percentChange) >= percentDiffForMaxScale ? 255 : Math.abs(percentChange) * colorPerPercent); if (greenForIncrease && newValue.doubleValue() > oldValue.doubleValue() || !greenForIncrease && newValue.doubleValue() < oldValue.doubleValue()) { plot.setSectionPaint(key, new Color(0, (int) shade, 0)); } else { plot.setSectionPaint(key, new Color((int) shade, 0, 0)); } if (showDifference) { assert series != null; // suppresses compiler warning series.setValue(key + " (" + (percentChange >= 0 ? "+" : "") + NumberFormat.getPercentInstance().format( percentChange / 100.0) + ")", newValue); } } } if (showDifference) { plot.setDataset(series); } JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, legend); if (subTitle) { TextTitle subtitle = new TextTitle("Bright " + (greenForIncrease ? "red" : "green") + "=change >=-" + percentDiffForMaxScale + "%, Bright " + (!greenForIncrease ? "red" : "green") + "=change >=+" + percentDiffForMaxScale + "%", new Font("SansSerif", Font.PLAIN, 10)); chart.addSubtitle(subtitle); } currentTheme.apply(chart); return chart; } /** * Creates a pie chart with default settings that compares 2 datasets. * The colour of each section will be determined by the move from the value * for the same key in {@code previousDataset}. ie if value1 > * value2 then the section will be in green (unless * {@code greenForIncrease} is {@code false}, in which case it * would be {@code red}). Each section can have a shade of red or * green as the difference can be tailored between 0% (black) and * percentDiffForMaxScale% (bright red/green). *
* For instance if {@code percentDiffForMaxScale} is 10 (10%), a * difference of 5% will have a half shade of red/green, a difference of * 10% or more will have a maximum shade/brightness of red/green. *
* The chart object returned by this method uses a {@link PiePlot} instance * as the plot. *
* Written by Benoit * Xhenseval. * * @param title the chart title ({@code null} permitted). * @param dataset the dataset for the chart ({@code null} permitted). * @param previousDataset the dataset for the last run, this will be used * to compare each key in the dataset * @param percentDiffForMaxScale scale goes from bright red/green to black, * percentDiffForMaxScale indicate the change * required to reach top scale. * @param greenForIncrease an increase since previousDataset will be * displayed in green (decrease red) if true. * @param legend a flag specifying whether or not a legend is required. * @param tooltips configure chart to generate tool tips? * @param urls configure chart to generate URLs? * @param subTitle displays a subtitle with colour scheme if true * @param showDifference create a new dataset that will show the % * difference between the two datasets. * * @return A pie chart. */ public static JFreeChart createPieChart(String title, PieDataset dataset, PieDataset previousDataset, int percentDiffForMaxScale, boolean greenForIncrease, boolean legend, boolean tooltips, boolean urls, boolean subTitle, boolean showDifference) { PiePlot plot = new PiePlot(dataset); plot.setLabelGenerator(new StandardPieSectionLabelGenerator()); plot.setInsets(new RectangleInsets(0.0, 5.0, 5.0, 5.0)); if (tooltips) { plot.setToolTipGenerator(new StandardPieToolTipGenerator()); } if (urls) { plot.setURLGenerator(new StandardPieURLGenerator()); } List keys = dataset.getKeys(); DefaultPieDataset series = null; if (showDifference) { series = new DefaultPieDataset(); } double colorPerPercent = 255.0 / percentDiffForMaxScale; for (Iterator it = keys.iterator(); it.hasNext();) { Comparable key = (Comparable) it.next(); Number newValue = dataset.getValue(key); Number oldValue = previousDataset.getValue(key); if (oldValue == null) { if (greenForIncrease) { plot.setSectionPaint(key, Color.GREEN); } else { plot.setSectionPaint(key, Color.RED); } if (showDifference) { assert series != null; // suppresses compiler warning series.setValue(key + " (+100%)", newValue); } } else { double percentChange = (newValue.doubleValue() / oldValue.doubleValue() - 1.0) * 100.0; double shade = (Math.abs(percentChange) >= percentDiffForMaxScale ? 255 : Math.abs(percentChange) * colorPerPercent); if (greenForIncrease && newValue.doubleValue() > oldValue.doubleValue() || !greenForIncrease && newValue.doubleValue() < oldValue.doubleValue()) { plot.setSectionPaint(key, new Color(0, (int) shade, 0)); } else { plot.setSectionPaint(key, new Color((int) shade, 0, 0)); } if (showDifference) { assert series != null; // suppresses compiler warning series.setValue(key + " (" + (percentChange >= 0 ? "+" : "") + NumberFormat.getPercentInstance().format( percentChange / 100.0) + ")", newValue); } } } if (showDifference) { plot.setDataset(series); } JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, legend); if (subTitle) { TextTitle subtitle = new TextTitle("Bright " + (greenForIncrease ? "red" : "green") + "=change >=-" + percentDiffForMaxScale + "%, Bright " + (!greenForIncrease ? "red" : "green") + "=change >=+" + percentDiffForMaxScale + "%", new Font("SansSerif", Font.PLAIN, 10)); chart.addSubtitle(subtitle); } currentTheme.apply(chart); return chart; } /** * Creates a ring chart with default settings. *
* The chart object returned by this method uses a {@link RingPlot} * instance as the plot. * * @param title the chart title ({@code null} permitted). * @param dataset the dataset for the chart ({@code null} permitted). * @param legend a flag specifying whether or not a legend is required. * @param tooltips configure chart to generate tool tips? * @param locale the locale ({@code null} not permitted). * * @return A ring chart. */ public static JFreeChart createRingChart(String title, PieDataset dataset, boolean legend, boolean tooltips, Locale locale) { RingPlot plot = new RingPlot(dataset); plot.setLabelGenerator(new StandardPieSectionLabelGenerator(locale)); plot.setInsets(new RectangleInsets(0.0, 5.0, 5.0, 5.0)); if (tooltips) { plot.setToolTipGenerator(new StandardPieToolTipGenerator(locale)); } JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, legend); currentTheme.apply(chart); return chart; } /** * Creates a ring chart with default settings. *
* The chart object returned by this method uses a {@link RingPlot} * instance as the plot. * * @param title the chart title ({@code null} permitted). * @param dataset the dataset for the chart ({@code null} permitted). * @param legend a flag specifying whether or not a legend is required. * @param tooltips configure chart to generate tool tips? * @param urls configure chart to generate URLs? * * @return A ring chart. */ public static JFreeChart createRingChart(String title, PieDataset dataset, boolean legend, boolean tooltips, boolean urls) { RingPlot plot = new RingPlot(dataset); plot.setLabelGenerator(new StandardPieSectionLabelGenerator()); plot.setInsets(new RectangleInsets(0.0, 5.0, 5.0, 5.0)); if (tooltips) { plot.setToolTipGenerator(new StandardPieToolTipGenerator()); } if (urls) { plot.setURLGenerator(new StandardPieURLGenerator()); } JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, legend); currentTheme.apply(chart); return chart; } /** * Creates a chart that displays multiple pie plots. The chart object * returned by this method uses a {@link MultiplePiePlot} instance as the * plot. * * @param title the chart title ({@code null} permitted). * @param dataset the dataset ({@code null} permitted). * @param order the order that the data is extracted (by row or by column) * ({@code null} not permitted). * @param legend include a legend? * @param tooltips generate tooltips? * @param urls generate URLs? * * @return A chart. */ public static JFreeChart createMultiplePieChart(String title, CategoryDataset dataset, TableOrder order, boolean legend, boolean tooltips, boolean urls) { Args.nullNotPermitted(order, "order"); MultiplePiePlot plot = new MultiplePiePlot(dataset); plot.setDataExtractOrder(order); plot.setBackgroundPaint(null); plot.setOutlineStroke(null); if (tooltips) { PieToolTipGenerator tooltipGenerator = new StandardPieToolTipGenerator(); PiePlot pp = (PiePlot) plot.getPieChart().getPlot(); pp.setToolTipGenerator(tooltipGenerator); } if (urls) { PieURLGenerator urlGenerator = new StandardPieURLGenerator(); PiePlot pp = (PiePlot) plot.getPieChart().getPlot(); pp.setURLGenerator(urlGenerator); } JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, legend); currentTheme.apply(chart); return chart; } /** * Creates a 3D pie chart using the specified dataset. The chart object * returned by this method uses a {@link PiePlot3D} instance as the * plot. * * @param title the chart title ({@code null} permitted). * @param dataset the dataset for the chart ({@code null} permitted). * @param legend a flag specifying whether or not a legend is required. * @param tooltips configure chart to generate tool tips? * @param locale the locale ({@code null} not permitted). * * @return A pie chart. * * @deprecated For 3D pie charts, use Orson Charts (https://github.com/jfree/orson-charts). */ public static JFreeChart createPieChart3D(String title, PieDataset dataset, boolean legend, boolean tooltips, Locale locale) { Args.nullNotPermitted(locale, "locale"); PiePlot3D plot = new PiePlot3D(dataset); plot.setInsets(new RectangleInsets(0.0, 5.0, 5.0, 5.0)); if (tooltips) { plot.setToolTipGenerator(new StandardPieToolTipGenerator(locale)); } JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, legend); currentTheme.apply(chart); return chart; } /** * Creates a 3D pie chart using the specified dataset. The chart object * returned by this method uses a {@link PiePlot3D} instance as the * plot. * * @param title the chart title ({@code null} permitted). * @param dataset the dataset for the chart ({@code null} permitted). * * @return A pie chart. * * @deprecated For 3D pie charts, use Orson Charts (https://github.com/jfree/orson-charts). */ public static JFreeChart createPieChart3D(String title, PieDataset dataset) { return createPieChart3D(title, dataset, true, true, false); } /** * Creates a 3D pie chart using the specified dataset. The chart object * returned by this method uses a {@link PiePlot3D} instance as the * plot. * * @param title the chart title ({@code null} permitted). * @param dataset the dataset for the chart ({@code null} permitted). * @param legend a flag specifying whether or not a legend is required. * @param tooltips configure chart to generate tool tips? * @param urls configure chart to generate URLs? * * @return A pie chart. * @deprecated For 3D pie charts, use Orson Charts (https://github.com/jfree/orson-charts). */ public static JFreeChart createPieChart3D(String title, PieDataset dataset, boolean legend, boolean tooltips, boolean urls) { PiePlot3D plot = new PiePlot3D(dataset); plot.setInsets(new RectangleInsets(0.0, 5.0, 5.0, 5.0)); if (tooltips) { plot.setToolTipGenerator(new StandardPieToolTipGenerator()); } if (urls) { plot.setURLGenerator(new StandardPieURLGenerator()); } JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, legend); currentTheme.apply(chart); return chart; } /** * Creates a chart that displays multiple pie plots. The chart object * returned by this method uses a {@link MultiplePiePlot} instance as the * plot. * * @param title the chart title ({@code null} permitted). * @param dataset the dataset ({@code null} permitted). * @param order the order that the data is extracted (by row or by column) * ({@code null} not permitted). * @param legend include a legend? * @param tooltips generate tooltips? * @param urls generate URLs? * * @return A chart. */ public static JFreeChart createMultiplePieChart3D(String title, CategoryDataset dataset, TableOrder order, boolean legend, boolean tooltips, boolean urls) { Args.nullNotPermitted(order, "order"); MultiplePiePlot plot = new MultiplePiePlot(dataset); plot.setDataExtractOrder(order); plot.setBackgroundPaint(null); plot.setOutlineStroke(null); JFreeChart pieChart = new JFreeChart(new PiePlot3D(null)); TextTitle seriesTitle = new TextTitle("Series Title", new Font("SansSerif", Font.BOLD, 12)); seriesTitle.setPosition(RectangleEdge.BOTTOM); pieChart.setTitle(seriesTitle); pieChart.removeLegend(); pieChart.setBackgroundPaint(null); plot.setPieChart(pieChart); if (tooltips) { PieToolTipGenerator tooltipGenerator = new StandardPieToolTipGenerator(); PiePlot pp = (PiePlot) plot.getPieChart().getPlot(); pp.setToolTipGenerator(tooltipGenerator); } if (urls) { PieURLGenerator urlGenerator = new StandardPieURLGenerator(); PiePlot pp = (PiePlot) plot.getPieChart().getPlot(); pp.setURLGenerator(urlGenerator); } JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, legend); currentTheme.apply(chart); return chart; } /** * Creates a bar chart with a vertical orientation. The chart object * returned by this method uses a {@link CategoryPlot} instance as the * plot, with a {@link CategoryAxis} for the domain axis, a * {@link NumberAxis} as the range axis, and a {@link BarRenderer} as the * renderer. * * @param title the chart title ({@code null} permitted). * @param categoryAxisLabel the label for the category axis * ({@code null} permitted). * @param valueAxisLabel the label for the value axis * ({@code null} permitted). * @param dataset the dataset for the chart ({@code null} permitted). * * @return A bar chart. */ public static JFreeChart createBarChart(String title, String categoryAxisLabel, String valueAxisLabel, CategoryDataset dataset) { return createBarChart(title, categoryAxisLabel, valueAxisLabel, dataset, PlotOrientation.VERTICAL, true, true, false); } /** * Creates a bar chart. The chart object returned by this method uses a * {@link CategoryPlot} instance as the plot, with a {@link CategoryAxis} * for the domain axis, a {@link NumberAxis} as the range axis, and a * {@link BarRenderer} as the renderer. * * @param title the chart title ({@code null} permitted). * @param categoryAxisLabel the label for the category axis * ({@code null} permitted). * @param valueAxisLabel the label for the value axis * ({@code null} permitted). * @param dataset the dataset for the chart ({@code null} permitted). * @param orientation the plot orientation (horizontal or vertical) * ({@code null} not permitted). * @param legend a flag specifying whether or not a legend is required. * @param tooltips configure chart to generate tool tips? * @param urls configure chart to generate URLs? * * @return A bar chart. */ public static JFreeChart createBarChart(String title, String categoryAxisLabel, String valueAxisLabel, CategoryDataset dataset, PlotOrientation orientation, boolean legend, boolean tooltips, boolean urls) { Args.nullNotPermitted(orientation, "orientation"); CategoryAxis categoryAxis = new CategoryAxis(categoryAxisLabel); ValueAxis valueAxis = new NumberAxis(valueAxisLabel); BarRenderer renderer = new BarRenderer(); if (orientation == PlotOrientation.HORIZONTAL) { ItemLabelPosition position1 = new ItemLabelPosition( ItemLabelAnchor.OUTSIDE3, TextAnchor.CENTER_LEFT); renderer.setDefaultPositiveItemLabelPosition(position1); ItemLabelPosition position2 = new ItemLabelPosition( ItemLabelAnchor.OUTSIDE9, TextAnchor.CENTER_RIGHT); renderer.setDefaultNegativeItemLabelPosition(position2); } else if (orientation == PlotOrientation.VERTICAL) { ItemLabelPosition position1 = new ItemLabelPosition( ItemLabelAnchor.OUTSIDE12, TextAnchor.BOTTOM_CENTER); renderer.setDefaultPositiveItemLabelPosition(position1); ItemLabelPosition position2 = new ItemLabelPosition( ItemLabelAnchor.OUTSIDE6, TextAnchor.TOP_CENTER); renderer.setDefaultNegativeItemLabelPosition(position2); } if (tooltips) { renderer.setDefaultToolTipGenerator( new StandardCategoryToolTipGenerator()); } if (urls) { renderer.setDefaultItemURLGenerator( new StandardCategoryURLGenerator()); } CategoryPlot plot = new CategoryPlot(dataset, categoryAxis, valueAxis, renderer); plot.setOrientation(orientation); JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, legend); currentTheme.apply(chart); return chart; } /** * Creates a stacked bar chart with default settings. The chart object * returned by this method uses a {@link CategoryPlot} instance as the * plot, with a {@link CategoryAxis} for the domain axis, a * {@link NumberAxis} as the range axis, and a {@link StackedBarRenderer} * as the renderer. * * @param title the chart title ({@code null} permitted). * @param domainAxisLabel the label for the category axis * ({@code null} permitted). * @param rangeAxisLabel the label for the value axis * ({@code null} permitted). * @param dataset the dataset for the chart ({@code null} permitted). * * @return A stacked bar chart. */ public static JFreeChart createStackedBarChart(String title, String domainAxisLabel, String rangeAxisLabel, CategoryDataset dataset) { return createStackedBarChart(title, domainAxisLabel, rangeAxisLabel, dataset, PlotOrientation.VERTICAL, true, true, false); } /** * Creates a stacked bar chart with default settings. The chart object * returned by this method uses a {@link CategoryPlot} instance as the * plot, with a {@link CategoryAxis} for the domain axis, a * {@link NumberAxis} as the range axis, and a {@link StackedBarRenderer} * as the renderer. * * @param title the chart title ({@code null} permitted). * @param domainAxisLabel the label for the category axis * ({@code null} permitted). * @param rangeAxisLabel the label for the value axis * ({@code null} permitted). * @param dataset the dataset for the chart ({@code null} permitted). * @param orientation the orientation of the chart (horizontal or * vertical) ({@code null} not permitted). * @param legend a flag specifying whether or not a legend is required. * @param tooltips configure chart to generate tool tips? * @param urls configure chart to generate URLs? * * @return A stacked bar chart. */ public static JFreeChart createStackedBarChart(String title, String domainAxisLabel, String rangeAxisLabel, CategoryDataset dataset, PlotOrientation orientation, boolean legend, boolean tooltips, boolean urls) { Args.nullNotPermitted(orientation, "orientation"); CategoryAxis categoryAxis = new CategoryAxis(domainAxisLabel); ValueAxis valueAxis = new NumberAxis(rangeAxisLabel); StackedBarRenderer renderer = new StackedBarRenderer(); if (tooltips) { renderer.setDefaultToolTipGenerator( new StandardCategoryToolTipGenerator()); } if (urls) { renderer.setDefaultItemURLGenerator( new StandardCategoryURLGenerator()); } CategoryPlot plot = new CategoryPlot(dataset, categoryAxis, valueAxis, renderer); plot.setOrientation(orientation); JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, legend); currentTheme.apply(chart); return chart; } /** * Creates an area chart with default settings. The chart object returned * by this method uses a {@link CategoryPlot} instance as the plot, with a * {@link CategoryAxis} for the domain axis, a {@link NumberAxis} as the * range axis, and an {@link AreaRenderer} as the renderer. * * @param title the chart title ({@code null} permitted). * @param categoryAxisLabel the label for the category axis * ({@code null} permitted). * @param valueAxisLabel the label for the value axis ({@code null} * permitted). * @param dataset the dataset for the chart ({@code null} permitted). * * @return An area chart. */ public static JFreeChart createAreaChart(String title, String categoryAxisLabel, String valueAxisLabel, CategoryDataset dataset) { return createAreaChart(title, categoryAxisLabel, valueAxisLabel, dataset, PlotOrientation.VERTICAL, true, true, false); } /** * Creates an area chart with default settings. The chart object returned * by this method uses a {@link CategoryPlot} instance as the plot, with a * {@link CategoryAxis} for the domain axis, a {@link NumberAxis} as the * range axis, and an {@link AreaRenderer} as the renderer. * * @param title the chart title ({@code null} permitted). * @param categoryAxisLabel the label for the category axis * ({@code null} permitted). * @param valueAxisLabel the label for the value axis ({@code null} * permitted). * @param dataset the dataset for the chart ({@code null} permitted). * @param orientation the plot orientation ({@code null} not * permitted). * @param legend a flag specifying whether or not a legend is required. * @param tooltips configure chart to generate tool tips? * @param urls configure chart to generate URLs? * * @return An area chart. */ public static JFreeChart createAreaChart(String title, String categoryAxisLabel, String valueAxisLabel, CategoryDataset dataset, PlotOrientation orientation, boolean legend, boolean tooltips, boolean urls) { Args.nullNotPermitted(orientation, "orientation"); CategoryAxis categoryAxis = new CategoryAxis(categoryAxisLabel); categoryAxis.setCategoryMargin(0.0); ValueAxis valueAxis = new NumberAxis(valueAxisLabel); AreaRenderer renderer = new AreaRenderer(); if (tooltips) { renderer.setDefaultToolTipGenerator( new StandardCategoryToolTipGenerator()); } if (urls) { renderer.setDefaultItemURLGenerator( new StandardCategoryURLGenerator()); } CategoryPlot plot = new CategoryPlot(dataset, categoryAxis, valueAxis, renderer); plot.setOrientation(orientation); JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, legend); currentTheme.apply(chart); return chart; } /** * Creates a stacked area chart with default settings. The chart object * returned by this method uses a {@link CategoryPlot} instance as the * plot, with a {@link CategoryAxis} for the domain axis, a * {@link NumberAxis} as the range axis, and a {@link StackedAreaRenderer} * as the renderer. * * @param title the chart title ({@code null} permitted). * @param categoryAxisLabel the label for the category axis * ({@code null} permitted). * @param valueAxisLabel the label for the value axis ({@code null} * permitted). * @param dataset the dataset for the chart ({@code null} permitted). * * @return A stacked area chart. */ public static JFreeChart createStackedAreaChart(String title, String categoryAxisLabel, String valueAxisLabel, CategoryDataset dataset) { return createStackedAreaChart(title, categoryAxisLabel, valueAxisLabel, dataset, PlotOrientation.VERTICAL, true, true, false); } /** * Creates a stacked area chart with default settings. The chart object * returned by this method uses a {@link CategoryPlot} instance as the * plot, with a {@link CategoryAxis} for the domain axis, a * {@link NumberAxis} as the range axis, and a {@link StackedAreaRenderer} * as the renderer. * * @param title the chart title ({@code null} permitted). * @param categoryAxisLabel the label for the category axis * ({@code null} permitted). * @param valueAxisLabel the label for the value axis ({@code null} * permitted). * @param dataset the dataset for the chart ({@code null} permitted). * @param orientation the plot orientation (horizontal or vertical) * ({@code null} not permitted). * @param legend a flag specifying whether or not a legend is required. * @param tooltips configure chart to generate tool tips? * @param urls configure chart to generate URLs? * * @return A stacked area chart. */ public static JFreeChart createStackedAreaChart(String title, String categoryAxisLabel, String valueAxisLabel, CategoryDataset dataset, PlotOrientation orientation, boolean legend, boolean tooltips, boolean urls) { Args.nullNotPermitted(orientation, "orientation"); CategoryAxis categoryAxis = new CategoryAxis(categoryAxisLabel); categoryAxis.setCategoryMargin(0.0); ValueAxis valueAxis = new NumberAxis(valueAxisLabel); StackedAreaRenderer renderer = new StackedAreaRenderer(); if (tooltips) { renderer.setDefaultToolTipGenerator( new StandardCategoryToolTipGenerator()); } if (urls) { renderer.setDefaultItemURLGenerator( new StandardCategoryURLGenerator()); } CategoryPlot plot = new CategoryPlot(dataset, categoryAxis, valueAxis, renderer); plot.setOrientation(orientation); JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, legend); currentTheme.apply(chart); return chart; } /** * Creates a line chart with default settings. The chart object returned * by this method uses a {@link CategoryPlot} instance as the plot, with a * {@link CategoryAxis} for the domain axis, a {@link NumberAxis} as the * range axis, and a {@link LineAndShapeRenderer} as the renderer. * * @param title the chart title ({@code null} permitted). * @param categoryAxisLabel the label for the category axis * ({@code null} permitted). * @param valueAxisLabel the label for the value axis ({@code null} * permitted). * @param dataset the dataset for the chart ({@code null} permitted). * * @return A line chart. */ public static JFreeChart createLineChart(String title, String categoryAxisLabel, String valueAxisLabel, CategoryDataset dataset) { return createLineChart(title, categoryAxisLabel, valueAxisLabel, dataset, PlotOrientation.VERTICAL, true, true, false); } /** * Creates a line chart with default settings. The chart object returned * by this method uses a {@link CategoryPlot} instance as the plot, with a * {@link CategoryAxis} for the domain axis, a {@link NumberAxis} as the * range axis, and a {@link LineAndShapeRenderer} as the renderer. * * @param title the chart title ({@code null} permitted). * @param categoryAxisLabel the label for the category axis * ({@code null} permitted). * @param valueAxisLabel the label for the value axis ({@code null} * permitted). * @param dataset the dataset for the chart ({@code null} permitted). * @param orientation the chart orientation (horizontal or vertical) * ({@code null} not permitted). * @param legend a flag specifying whether or not a legend is required. * @param tooltips configure chart to generate tool tips? * @param urls configure chart to generate URLs? * * @return A line chart. */ public static JFreeChart createLineChart(String title, String categoryAxisLabel, String valueAxisLabel, CategoryDataset dataset, PlotOrientation orientation, boolean legend, boolean tooltips, boolean urls) { Args.nullNotPermitted(orientation, "orientation"); CategoryAxis categoryAxis = new CategoryAxis(categoryAxisLabel); ValueAxis valueAxis = new NumberAxis(valueAxisLabel); LineAndShapeRenderer renderer = new LineAndShapeRenderer(true, false); if (tooltips) { renderer.setDefaultToolTipGenerator( new StandardCategoryToolTipGenerator()); } if (urls) { renderer.setDefaultItemURLGenerator( new StandardCategoryURLGenerator()); } CategoryPlot plot = new CategoryPlot(dataset, categoryAxis, valueAxis, renderer); plot.setOrientation(orientation); JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, legend); currentTheme.apply(chart); return chart; } /** * Creates a Gantt chart using the supplied attributes plus default values * where required. The chart object returned by this method uses a * {@link CategoryPlot} instance as the plot, with a {@link CategoryAxis} * for the domain axis, a {@link DateAxis} as the range axis, and a * {@link GanttRenderer} as the renderer. * * @param title the chart title ({@code null} permitted). * @param categoryAxisLabel the label for the category axis * ({@code null} permitted). * @param dateAxisLabel the label for the date axis * ({@code null} permitted). * @param dataset the dataset for the chart ({@code null} permitted). * * @return A Gantt chart. */ public static JFreeChart createGanttChart(String title, String categoryAxisLabel, String dateAxisLabel, IntervalCategoryDataset dataset) { return createGanttChart(title, categoryAxisLabel, dateAxisLabel, dataset, true, true, false); } /** * Creates a Gantt chart using the supplied attributes plus default values * where required. The chart object returned by this method uses a * {@link CategoryPlot} instance as the plot, with a {@link CategoryAxis} * for the domain axis, a {@link DateAxis} as the range axis, and a * {@link GanttRenderer} as the renderer. * * @param title the chart title ({@code null} permitted). * @param categoryAxisLabel the label for the category axis * ({@code null} permitted). * @param dateAxisLabel the label for the date axis * ({@code null} permitted). * @param dataset the dataset for the chart ({@code null} permitted). * @param legend a flag specifying whether or not a legend is required. * @param tooltips configure chart to generate tool tips? * @param urls configure chart to generate URLs? * * @return A Gantt chart. */ public static JFreeChart createGanttChart(String title, String categoryAxisLabel, String dateAxisLabel, IntervalCategoryDataset dataset, boolean legend, boolean tooltips, boolean urls) { CategoryAxis categoryAxis = new CategoryAxis(categoryAxisLabel); DateAxis dateAxis = new DateAxis(dateAxisLabel); CategoryItemRenderer renderer = new GanttRenderer(); if (tooltips) { renderer.setDefaultToolTipGenerator( new IntervalCategoryToolTipGenerator( "{3} - {4}", DateFormat.getDateInstance())); } if (urls) { renderer.setDefaultItemURLGenerator( new StandardCategoryURLGenerator()); } CategoryPlot plot = new CategoryPlot(dataset, categoryAxis, dateAxis, renderer); plot.setOrientation(PlotOrientation.HORIZONTAL); JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, legend); currentTheme.apply(chart); return chart; } /** * Creates a waterfall chart. The chart object returned by this method * uses a {@link CategoryPlot} instance as the plot, with a * {@link CategoryAxis} for the domain axis, a {@link NumberAxis} as the * range axis, and a {@link WaterfallBarRenderer} as the renderer. * * @param title the chart title ({@code null} permitted). * @param categoryAxisLabel the label for the category axis * ({@code null} permitted). * @param valueAxisLabel the label for the value axis ({@code null} * permitted). * @param dataset the dataset for the chart ({@code null} permitted). * @param orientation the plot orientation (horizontal or vertical) * ({@code null} NOT permitted). * @param legend a flag specifying whether or not a legend is required. * @param tooltips configure chart to generate tool tips? * @param urls configure chart to generate URLs? * * @return A waterfall chart. */ public static JFreeChart createWaterfallChart(String title, String categoryAxisLabel, String valueAxisLabel, CategoryDataset dataset, PlotOrientation orientation, boolean legend, boolean tooltips, boolean urls) { Args.nullNotPermitted(orientation, "orientation"); CategoryAxis categoryAxis = new CategoryAxis(categoryAxisLabel); categoryAxis.setCategoryMargin(0.0); ValueAxis valueAxis = new NumberAxis(valueAxisLabel); WaterfallBarRenderer renderer = new WaterfallBarRenderer(); if (orientation == PlotOrientation.HORIZONTAL) { ItemLabelPosition position = new ItemLabelPosition( ItemLabelAnchor.CENTER, TextAnchor.CENTER, TextAnchor.CENTER, Math.PI / 2.0); renderer.setDefaultPositiveItemLabelPosition(position); renderer.setDefaultNegativeItemLabelPosition(position); } else if (orientation == PlotOrientation.VERTICAL) { ItemLabelPosition position = new ItemLabelPosition( ItemLabelAnchor.CENTER, TextAnchor.CENTER, TextAnchor.CENTER, 0.0); renderer.setDefaultPositiveItemLabelPosition(position); renderer.setDefaultNegativeItemLabelPosition(position); } if (tooltips) { StandardCategoryToolTipGenerator generator = new StandardCategoryToolTipGenerator(); renderer.setDefaultToolTipGenerator(generator); } if (urls) { renderer.setDefaultItemURLGenerator( new StandardCategoryURLGenerator()); } CategoryPlot plot = new CategoryPlot(dataset, categoryAxis, valueAxis, renderer); plot.clearRangeMarkers(); Marker baseline = new ValueMarker(0.0); baseline.setPaint(Color.BLACK); plot.addRangeMarker(baseline, Layer.FOREGROUND); plot.setOrientation(orientation); JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, legend); currentTheme.apply(chart); return chart; } /** * Creates a polar plot for the specified dataset (x-values interpreted as * angles in degrees). The chart object returned by this method uses a * {@link PolarPlot} instance as the plot, with a {@link NumberAxis} for * the radial axis. * * @param title the chart title ({@code null} permitted). * @param dataset the dataset ({@code null} permitted). * @param legend legend required? * @param tooltips tooltips required? * @param urls URLs required? * * @return A chart. */ public static JFreeChart createPolarChart(String title, XYDataset dataset, boolean legend, boolean tooltips, boolean urls) { PolarPlot plot = new PolarPlot(); plot.setDataset(dataset); NumberAxis rangeAxis = new NumberAxis(); rangeAxis.setAxisLineVisible(false); rangeAxis.setTickMarksVisible(false); rangeAxis.setTickLabelInsets(new RectangleInsets(0.0, 0.0, 0.0, 0.0)); plot.setAxis(rangeAxis); plot.setRenderer(new DefaultPolarItemRenderer()); JFreeChart chart = new JFreeChart( title, JFreeChart.DEFAULT_TITLE_FONT, plot, legend); currentTheme.apply(chart); return chart; } /** * Creates a scatter plot with default settings. The chart object * returned by this method uses an {@link XYPlot} instance as the plot, * with a {@link NumberAxis} for the domain axis, a {@link NumberAxis} * as the range axis, and an {@link XYLineAndShapeRenderer} as the * renderer. * * @param title the chart title ({@code null} permitted). * @param xAxisLabel a label for the X-axis ({@code null} permitted). * @param yAxisLabel a label for the Y-axis ({@code null} permitted). * @param dataset the dataset for the chart ({@code null} permitted). * * @return A scatter plot. */ public static JFreeChart createScatterPlot(String title, String xAxisLabel, String yAxisLabel, XYDataset dataset) { return createScatterPlot(title, xAxisLabel, yAxisLabel, dataset, PlotOrientation.VERTICAL, true, true, false); } /** * Creates a scatter plot with default settings. The chart object * returned by this method uses an {@link XYPlot} instance as the plot, * with a {@link NumberAxis} for the domain axis, a {@link NumberAxis} * as the range axis, and an {@link XYLineAndShapeRenderer} as the * renderer. * * @param title the chart title ({@code null} permitted). * @param xAxisLabel a label for the X-axis ({@code null} permitted). * @param yAxisLabel a label for the Y-axis ({@code null} permitted). * @param dataset the dataset for the chart ({@code null} permitted). * @param orientation the plot orientation (horizontal or vertical) * ({@code null} NOT permitted). * @param legend a flag specifying whether or not a legend is required. * @param tooltips configure chart to generate tool tips? * @param urls configure chart to generate URLs? * * @return A scatter plot. */ public static JFreeChart createScatterPlot(String title, String xAxisLabel, String yAxisLabel, XYDataset dataset, PlotOrientation orientation, boolean legend, boolean tooltips, boolean urls) { Args.nullNotPermitted(orientation, "orientation"); NumberAxis xAxis = new NumberAxis(xAxisLabel); xAxis.setAutoRangeIncludesZero(false); NumberAxis yAxis = new NumberAxis(yAxisLabel); yAxis.setAutoRangeIncludesZero(false); XYPlot plot = new XYPlot(dataset, xAxis, yAxis, null); XYToolTipGenerator toolTipGenerator = null; if (tooltips) { toolTipGenerator = new StandardXYToolTipGenerator(); } XYURLGenerator urlGenerator = null; if (urls) { urlGenerator = new StandardXYURLGenerator(); } XYItemRenderer renderer = new XYLineAndShapeRenderer(false, true); renderer.setDefaultToolTipGenerator(toolTipGenerator); renderer.setURLGenerator(urlGenerator); plot.setRenderer(renderer); plot.setOrientation(orientation); JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, legend); currentTheme.apply(chart); return chart; } /** * Creates and returns a default instance of an XY bar chart. *
* The chart object returned by this method uses an {@link XYPlot} instance * as the plot, with a {@link DateAxis} for the domain axis, a * {@link NumberAxis} as the range axis, and a {@link XYBarRenderer} as the * renderer. * * @param title the chart title ({@code null} permitted). * @param xAxisLabel a label for the X-axis ({@code null} permitted). * @param dateAxis make the domain axis display dates? * @param yAxisLabel a label for the Y-axis ({@code null} permitted). * @param dataset the dataset for the chart ({@code null} permitted). * * @return An XY bar chart. */ public static JFreeChart createXYBarChart(String title, String xAxisLabel, boolean dateAxis, String yAxisLabel, IntervalXYDataset dataset) { return createXYBarChart(title, xAxisLabel, dateAxis, yAxisLabel, dataset, PlotOrientation.VERTICAL, true, true, false); } /** * Creates and returns a default instance of an XY bar chart. *
* The chart object returned by this method uses an {@link XYPlot} instance * as the plot, with a {@link DateAxis} for the domain axis, a * {@link NumberAxis} as the range axis, and a {@link XYBarRenderer} as the * renderer. * * @param title the chart title ({@code null} permitted). * @param xAxisLabel a label for the X-axis ({@code null} permitted). * @param dateAxis make the domain axis display dates? * @param yAxisLabel a label for the Y-axis ({@code null} permitted). * @param dataset the dataset for the chart ({@code null} permitted). * @param orientation the orientation (horizontal or vertical) * ({@code null} NOT permitted). * @param legend a flag specifying whether or not a legend is required. * @param tooltips configure chart to generate tool tips? * @param urls configure chart to generate URLs? * * @return An XY bar chart. */ public static JFreeChart createXYBarChart(String title, String xAxisLabel, boolean dateAxis, String yAxisLabel, IntervalXYDataset dataset, PlotOrientation orientation, boolean legend, boolean tooltips, boolean urls) { Args.nullNotPermitted(orientation, "orientation"); ValueAxis domainAxis; if (dateAxis) { domainAxis = new DateAxis(xAxisLabel); } else { NumberAxis axis = new NumberAxis(xAxisLabel); axis.setAutoRangeIncludesZero(false); domainAxis = axis; } ValueAxis valueAxis = new NumberAxis(yAxisLabel); XYBarRenderer renderer = new XYBarRenderer(); if (tooltips) { XYToolTipGenerator tt; if (dateAxis) { tt = StandardXYToolTipGenerator.getTimeSeriesInstance(); } else { tt = new StandardXYToolTipGenerator(); } renderer.setDefaultToolTipGenerator(tt); } if (urls) { renderer.setURLGenerator(new StandardXYURLGenerator()); } XYPlot plot = new XYPlot(dataset, domainAxis, valueAxis, renderer); plot.setOrientation(orientation); JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, legend); currentTheme.apply(chart); return chart; } /** * Creates an area chart using an {@link XYDataset}. *
* The chart object returned by this method uses an {@link XYPlot} instance * as the plot, with a {@link NumberAxis} for the domain axis, a * {@link NumberAxis} as the range axis, and a {@link XYAreaRenderer} as * the renderer. * * @param title the chart title ({@code null} permitted). * @param xAxisLabel a label for the X-axis ({@code null} permitted). * @param yAxisLabel a label for the Y-axis ({@code null} permitted). * @param dataset the dataset for the chart ({@code null} permitted). * * @return An XY area chart. */ public static JFreeChart createXYAreaChart(String title,String xAxisLabel, String yAxisLabel, XYDataset dataset) { return createXYAreaChart(title, xAxisLabel, yAxisLabel, dataset, PlotOrientation.VERTICAL, true, true, false); } /** * Creates an area chart using an {@link XYDataset}. *
* The chart object returned by this method uses an {@link XYPlot} instance * as the plot, with a {@link NumberAxis} for the domain axis, a * {@link NumberAxis} as the range axis, and a {@link XYAreaRenderer} as * the renderer. * * @param title the chart title ({@code null} permitted). * @param xAxisLabel a label for the X-axis ({@code null} permitted). * @param yAxisLabel a label for the Y-axis ({@code null} permitted). * @param dataset the dataset for the chart ({@code null} permitted). * @param orientation the plot orientation (horizontal or vertical) * ({@code null} NOT permitted). * @param legend a flag specifying whether or not a legend is required. * @param tooltips configure chart to generate tool tips? * @param urls configure chart to generate URLs? * * @return An XY area chart. */ public static JFreeChart createXYAreaChart(String title, String xAxisLabel, String yAxisLabel, XYDataset dataset, PlotOrientation orientation, boolean legend, boolean tooltips, boolean urls) { Args.nullNotPermitted(orientation, "orientation"); NumberAxis xAxis = new NumberAxis(xAxisLabel); xAxis.setAutoRangeIncludesZero(false); NumberAxis yAxis = new NumberAxis(yAxisLabel); XYPlot plot = new XYPlot(dataset, xAxis, yAxis, null); plot.setOrientation(orientation); plot.setForegroundAlpha(0.5f); XYToolTipGenerator tipGenerator = null; if (tooltips) { tipGenerator = new StandardXYToolTipGenerator(); } XYURLGenerator urlGenerator = null; if (urls) { urlGenerator = new StandardXYURLGenerator(); } plot.setRenderer(new XYAreaRenderer(XYAreaRenderer.AREA, tipGenerator, urlGenerator)); JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, legend); currentTheme.apply(chart); return chart; } /** * Creates a stacked XY area plot. The chart object returned by this * method uses an {@link XYPlot} instance as the plot, with a * {@link NumberAxis} for the domain axis, a {@link NumberAxis} as the * range axis, and a {@link StackedXYAreaRenderer2} as the renderer. * * @param title the chart title ({@code null} permitted). * @param xAxisLabel a label for the X-axis ({@code null} permitted). * @param yAxisLabel a label for the Y-axis ({@code null} permitted). * @param dataset the dataset for the chart ({@code null} permitted). * * @return A stacked XY area chart. */ public static JFreeChart createStackedXYAreaChart(String title, String xAxisLabel, String yAxisLabel, TableXYDataset dataset) { return createStackedXYAreaChart(title, xAxisLabel, yAxisLabel, dataset, PlotOrientation.VERTICAL, true, true, false); } /** * Creates a stacked XY area plot. The chart object returned by this * method uses an {@link XYPlot} instance as the plot, with a * {@link NumberAxis} for the domain axis, a {@link NumberAxis} as the * range axis, and a {@link StackedXYAreaRenderer2} as the renderer. * * @param title the chart title ({@code null} permitted). * @param xAxisLabel a label for the X-axis ({@code null} permitted). * @param yAxisLabel a label for the Y-axis ({@code null} permitted). * @param dataset the dataset for the chart ({@code null} permitted). * @param orientation the plot orientation (horizontal or vertical) * ({@code null} NOT permitted). * @param legend a flag specifying whether or not a legend is required. * @param tooltips configure chart to generate tool tips? * @param urls configure chart to generate URLs? * * @return A stacked XY area chart. */ public static JFreeChart createStackedXYAreaChart(String title, String xAxisLabel, String yAxisLabel, TableXYDataset dataset, PlotOrientation orientation, boolean legend, boolean tooltips, boolean urls) { Args.nullNotPermitted(orientation, "orientation"); NumberAxis xAxis = new NumberAxis(xAxisLabel); xAxis.setAutoRangeIncludesZero(false); xAxis.setLowerMargin(0.0); xAxis.setUpperMargin(0.0); NumberAxis yAxis = new NumberAxis(yAxisLabel); XYToolTipGenerator toolTipGenerator = null; if (tooltips) { toolTipGenerator = new StandardXYToolTipGenerator(); } XYURLGenerator urlGenerator = null; if (urls) { urlGenerator = new StandardXYURLGenerator(); } StackedXYAreaRenderer2 renderer = new StackedXYAreaRenderer2( toolTipGenerator, urlGenerator); renderer.setOutline(true); XYPlot plot = new XYPlot(dataset, xAxis, yAxis, renderer); plot.setOrientation(orientation); plot.setRangeAxis(yAxis); // forces recalculation of the axis range JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, legend); currentTheme.apply(chart); return chart; } /** * Creates a line chart (based on an {@link XYDataset}) with default * settings. * * @param title the chart title ({@code null} permitted). * @param xAxisLabel a label for the X-axis ({@code null} permitted). * @param yAxisLabel a label for the Y-axis ({@code null} permitted). * @param dataset the dataset for the chart ({@code null} permitted). * * @return The chart. */ public static JFreeChart createXYLineChart(String title, String xAxisLabel, String yAxisLabel, XYDataset dataset) { return createXYLineChart(title, xAxisLabel, yAxisLabel, dataset, PlotOrientation.VERTICAL, true, true, false); } /** * Creates a line chart (based on an {@link XYDataset}) with default * settings. * * @param title the chart title ({@code null} permitted). * @param xAxisLabel a label for the X-axis ({@code null} permitted). * @param yAxisLabel a label for the Y-axis ({@code null} permitted). * @param dataset the dataset for the chart ({@code null} permitted). * @param orientation the plot orientation (horizontal or vertical) * ({@code null} NOT permitted). * @param legend a flag specifying whether or not a legend is required. * @param tooltips configure chart to generate tool tips? * @param urls configure chart to generate URLs? * * @return The chart. */ public static JFreeChart createXYLineChart(String title, String xAxisLabel, String yAxisLabel, XYDataset dataset, PlotOrientation orientation, boolean legend, boolean tooltips, boolean urls) { Args.nullNotPermitted(orientation, "orientation"); NumberAxis xAxis = new NumberAxis(xAxisLabel); xAxis.setAutoRangeIncludesZero(false); NumberAxis yAxis = new NumberAxis(yAxisLabel); XYItemRenderer renderer = new XYLineAndShapeRenderer(true, false); XYPlot plot = new XYPlot(dataset, xAxis, yAxis, renderer); plot.setOrientation(orientation); if (tooltips) { renderer.setDefaultToolTipGenerator(new StandardXYToolTipGenerator()); } if (urls) { renderer.setURLGenerator(new StandardXYURLGenerator()); } JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, legend); currentTheme.apply(chart); return chart; } /** * Creates a stepped XY plot with default settings. * * @param title the chart title ({@code null} permitted). * @param xAxisLabel a label for the X-axis ({@code null} permitted). * @param yAxisLabel a label for the Y-axis ({@code null} permitted). * @param dataset the dataset for the chart ({@code null} permitted). * * @return A chart. */ public static JFreeChart createXYStepChart(String title, String xAxisLabel, String yAxisLabel, XYDataset dataset) { return createXYStepChart(title, xAxisLabel, yAxisLabel, dataset, PlotOrientation.VERTICAL, true, true, false); } /** * Creates a stepped XY plot with default settings. * * @param title the chart title ({@code null} permitted). * @param xAxisLabel a label for the X-axis ({@code null} permitted). * @param yAxisLabel a label for the Y-axis ({@code null} permitted). * @param dataset the dataset for the chart ({@code null} permitted). * @param orientation the plot orientation (horizontal or vertical) * ({@code null} NOT permitted). * @param legend a flag specifying whether or not a legend is required. * @param tooltips configure chart to generate tool tips? * @param urls configure chart to generate URLs? * * @return A chart. */ public static JFreeChart createXYStepChart(String title, String xAxisLabel, String yAxisLabel, XYDataset dataset, PlotOrientation orientation, boolean legend, boolean tooltips, boolean urls) { Args.nullNotPermitted(orientation, "orientation"); DateAxis xAxis = new DateAxis(xAxisLabel); NumberAxis yAxis = new NumberAxis(yAxisLabel); yAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); XYToolTipGenerator toolTipGenerator = null; if (tooltips) { toolTipGenerator = new StandardXYToolTipGenerator(); } XYURLGenerator urlGenerator = null; if (urls) { urlGenerator = new StandardXYURLGenerator(); } XYItemRenderer renderer = new XYStepRenderer(toolTipGenerator, urlGenerator); XYPlot plot = new XYPlot(dataset, xAxis, yAxis, null); plot.setRenderer(renderer); plot.setOrientation(orientation); plot.setDomainCrosshairVisible(false); plot.setRangeCrosshairVisible(false); JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, legend); currentTheme.apply(chart); return chart; } /** * Creates a filled stepped XY plot with default settings. * * @param title the chart title ({@code null} permitted). * @param xAxisLabel a label for the X-axis ({@code null} permitted). * @param yAxisLabel a label for the Y-axis ({@code null} permitted). * @param dataset the dataset for the chart ({@code null} permitted). * * @return A chart. */ public static JFreeChart createXYStepAreaChart(String title, String xAxisLabel, String yAxisLabel, XYDataset dataset) { return createXYStepAreaChart(title, xAxisLabel, yAxisLabel, dataset, PlotOrientation.VERTICAL, true, true, false); } /** * Creates a filled stepped XY plot with default settings. * * @param title the chart title ({@code null} permitted). * @param xAxisLabel a label for the X-axis ({@code null} permitted). * @param yAxisLabel a label for the Y-axis ({@code null} permitted). * @param dataset the dataset for the chart ({@code null} permitted). * @param orientation the plot orientation (horizontal or vertical) * ({@code null} NOT permitted). * @param legend a flag specifying whether or not a legend is required. * @param tooltips configure chart to generate tool tips? * @param urls configure chart to generate URLs? * * @return A chart. */ public static JFreeChart createXYStepAreaChart(String title, String xAxisLabel, String yAxisLabel, XYDataset dataset, PlotOrientation orientation, boolean legend, boolean tooltips, boolean urls) { Args.nullNotPermitted(orientation, "orientation"); NumberAxis xAxis = new NumberAxis(xAxisLabel); xAxis.setAutoRangeIncludesZero(false); NumberAxis yAxis = new NumberAxis(yAxisLabel); XYToolTipGenerator toolTipGenerator = null; if (tooltips) { toolTipGenerator = new StandardXYToolTipGenerator(); } XYURLGenerator urlGenerator = null; if (urls) { urlGenerator = new StandardXYURLGenerator(); } XYItemRenderer renderer = new XYStepAreaRenderer( XYStepAreaRenderer.AREA_AND_SHAPES, toolTipGenerator, urlGenerator); XYPlot plot = new XYPlot(dataset, xAxis, yAxis, null); plot.setRenderer(renderer); plot.setOrientation(orientation); plot.setDomainCrosshairVisible(false); plot.setRangeCrosshairVisible(false); JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, legend); currentTheme.apply(chart); return chart; } /** * Creates and returns a time series chart. A time series chart is an * {@link XYPlot} with a {@link DateAxis} for the x-axis and a * {@link NumberAxis} for the y-axis. The default renderer is an * {@link XYLineAndShapeRenderer}. *
* A convenient dataset to use with this chart is a * {@link org.jfree.data.time.TimeSeriesCollection}. * * @param title the chart title ({@code null} permitted). * @param timeAxisLabel a label for the time axis ({@code null} * permitted). * @param valueAxisLabel a label for the value axis ({@code null} * permitted). * @param dataset the dataset for the chart ({@code null} permitted). * * @return A time series chart. */ public static JFreeChart createTimeSeriesChart(String title, String timeAxisLabel, String valueAxisLabel, XYDataset dataset) { return createTimeSeriesChart(title, timeAxisLabel, valueAxisLabel, dataset, true, true, false); } /** * Creates and returns a time series chart. A time series chart is an * {@link XYPlot} with a {@link DateAxis} for the x-axis and a * {@link NumberAxis} for the y-axis. The default renderer is an * {@link XYLineAndShapeRenderer}. *
* A convenient dataset to use with this chart is a * {@link org.jfree.data.time.TimeSeriesCollection}. * * @param title the chart title ({@code null} permitted). * @param timeAxisLabel a label for the time axis ({@code null} * permitted). * @param valueAxisLabel a label for the value axis ({@code null} * permitted). * @param dataset the dataset for the chart ({@code null} permitted). * @param legend a flag specifying whether or not a legend is required. * @param tooltips configure chart to generate tool tips? * @param urls configure chart to generate URLs? * * @return A time series chart. */ public static JFreeChart createTimeSeriesChart(String title, String timeAxisLabel, String valueAxisLabel, XYDataset dataset, boolean legend, boolean tooltips, boolean urls) { ValueAxis timeAxis = new DateAxis(timeAxisLabel); timeAxis.setLowerMargin(0.02); // reduce the default margins timeAxis.setUpperMargin(0.02); NumberAxis valueAxis = new NumberAxis(valueAxisLabel); valueAxis.setAutoRangeIncludesZero(false); // override default XYPlot plot = new XYPlot(dataset, timeAxis, valueAxis, null); XYToolTipGenerator toolTipGenerator = null; if (tooltips) { toolTipGenerator = StandardXYToolTipGenerator.getTimeSeriesInstance(); } XYURLGenerator urlGenerator = null; if (urls) { urlGenerator = new StandardXYURLGenerator(); } XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer(true, false); renderer.setDefaultToolTipGenerator(toolTipGenerator); renderer.setURLGenerator(urlGenerator); plot.setRenderer(renderer); JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, legend); currentTheme.apply(chart); return chart; } /** * Creates and returns a default instance of a candlesticks chart. * * @param title the chart title ({@code null} permitted). * @param timeAxisLabel a label for the time axis ({@code null} * permitted). * @param valueAxisLabel a label for the value axis ({@code null} * permitted). * @param dataset the dataset for the chart ({@code null} permitted). * @param legend a flag specifying whether or not a legend is required. * * @return A candlestick chart. */ public static JFreeChart createCandlestickChart(String title, String timeAxisLabel, String valueAxisLabel, OHLCDataset dataset, boolean legend) { ValueAxis timeAxis = new DateAxis(timeAxisLabel); NumberAxis valueAxis = new NumberAxis(valueAxisLabel); XYPlot plot = new XYPlot(dataset, timeAxis, valueAxis, null); plot.setRenderer(new CandlestickRenderer()); JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, legend); currentTheme.apply(chart); return chart; } /** * Creates and returns a default instance of a high-low-open-close chart. * * @param title the chart title ({@code null} permitted). * @param timeAxisLabel a label for the time axis ({@code null} * permitted). * @param valueAxisLabel a label for the value axis ({@code null} * permitted). * @param dataset the dataset for the chart ({@code null} permitted). * @param legend a flag specifying whether or not a legend is required. * * @return A high-low-open-close chart. */ public static JFreeChart createHighLowChart(String title, String timeAxisLabel, String valueAxisLabel, OHLCDataset dataset, boolean legend) { ValueAxis timeAxis = new DateAxis(timeAxisLabel); NumberAxis valueAxis = new NumberAxis(valueAxisLabel); HighLowRenderer renderer = new HighLowRenderer(); renderer.setDefaultToolTipGenerator(new HighLowItemLabelGenerator()); XYPlot plot = new XYPlot(dataset, timeAxis, valueAxis, renderer); JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, legend); currentTheme.apply(chart); return chart; } /** * Creates a bubble chart with default settings. The chart is composed of * an {@link XYPlot}, with a {@link NumberAxis} for the domain axis, * a {@link NumberAxis} for the range axis, and an {@link XYBubbleRenderer} * to draw the data items. * * @param title the chart title ({@code null} permitted). * @param xAxisLabel a label for the X-axis ({@code null} permitted). * @param yAxisLabel a label for the Y-axis ({@code null} permitted). * @param dataset the dataset for the chart ({@code null} permitted). * * @return A bubble chart. */ public static JFreeChart createBubbleChart(String title, String xAxisLabel, String yAxisLabel, XYZDataset dataset) { return createBubbleChart(title, xAxisLabel, yAxisLabel, dataset, PlotOrientation.VERTICAL, true, true, false); } /** * Creates a bubble chart with default settings. The chart is composed of * an {@link XYPlot}, with a {@link NumberAxis} for the domain axis, * a {@link NumberAxis} for the range axis, and an {@link XYBubbleRenderer} * to draw the data items. * * @param title the chart title ({@code null} permitted). * @param xAxisLabel a label for the X-axis ({@code null} permitted). * @param yAxisLabel a label for the Y-axis ({@code null} permitted). * @param dataset the dataset for the chart ({@code null} permitted). * @param orientation the orientation (horizontal or vertical) * ({@code null} NOT permitted). * @param legend a flag specifying whether or not a legend is required. * @param tooltips configure chart to generate tool tips? * @param urls configure chart to generate URLs? * * @return A bubble chart. */ public static JFreeChart createBubbleChart(String title, String xAxisLabel, String yAxisLabel, XYZDataset dataset, PlotOrientation orientation, boolean legend, boolean tooltips, boolean urls) { Args.nullNotPermitted(orientation, "orientation"); NumberAxis xAxis = new NumberAxis(xAxisLabel); xAxis.setAutoRangeIncludesZero(false); NumberAxis yAxis = new NumberAxis(yAxisLabel); yAxis.setAutoRangeIncludesZero(false); XYPlot plot = new XYPlot(dataset, xAxis, yAxis, null); XYItemRenderer renderer = new XYBubbleRenderer( XYBubbleRenderer.SCALE_ON_RANGE_AXIS); if (tooltips) { renderer.setDefaultToolTipGenerator(new StandardXYZToolTipGenerator()); } if (urls) { renderer.setURLGenerator(new StandardXYZURLGenerator()); } plot.setRenderer(renderer); plot.setOrientation(orientation); JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, legend); currentTheme.apply(chart); return chart; } /** * Creates a histogram chart. This chart is constructed with an * {@link XYPlot} using an {@link XYBarRenderer}. The domain and range * axes are {@link NumberAxis} instances. * * @param title the chart title ({@code null} permitted). * @param xAxisLabel the x axis label ({@code null} permitted). * @param yAxisLabel the y axis label ({@code null} permitted). * @param dataset the dataset ({@code null} permitted). * * @return A chart. */ public static JFreeChart createHistogram(String title, String xAxisLabel, String yAxisLabel, IntervalXYDataset dataset) { return createHistogram(title, xAxisLabel, yAxisLabel, dataset, PlotOrientation.VERTICAL, true, true, false); } /** * Creates a histogram chart. This chart is constructed with an * {@link XYPlot} using an {@link XYBarRenderer}. The domain and range * axes are {@link NumberAxis} instances. * * @param title the chart title ({@code null} permitted). * @param xAxisLabel the x axis label ({@code null} permitted). * @param yAxisLabel the y axis label ({@code null} permitted). * @param dataset the dataset ({@code null} permitted). * @param orientation the orientation (horizontal or vertical) * ({@code null} NOT permitted). * @param legend create a legend? * @param tooltips display tooltips? * @param urls generate URLs? * * @return The chart. */ public static JFreeChart createHistogram(String title, String xAxisLabel, String yAxisLabel, IntervalXYDataset dataset, PlotOrientation orientation, boolean legend, boolean tooltips, boolean urls) { Args.nullNotPermitted(orientation, "orientation"); NumberAxis xAxis = new NumberAxis(xAxisLabel); xAxis.setAutoRangeIncludesZero(false); ValueAxis yAxis = new NumberAxis(yAxisLabel); XYItemRenderer renderer = new XYBarRenderer(); if (tooltips) { renderer.setDefaultToolTipGenerator(new StandardXYToolTipGenerator()); } if (urls) { renderer.setURLGenerator(new StandardXYURLGenerator()); } XYPlot plot = new XYPlot(dataset, xAxis, yAxis, renderer); plot.setOrientation(orientation); plot.setDomainZeroBaselineVisible(true); plot.setRangeZeroBaselineVisible(true); JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, legend); currentTheme.apply(chart); return chart; } /** * Creates and returns a default instance of a box and whisker chart * based on data from a {@link BoxAndWhiskerCategoryDataset}. * * @param title the chart title ({@code null} permitted). * @param categoryAxisLabel a label for the category axis * ({@code null} permitted). * @param valueAxisLabel a label for the value axis ({@code null} * permitted). * @param dataset the dataset for the chart ({@code null} permitted). * @param legend a flag specifying whether or not a legend is required. * * @return A box and whisker chart. */ public static JFreeChart createBoxAndWhiskerChart(String title, String categoryAxisLabel, String valueAxisLabel, BoxAndWhiskerCategoryDataset dataset, boolean legend) { CategoryAxis categoryAxis = new CategoryAxis(categoryAxisLabel); NumberAxis valueAxis = new NumberAxis(valueAxisLabel); valueAxis.setAutoRangeIncludesZero(false); BoxAndWhiskerRenderer renderer = new BoxAndWhiskerRenderer(); renderer.setDefaultToolTipGenerator(new BoxAndWhiskerToolTipGenerator()); CategoryPlot plot = new CategoryPlot(dataset, categoryAxis, valueAxis, renderer); JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, legend); currentTheme.apply(chart); return chart; } /** * Creates and returns a default instance of a box and whisker chart. * * @param title the chart title ({@code null} permitted). * @param timeAxisLabel a label for the time axis ({@code null} * permitted). * @param valueAxisLabel a label for the value axis ({@code null} * permitted). * @param dataset the dataset for the chart ({@code null} permitted). * @param legend a flag specifying whether or not a legend is required. * * @return A box and whisker chart. */ public static JFreeChart createBoxAndWhiskerChart(String title, String timeAxisLabel, String valueAxisLabel, BoxAndWhiskerXYDataset dataset, boolean legend) { ValueAxis timeAxis = new DateAxis(timeAxisLabel); NumberAxis valueAxis = new NumberAxis(valueAxisLabel); valueAxis.setAutoRangeIncludesZero(false); XYBoxAndWhiskerRenderer renderer = new XYBoxAndWhiskerRenderer(10.0); XYPlot plot = new XYPlot(dataset, timeAxis, valueAxis, renderer); JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, legend); currentTheme.apply(chart); return chart; } /** * Creates a wind plot with default settings. * * @param title the chart title ({@code null} permitted). * @param xAxisLabel a label for the x-axis ({@code null} permitted). * @param yAxisLabel a label for the y-axis ({@code null} permitted). * @param dataset the dataset for the chart ({@code null} permitted). * @param legend a flag that controls whether or not a legend is created. * @param tooltips configure chart to generate tool tips? * @param urls configure chart to generate URLs? * * @return A wind plot. * */ public static JFreeChart createWindPlot(String title, String xAxisLabel, String yAxisLabel, WindDataset dataset, boolean legend, boolean tooltips, boolean urls) { ValueAxis xAxis = new DateAxis(xAxisLabel); ValueAxis yAxis = new NumberAxis(yAxisLabel); yAxis.setRange(-12.0, 12.0); WindItemRenderer renderer = new WindItemRenderer(); if (tooltips) { renderer.setDefaultToolTipGenerator(new StandardXYToolTipGenerator()); } if (urls) { renderer.setURLGenerator(new StandardXYURLGenerator()); } XYPlot plot = new XYPlot(dataset, xAxis, yAxis, renderer); JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, legend); currentTheme.apply(chart); return chart; } /** * Creates a wafer map chart. * * @param title the chart title ({@code null} permitted). * @param dataset the dataset ({@code null} permitted). * @param orientation the plot orientation (horizontal or vertical) * ({@code null} NOT permitted. * @param legend display a legend? * @param tooltips generate tooltips? * @param urls generate URLs? * * @return A wafer map chart. */ public static JFreeChart createWaferMapChart(String title, WaferMapDataset dataset, PlotOrientation orientation, boolean legend, boolean tooltips, boolean urls) { Args.nullNotPermitted(orientation, "orientation"); WaferMapPlot plot = new WaferMapPlot(dataset); WaferMapRenderer renderer = new WaferMapRenderer(); plot.setRenderer(renderer); JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, legend); currentTheme.apply(chart); return chart; } } jfree-jfreechart-cb8ff67/src/main/java/org/jfree/chart/ChartFrame.java 0000664 0000000 0000000 00000005406 14636042355 0025742 0 ustar 00root root 0000000 0000000 /* =========================================================== * JFreeChart : a free chart library for the Java(tm) platform * =========================================================== * * (C) Copyright 2000-present, by David Gilbert and Contributors. * * Project Info: http://www.jfree.org/jfreechart/index.html * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * --------------- * ChartFrame.java * --------------- * (C) Copyright 2001-present, by David Gilbert and Contributors. * * Original Author: David Gilbert; * Contributor(s): -; * */ package org.jfree.chart; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.WindowConstants; /** * A frame for displaying a chart. */ public class ChartFrame extends JFrame { /** The chart panel. */ private final ChartPanel chartPanel; /** * Constructs a frame for a chart. * * @param title the frame title. * @param chart the chart. */ public ChartFrame(String title, JFreeChart chart) { this(title, chart, false); } /** * Constructs a frame for a chart. * * @param title the frame title. * @param chart the chart. * @param scrollPane if {@code true}, put the Chart(Panel) into a * JScrollPane. */ public ChartFrame(String title, JFreeChart chart, boolean scrollPane) { super(title); setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); this.chartPanel = new ChartPanel(chart); if (scrollPane) { setContentPane(new JScrollPane(this.chartPanel)); } else { setContentPane(this.chartPanel); } } /** * Returns the chart panel for the frame. * * @return The chart panel. */ public ChartPanel getChartPanel() { return this.chartPanel; } } jfree-jfreechart-cb8ff67/src/main/java/org/jfree/chart/ChartHints.java 0000664 0000000 0000000 00000006602 14636042355 0025774 0 ustar 00root root 0000000 0000000 /* =========================================================== * JFreeChart : a free chart library for the Java(tm) platform * =========================================================== * * (C) Copyright 2000-present, by David Gilbert and Contributors. * * Project Info: http://www.jfree.org/jfreechart/index.html * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * --------------- * ChartHints.java * --------------- * (C) Copyright 2014-present, by David Gilbert and Contributors. * * Original Author: David Gilbert; * Contributor(s): -; * */ package org.jfree.chart; import java.util.Map; /** * Special rendering hints that can be used internally by JFreeChart or by * specialised implementations of the {@code Graphics2D} API. For example, * JFreeSVG's {@code SVGGraphics2D} class, will use the * {@code KEY_BEGIN_ELEMENT} and {@code KEY_END_ELEMENT} hints to drive the * output content. */ public final class ChartHints { private ChartHints() { // no need to instantiate this } /** * The key for a hint to signal the beginning of an element. The value * should be a string containing the element id or, alternatively, a Map * containing the 'id' (String) and 'ref' (String in JSON format). */ public static final Key KEY_BEGIN_ELEMENT = new ChartHints.Key(0); /** * The key for a hint that ends an element. */ public static final Key KEY_END_ELEMENT = new ChartHints.Key(1); /** * A key for rendering hints that can be used with JFreeChart (in * addition to the regular Java2D rendering hints). */ public static class Key extends java.awt.RenderingHints.Key { /** * Creates a new key. * * @param privateKey the private key. */ public Key(int privateKey) { super(privateKey); } /** * Returns {@code true} if {@code val} is a value that is * compatible with this key, and {@code false} otherwise. * * @param val the value. * * @return A boolean. */ @Override public boolean isCompatibleValue(Object val) { switch (intKey()) { case 0: return val == null || val instanceof String || val instanceof Map; case 1: return val == null || val instanceof Object; default: throw new RuntimeException("Not possible!"); } } } } jfree-jfreechart-cb8ff67/src/main/java/org/jfree/chart/ChartMouseEvent.java 0000664 0000000 0000000 00000006614 14636042355 0027004 0 ustar 00root root 0000000 0000000 /* =========================================================== * JFreeChart : a free chart library for the Java(tm) platform * =========================================================== * * (C) Copyright 2000-present, by David Gilbert and Contributors. * * Project Info: http://www.jfree.org/jfreechart/index.html * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * -------------------- * ChartMouseEvent.java * -------------------- * (C) Copyright 2002-present, by David Gilbert and Contributors. * * Original Author: David Gilbert; * Contributor(s): Alex Weber; * */ package org.jfree.chart; import java.awt.event.MouseEvent; import java.io.Serializable; import java.util.EventObject; import org.jfree.chart.entity.ChartEntity; /** * A mouse event for a chart that is displayed in a {@link ChartPanel}. * * @see ChartMouseListener */ public class ChartMouseEvent extends EventObject implements Serializable { /** For serialization. */ private static final long serialVersionUID = -682393837314562149L; /** The chart that the mouse event relates to. */ private final JFreeChart chart; /** The Java mouse event that triggered this event. */ private final MouseEvent trigger; /** The chart entity (if any). */ private final ChartEntity entity; /** * Constructs a new event. * * @param chart the source chart ({@code null} not permitted). * @param trigger the mouse event that triggered this event * ({@code null} not permitted). * @param entity the chart entity (if any) under the mouse point * ({@code null} permitted). */ public ChartMouseEvent(JFreeChart chart, MouseEvent trigger, ChartEntity entity) { super(chart); this.chart = chart; this.trigger = trigger; this.entity = entity; } /** * Returns the chart that the mouse event relates to. * * @return The chart (never {@code null}). */ public JFreeChart getChart() { return this.chart; } /** * Returns the mouse event that triggered this event. * * @return The event (never {@code null}). */ public MouseEvent getTrigger() { return this.trigger; } /** * Returns the chart entity (if any) under the mouse point. * * @return The chart entity (possibly {@code null}). */ public ChartEntity getEntity() { return this.entity; } } jfree-jfreechart-cb8ff67/src/main/java/org/jfree/chart/ChartMouseListener.java 0000664 0000000 0000000 00000004324 14636042355 0027504 0 ustar 00root root 0000000 0000000 /* =========================================================== * JFreeChart : a free chart library for the Java(tm) platform * =========================================================== * * (C) Copyright 2000-present, by David Gilbert and Contributors. * * Project Info: http://www.jfree.org/jfreechart/index.html * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * ----------------------- * ChartMouseListener.java * ----------------------- * (C) Copyright 2002-present, by David Gilbert and Contributors. * * Original Author: David Gilbert; * Contributor(s): Alex Weber; * */ package org.jfree.chart; import java.util.EventListener; /** * The interface that must be implemented by classes that wish to receive * {@link ChartMouseEvent} notifications from a {@link ChartPanel}. * * @see ChartPanel#addChartMouseListener(ChartMouseListener) */ public interface ChartMouseListener extends EventListener { /** * Callback method for receiving notification of a mouse click on a chart. * * @param event information about the event. */ void chartMouseClicked(ChartMouseEvent event); /** * Callback method for receiving notification of a mouse movement on a * chart. * * @param event information about the event. */ void chartMouseMoved(ChartMouseEvent event); } jfree-jfreechart-cb8ff67/src/main/java/org/jfree/chart/ChartPanel.java 0000664 0000000 0000000 00000336676 14636042355 0025767 0 ustar 00root root 0000000 0000000 /* =========================================================== * JFreeChart : a free chart library for the Java(tm) platform * =========================================================== * * (C) Copyright 2000-present, by David Gilbert and Contributors. * * Project Info: http://www.jfree.org/jfreechart/index.html * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * --------------- * ChartPanel.java * --------------- * (C) Copyright 2000-present, by David Gilbert and Contributors. * * Original Author: David Gilbert; * Contributor(s): Andrzej Porebski; * Soren Caspersen; * Jonathan Nash; * Hans-Jurgen Greiner; * Andreas Schneider; * Daniel van Enckevort; * David M O'Donnell; * Arnaud Lelievre; * Matthias Rose; * Onno vd Akker; * Sergei Ivanov; * Ulrich Voigt - patch 2686040; * Alessandro Borges - patch 1460845; * Martin Hoeller; * Simon Legner - patch from bug 1129; * Yuri Blankenstein; */ package org.jfree.chart; import java.awt.AWTEvent; import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Composite; import java.awt.Cursor; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GraphicsConfiguration; import java.awt.Insets; import java.awt.Paint; import java.awt.Point; import java.awt.Rectangle; import java.awt.Toolkit; import java.awt.Transparency; import java.awt.datatransfer.Clipboard; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.InputEvent; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.awt.geom.AffineTransform; import java.awt.geom.Line2D; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.awt.print.PageFormat; import java.awt.print.Printable; import java.awt.print.PrinterException; import java.awt.print.PrinterJob; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.EventListener; import java.util.List; import java.util.ResourceBundle; import javax.swing.JFileChooser; import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.SwingUtilities; import javax.swing.ToolTipManager; import javax.swing.event.EventListenerList; import javax.swing.filechooser.FileNameExtensionFilter; import org.jfree.chart.editor.ChartEditor; import org.jfree.chart.editor.ChartEditorManager; import org.jfree.chart.entity.ChartEntity; import org.jfree.chart.entity.EntityCollection; import org.jfree.chart.event.ChartChangeEvent; import org.jfree.chart.event.ChartChangeListener; import org.jfree.chart.event.ChartProgressEvent; import org.jfree.chart.event.ChartProgressListener; import org.jfree.chart.event.OverlayChangeEvent; import org.jfree.chart.event.OverlayChangeListener; import org.jfree.chart.panel.Overlay; import org.jfree.chart.plot.Pannable; import org.jfree.chart.plot.Plot; import org.jfree.chart.plot.PlotOrientation; import org.jfree.chart.plot.PlotRenderingInfo; import org.jfree.chart.plot.Zoomable; import org.jfree.chart.util.Args; import org.jfree.chart.util.ResourceBundleWrapper; import org.jfree.chart.util.SerialUtils; /** * A Swing GUI component for displaying a {@link JFreeChart} object. *
* The panel registers with the chart to receive notification of changes to any
* component of the chart. The chart is redrawn automatically whenever this
* notification is received.
*/
public class ChartPanel extends JPanel implements ChartChangeListener,
ChartProgressListener, ActionListener, MouseListener,
MouseMotionListener, OverlayChangeListener, Printable, Serializable {
/** For serialization. */
private static final long serialVersionUID = 6046366297214274674L;
/**
* Default setting for buffer usage. The default has been changed to
* {@code true} from version 1.0.13 onwards, because of a severe
* performance problem with drawing the zoom rectangle using XOR (which
* now happens only when the buffer is NOT used).
*/
public static final boolean DEFAULT_BUFFER_USED = true;
/** The default panel width. */
public static final int DEFAULT_WIDTH = 1024;
/** The default panel height. */
public static final int DEFAULT_HEIGHT = 768;
/** The default limit below which chart scaling kicks in. */
public static final int DEFAULT_MINIMUM_DRAW_WIDTH = 300;
/** The default limit below which chart scaling kicks in. */
public static final int DEFAULT_MINIMUM_DRAW_HEIGHT = 200;
/** The default limit above which chart scaling kicks in. */
public static final int DEFAULT_MAXIMUM_DRAW_WIDTH = 2048;
/** The default limit above which chart scaling kicks in. */
public static final int DEFAULT_MAXIMUM_DRAW_HEIGHT = 1536;
/** The minimum size required to perform a zoom on a rectangle */
public static final int DEFAULT_ZOOM_TRIGGER_DISTANCE = 10;
/** Properties action command. */
public static final String PROPERTIES_COMMAND = "PROPERTIES";
/**
* Copy action command.
*/
public static final String COPY_COMMAND = "COPY";
/** Save action command. */
public static final String SAVE_COMMAND = "SAVE";
/** Action command to save as PNG. */
private static final String SAVE_AS_PNG_COMMAND = "SAVE_AS_PNG";
/** Action command to save as SVG. */
private static final String SAVE_AS_SVG_COMMAND = "SAVE_AS_SVG";
/** Action command to save as PDF. */
private static final String SAVE_AS_PDF_COMMAND = "SAVE_AS_PDF";
/** Print action command. */
public static final String PRINT_COMMAND = "PRINT";
/** Zoom in (both axes) action command. */
public static final String ZOOM_IN_BOTH_COMMAND = "ZOOM_IN_BOTH";
/** Zoom in (domain axis only) action command. */
public static final String ZOOM_IN_DOMAIN_COMMAND = "ZOOM_IN_DOMAIN";
/** Zoom in (range axis only) action command. */
public static final String ZOOM_IN_RANGE_COMMAND = "ZOOM_IN_RANGE";
/** Zoom out (both axes) action command. */
public static final String ZOOM_OUT_BOTH_COMMAND = "ZOOM_OUT_BOTH";
/** Zoom out (domain axis only) action command. */
public static final String ZOOM_OUT_DOMAIN_COMMAND = "ZOOM_DOMAIN_BOTH";
/** Zoom out (range axis only) action command. */
public static final String ZOOM_OUT_RANGE_COMMAND = "ZOOM_RANGE_BOTH";
/** Zoom reset (both axes) action command. */
public static final String ZOOM_RESET_BOTH_COMMAND = "ZOOM_RESET_BOTH";
/** Zoom reset (domain axis only) action command. */
public static final String ZOOM_RESET_DOMAIN_COMMAND = "ZOOM_RESET_DOMAIN";
/** Zoom reset (range axis only) action command. */
public static final String ZOOM_RESET_RANGE_COMMAND = "ZOOM_RESET_RANGE";
/** The chart that is displayed in the panel. */
private JFreeChart chart;
/** Storage for registered (chart) mouse listeners. */
private transient EventListenerList chartMouseListeners;
/** A flag that controls whether the off-screen buffer is used. */
private final boolean useBuffer;
/** A flag that indicates that the buffer should be refreshed. */
private boolean refreshBuffer;
/** A buffer for the rendered chart. */
private transient BufferedImage chartBuffer;
/**
* The minimum width for drawing a chart (uses scaling for smaller widths).
*/
private int minimumDrawWidth;
/**
* The minimum height for drawing a chart (uses scaling for smaller
* heights).
*/
private int minimumDrawHeight;
/**
* The maximum width for drawing a chart (uses scaling for bigger
* widths).
*/
private int maximumDrawWidth;
/**
* The maximum height for drawing a chart (uses scaling for bigger
* heights).
*/
private int maximumDrawHeight;
/** The popup menu for the frame. */
private JPopupMenu popup;
/** The drawing info collected the last time the chart was drawn. */
private final ChartRenderingInfo info;
/** The chart anchor point. */
private Point2D anchor;
/** The scale factor used to draw the chart. */
private double scaleX;
/** The scale factor used to draw the chart. */
private double scaleY;
/** The plot orientation. */
private PlotOrientation orientation = PlotOrientation.VERTICAL;
/** A flag that controls whether or not domain zooming is enabled. */
private boolean domainZoomable = false;
/** A flag that controls whether or not range zooming is enabled. */
private boolean rangeZoomable = false;
/**
* The zoom rectangle starting point (selected by the user with a mouse
* click). This is a point on the screen, not the chart (which may have
* been scaled up or down to fit the panel).
*/
private Point2D zoomPoint = null;
/** The zoom rectangle (selected by the user with the mouse). */
private transient Rectangle2D zoomRectangle = null;
/** Controls if the zoom rectangle is drawn as an outline or filled. */
private boolean fillZoomRectangle = true;
/** The minimum distance required to drag the mouse to trigger a zoom. */
private int zoomTriggerDistance;
/** A flag that controls whether or not horizontal tracing is enabled. */
private boolean horizontalAxisTrace = false;
/** A flag that controls whether or not vertical tracing is enabled. */
private boolean verticalAxisTrace = false;
/** A vertical trace line. */
private transient Line2D verticalTraceLine;
/** A horizontal trace line. */
private transient Line2D horizontalTraceLine;
/** Menu item for zooming in on a chart (both axes). */
private JMenuItem zoomInBothMenuItem;
/** Menu item for zooming in on a chart (domain axis). */
private JMenuItem zoomInDomainMenuItem;
/** Menu item for zooming in on a chart (range axis). */
private JMenuItem zoomInRangeMenuItem;
/** Menu item for zooming out on a chart. */
private JMenuItem zoomOutBothMenuItem;
/** Menu item for zooming out on a chart (domain axis). */
private JMenuItem zoomOutDomainMenuItem;
/** Menu item for zooming out on a chart (range axis). */
private JMenuItem zoomOutRangeMenuItem;
/** Menu item for resetting the zoom (both axes). */
private JMenuItem zoomResetBothMenuItem;
/** Menu item for resetting the zoom (domain axis only). */
private JMenuItem zoomResetDomainMenuItem;
/** Menu item for resetting the zoom (range axis only). */
private JMenuItem zoomResetRangeMenuItem;
/**
* The default directory for saving charts to file.
*/
private File defaultDirectoryForSaveAs;
/** A flag that controls whether or not file extensions are enforced. */
private boolean enforceFileExtensions;
/** A flag that indicates if original tooltip delays are changed. */
private boolean ownToolTipDelaysActive;
/** Original initial tooltip delay of ToolTipManager.sharedInstance(). */
private int originalToolTipInitialDelay;
/** Original reshow tooltip delay of ToolTipManager.sharedInstance(). */
private int originalToolTipReshowDelay;
/** Original dismiss tooltip delay of ToolTipManager.sharedInstance(). */
private int originalToolTipDismissDelay;
/** Own initial tooltip delay to be used in this chart panel. */
private int ownToolTipInitialDelay;
/** Own reshow tooltip delay to be used in this chart panel. */
private int ownToolTipReshowDelay;
/** Own dismiss tooltip delay to be used in this chart panel. */
private int ownToolTipDismissDelay;
/** The factor used to zoom in on an axis range. */
private double zoomInFactor = 0.5;
/** The factor used to zoom out on an axis range. */
private double zoomOutFactor = 2.0;
/**
* A flag that controls whether zoom operations are centred on the
* current anchor point, or the centre point of the relevant axis.
*/
private boolean zoomAroundAnchor;
/**
* The paint used to draw the zoom rectangle outline.
*/
private transient Paint zoomOutlinePaint;
/**
* The zoom fill paint (should use transparency).
*/
private transient Paint zoomFillPaint;
/** The resourceBundle for the localization. */
protected static ResourceBundle localizationResources
= ResourceBundleWrapper.getBundle(
"org.jfree.chart.LocalizationBundle");
/**
* Temporary storage for the width and height of the chart
* drawing area during panning.
*/
private double panW, panH;
/** The last mouse position during panning. */
private Point panLast;
/**
* The mask for mouse events to trigger panning.
*/
private int panMask = InputEvent.CTRL_MASK;
/**
* A list of overlays for the panel.
*/
private final List
* If the width available on the panel is less than this, then the chart is
* drawn at the minimum width then scaled down to fit.
*
* @return The minimum drawing width.
*/
public int getMinimumDrawWidth() {
return this.minimumDrawWidth;
}
/**
* Sets the minimum drawing width for the chart on this panel.
*
* At the time the chart is drawn on the panel, if the available width is
* less than this amount, the chart will be drawn using the minimum width
* then scaled down to fit the available space.
*
* @param width The width.
*/
public void setMinimumDrawWidth(int width) {
this.minimumDrawWidth = width;
}
/**
* Returns the maximum drawing width for charts.
*
* If the width available on the panel is greater than this, then the chart
* is drawn at the maximum width then scaled up to fit.
*
* @return The maximum drawing width.
*/
public int getMaximumDrawWidth() {
return this.maximumDrawWidth;
}
/**
* Sets the maximum drawing width for the chart on this panel.
*
* At the time the chart is drawn on the panel, if the available width is
* greater than this amount, the chart will be drawn using the maximum
* width then scaled up to fit the available space.
*
* @param width The width.
*/
public void setMaximumDrawWidth(int width) {
this.maximumDrawWidth = width;
}
/**
* Returns the minimum drawing height for charts.
*
* If the height available on the panel is less than this, then the chart
* is drawn at the minimum height then scaled down to fit.
*
* @return The minimum drawing height.
*/
public int getMinimumDrawHeight() {
return this.minimumDrawHeight;
}
/**
* Sets the minimum drawing height for the chart on this panel.
*
* At the time the chart is drawn on the panel, if the available height is
* less than this amount, the chart will be drawn using the minimum height
* then scaled down to fit the available space.
*
* @param height The height.
*/
public void setMinimumDrawHeight(int height) {
this.minimumDrawHeight = height;
}
/**
* Returns the maximum drawing height for charts.
*
* If the height available on the panel is greater than this, then the
* chart is drawn at the maximum height then scaled up to fit.
*
* @return The maximum drawing height.
*/
public int getMaximumDrawHeight() {
return this.maximumDrawHeight;
}
/**
* Sets the maximum drawing height for the chart on this panel.
*
* At the time the chart is drawn on the panel, if the available height is
* greater than this amount, the chart will be drawn using the maximum
* height then scaled up to fit the available space.
*
* @param height The height.
*/
public void setMaximumDrawHeight(int height) {
this.maximumDrawHeight = height;
}
/**
* Returns the X scale factor for the chart. This will be 1.0 if no
* scaling has been used.
*
* @return The scale factor.
*/
public double getScaleX() {
return this.scaleX;
}
/**
* Returns the Y scale factory for the chart. This will be 1.0 if no
* scaling has been used.
*
* @return The scale factor.
*/
public double getScaleY() {
return this.scaleY;
}
/**
* Returns the anchor point.
*
* @return The anchor point (possibly {@code null}).
*/
public Point2D getAnchor() {
return this.anchor;
}
/**
* Sets the anchor point. This method is provided for the use of
* subclasses, not end users.
*
* @param anchor the anchor point ({@code null} permitted).
*/
protected void setAnchor(Point2D anchor) {
this.anchor = anchor;
}
/**
* Returns the popup menu.
*
* @return The popup menu.
*/
public JPopupMenu getPopupMenu() {
return this.popup;
}
/**
* Sets the popup menu for the panel.
*
* @param popup the popup menu ({@code null} permitted).
*/
public void setPopupMenu(JPopupMenu popup) {
this.popup = popup;
}
/**
* Returns the chart rendering info from the most recent chart redraw.
*
* @return The chart rendering info.
*/
public ChartRenderingInfo getChartRenderingInfo() {
return this.info;
}
/**
* A convenience method that switches on mouse-based zooming.
*
* @param flag {@code true} enables zooming and rectangle fill on
* zoom.
*/
public void setMouseZoomable(boolean flag) {
setMouseZoomable(flag, true);
}
/**
* A convenience method that switches on mouse-based zooming.
*
* @param flag {@code true} if zooming enabled
* @param fillRectangle {@code true} if zoom rectangle is filled,
* false if rectangle is shown as outline only.
*/
public void setMouseZoomable(boolean flag, boolean fillRectangle) {
setDomainZoomable(flag);
setRangeZoomable(flag);
setFillZoomRectangle(fillRectangle);
}
/**
* Returns the flag that determines whether or not zooming is enabled for
* the domain axis.
*
* @return A boolean.
*/
public boolean isDomainZoomable() {
return this.domainZoomable;
}
/**
* Sets the flag that controls whether zooming is enabled for the
* domain axis. A check is made to ensure that the current plot supports
* zooming for the domain values.
*
* @param flag {@code true} enables zooming if possible.
*/
public void setDomainZoomable(boolean flag) {
if (flag) {
Plot plot = this.chart.getPlot();
if (plot instanceof Zoomable) {
Zoomable z = (Zoomable) plot;
this.domainZoomable = z.isDomainZoomable();
}
} else {
this.domainZoomable = false;
}
}
/**
* Returns the flag that determines whether or not zooming is enabled for
* the range axis.
*
* @return A boolean.
*/
public boolean isRangeZoomable() {
return this.rangeZoomable;
}
/**
* A flag that controls mouse-based zooming on the vertical axis.
*
* @param flag {@code true} enables zooming.
*/
public void setRangeZoomable(boolean flag) {
if (flag) {
Plot plot = this.chart.getPlot();
if (plot instanceof Zoomable) {
Zoomable z = (Zoomable) plot;
this.rangeZoomable = z.isRangeZoomable();
}
} else {
this.rangeZoomable = false;
}
}
/**
* Returns the flag that controls whether or not the zoom rectangle is
* filled when drawn.
*
* @return A boolean.
*/
public boolean getFillZoomRectangle() {
return this.fillZoomRectangle;
}
/**
* A flag that controls how the zoom rectangle is drawn.
*
* @param flag {@code true} instructs to fill the rectangle on
* zoom, otherwise it will be outlined.
*/
public void setFillZoomRectangle(boolean flag) {
this.fillZoomRectangle = flag;
}
/**
* Returns the zoom trigger distance. This controls how far the mouse must
* move before a zoom action is triggered.
*
* @return The distance (in Java2D units).
*/
public int getZoomTriggerDistance() {
return this.zoomTriggerDistance;
}
/**
* Sets the zoom trigger distance. This controls how far the mouse must
* move before a zoom action is triggered.
*
* @param distance the distance (in Java2D units).
*/
public void setZoomTriggerDistance(int distance) {
this.zoomTriggerDistance = distance;
}
/**
* Returns the flag that controls whether or not a horizontal axis trace
* line is drawn over the plot area at the current mouse location.
*
* @return A boolean.
*/
public boolean getHorizontalAxisTrace() {
return this.horizontalAxisTrace;
}
/**
* A flag that controls trace lines on the horizontal axis.
*
* @param flag {@code true} enables trace lines for the mouse
* pointer on the horizontal axis.
*/
public void setHorizontalAxisTrace(boolean flag) {
this.horizontalAxisTrace = flag;
}
/**
* Returns the horizontal trace line.
*
* @return The horizontal trace line (possibly {@code null}).
*/
protected Line2D getHorizontalTraceLine() {
return this.horizontalTraceLine;
}
/**
* Sets the horizontal trace line.
*
* @param line the line ({@code null} permitted).
*/
protected void setHorizontalTraceLine(Line2D line) {
this.horizontalTraceLine = line;
}
/**
* Returns the flag that controls whether or not a vertical axis trace
* line is drawn over the plot area at the current mouse location.
*
* @return A boolean.
*/
public boolean getVerticalAxisTrace() {
return this.verticalAxisTrace;
}
/**
* A flag that controls trace lines on the vertical axis.
*
* @param flag {@code true} enables trace lines for the mouse
* pointer on the vertical axis.
*/
public void setVerticalAxisTrace(boolean flag) {
this.verticalAxisTrace = flag;
}
/**
* Returns the vertical trace line.
*
* @return The vertical trace line (possibly {@code null}).
*/
protected Line2D getVerticalTraceLine() {
return this.verticalTraceLine;
}
/**
* Sets the vertical trace line.
*
* @param line the line ({@code null} permitted).
*/
protected void setVerticalTraceLine(Line2D line) {
this.verticalTraceLine = line;
}
/**
* Returns the default directory for the "save as" option.
*
* @return The default directory (possibly {@code null}).
*/
public File getDefaultDirectoryForSaveAs() {
return this.defaultDirectoryForSaveAs;
}
/**
* Sets the default directory for the "save as" option. If you set this
* to {@code null}, the user's default directory will be used.
*
* @param directory the directory ({@code null} permitted).
*/
public void setDefaultDirectoryForSaveAs(File directory) {
if (directory != null) {
if (!directory.isDirectory()) {
throw new IllegalArgumentException(
"The 'directory' argument is not a directory.");
}
}
this.defaultDirectoryForSaveAs = directory;
}
/**
* Returns {@code true} if file extensions should be enforced, and
* {@code false} otherwise.
*
* @return The flag.
*
* @see #setEnforceFileExtensions(boolean)
*/
public boolean isEnforceFileExtensions() {
return this.enforceFileExtensions;
}
/**
* Sets a flag that controls whether or not file extensions are enforced.
*
* @param enforce the new flag value.
*
* @see #isEnforceFileExtensions()
*/
public void setEnforceFileExtensions(boolean enforce) {
this.enforceFileExtensions = enforce;
}
/**
* Returns the flag that controls whether or not zoom operations are
* centered around the current anchor point.
*
* @return A boolean.
*
* @see #setZoomAroundAnchor(boolean)
*/
public boolean getZoomAroundAnchor() {
return this.zoomAroundAnchor;
}
/**
* Sets the flag that controls whether or not zoom operations are
* centered around the current anchor point.
*
* @param zoomAroundAnchor the new flag value.
*
* @see #getZoomAroundAnchor()
*/
public void setZoomAroundAnchor(boolean zoomAroundAnchor) {
this.zoomAroundAnchor = zoomAroundAnchor;
}
/**
* Returns the zoom rectangle fill paint.
*
* @return The zoom rectangle fill paint (never {@code null}).
*
* @see #setZoomFillPaint(java.awt.Paint)
* @see #setFillZoomRectangle(boolean)
*/
public Paint getZoomFillPaint() {
return this.zoomFillPaint;
}
/**
* Sets the zoom rectangle fill paint.
*
* @param paint the paint ({@code null} not permitted).
*
* @see #getZoomFillPaint()
* @see #getFillZoomRectangle()
*/
public void setZoomFillPaint(Paint paint) {
Args.nullNotPermitted(paint, "paint");
this.zoomFillPaint = paint;
}
/**
* Returns the zoom rectangle outline paint.
*
* @return The zoom rectangle outline paint (never {@code null}).
*
* @see #setZoomOutlinePaint(java.awt.Paint)
* @see #setFillZoomRectangle(boolean)
*/
public Paint getZoomOutlinePaint() {
return this.zoomOutlinePaint;
}
/**
* Sets the zoom rectangle outline paint.
*
* @param paint the paint ({@code null} not permitted).
*
* @see #getZoomOutlinePaint()
* @see #getFillZoomRectangle()
*/
public void setZoomOutlinePaint(Paint paint) {
this.zoomOutlinePaint = paint;
}
/**
* The mouse wheel handler.
*/
private MouseWheelHandler mouseWheelHandler;
/**
* Returns {@code true} if the mouse wheel handler is enabled, and
* {@code false} otherwise.
*
* @return A boolean.
*/
public boolean isMouseWheelEnabled() {
return this.mouseWheelHandler != null;
}
/**
* Enables or disables mouse wheel support for the panel.
*
* @param flag a boolean.
*/
public void setMouseWheelEnabled(boolean flag) {
if (flag && this.mouseWheelHandler == null) {
this.mouseWheelHandler = new MouseWheelHandler(this);
}
else if (!flag && this.mouseWheelHandler != null) {
this.removeMouseWheelListener(this.mouseWheelHandler);
this.mouseWheelHandler = null;
}
}
/**
* Add an overlay to the panel.
*
* @param overlay the overlay ({@code null} not permitted).
*/
public void addOverlay(Overlay overlay) {
Args.nullNotPermitted(overlay, "overlay");
this.overlays.add(overlay);
overlay.addChangeListener(this);
repaint();
}
/**
* Removes an overlay from the panel.
*
* @param overlay the overlay to remove ({@code null} not permitted).
*/
public void removeOverlay(Overlay overlay) {
Args.nullNotPermitted(overlay, "overlay");
boolean removed = this.overlays.remove(overlay);
if (removed) {
overlay.removeChangeListener(this);
repaint();
}
}
/**
* Handles a change to an overlay by repainting the panel.
*
* @param event the event.
*/
@Override
public void overlayChanged(OverlayChangeEvent event) {
repaint();
}
/**
* Switches the display of tooltips for the panel on or off. Note that
* tooltips can only be displayed if the chart has been configured to
* generate tooltip items.
*
* @param flag {@code true} to enable tooltips, {@code false} to
* disable tooltips.
*/
public void setDisplayToolTips(boolean flag) {
if (flag) {
ToolTipManager.sharedInstance().registerComponent(this);
}
else {
ToolTipManager.sharedInstance().unregisterComponent(this);
}
}
/**
* Returns a string for the tooltip.
*
* @param e the mouse event.
*
* @return A tool tip or {@code null} if no tooltip is available.
*/
@Override
public String getToolTipText(MouseEvent e) {
String result = null;
if (this.info != null) {
EntityCollection entities = this.info.getEntityCollection();
if (entities != null) {
Insets insets = getInsets();
ChartEntity entity = entities.getEntity(
(int) ((e.getX() - insets.left) / this.scaleX),
(int) ((e.getY() - insets.top) / this.scaleY));
if (entity != null) {
result = entity.getToolTipText();
}
}
}
return result;
}
/**
* Translates a Java2D point on the chart to a screen location.
*
* @param java2DPoint the Java2D point.
*
* @return The screen location.
*/
public Point translateJava2DToScreen(Point2D java2DPoint) {
Insets insets = getInsets();
int x = (int) (java2DPoint.getX() * this.scaleX + insets.left);
int y = (int) (java2DPoint.getY() * this.scaleY + insets.top);
return new Point(x, y);
}
/**
* Translates a panel (component) location to a Java2D point.
*
* @param screenPoint the screen location ({@code null} not
* permitted).
*
* @return The Java2D coordinates.
*/
public Point2D translateScreenToJava2D(Point screenPoint) {
Insets insets = getInsets();
double x = (screenPoint.getX() - insets.left) / this.scaleX;
double y = (screenPoint.getY() - insets.top) / this.scaleY;
return new Point2D.Double(x, y);
}
/**
* Applies any scaling that is in effect for the chart drawing to the
* given rectangle.
*
* @param rect the rectangle ({@code null} not permitted).
*
* @return A new scaled rectangle.
*/
public Rectangle2D scale(Rectangle2D rect) {
Insets insets = getInsets();
double x = rect.getX() * getScaleX() + insets.left;
double y = rect.getY() * getScaleY() + insets.top;
double w = rect.getWidth() * getScaleX();
double h = rect.getHeight() * getScaleY();
return new Rectangle2D.Double(x, y, w, h);
}
/**
* Returns the chart entity at a given point.
*
* This method will return null if there is (a) no entity at the given
* point, or (b) no entity collection has been generated.
*
* @param viewX the x-coordinate.
* @param viewY the y-coordinate.
*
* @return The chart entity (possibly {@code null}).
*/
public ChartEntity getEntityForPoint(int viewX, int viewY) {
ChartEntity result = null;
if (this.info != null) {
Insets insets = getInsets();
double x = (viewX - insets.left) / this.scaleX;
double y = (viewY - insets.top) / this.scaleY;
EntityCollection entities = this.info.getEntityCollection();
result = entities != null ? entities.getEntity(x, y) : null;
}
return result;
}
/**
* Returns the flag that controls whether or not the offscreen buffer
* needs to be refreshed.
*
* @return A boolean.
*/
public boolean getRefreshBuffer() {
return this.refreshBuffer;
}
/**
* Sets the refresh buffer flag. This flag is used to avoid unnecessary
* redrawing of the chart when the offscreen image buffer is used.
*
* @param flag {@code true} indicates that the buffer should be
* refreshed.
*/
public void setRefreshBuffer(boolean flag) {
this.refreshBuffer = flag;
}
/**
* Paints the component by drawing the chart to fill the entire component,
* but allowing for the insets (which will be non-zero if a border has been
* set for this component). To increase performance (at the expense of
* memory), an off-screen buffer image can be used.
*
* @param g the graphics device for drawing on.
*/
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (this.chart == null) {
return;
}
Graphics2D g2 = (Graphics2D) g.create();
// first determine the size of the chart rendering area...
Dimension size = getSize();
Insets insets = getInsets();
final int availableWidth = size.width - insets.left - insets.right;
final int availableHeight = size.height - insets.top - insets.bottom;
// work out if scaling is required...
boolean scale = false;
int drawWidth = availableWidth;
int drawHeight = availableHeight;
this.scaleX = 1.0;
this.scaleY = 1.0;
if (drawWidth < this.minimumDrawWidth) {
this.scaleX = (double) drawWidth / (double) this.minimumDrawWidth;
drawWidth = this.minimumDrawWidth;
scale = true;
}
else if (drawWidth > this.maximumDrawWidth) {
this.scaleX = (double) drawWidth / (double) this.maximumDrawWidth;
drawWidth = this.maximumDrawWidth;
scale = true;
}
if (drawHeight < this.minimumDrawHeight) {
this.scaleY = (double) drawHeight / (double) this.minimumDrawHeight;
drawHeight = this.minimumDrawHeight;
scale = true;
}
else if (drawHeight > this.maximumDrawHeight) {
this.scaleY = (double) drawHeight / (double) this.maximumDrawHeight;
drawHeight = this.maximumDrawHeight;
scale = true;
}
Dimension chartSize = new Dimension(drawWidth, drawHeight);
// are we using the chart buffer?
if (this.useBuffer) {
// for better rendering on the HiDPI monitors upscaling the buffer to the "native" resolution
// instead of using logical one provided by Swing
final AffineTransform globalTransform = ((Graphics2D) g).getTransform();
final double globalScaleX = globalTransform.getScaleX();
final double globalScaleY = globalTransform.getScaleY();
final Dimension bufferSize = new Dimension(
(int) Math.ceil(availableWidth * globalScaleX),
(int) Math.ceil(availableHeight * globalScaleY));
this.chartBuffer = paintChartToBuffer(g2, bufferSize, chartSize, anchor, info);
// zap the buffer onto the panel...
g2.drawImage(this.chartBuffer, insets.left, insets.top, availableWidth, availableHeight, this);
g2.addRenderingHints(this.chart.getRenderingHints()); // bug#187
} else { // redrawing the chart every time...
AffineTransform saved = g2.getTransform();
g2.translate(insets.left, insets.top);
if (scale) {
AffineTransform st = AffineTransform.getScaleInstance(
this.scaleX, this.scaleY);
g2.transform(st);
}
this.chart.draw(g2, new Rectangle(chartSize), this.anchor, this.info);
g2.setTransform(saved);
}
for (Overlay overlay : this.overlays) {
overlay.paintOverlay(g2, this);
}
// redraw the zoom rectangle (if present) - if useBuffer is false,
// we use XOR so we can XOR the rectangle away again without redrawing
// the chart
drawZoomRectangle(g2, !this.useBuffer);
g2.dispose();
this.anchor = null;
this.verticalTraceLine = null;
this.horizontalTraceLine = null;
}
/**
* Paints the chart to fill the entire off-screen buffer image.
*
* @param g2 the graphics context to create an off-screen buffer
* image.
* @param bufferSize the required off-screen buffer image size.
* @param chartSize the size with which the chart should be drawn (apply
* scaling if not equal to {@code bufferSize}).
* @param anchor the anchor point (in Java2D space) for the chart
* ({@code null} permitted).
* @param info records info about the drawing ({@code null} means
* collect no info).
* @return the off-screen buffer image to draw onto the panel.
*/
protected BufferedImage paintChartToBuffer(Graphics2D g2, Dimension bufferSize,
Dimension chartSize, Point2D anchor, ChartRenderingInfo info) {
final BufferedImage buffer;
if ((this.chartBuffer == null)
|| (this.chartBuffer.getWidth() != bufferSize.width)
|| (this.chartBuffer.getHeight() != bufferSize.height)) {
GraphicsConfiguration gc = g2.getDeviceConfiguration();
buffer = gc.createCompatibleImage(bufferSize.width,
bufferSize.height, Transparency.TRANSLUCENT);
this.refreshBuffer = true;
} else {
buffer = this.chartBuffer;
}
// do we need to redraw the buffer?
if (this.refreshBuffer) {
this.refreshBuffer = false; // clear the flag
Graphics2D bufferG2 = buffer.createGraphics();
if (!bufferSize.equals(chartSize)) {
// Scale the chart to fit the buffer
bufferG2.scale(
bufferSize.getWidth() / chartSize.getWidth(),
bufferSize.getHeight() / chartSize.getHeight());
}
Rectangle chartArea = new Rectangle(chartSize);
// make the background of the buffer clear and transparent
Composite savedComposite = bufferG2.getComposite();
bufferG2.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR, 0.0f));
bufferG2.fill(chartArea);
bufferG2.setComposite(savedComposite);
this.chart.draw(bufferG2, chartArea, this.anchor, this.info);
bufferG2.dispose();
}
return buffer;
}
/**
* Receives notification of changes to the chart, and redraws the chart.
*
* @param event details of the chart change event.
*/
@Override
public void chartChanged(ChartChangeEvent event) {
this.refreshBuffer = true;
Plot plot = this.chart.getPlot();
if (plot instanceof Zoomable) {
Zoomable z = (Zoomable) plot;
this.orientation = z.getOrientation();
}
repaint();
}
/**
* Receives notification of a chart progress event.
*
* @param event the event.
*/
@Override
public void chartProgress(ChartProgressEvent event) {
// does nothing - override if necessary
}
/**
* Handles action events generated by the popup menu.
*
* @param event the event.
*/
@Override
public void actionPerformed(ActionEvent event) {
String command = event.getActionCommand();
// many of the zoom methods need a screen location - all we have is
// the zoomPoint, but it might be null. Here we grab the x and y
// coordinates, or use defaults...
double screenX = -1.0;
double screenY = -1.0;
if (this.zoomPoint != null) {
screenX = this.zoomPoint.getX();
screenY = this.zoomPoint.getY();
}
if (command.equals(PROPERTIES_COMMAND)) {
doEditChartProperties();
}
else if (command.equals(COPY_COMMAND)) {
doCopy();
}
else if (command.equals(SAVE_AS_PNG_COMMAND)) {
try {
doSaveAs();
}
catch (IOException e) {
JOptionPane.showMessageDialog(this, "I/O error occurred.",
localizationResources.getString("Save_as_PNG"),
JOptionPane.WARNING_MESSAGE);
}
}
else if (command.equals(SAVE_AS_SVG_COMMAND)) {
try {
saveAsSVG(null);
} catch (IOException e) {
JOptionPane.showMessageDialog(this, "I/O error occurred.",
localizationResources.getString("Save_as_SVG"),
JOptionPane.WARNING_MESSAGE);
}
}
else if (command.equals(SAVE_AS_PDF_COMMAND)) {
saveAsPDF(null);
}
else if (command.equals(PRINT_COMMAND)) {
createChartPrintJob();
}
else if (command.equals(ZOOM_IN_BOTH_COMMAND)) {
zoomInBoth(screenX, screenY);
}
else if (command.equals(ZOOM_IN_DOMAIN_COMMAND)) {
zoomInDomain(screenX, screenY);
}
else if (command.equals(ZOOM_IN_RANGE_COMMAND)) {
zoomInRange(screenX, screenY);
}
else if (command.equals(ZOOM_OUT_BOTH_COMMAND)) {
zoomOutBoth(screenX, screenY);
}
else if (command.equals(ZOOM_OUT_DOMAIN_COMMAND)) {
zoomOutDomain(screenX, screenY);
}
else if (command.equals(ZOOM_OUT_RANGE_COMMAND)) {
zoomOutRange(screenX, screenY);
}
else if (command.equals(ZOOM_RESET_BOTH_COMMAND)) {
restoreAutoBounds();
}
else if (command.equals(ZOOM_RESET_DOMAIN_COMMAND)) {
restoreAutoDomainBounds();
}
else if (command.equals(ZOOM_RESET_RANGE_COMMAND)) {
restoreAutoRangeBounds();
}
}
/**
* Handles a 'mouse entered' event. This method changes the tooltip delays
* of ToolTipManager.sharedInstance() to the possibly different values set
* for this chart panel.
*
* @param e the mouse event.
*/
@Override
public void mouseEntered(MouseEvent e) {
if (!this.ownToolTipDelaysActive) {
ToolTipManager ttm = ToolTipManager.sharedInstance();
this.originalToolTipInitialDelay = ttm.getInitialDelay();
ttm.setInitialDelay(this.ownToolTipInitialDelay);
this.originalToolTipReshowDelay = ttm.getReshowDelay();
ttm.setReshowDelay(this.ownToolTipReshowDelay);
this.originalToolTipDismissDelay = ttm.getDismissDelay();
ttm.setDismissDelay(this.ownToolTipDismissDelay);
this.ownToolTipDelaysActive = true;
}
}
/**
* Handles a 'mouse exited' event. This method resets the tooltip delays of
* ToolTipManager.sharedInstance() to their
* original values in effect before mouseEntered()
*
* @param e the mouse event.
*/
@Override
public void mouseExited(MouseEvent e) {
if (this.ownToolTipDelaysActive) {
// restore original tooltip dealys
ToolTipManager ttm = ToolTipManager.sharedInstance();
ttm.setInitialDelay(this.originalToolTipInitialDelay);
ttm.setReshowDelay(this.originalToolTipReshowDelay);
ttm.setDismissDelay(this.originalToolTipDismissDelay);
this.ownToolTipDelaysActive = false;
}
}
/**
* Handles a 'mouse pressed' event.
*
* This event is the popup trigger on Unix/Linux. For Windows, the popup
* trigger is the 'mouse released' event.
*
* @param e The mouse event.
*/
@Override
public void mousePressed(MouseEvent e) {
if (this.chart == null) {
return;
}
Plot plot = this.chart.getPlot();
int mods = e.getModifiers();
if ((mods & this.panMask) == this.panMask) {
// can we pan this plot?
if (plot instanceof Pannable) {
Pannable pannable = (Pannable) plot;
if (pannable.isDomainPannable() || pannable.isRangePannable()) {
Rectangle2D screenDataArea = getScreenDataArea(e.getX(),
e.getY());
if (screenDataArea != null && screenDataArea.contains(
e.getPoint())) {
this.panW = screenDataArea.getWidth();
this.panH = screenDataArea.getHeight();
this.panLast = e.getPoint();
setCursor(Cursor.getPredefinedCursor(
Cursor.MOVE_CURSOR));
}
}
// the actual panning occurs later in the mouseDragged()
// method
}
}
else if (this.zoomRectangle == null) {
Rectangle2D screenDataArea = getScreenDataArea(e.getX(), e.getY());
if (screenDataArea != null) {
this.zoomPoint = getPointInRectangle(e.getX(), e.getY(),
screenDataArea);
}
else {
this.zoomPoint = null;
}
if (e.isPopupTrigger()) {
if (this.popup != null) {
displayPopupMenu(e.getX(), e.getY());
}
}
}
}
/**
* Returns a point based on (x, y) but constrained to be within the bounds
* of the given rectangle. This method could be moved to JCommon.
*
* @param x the x-coordinate.
* @param y the y-coordinate.
* @param area the rectangle ({@code null} not permitted).
*
* @return A point within the rectangle.
*/
private Point2D getPointInRectangle(int x, int y, Rectangle2D area) {
double xx = Math.max(area.getMinX(), Math.min(x, area.getMaxX()));
double yy = Math.max(area.getMinY(), Math.min(y, area.getMaxY()));
return new Point2D.Double(xx, yy);
}
/**
* Handles a 'mouse dragged' event.
*
* @param e the mouse event.
*/
@Override
public void mouseDragged(MouseEvent e) {
// if the popup menu has already been triggered, then ignore dragging...
if (this.popup != null && this.popup.isShowing()) {
return;
}
// handle panning if we have a start point
if (this.panLast != null) {
double dx = e.getX() - this.panLast.getX();
double dy = e.getY() - this.panLast.getY();
if (dx == 0.0 && dy == 0.0) {
return;
}
double wPercent = -dx / this.panW;
double hPercent = dy / this.panH;
boolean old = this.chart.getPlot().isNotify();
this.chart.getPlot().setNotify(false);
Pannable p = (Pannable) this.chart.getPlot();
if (p.getOrientation() == PlotOrientation.VERTICAL) {
p.panDomainAxes(wPercent, this.info.getPlotInfo(),
this.panLast);
p.panRangeAxes(hPercent, this.info.getPlotInfo(),
this.panLast);
}
else {
p.panDomainAxes(hPercent, this.info.getPlotInfo(),
this.panLast);
p.panRangeAxes(wPercent, this.info.getPlotInfo(),
this.panLast);
}
this.panLast = e.getPoint();
this.chart.getPlot().setNotify(old);
return;
}
// if no initial zoom point was set, ignore dragging...
if (this.zoomPoint == null) {
return;
}
Graphics2D g2 = (Graphics2D) getGraphics();
// erase the previous zoom rectangle (if any). We only need to do
// this is we are using XOR mode, which we do when we're not using
// the buffer (if there is a buffer, then at the end of this method we
// just trigger a repaint)
if (!this.useBuffer) {
drawZoomRectangle(g2, true);
}
boolean hZoom, vZoom;
if (this.orientation == PlotOrientation.HORIZONTAL) {
hZoom = this.rangeZoomable;
vZoom = this.domainZoomable;
}
else {
hZoom = this.domainZoomable;
vZoom = this.rangeZoomable;
}
Rectangle2D scaledDataArea = getScreenDataArea(
(int) this.zoomPoint.getX(), (int) this.zoomPoint.getY());
if (hZoom && vZoom) {
// selected rectangle shouldn't extend outside the data area...
double xmax = Math.min(e.getX(), scaledDataArea.getMaxX());
double ymax = Math.min(e.getY(), scaledDataArea.getMaxY());
this.zoomRectangle = new Rectangle2D.Double(
this.zoomPoint.getX(), this.zoomPoint.getY(),
xmax - this.zoomPoint.getX(), ymax - this.zoomPoint.getY());
}
else if (hZoom) {
double xmax = Math.min(e.getX(), scaledDataArea.getMaxX());
this.zoomRectangle = new Rectangle2D.Double(
this.zoomPoint.getX(), scaledDataArea.getMinY(),
xmax - this.zoomPoint.getX(), scaledDataArea.getHeight());
}
else if (vZoom) {
double ymax = Math.min(e.getY(), scaledDataArea.getMaxY());
this.zoomRectangle = new Rectangle2D.Double(
scaledDataArea.getMinX(), this.zoomPoint.getY(),
scaledDataArea.getWidth(), ymax - this.zoomPoint.getY());
}
// Draw the new zoom rectangle...
if (this.useBuffer) {
repaint();
}
else {
// with no buffer, we use XOR to draw the rectangle "over" the
// chart...
drawZoomRectangle(g2, true);
}
g2.dispose();
}
/**
* Handles a 'mouse released' event. On Windows, we need to check if this
* is a popup trigger, but only if we haven't already been tracking a zoom
* rectangle.
*
* @param e information about the event.
*/
@Override
public void mouseReleased(MouseEvent e) {
// if we've been panning, we need to reset now that the mouse is
// released...
if (this.panLast != null) {
this.panLast = null;
setCursor(Cursor.getDefaultCursor());
}
else if (this.zoomRectangle != null) {
boolean hZoom, vZoom;
if (this.orientation == PlotOrientation.HORIZONTAL) {
hZoom = this.rangeZoomable;
vZoom = this.domainZoomable;
}
else {
hZoom = this.domainZoomable;
vZoom = this.rangeZoomable;
}
boolean zoomTrigger1 = hZoom && Math.abs(e.getX()
- this.zoomPoint.getX()) >= this.zoomTriggerDistance;
boolean zoomTrigger2 = vZoom && Math.abs(e.getY()
- this.zoomPoint.getY()) >= this.zoomTriggerDistance;
if (zoomTrigger1 || zoomTrigger2) {
if ((hZoom && (e.getX() < this.zoomPoint.getX()))
|| (vZoom && (e.getY() < this.zoomPoint.getY()))) {
restoreAutoBounds();
}
else {
double x, y, w, h;
Rectangle2D screenDataArea = getScreenDataArea(
(int) this.zoomPoint.getX(),
(int) this.zoomPoint.getY());
double maxX = screenDataArea.getMaxX();
double maxY = screenDataArea.getMaxY();
// for mouseReleased event, (horizontalZoom || verticalZoom)
// will be true, so we can just test for either being false;
// otherwise both are true
if (!vZoom) {
x = this.zoomPoint.getX();
y = screenDataArea.getMinY();
w = Math.min(this.zoomRectangle.getWidth(),
maxX - this.zoomPoint.getX());
h = screenDataArea.getHeight();
}
else if (!hZoom) {
x = screenDataArea.getMinX();
y = this.zoomPoint.getY();
w = screenDataArea.getWidth();
h = Math.min(this.zoomRectangle.getHeight(),
maxY - this.zoomPoint.getY());
}
else {
x = this.zoomPoint.getX();
y = this.zoomPoint.getY();
w = Math.min(this.zoomRectangle.getWidth(),
maxX - this.zoomPoint.getX());
h = Math.min(this.zoomRectangle.getHeight(),
maxY - this.zoomPoint.getY());
}
Rectangle2D zoomArea = new Rectangle2D.Double(x, y, w, h);
zoom(zoomArea);
}
this.zoomPoint = null;
this.zoomRectangle = null;
}
else {
// erase the zoom rectangle
Graphics2D g2 = (Graphics2D) getGraphics();
if (this.useBuffer) {
repaint();
}
else {
drawZoomRectangle(g2, true);
}
g2.dispose();
this.zoomPoint = null;
this.zoomRectangle = null;
}
}
else if (e.isPopupTrigger()) {
if (this.popup != null) {
displayPopupMenu(e.getX(), e.getY());
}
}
}
/**
* Receives notification of mouse clicks on the panel. These are
* translated and passed on to any registered {@link ChartMouseListener}s.
*
* @param event Information about the mouse event.
*/
@Override
public void mouseClicked(MouseEvent event) {
Insets insets = getInsets();
int x = (int) ((event.getX() - insets.left) / this.scaleX);
int y = (int) ((event.getY() - insets.top) / this.scaleY);
this.anchor = new Point2D.Double(x, y);
if (this.chart == null) {
return;
}
this.chart.setNotify(true);
// new entity code...
Object[] listeners = this.chartMouseListeners.getListeners(
ChartMouseListener.class);
if (listeners.length == 0) {
return;
}
ChartEntity entity = null;
if (this.info != null) {
EntityCollection entities = this.info.getEntityCollection();
if (entities != null) {
entity = entities.getEntity(x, y);
}
}
ChartMouseEvent chartEvent = new ChartMouseEvent(getChart(), event,
entity);
for (int i = listeners.length - 1; i >= 0; i -= 1) {
((ChartMouseListener) listeners[i]).chartMouseClicked(chartEvent);
}
}
/**
* Implementation of the MouseMotionListener's method.
*
* @param e the event.
*/
@Override
public void mouseMoved(MouseEvent e) {
Graphics2D g2 = (Graphics2D) getGraphics();
if (this.horizontalAxisTrace) {
drawHorizontalAxisTrace(g2, e.getX());
}
if (this.verticalAxisTrace) {
drawVerticalAxisTrace(g2, e.getY());
}
g2.dispose();
Object[] listeners = this.chartMouseListeners.getListeners(
ChartMouseListener.class);
if (listeners.length == 0) {
return;
}
Insets insets = getInsets();
int x = (int) ((e.getX() - insets.left) / this.scaleX);
int y = (int) ((e.getY() - insets.top) / this.scaleY);
ChartEntity entity = null;
if (this.info != null) {
EntityCollection entities = this.info.getEntityCollection();
if (entities != null) {
entity = entities.getEntity(x, y);
}
}
// we can only generate events if the panel's chart is not null
// (see bug report 1556951)
if (this.chart != null) {
ChartMouseEvent event = new ChartMouseEvent(getChart(), e, entity);
for (int i = listeners.length - 1; i >= 0; i -= 1) {
((ChartMouseListener) listeners[i]).chartMouseMoved(event);
}
}
}
/**
* Zooms in on an anchor point (specified in screen coordinate space).
*
* @param x the x value (in screen coordinates).
* @param y the y value (in screen coordinates).
*/
public void zoomInBoth(double x, double y) {
Plot plot = this.chart.getPlot();
if (plot == null) {
return;
}
// here we tweak the notify flag on the plot so that only
// one notification happens even though we update multiple
// axes...
boolean savedNotify = plot.isNotify();
plot.setNotify(false);
zoomInDomain(x, y);
zoomInRange(x, y);
plot.setNotify(savedNotify);
}
/**
* Decreases the length of the domain axis, centered about the given
* coordinate on the screen. The length of the domain axis is reduced
* by the value of {@link #getZoomInFactor()}.
*
* @param x the x coordinate (in screen coordinates).
* @param y the y-coordinate (in screen coordinates).
*/
public void zoomInDomain(double x, double y) {
Plot plot = this.chart.getPlot();
if (plot instanceof Zoomable) {
// here we tweak the notify flag on the plot so that only
// one notification happens even though we update multiple
// axes...
boolean savedNotify = plot.isNotify();
plot.setNotify(false);
Zoomable z = (Zoomable) plot;
z.zoomDomainAxes(this.zoomInFactor, this.info.getPlotInfo(),
translateScreenToJava2D(new Point((int) x, (int) y)),
this.zoomAroundAnchor);
plot.setNotify(savedNotify);
}
}
/**
* Decreases the length of the range axis, centered about the given
* coordinate on the screen. The length of the range axis is reduced by
* the value of {@link #getZoomInFactor()}.
*
* @param x the x-coordinate (in screen coordinates).
* @param y the y coordinate (in screen coordinates).
*/
public void zoomInRange(double x, double y) {
Plot plot = this.chart.getPlot();
if (plot instanceof Zoomable) {
// here we tweak the notify flag on the plot so that only
// one notification happens even though we update multiple
// axes...
boolean savedNotify = plot.isNotify();
plot.setNotify(false);
Zoomable z = (Zoomable) plot;
z.zoomRangeAxes(this.zoomInFactor, this.info.getPlotInfo(),
translateScreenToJava2D(new Point((int) x, (int) y)),
this.zoomAroundAnchor);
plot.setNotify(savedNotify);
}
}
/**
* Zooms out on an anchor point (specified in screen coordinate space).
*
* @param x the x value (in screen coordinates).
* @param y the y value (in screen coordinates).
*/
public void zoomOutBoth(double x, double y) {
Plot plot = this.chart.getPlot();
if (plot == null) {
return;
}
// here we tweak the notify flag on the plot so that only
// one notification happens even though we update multiple
// axes...
boolean savedNotify = plot.isNotify();
plot.setNotify(false);
zoomOutDomain(x, y);
zoomOutRange(x, y);
plot.setNotify(savedNotify);
}
/**
* Increases the length of the domain axis, centered about the given
* coordinate on the screen. The length of the domain axis is increased
* by the value of {@link #getZoomOutFactor()}.
*
* @param x the x coordinate (in screen coordinates).
* @param y the y-coordinate (in screen coordinates).
*/
public void zoomOutDomain(double x, double y) {
Plot plot = this.chart.getPlot();
if (plot instanceof Zoomable) {
// here we tweak the notify flag on the plot so that only
// one notification happens even though we update multiple
// axes...
boolean savedNotify = plot.isNotify();
plot.setNotify(false);
Zoomable z = (Zoomable) plot;
z.zoomDomainAxes(this.zoomOutFactor, this.info.getPlotInfo(),
translateScreenToJava2D(new Point((int) x, (int) y)),
this.zoomAroundAnchor);
plot.setNotify(savedNotify);
}
}
/**
* Increases the length the range axis, centered about the given
* coordinate on the screen. The length of the range axis is increased
* by the value of {@link #getZoomOutFactor()}.
*
* @param x the x coordinate (in screen coordinates).
* @param y the y-coordinate (in screen coordinates).
*/
public void zoomOutRange(double x, double y) {
Plot plot = this.chart.getPlot();
if (plot instanceof Zoomable) {
// here we tweak the notify flag on the plot so that only
// one notification happens even though we update multiple
// axes...
boolean savedNotify = plot.isNotify();
plot.setNotify(false);
Zoomable z = (Zoomable) plot;
z.zoomRangeAxes(this.zoomOutFactor, this.info.getPlotInfo(),
translateScreenToJava2D(new Point((int) x, (int) y)),
this.zoomAroundAnchor);
plot.setNotify(savedNotify);
}
}
/**
* Zooms in on a selected region.
*
* @param selection the selected region.
*/
public void zoom(Rectangle2D selection) {
// get the origin of the zoom selection in the Java2D space used for
// drawing the chart (that is, before any scaling to fit the panel)
Point2D selectOrigin = translateScreenToJava2D(new Point(
(int) Math.ceil(selection.getX()),
(int) Math.ceil(selection.getY())));
PlotRenderingInfo plotInfo = this.info.getPlotInfo();
Rectangle2D scaledDataArea = getScreenDataArea(
(int) selection.getCenterX(), (int) selection.getCenterY());
if ((selection.getHeight() > 0) && (selection.getWidth() > 0)) {
double hLower = (selection.getMinX() - scaledDataArea.getMinX())
/ scaledDataArea.getWidth();
double hUpper = (selection.getMaxX() - scaledDataArea.getMinX())
/ scaledDataArea.getWidth();
double vLower = (scaledDataArea.getMaxY() - selection.getMaxY())
/ scaledDataArea.getHeight();
double vUpper = (scaledDataArea.getMaxY() - selection.getMinY())
/ scaledDataArea.getHeight();
Plot p = this.chart.getPlot();
if (p instanceof Zoomable) {
// here we tweak the notify flag on the plot so that only
// one notification happens even though we update multiple
// axes...
boolean savedNotify = p.isNotify();
p.setNotify(false);
Zoomable z = (Zoomable) p;
if (z.getOrientation() == PlotOrientation.HORIZONTAL) {
z.zoomDomainAxes(vLower, vUpper, plotInfo, selectOrigin);
z.zoomRangeAxes(hLower, hUpper, plotInfo, selectOrigin);
}
else {
z.zoomDomainAxes(hLower, hUpper, plotInfo, selectOrigin);
z.zoomRangeAxes(vLower, vUpper, plotInfo, selectOrigin);
}
p.setNotify(savedNotify);
}
}
}
/**
* Restores the auto-range calculation on both axes.
*/
public void restoreAutoBounds() {
Plot plot = this.chart.getPlot();
if (plot == null) {
return;
}
// here we tweak the notify flag on the plot so that only
// one notification happens even though we update multiple
// axes...
boolean savedNotify = plot.isNotify();
plot.setNotify(false);
restoreAutoDomainBounds();
restoreAutoRangeBounds();
plot.setNotify(savedNotify);
}
/**
* Restores the auto-range calculation on the domain axis.
*/
public void restoreAutoDomainBounds() {
Plot plot = this.chart.getPlot();
if (plot instanceof Zoomable) {
Zoomable z = (Zoomable) plot;
// here we tweak the notify flag on the plot so that only
// one notification happens even though we update multiple
// axes...
boolean savedNotify = plot.isNotify();
plot.setNotify(false);
// we need to guard against this.zoomPoint being null
Point2D zp = (this.zoomPoint != null
? this.zoomPoint : new Point());
z.zoomDomainAxes(0.0, this.info.getPlotInfo(), zp);
plot.setNotify(savedNotify);
}
}
/**
* Restores the auto-range calculation on the range axis.
*/
public void restoreAutoRangeBounds() {
Plot plot = this.chart.getPlot();
if (plot instanceof Zoomable) {
Zoomable z = (Zoomable) plot;
// here we tweak the notify flag on the plot so that only
// one notification happens even though we update multiple
// axes...
boolean savedNotify = plot.isNotify();
plot.setNotify(false);
// we need to guard against this.zoomPoint being null
Point2D zp = (this.zoomPoint != null
? this.zoomPoint : new Point());
z.zoomRangeAxes(0.0, this.info.getPlotInfo(), zp);
plot.setNotify(savedNotify);
}
}
/**
* Returns the data area for the chart (the area inside the axes) with the
* current scaling applied (that is, the area as it appears on screen).
*
* @return The scaled data area.
*/
public Rectangle2D getScreenDataArea() {
Rectangle2D dataArea = this.info.getPlotInfo().getDataArea();
Insets insets = getInsets();
double x = dataArea.getX() * this.scaleX + insets.left;
double y = dataArea.getY() * this.scaleY + insets.top;
double w = dataArea.getWidth() * this.scaleX;
double h = dataArea.getHeight() * this.scaleY;
return new Rectangle2D.Double(x, y, w, h);
}
/**
* Returns the data area (the area inside the axes) for the plot or subplot,
* with the current scaling applied.
*
* @param x the x-coordinate (for subplot selection).
* @param y the y-coordinate (for subplot selection).
*
* @return The scaled data area.
*/
public Rectangle2D getScreenDataArea(int x, int y) {
PlotRenderingInfo plotInfo = this.info.getPlotInfo();
Rectangle2D result;
if (plotInfo.getSubplotCount() == 0) {
result = getScreenDataArea();
}
else {
// get the origin of the zoom selection in the Java2D space used for
// drawing the chart (that is, before any scaling to fit the panel)
Point2D selectOrigin = translateScreenToJava2D(new Point(x, y));
int subplotIndex = plotInfo.getSubplotIndex(selectOrigin);
if (subplotIndex == -1) {
return null;
}
result = scale(plotInfo.getSubplotInfo(subplotIndex).getDataArea());
}
return result;
}
/**
* Returns the initial tooltip delay value used inside this chart panel.
*
* @return An integer representing the initial delay value, in milliseconds.
*
* @see javax.swing.ToolTipManager#getInitialDelay()
*/
public int getInitialDelay() {
return this.ownToolTipInitialDelay;
}
/**
* Returns the reshow tooltip delay value used inside this chart panel.
*
* @return An integer representing the reshow delay value, in milliseconds.
*
* @see javax.swing.ToolTipManager#getReshowDelay()
*/
public int getReshowDelay() {
return this.ownToolTipReshowDelay;
}
/**
* Returns the dismissal tooltip delay value used inside this chart panel.
*
* @return An integer representing the dismissal delay value, in
* milliseconds.
*
* @see javax.swing.ToolTipManager#getDismissDelay()
*/
public int getDismissDelay() {
return this.ownToolTipDismissDelay;
}
/**
* Specifies the initial delay value for this chart panel.
*
* @param delay the number of milliseconds to delay (after the cursor has
* paused) before displaying.
*
* @see javax.swing.ToolTipManager#setInitialDelay(int)
*/
public void setInitialDelay(int delay) {
this.ownToolTipInitialDelay = delay;
}
/**
* Specifies the amount of time before the user has to wait initialDelay
* milliseconds before a tooltip will be shown.
*
* @param delay time in milliseconds
*
* @see javax.swing.ToolTipManager#setReshowDelay(int)
*/
public void setReshowDelay(int delay) {
this.ownToolTipReshowDelay = delay;
}
/**
* Specifies the dismissal delay value for this chart panel.
*
* @param delay the number of milliseconds to delay before taking away the
* tooltip
*
* @see javax.swing.ToolTipManager#setDismissDelay(int)
*/
public void setDismissDelay(int delay) {
this.ownToolTipDismissDelay = delay;
}
/**
* Returns the zoom in factor.
*
* @return The zoom in factor.
*
* @see #setZoomInFactor(double)
*/
public double getZoomInFactor() {
return this.zoomInFactor;
}
/**
* Sets the zoom in factor.
*
* @param factor the factor.
*
* @see #getZoomInFactor()
*/
public void setZoomInFactor(double factor) {
this.zoomInFactor = factor;
}
/**
* Returns the zoom out factor.
*
* @return The zoom out factor.
*
* @see #setZoomOutFactor(double)
*/
public double getZoomOutFactor() {
return this.zoomOutFactor;
}
/**
* Sets the zoom out factor.
*
* @param factor the factor.
*
* @see #getZoomOutFactor()
*/
public void setZoomOutFactor(double factor) {
this.zoomOutFactor = factor;
}
/**
* Draws zoom rectangle (if present).
* The drawing is performed in XOR mode, therefore
* when this method is called twice in a row,
* the second call will completely restore the state
* of the canvas.
*
* @param g2 the graphics device.
* @param xor use XOR for drawing?
*/
private void drawZoomRectangle(Graphics2D g2, boolean xor) {
if (this.zoomRectangle != null) {
if (xor) {
// Set XOR mode to draw the zoom rectangle
g2.setXORMode(Color.GRAY);
}
if (this.fillZoomRectangle) {
g2.setPaint(this.zoomFillPaint);
g2.fill(this.zoomRectangle);
}
else {
g2.setPaint(this.zoomOutlinePaint);
g2.draw(this.zoomRectangle);
}
if (xor) {
// Reset to the default 'overwrite' mode
g2.setPaintMode();
}
}
}
/**
* Draws a vertical line used to trace the mouse position to the horizontal
* axis.
*
* @param g2 the graphics device.
* @param x the x-coordinate of the trace line.
*/
private void drawHorizontalAxisTrace(Graphics2D g2, int x) {
Rectangle2D dataArea = getScreenDataArea();
g2.setXORMode(Color.ORANGE);
if (((int) dataArea.getMinX() < x) && (x < (int) dataArea.getMaxX())) {
if (this.verticalTraceLine != null) {
g2.draw(this.verticalTraceLine);
this.verticalTraceLine.setLine(x, (int) dataArea.getMinY(), x,
(int) dataArea.getMaxY());
}
else {
this.verticalTraceLine = new Line2D.Float(x,
(int) dataArea.getMinY(), x, (int) dataArea.getMaxY());
}
g2.draw(this.verticalTraceLine);
}
// Reset to the default 'overwrite' mode
g2.setPaintMode();
}
/**
* Draws a horizontal line used to trace the mouse position to the vertical
* axis.
*
* @param g2 the graphics device.
* @param y the y-coordinate of the trace line.
*/
private void drawVerticalAxisTrace(Graphics2D g2, int y) {
Rectangle2D dataArea = getScreenDataArea();
g2.setXORMode(Color.ORANGE);
if (((int) dataArea.getMinY() < y) && (y < (int) dataArea.getMaxY())) {
if (this.horizontalTraceLine != null) {
g2.draw(this.horizontalTraceLine);
this.horizontalTraceLine.setLine((int) dataArea.getMinX(), y,
(int) dataArea.getMaxX(), y);
}
else {
this.horizontalTraceLine = new Line2D.Float(
(int) dataArea.getMinX(), y, (int) dataArea.getMaxX(),
y);
}
g2.draw(this.horizontalTraceLine);
}
// Reset to the default 'overwrite' mode
g2.setPaintMode();
}
/**
* Displays a dialog that allows the user to edit the properties for the
* current chart.
*/
public void doEditChartProperties() {
ChartEditor editor = ChartEditorManager.getChartEditor(this.chart);
int result = JOptionPane.showConfirmDialog(this, editor,
localizationResources.getString("Chart_Properties"),
JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
if (result == JOptionPane.OK_OPTION) {
editor.updateChart(this.chart);
}
}
/**
* Copies the current chart to the system clipboard.
*/
public void doCopy() {
Clipboard systemClipboard
= Toolkit.getDefaultToolkit().getSystemClipboard();
Insets insets = getInsets();
int w = getWidth() - insets.left - insets.right;
int h = getHeight() - insets.top - insets.bottom;
ChartTransferable selection = new ChartTransferable(this.chart, w, h,
getMinimumDrawWidth(), getMinimumDrawHeight(),
getMaximumDrawWidth(), getMaximumDrawHeight(), true);
systemClipboard.setContents(selection, null);
}
/**
* Opens a file chooser and gives the user an opportunity to save the chart
* in PNG format.
*
* @throws IOException if there is an I/O error.
*/
public void doSaveAs() throws IOException {
JFileChooser fileChooser = new JFileChooser();
fileChooser.setCurrentDirectory(this.defaultDirectoryForSaveAs);
FileNameExtensionFilter filter = new FileNameExtensionFilter(
localizationResources.getString("PNG_Image_Files"), "png");
fileChooser.addChoosableFileFilter(filter);
fileChooser.setFileFilter(filter);
int option = fileChooser.showSaveDialog(this);
if (option == JFileChooser.APPROVE_OPTION) {
String filename = fileChooser.getSelectedFile().getPath();
if (isEnforceFileExtensions()) {
if (!filename.endsWith(".png")) {
filename = filename + ".png";
}
}
ChartUtils.saveChartAsPNG(new File(filename), this.chart,
getWidth(), getHeight());
}
}
/**
* Saves the chart in SVG format (a filechooser will be displayed so that
* the user can specify the filename). Note that this method only works
* if the JFreeSVG library is on the classpath...if this library is not
* present, the method will fail.
*/
private void saveAsSVG(File f) throws IOException {
File file = f;
if (file == null) {
JFileChooser fileChooser = new JFileChooser();
fileChooser.setCurrentDirectory(this.defaultDirectoryForSaveAs);
FileNameExtensionFilter filter = new FileNameExtensionFilter(
localizationResources.getString("SVG_Files"), "svg");
fileChooser.addChoosableFileFilter(filter);
fileChooser.setFileFilter(filter);
int option = fileChooser.showSaveDialog(this);
if (option == JFileChooser.APPROVE_OPTION) {
String filename = fileChooser.getSelectedFile().getPath();
if (isEnforceFileExtensions()) {
if (!filename.endsWith(".svg")) {
filename = filename + ".svg";
}
}
file = new File(filename);
if (file.exists()) {
String fileExists = localizationResources.getString(
"FILE_EXISTS_CONFIRM_OVERWRITE");
int response = JOptionPane.showConfirmDialog(this,
fileExists,
localizationResources.getString("Save_as_SVG"),
JOptionPane.OK_CANCEL_OPTION);
if (response == JOptionPane.CANCEL_OPTION) {
file = null;
}
}
}
}
if (file != null) {
// use reflection to get the SVG string
String svg = generateSVG(getWidth(), getHeight());
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new FileWriter(file));
writer.write("\n");
writer.write(svg + "\n");
writer.flush();
} finally {
try {
if (writer != null) {
writer.close();
}
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
}
}
/**
* Generates a string containing a rendering of the chart in SVG format.
* This feature is only supported if the JFreeSVG library is included on
* the classpath.
*
* @return A string containing an SVG element for the current chart, or
* {@code null} if there is a problem with the method invocation
* by reflection.
*/
private String generateSVG(int width, int height) {
Graphics2D g2 = createSVGGraphics2D(width, height);
if (g2 == null) {
throw new IllegalStateException("JFreeSVG library is not present.");
}
// we suppress shadow generation, because SVG is a vector format and
// the shadow effect is applied via bitmap effects...
g2.setRenderingHint(JFreeChart.KEY_SUPPRESS_SHADOW_GENERATION, true);
String svg = null;
Rectangle2D drawArea = new Rectangle2D.Double(0, 0, width, height);
this.chart.draw(g2, drawArea);
try {
Method m = g2.getClass().getMethod("getSVGElement");
svg = (String) m.invoke(g2);
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException |
InvocationTargetException e) {
// null will be returned
}
return svg;
}
private Graphics2D createSVGGraphics2D(int w, int h) {
try {
Class svgGraphics2d = Class.forName("org.jfree.graphics2d.svg.SVGGraphics2D");
Constructor ctor = svgGraphics2d.getConstructor(int.class, int.class);
return (Graphics2D) ctor.newInstance(w, h);
} catch (ClassNotFoundException | NoSuchMethodException | SecurityException | InstantiationException |
IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
return null;
}
}
/**
* Saves the chart in PDF format (a filechooser will be displayed so that
* the user can specify the filename). Note that this method only works
* if the OrsonPDF library is on the classpath...if this library is not
* present, the method will fail.
*/
private void saveAsPDF(File f) {
File file = f;
if (file == null) {
JFileChooser fileChooser = new JFileChooser();
fileChooser.setCurrentDirectory(this.defaultDirectoryForSaveAs);
FileNameExtensionFilter filter = new FileNameExtensionFilter(
localizationResources.getString("PDF_Files"), "pdf");
fileChooser.addChoosableFileFilter(filter);
fileChooser.setFileFilter(filter);
int option = fileChooser.showSaveDialog(this);
if (option == JFileChooser.APPROVE_OPTION) {
String filename = fileChooser.getSelectedFile().getPath();
if (isEnforceFileExtensions()) {
if (!filename.endsWith(".pdf")) {
filename = filename + ".pdf";
}
}
file = new File(filename);
if (file.exists()) {
String fileExists = localizationResources.getString(
"FILE_EXISTS_CONFIRM_OVERWRITE");
int response = JOptionPane.showConfirmDialog(this,
fileExists,
localizationResources.getString("Save_as_PDF"),
JOptionPane.OK_CANCEL_OPTION);
if (response == JOptionPane.CANCEL_OPTION) {
file = null;
}
}
}
}
if (file != null) {
writeAsPDF(file, getWidth(), getHeight());
}
}
/**
* Returns {@code true} if OrsonPDF is on the classpath, and
* {@code false} otherwise. The OrsonPDF library can be found at
* http://www.object-refinery.com/pdf/
*
* @return A boolean.
*/
private boolean isOrsonPDFAvailable() {
Class pdfDocumentClass = null;
try {
pdfDocumentClass = Class.forName("com.orsonpdf.PDFDocument");
} catch (ClassNotFoundException e) {
// pdfDocument class will be null so the function will return false
}
return (pdfDocumentClass != null);
}
/**
* Writes the current chart to the specified file in PDF format. This
* will only work when the OrsonPDF library is found on the classpath.
* Reflection is used to ensure there is no compile-time dependency on
* OrsonPDF (which is non-free software).
*
* @param file the output file ({@code null} not permitted).
* @param w the chart width.
* @param h the chart height.
*/
private void writeAsPDF(File file, int w, int h) {
if (!isOrsonPDFAvailable()) {
throw new IllegalStateException(
"OrsonPDF is not present on the classpath.");
}
Args.nullNotPermitted(file, "file");
try {
Class pdfDocClass = Class.forName("com.orsonpdf.PDFDocument");
Object pdfDoc = pdfDocClass.newInstance();
Method m = pdfDocClass.getMethod("createPage", Rectangle2D.class);
Rectangle2D rect = new Rectangle(w, h);
Object page = m.invoke(pdfDoc, rect);
Method m2 = page.getClass().getMethod("getGraphics2D");
Graphics2D g2 = (Graphics2D) m2.invoke(page);
// we suppress shadow generation, because PDF is a vector format and
// the shadow effect is applied via bitmap effects...
g2.setRenderingHint(JFreeChart.KEY_SUPPRESS_SHADOW_GENERATION, true);
Rectangle2D drawArea = new Rectangle2D.Double(0, 0, w, h);
this.chart.draw(g2, drawArea);
Method m3 = pdfDocClass.getMethod("writeToFile", File.class);
m3.invoke(pdfDoc, file);
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | NoSuchMethodException |
SecurityException | IllegalArgumentException | InvocationTargetException ex) {
throw new RuntimeException(ex);
}
}
/**
* Creates a print job for the chart.
*/
public void createChartPrintJob() {
PrinterJob job = PrinterJob.getPrinterJob();
PageFormat pf = job.defaultPage();
PageFormat pf2 = job.pageDialog(pf);
if (pf2 != pf) {
job.setPrintable(this, pf2);
if (job.printDialog()) {
try {
job.print();
}
catch (PrinterException e) {
JOptionPane.showMessageDialog(this, e);
}
}
}
}
/**
* Prints the chart on a single page.
*
* @param g the graphics context.
* @param pf the page format to use.
* @param pageIndex the index of the page. If not {@code 0}, nothing
* gets printed.
*
* @return The result of printing.
*/
@Override
public int print(Graphics g, PageFormat pf, int pageIndex) {
if (pageIndex != 0) {
return NO_SUCH_PAGE;
}
Graphics2D g2 = (Graphics2D) g;
double x = pf.getImageableX();
double y = pf.getImageableY();
double w = pf.getImageableWidth();
double h = pf.getImageableHeight();
this.chart.draw(g2, new Rectangle2D.Double(x, y, w, h), this.anchor,
null);
return PAGE_EXISTS;
}
/**
* Adds a listener to the list of objects listening for chart mouse events.
*
* @param listener the listener ({@code null} not permitted).
*/
public void addChartMouseListener(ChartMouseListener listener) {
Args.nullNotPermitted(listener, "listener");
this.chartMouseListeners.add(ChartMouseListener.class, listener);
}
/**
* Removes a listener from the list of objects listening for chart mouse
* events.
*
* @param listener the listener.
*/
public void removeChartMouseListener(ChartMouseListener listener) {
this.chartMouseListeners.remove(ChartMouseListener.class, listener);
}
/**
* Returns an array of the listeners of the given type registered with the
* panel.
*
* @param listenerType the listener type.
*
* @return An array of listeners.
*/
@Override
public EventListener[] getListeners(Class listenerType) {
if (listenerType == ChartMouseListener.class) {
// fetch listeners from local storage
return this.chartMouseListeners.getListeners(listenerType);
}
else {
return super.getListeners(listenerType);
}
}
/**
* Creates a popup menu for the panel.
*
* @param properties include a menu item for the chart property editor.
* @param save include a menu item for saving the chart.
* @param print include a menu item for printing the chart.
* @param zoom include menu items for zooming.
*
* @return The popup menu.
*/
protected JPopupMenu createPopupMenu(boolean properties, boolean save,
boolean print, boolean zoom) {
return createPopupMenu(properties, false, save, print, zoom);
}
/**
* Creates a popup menu for the panel.
*
* @param properties include a menu item for the chart property editor.
* @param copy include a menu item for copying to the clipboard.
* @param save include a menu item for saving the chart.
* @param print include a menu item for printing the chart.
* @param zoom include menu items for zooming.
*
* @return The popup menu.
*/
protected JPopupMenu createPopupMenu(boolean properties,
boolean copy, boolean save, boolean print, boolean zoom) {
JPopupMenu result = new JPopupMenu(localizationResources.getString("Chart") + ":");
boolean separator = false;
if (properties) {
JMenuItem propertiesItem = new JMenuItem(
localizationResources.getString("Properties..."));
propertiesItem.setActionCommand(PROPERTIES_COMMAND);
propertiesItem.addActionListener(this);
result.add(propertiesItem);
separator = true;
}
if (copy) {
if (separator) {
result.addSeparator();
}
JMenuItem copyItem = new JMenuItem(
localizationResources.getString("Copy"));
copyItem.setActionCommand(COPY_COMMAND);
copyItem.addActionListener(this);
result.add(copyItem);
separator = !save;
}
if (save) {
if (separator) {
result.addSeparator();
}
JMenu saveSubMenu = new JMenu(localizationResources.getString(
"Save_as"));
JMenuItem pngItem = new JMenuItem(localizationResources.getString(
"PNG..."));
pngItem.setActionCommand("SAVE_AS_PNG");
pngItem.addActionListener(this);
saveSubMenu.add(pngItem);
if (createSVGGraphics2D(10, 10) != null) {
JMenuItem svgItem = new JMenuItem(localizationResources.getString(
"SVG..."));
svgItem.setActionCommand("SAVE_AS_SVG");
svgItem.addActionListener(this);
saveSubMenu.add(svgItem);
}
if (isOrsonPDFAvailable()) {
JMenuItem pdfItem = new JMenuItem(
localizationResources.getString("PDF..."));
pdfItem.setActionCommand("SAVE_AS_PDF");
pdfItem.addActionListener(this);
saveSubMenu.add(pdfItem);
}
result.add(saveSubMenu);
separator = true;
}
if (print) {
if (separator) {
result.addSeparator();
}
JMenuItem printItem = new JMenuItem(
localizationResources.getString("Print..."));
printItem.setActionCommand(PRINT_COMMAND);
printItem.addActionListener(this);
result.add(printItem);
separator = true;
}
if (zoom) {
if (separator) {
result.addSeparator();
}
JMenu zoomInMenu = new JMenu(
localizationResources.getString("Zoom_In"));
this.zoomInBothMenuItem = new JMenuItem(
localizationResources.getString("All_Axes"));
this.zoomInBothMenuItem.setActionCommand(ZOOM_IN_BOTH_COMMAND);
this.zoomInBothMenuItem.addActionListener(this);
zoomInMenu.add(this.zoomInBothMenuItem);
zoomInMenu.addSeparator();
this.zoomInDomainMenuItem = new JMenuItem(
localizationResources.getString("Domain_Axis"));
this.zoomInDomainMenuItem.setActionCommand(ZOOM_IN_DOMAIN_COMMAND);
this.zoomInDomainMenuItem.addActionListener(this);
zoomInMenu.add(this.zoomInDomainMenuItem);
this.zoomInRangeMenuItem = new JMenuItem(
localizationResources.getString("Range_Axis"));
this.zoomInRangeMenuItem.setActionCommand(ZOOM_IN_RANGE_COMMAND);
this.zoomInRangeMenuItem.addActionListener(this);
zoomInMenu.add(this.zoomInRangeMenuItem);
result.add(zoomInMenu);
JMenu zoomOutMenu = new JMenu(
localizationResources.getString("Zoom_Out"));
this.zoomOutBothMenuItem = new JMenuItem(
localizationResources.getString("All_Axes"));
this.zoomOutBothMenuItem.setActionCommand(ZOOM_OUT_BOTH_COMMAND);
this.zoomOutBothMenuItem.addActionListener(this);
zoomOutMenu.add(this.zoomOutBothMenuItem);
zoomOutMenu.addSeparator();
this.zoomOutDomainMenuItem = new JMenuItem(
localizationResources.getString("Domain_Axis"));
this.zoomOutDomainMenuItem.setActionCommand(
ZOOM_OUT_DOMAIN_COMMAND);
this.zoomOutDomainMenuItem.addActionListener(this);
zoomOutMenu.add(this.zoomOutDomainMenuItem);
this.zoomOutRangeMenuItem = new JMenuItem(
localizationResources.getString("Range_Axis"));
this.zoomOutRangeMenuItem.setActionCommand(ZOOM_OUT_RANGE_COMMAND);
this.zoomOutRangeMenuItem.addActionListener(this);
zoomOutMenu.add(this.zoomOutRangeMenuItem);
result.add(zoomOutMenu);
JMenu autoRangeMenu = new JMenu(
localizationResources.getString("Auto_Range"));
this.zoomResetBothMenuItem = new JMenuItem(
localizationResources.getString("All_Axes"));
this.zoomResetBothMenuItem.setActionCommand(
ZOOM_RESET_BOTH_COMMAND);
this.zoomResetBothMenuItem.addActionListener(this);
autoRangeMenu.add(this.zoomResetBothMenuItem);
autoRangeMenu.addSeparator();
this.zoomResetDomainMenuItem = new JMenuItem(
localizationResources.getString("Domain_Axis"));
this.zoomResetDomainMenuItem.setActionCommand(
ZOOM_RESET_DOMAIN_COMMAND);
this.zoomResetDomainMenuItem.addActionListener(this);
autoRangeMenu.add(this.zoomResetDomainMenuItem);
this.zoomResetRangeMenuItem = new JMenuItem(
localizationResources.getString("Range_Axis"));
this.zoomResetRangeMenuItem.setActionCommand(
ZOOM_RESET_RANGE_COMMAND);
this.zoomResetRangeMenuItem.addActionListener(this);
autoRangeMenu.add(this.zoomResetRangeMenuItem);
result.addSeparator();
result.add(autoRangeMenu);
}
return result;
}
/**
* The idea is to modify the zooming options depending on the type of chart
* being displayed by the panel.
*
* @param x horizontal position of the popup.
* @param y vertical position of the popup.
*/
protected void displayPopupMenu(int x, int y) {
if (this.popup == null) {
return;
}
// go through each zoom menu item and decide whether or not to
// enable it...
boolean isDomainZoomable = false;
boolean isRangeZoomable = false;
Plot plot = (this.chart != null ? this.chart.getPlot() : null);
if (plot instanceof Zoomable) {
Zoomable z = (Zoomable) plot;
isDomainZoomable = z.isDomainZoomable();
isRangeZoomable = z.isRangeZoomable();
}
if (this.zoomInDomainMenuItem != null) {
this.zoomInDomainMenuItem.setEnabled(isDomainZoomable);
}
if (this.zoomOutDomainMenuItem != null) {
this.zoomOutDomainMenuItem.setEnabled(isDomainZoomable);
}
if (this.zoomResetDomainMenuItem != null) {
this.zoomResetDomainMenuItem.setEnabled(isDomainZoomable);
}
if (this.zoomInRangeMenuItem != null) {
this.zoomInRangeMenuItem.setEnabled(isRangeZoomable);
}
if (this.zoomOutRangeMenuItem != null) {
this.zoomOutRangeMenuItem.setEnabled(isRangeZoomable);
}
if (this.zoomResetRangeMenuItem != null) {
this.zoomResetRangeMenuItem.setEnabled(isRangeZoomable);
}
if (this.zoomInBothMenuItem != null) {
this.zoomInBothMenuItem.setEnabled(isDomainZoomable
&& isRangeZoomable);
}
if (this.zoomOutBothMenuItem != null) {
this.zoomOutBothMenuItem.setEnabled(isDomainZoomable
&& isRangeZoomable);
}
if (this.zoomResetBothMenuItem != null) {
this.zoomResetBothMenuItem.setEnabled(isDomainZoomable
&& isRangeZoomable);
}
this.popup.show(this, x, y);
}
/**
* Updates the UI for a LookAndFeel change.
*/
@Override
public void updateUI() {
// here we need to update the UI for the popup menu, if the panel
// has one...
if (this.popup != null) {
SwingUtilities.updateComponentTreeUI(this.popup);
}
super.updateUI();
}
/**
* Provides serialization support.
*
* @param stream the output stream.
*
* @throws IOException if there is an I/O error.
*/
private void writeObject(ObjectOutputStream stream) throws IOException {
stream.defaultWriteObject();
SerialUtils.writePaint(this.zoomFillPaint, stream);
SerialUtils.writePaint(this.zoomOutlinePaint, stream);
}
/**
* Provides serialization support.
*
* @param stream the input stream.
*
* @throws IOException if there is an I/O error.
* @throws ClassNotFoundException if there is a classpath problem.
*/
private void readObject(ObjectInputStream stream)
throws IOException, ClassNotFoundException {
stream.defaultReadObject();
this.zoomFillPaint = SerialUtils.readPaint(stream);
this.zoomOutlinePaint = SerialUtils.readPaint(stream);
// we create a new but empty chartMouseListeners list
this.chartMouseListeners = new EventListenerList();
// register as a listener with sub-components...
if (this.chart != null) {
this.chart.addChangeListener(this);
}
}
}
jfree-jfreechart-cb8ff67/src/main/java/org/jfree/chart/ChartRenderingInfo.java 0000664 0000000 0000000 00000020324 14636042355 0027435 0 ustar 00root root 0000000 0000000 /* ===========================================================
* JFreeChart : a free chart library for the Java(tm) platform
* ===========================================================
*
* (C) Copyright 2000-present, by David Gilbert and Contributors.
*
* Project Info: http://www.jfree.org/jfreechart/index.html
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* [Oracle and Java are registered trademarks of Oracle and/or its affiliates.
* Other names may be trademarks of their respective owners.]
*
* -----------------------
* ChartRenderingInfo.java
* -----------------------
* (C) Copyright 2002-present, by David Gilbert.
*
* Original Author: David Gilbert;
* Contributor(s): Tracy Hiltbrand (equals/hashCode comply with EqualsVerifier);
*
*/
package org.jfree.chart;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Objects;
import org.jfree.chart.entity.EntityCollection;
import org.jfree.chart.entity.StandardEntityCollection;
import org.jfree.chart.plot.PlotRenderingInfo;
import org.jfree.chart.util.PublicCloneable;
import org.jfree.chart.util.SerialUtils;
/**
* A structure for storing rendering information from one call to the
* JFreeChart.draw() method.
*
* An instance of the {@link JFreeChart} class can draw itself within an
* arbitrary rectangle on any {@code Graphics2D}. It is assumed that
* client code will sometimes render the same chart in more than one view, so
* the {@link JFreeChart} instance does not retain any information about its
* rendered dimensions. This information can be useful sometimes, so you have
* the option to collect the information at each call to
* {@code JFreeChart.draw()}, by passing an instance of this
* {@code ChartRenderingInfo} class.
*/
public class ChartRenderingInfo implements Cloneable, Serializable {
/** For serialization. */
private static final long serialVersionUID = 2751952018173406822L;
/** The area in which the chart is drawn. */
private transient Rectangle2D chartArea;
/** Rendering info for the chart's plot (and subplots, if any). */
private PlotRenderingInfo plotInfo;
/**
* Storage for the chart entities. Since retaining entity information for
* charts with a large number of data points consumes a lot of memory, it
* is intended that you can set this to {@code null} to prevent the
* information being collected.
*/
private EntityCollection entities;
/**
* Constructs a new ChartRenderingInfo structure that can be used to
* collect information about the dimensions of a rendered chart.
*/
public ChartRenderingInfo() {
this(new StandardEntityCollection());
}
/**
* Constructs a new instance. If an entity collection is supplied, it will
* be populated with information about the entities in a chart. If it is
* {@code null}, no entity information (including tool tips) will
* be collected.
*
* @param entities an entity collection ({@code null} permitted).
*/
public ChartRenderingInfo(EntityCollection entities) {
this.chartArea = new Rectangle2D.Double();
this.plotInfo = new PlotRenderingInfo(this);
this.entities = entities;
}
/**
* Returns the area in which the chart was drawn.
*
* @return The area in which the chart was drawn.
*
* @see #setChartArea(Rectangle2D)
*/
public Rectangle2D getChartArea() {
return this.chartArea;
}
/**
* Sets the area in which the chart was drawn.
*
* @param area the chart area.
*
* @see #getChartArea()
*/
public void setChartArea(Rectangle2D area) {
this.chartArea.setRect(area);
}
/**
* Returns the collection of entities maintained by this instance.
*
* @return The entity collection (possibly {@code null}).
*
* @see #setEntityCollection(EntityCollection)
*/
public EntityCollection getEntityCollection() {
return this.entities;
}
/**
* Sets the entity collection.
*
* @param entities the entity collection ({@code null} permitted).
*
* @see #getEntityCollection()
*/
public void setEntityCollection(EntityCollection entities) {
this.entities = entities;
}
/**
* Clears the information recorded by this object.
*/
public void clear() {
this.chartArea.setRect(0.0, 0.0, 0.0, 0.0);
this.plotInfo = new PlotRenderingInfo(this);
if (this.entities != null) {
this.entities.clear();
}
}
/**
* Returns the rendering info for the chart's plot.
*
* @return The rendering info for the plot.
*/
public PlotRenderingInfo getPlotInfo() {
return this.plotInfo;
}
/**
* Tests this object for equality with an arbitrary object.
*
* @param obj the object to test against ({@code null} permitted).
*
* @return A boolean.
*/
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof ChartRenderingInfo)) {
return false;
}
ChartRenderingInfo that = (ChartRenderingInfo) obj;
if (!Objects.equals(this.chartArea, that.chartArea)) {
return false;
}
if (!Objects.equals(this.plotInfo, that.plotInfo)) {
return false;
}
if (!Objects.equals(this.entities, that.entities)) {
return false;
}
return true;
}
@Override
public int hashCode() {
int hash = 7;
hash = 37 * hash + Objects.hashCode(this.chartArea);
hash = 37 * hash + Objects.hashCode(this.plotInfo);
hash = 37 * hash + Objects.hashCode(this.entities);
return hash;
}
/**
* Returns a clone of this object.
*
* @return A clone.
*
* @throws CloneNotSupportedException if the object cannot be cloned.
*/
@Override
public ChartRenderingInfo clone() throws CloneNotSupportedException {
ChartRenderingInfo clone = (ChartRenderingInfo) super.clone();
if (this.chartArea != null) {
clone.chartArea = (Rectangle2D) this.chartArea.clone();
}
if (this.entities instanceof PublicCloneable) {
PublicCloneable pc = (PublicCloneable) this.entities;
clone.entities = (EntityCollection) pc.clone();
}
return clone;
}
/**
* Provides serialization support.
*
* @param stream the output stream.
*
* @throws IOException if there is an I/O error.
*/
private void writeObject(ObjectOutputStream stream) throws IOException {
stream.defaultWriteObject();
SerialUtils.writeShape(this.chartArea, stream);
}
/**
* Provides serialization support.
*
* @param stream the input stream.
*
* @throws IOException if there is an I/O error.
* @throws ClassNotFoundException if there is a classpath problem.
*/
private void readObject(ObjectInputStream stream)
throws IOException, ClassNotFoundException {
stream.defaultReadObject();
this.chartArea = (Rectangle2D) SerialUtils.readShape(stream);
}
}
jfree-jfreechart-cb8ff67/src/main/java/org/jfree/chart/ChartTheme.java 0000664 0000000 0000000 00000003777 14636042355 0025763 0 ustar 00root root 0000000 0000000 /* ===========================================================
* JFreeChart : a free chart library for the Java(tm) platform
* ===========================================================
*
* (C) Copyright 2000-present, by David Gilbert and Contributors.
*
* Project Info: http://www.jfree.org/jfreechart/index.html
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* [Oracle and Java are registered trademarks of Oracle and/or its affiliates.
* Other names may be trademarks of their respective owners.]
*
* ---------------
* ChartTheme.java
* ---------------
* (C) Copyright 2008-present, by David Gilbert.
*
* Original Author: David Gilbert;
* Contributor(s): -;
*
*/
package org.jfree.chart;
/**
* A {@link ChartTheme} a class that can apply a style or 'theme' to a chart.
* It can be implemented in an arbitrary manner, with the styling applied to
* the chart via the {@code apply(JFreeChart)} method. We provide one
* implementation ({@link StandardChartTheme}) that just mimics the manual
* process of calling methods to set various chart parameters.
*/
public interface ChartTheme {
/**
* Applies this theme to the supplied chart.
*
* @param chart the chart ({@code null} not permitted).
*/
void apply(JFreeChart chart);
}
jfree-jfreechart-cb8ff67/src/main/java/org/jfree/chart/ChartTransferable.java 0000664 0000000 0000000 00000020434 14636042355 0027316 0 ustar 00root root 0000000 0000000 /* ===========================================================
* JFreeChart : a free chart library for the Java(tm) platform
* ===========================================================
*
* (C) Copyright 2000-present, by David Gilbert and Contributors.
*
* Project Info: http://www.jfree.org/jfreechart/index.html
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* [Oracle and Java are registered trademarks of Oracle and/or its affiliates.
* Other names may be trademarks of their respective owners.]
*
* ----------------------
* ChartTransferable.java
* ----------------------
* (C) Copyright 2009-present, by David Gilbert.
*
* Original Author: David Gilbert;
* Contributor(s): -;
*
*/
package org.jfree.chart;
import java.awt.Graphics2D;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
/**
* A class used to represent a chart on the clipboard.
*/
public class ChartTransferable implements Transferable {
/** The data flavor. */
final DataFlavor imageFlavor = new DataFlavor(
"image/x-java-image; class=java.awt.Image", "Image");
/** The chart. */
private JFreeChart chart;
/** The width of the chart on the clipboard. */
private final int width;
/** The height of the chart on the clipboard. */
private final int height;
/**
* The smallest width at which the chart will be drawn (if necessary, the
* chart will then be scaled down to fit the requested width).
*/
private final int minDrawWidth;
/**
* The smallest height at which the chart will be drawn (if necessary, the
* chart will then be scaled down to fit the requested height).
*/
private final int minDrawHeight;
/**
* The largest width at which the chart will be drawn (if necessary, the
* chart will then be scaled up to fit the requested width).
*/
private final int maxDrawWidth;
/**
* The largest height at which the chart will be drawn (if necessary, the
* chart will then be scaled up to fit the requested height).
*/
private final int maxDrawHeight;
/**
* Creates a new chart selection.
*
* @param chart the chart.
* @param width the chart width.
* @param height the chart height.
*/
public ChartTransferable(JFreeChart chart, int width, int height) {
this(chart, width, height, true);
}
/**
* Creates a new chart selection.
*
* @param chart the chart.
* @param width the chart width.
* @param height the chart height.
* @param cloneData clone the dataset(s)?
*/
public ChartTransferable(JFreeChart chart, int width, int height,
boolean cloneData) {
this(chart, width, height, 0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE,
true);
}
/**
* Creates a new chart selection. The minimum and maximum drawing
* dimensions are used to match the scaling behaviour in the
* {@link ChartPanel} class.
*
* @param chart the chart.
* @param width the chart width.
* @param height the chart height.
* @param minDrawW the minimum drawing width.
* @param minDrawH the minimum drawing height.
* @param maxDrawW the maximum drawing width.
* @param maxDrawH the maximum drawing height.
* @param cloneData clone the dataset(s)?
*/
public ChartTransferable(JFreeChart chart, int width, int height,
int minDrawW, int minDrawH, int maxDrawW, int maxDrawH,
boolean cloneData) {
// we clone the chart because presumably there can be some delay
// between putting this instance on the system clipboard and
// actually having the getTransferData() method called...
try {
this.chart = (JFreeChart) chart.clone();
}
catch (CloneNotSupportedException e) {
this.chart = chart;
}
// FIXME: we've cloned the chart, but the dataset(s) aren't cloned
// and we should do that
this.width = width;
this.height = height;
this.minDrawWidth = minDrawW;
this.minDrawHeight = minDrawH;
this.maxDrawWidth = maxDrawW;
this.maxDrawHeight = maxDrawH;
}
/**
* Returns the data flavors supported.
*
* @return The data flavors supported.
*/
@Override
public DataFlavor[] getTransferDataFlavors() {
return new DataFlavor[] {this.imageFlavor};
}
/**
* Returns {@code true} if the specified flavor is supported.
*
* @param flavor the flavor.
*
* @return A boolean.
*/
@Override
public boolean isDataFlavorSupported(DataFlavor flavor) {
return this.imageFlavor.equals(flavor);
}
/**
* Returns the content for the requested flavor, if it is supported.
*
* @param flavor the requested flavor.
*
* @return The content.
*
* @throws java.awt.datatransfer.UnsupportedFlavorException if the flavor
* is not supported.
* @throws java.io.IOException if there is an IO problem.
*/
@Override
public Object getTransferData(DataFlavor flavor)
throws UnsupportedFlavorException, IOException {
if (this.imageFlavor.equals(flavor)) {
return createBufferedImage(this.chart, this.width, this.height,
this.minDrawWidth, this.minDrawHeight, this.maxDrawWidth,
this.maxDrawHeight);
} else {
throw new UnsupportedFlavorException(flavor);
}
}
/**
* A utility method that creates an image of a chart, with scaling.
*
* @param chart the chart.
* @param w the image width.
* @param h the image height.
* @param minDrawW the minimum width for chart drawing.
* @param minDrawH the minimum height for chart drawing.
* @param maxDrawW the maximum width for chart drawing.
* @param maxDrawH the maximum height for chart drawing.
*
* @return A chart image.
*/
private BufferedImage createBufferedImage(JFreeChart chart, int w, int h,
int minDrawW, int minDrawH, int maxDrawW, int maxDrawH) {
BufferedImage image = new BufferedImage(w, h,
BufferedImage.TYPE_INT_RGB); // bug #182
Graphics2D g2 = image.createGraphics();
// work out if scaling is required...
boolean scale = false;
double drawWidth = w;
double drawHeight = h;
double scaleX = 1.0;
double scaleY = 1.0;
if (drawWidth < minDrawW) {
scaleX = drawWidth / minDrawW;
drawWidth = minDrawW;
scale = true;
} else if (drawWidth > maxDrawW) {
scaleX = drawWidth / maxDrawW;
drawWidth = maxDrawW;
scale = true;
}
if (drawHeight < minDrawH) {
scaleY = drawHeight / minDrawH;
drawHeight = minDrawH;
scale = true;
} else if (drawHeight > maxDrawH) {
scaleY = drawHeight / maxDrawH;
drawHeight = maxDrawH;
scale = true;
}
Rectangle2D chartArea = new Rectangle2D.Double(0.0, 0.0, drawWidth,
drawHeight);
if (scale) {
AffineTransform st = AffineTransform.getScaleInstance(scaleX,
scaleY);
g2.transform(st);
}
chart.draw(g2, chartArea, null, null);
g2.dispose();
return image;
}
}
jfree-jfreechart-cb8ff67/src/main/java/org/jfree/chart/ChartUtils.java 0000664 0000000 0000000 00000064316 14636042355 0026015 0 ustar 00root root 0000000 0000000 /* ===========================================================
* JFreeChart : a free chart library for the Java(tm) platform
* ===========================================================
*
* (C) Copyright 2000-present, by David Gilbert and Contributors.
*
* Project Info: http://www.jfree.org/jfreechart/index.html
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* [Oracle and Java are registered trademarks of Oracle and/or its affiliates.
* Other names may be trademarks of their respective owners.]
*
* ---------------
* ChartUtils.java
* ---------------
* (C) Copyright 2001-present, by David Gilbert and Contributors.
*
* Original Author: David Gilbert;
* Contributor(s): Wolfgang Irler;
* Richard Atkinson;
* Xavier Poinsard;
*
*/
package org.jfree.chart;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import org.jfree.chart.encoders.EncoderUtil;
import org.jfree.chart.encoders.ImageFormat;
import org.jfree.chart.imagemap.ImageMapUtils;
import org.jfree.chart.imagemap.OverLIBToolTipTagFragmentGenerator;
import org.jfree.chart.imagemap.StandardToolTipTagFragmentGenerator;
import org.jfree.chart.imagemap.StandardURLTagFragmentGenerator;
import org.jfree.chart.imagemap.ToolTipTagFragmentGenerator;
import org.jfree.chart.imagemap.URLTagFragmentGenerator;
import org.jfree.chart.util.Args;
/**
* A collection of utility methods for JFreeChart. Includes methods for
* converting charts to image formats (PNG and JPEG) plus creating simple HTML
* image maps.
*
* @see ImageMapUtils
*/
public abstract class ChartUtils {
/**
* Applies the current theme to the specified chart. This method is
* provided for convenience, the theme itself is stored in the
* {@link ChartFactory} class.
*
* @param chart the chart ({@code null} not permitted).
*/
public static void applyCurrentTheme(JFreeChart chart) {
ChartFactory.getChartTheme().apply(chart);
}
/**
* Writes a chart to an output stream in PNG format.
*
* @param out the output stream ({@code null} not permitted).
* @param chart the chart ({@code null} not permitted).
* @param width the image width.
* @param height the image height.
*
* @throws IOException if there are any I/O errors.
*/
public static void writeChartAsPNG(OutputStream out, JFreeChart chart,
int width, int height) throws IOException {
// defer argument checking...
writeChartAsPNG(out, chart, width, height, null);
}
/**
* Writes a chart to an output stream in PNG format.
*
* @param out the output stream ({@code null} not permitted).
* @param chart the chart ({@code null} not permitted).
* @param width the image width.
* @param height the image height.
* @param encodeAlpha encode alpha?
* @param compression the compression level (0-9).
*
* @throws IOException if there are any I/O errors.
*/
public static void writeChartAsPNG(OutputStream out, JFreeChart chart,
int width, int height, boolean encodeAlpha, int compression)
throws IOException {
// defer argument checking...
ChartUtils.writeChartAsPNG(out, chart, width, height, null,
encodeAlpha, compression);
}
/**
* Writes a chart to an output stream in PNG format. This method allows
* you to pass in a {@link ChartRenderingInfo} object, to collect
* information about the chart dimensions/entities. You will need this
* info if you want to create an HTML image map.
*
* @param out the output stream ({@code null} not permitted).
* @param chart the chart ({@code null} not permitted).
* @param width the image width.
* @param height the image height.
* @param info the chart rendering info ({@code null} permitted).
*
* @throws IOException if there are any I/O errors.
*/
public static void writeChartAsPNG(OutputStream out, JFreeChart chart,
int width, int height, ChartRenderingInfo info)
throws IOException {
Args.nullNotPermitted(chart, "chart");
BufferedImage bufferedImage
= chart.createBufferedImage(width, height, info);
EncoderUtil.writeBufferedImage(bufferedImage, ImageFormat.PNG, out);
}
/**
* Writes a chart to an output stream in PNG format. This method allows
* you to pass in a {@link ChartRenderingInfo} object, to collect
* information about the chart dimensions/entities. You will need this
* info if you want to create an HTML image map.
*
* @param out the output stream ({@code null} not permitted).
* @param chart the chart ({@code null} not permitted).
* @param width the image width.
* @param height the image height.
* @param info carries back chart rendering info ({@code null}
* permitted).
* @param encodeAlpha encode alpha?
* @param compression the PNG compression level (0-9).
*
* @throws IOException if there are any I/O errors.
*/
public static void writeChartAsPNG(OutputStream out, JFreeChart chart,
int width, int height, ChartRenderingInfo info,
boolean encodeAlpha, int compression) throws IOException {
Args.nullNotPermitted(out, "out");
Args.nullNotPermitted(chart, "chart");
BufferedImage chartImage = chart.createBufferedImage(width, height,
BufferedImage.TYPE_INT_ARGB, info);
ChartUtils.writeBufferedImageAsPNG(out, chartImage, encodeAlpha,
compression);
}
/**
* Writes a scaled version of a chart to an output stream in PNG format.
*
* @param out the output stream ({@code null} not permitted).
* @param chart the chart ({@code null} not permitted).
* @param width the unscaled chart width.
* @param height the unscaled chart height.
* @param widthScaleFactor the horizontal scale factor.
* @param heightScaleFactor the vertical scale factor.
*
* @throws IOException if there are any I/O problems.
*/
public static void writeScaledChartAsPNG(OutputStream out,
JFreeChart chart, int width, int height, int widthScaleFactor,
int heightScaleFactor) throws IOException {
Args.nullNotPermitted(out, "out");
Args.nullNotPermitted(chart, "chart");
double desiredWidth = width * widthScaleFactor;
double desiredHeight = height * heightScaleFactor;
double defaultWidth = width;
double defaultHeight = height;
boolean scale = false;
// get desired width and height from somewhere then...
if ((widthScaleFactor != 1) || (heightScaleFactor != 1)) {
scale = true;
}
double scaleX = desiredWidth / defaultWidth;
double scaleY = desiredHeight / defaultHeight;
BufferedImage image = new BufferedImage((int) desiredWidth,
(int) desiredHeight, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = image.createGraphics();
if (scale) {
AffineTransform saved = g2.getTransform();
g2.transform(AffineTransform.getScaleInstance(scaleX, scaleY));
chart.draw(g2, new Rectangle2D.Double(0, 0, defaultWidth,
defaultHeight), null, null);
g2.setTransform(saved);
g2.dispose();
}
else {
chart.draw(g2, new Rectangle2D.Double(0, 0, defaultWidth,
defaultHeight), null, null);
}
out.write(encodeAsPNG(image));
}
/**
* Saves a chart to the specified file in PNG format.
*
* @param file the file name ({@code null} not permitted).
* @param chart the chart ({@code null} not permitted).
* @param width the image width.
* @param height the image height.
*
* @throws IOException if there are any I/O errors.
*/
public static void saveChartAsPNG(File file, JFreeChart chart,
int width, int height) throws IOException {
// defer argument checking...
saveChartAsPNG(file, chart, width, height, null);
}
/**
* Saves a chart to a file in PNG format. This method allows you to pass
* in a {@link ChartRenderingInfo} object, to collect information about the
* chart dimensions/entities. You will need this info if you want to
* create an HTML image map.
*
* @param file the file ({@code null} not permitted).
* @param chart the chart ({@code null} not permitted).
* @param width the image width.
* @param height the image height.
* @param info the chart rendering info ({@code null} permitted).
*
* @throws IOException if there are any I/O errors.
*/
public static void saveChartAsPNG(File file, JFreeChart chart,
int width, int height, ChartRenderingInfo info)
throws IOException {
Args.nullNotPermitted(file, "file");
OutputStream out = new BufferedOutputStream(new FileOutputStream(file));
try {
ChartUtils.writeChartAsPNG(out, chart, width, height, info);
}
finally {
out.close();
}
}
/**
* Saves a chart to a file in PNG format. This method allows you to pass
* in a {@link ChartRenderingInfo} object, to collect information about the
* chart dimensions/entities. You will need this info if you want to
* create an HTML image map.
*
* @param file the file ({@code null} not permitted).
* @param chart the chart ({@code null} not permitted).
* @param width the image width.
* @param height the image height.
* @param info the chart rendering info ({@code null} permitted).
* @param encodeAlpha encode alpha?
* @param compression the PNG compression level (0-9).
*
* @throws IOException if there are any I/O errors.
*/
public static void saveChartAsPNG(File file, JFreeChart chart,
int width, int height, ChartRenderingInfo info, boolean encodeAlpha,
int compression) throws IOException {
Args.nullNotPermitted(file, "file");
Args.nullNotPermitted(chart, "chart");
OutputStream out = new BufferedOutputStream(new FileOutputStream(file));
try {
writeChartAsPNG(out, chart, width, height, info, encodeAlpha,
compression);
}
finally {
out.close();
}
}
/**
* Writes a chart to an output stream in JPEG format. Please note that
* JPEG is a poor format for chart images, use PNG if possible.
*
* @param out the output stream ({@code null} not permitted).
* @param chart the chart ({@code null} not permitted).
* @param width the image width.
* @param height the image height.
*
* @throws IOException if there are any I/O errors.
*/
public static void writeChartAsJPEG(OutputStream out,
JFreeChart chart, int width, int height) throws IOException {
// defer argument checking...
writeChartAsJPEG(out, chart, width, height, null);
}
/**
* Writes a chart to an output stream in JPEG format. Please note that
* JPEG is a poor format for chart images, use PNG if possible.
*
* @param out the output stream ({@code null} not permitted).
* @param quality the quality setting.
* @param chart the chart ({@code null} not permitted).
* @param width the image width.
* @param height the image height.
*
* @throws IOException if there are any I/O errors.
*/
public static void writeChartAsJPEG(OutputStream out, float quality,
JFreeChart chart, int width, int height) throws IOException {
// defer argument checking...
ChartUtils.writeChartAsJPEG(out, quality, chart, width, height,
null);
}
/**
* Writes a chart to an output stream in JPEG format. This method allows
* you to pass in a {@link ChartRenderingInfo} object, to collect
* information about the chart dimensions/entities. You will need this
* info if you want to create an HTML image map.
*
* @param out the output stream ({@code null} not permitted).
* @param chart the chart ({@code null} not permitted).
* @param width the image width.
* @param height the image height.
* @param info the chart rendering info ({@code null} permitted).
*
* @throws IOException if there are any I/O errors.
*/
public static void writeChartAsJPEG(OutputStream out, JFreeChart chart,
int width, int height, ChartRenderingInfo info)
throws IOException {
Args.nullNotPermitted(out, "out");
Args.nullNotPermitted(chart, "chart");
BufferedImage image = chart.createBufferedImage(width, height,
BufferedImage.TYPE_INT_RGB, info);
EncoderUtil.writeBufferedImage(image, ImageFormat.JPEG, out);
}
/**
* Writes a chart to an output stream in JPEG format. This method allows
* you to pass in a {@link ChartRenderingInfo} object, to collect
* information about the chart dimensions/entities. You will need this
* info if you want to create an HTML image map.
*
* @param out the output stream ({@code null} not permitted).
* @param quality the output quality (0.0f to 1.0f).
* @param chart the chart ({@code null} not permitted).
* @param width the image width.
* @param height the image height.
* @param info the chart rendering info ({@code null} permitted).
*
* @throws IOException if there are any I/O errors.
*/
public static void writeChartAsJPEG(OutputStream out, float quality,
JFreeChart chart, int width, int height, ChartRenderingInfo info)
throws IOException {
Args.nullNotPermitted(out, "out");
Args.nullNotPermitted(chart, "chart");
BufferedImage image = chart.createBufferedImage(width, height,
BufferedImage.TYPE_INT_RGB, info);
EncoderUtil.writeBufferedImage(image, ImageFormat.JPEG, out, quality);
}
/**
* Saves a chart to a file in JPEG format.
*
* @param file the file ({@code null} not permitted).
* @param chart the chart ({@code null} not permitted).
* @param width the image width.
* @param height the image height.
*
* @throws IOException if there are any I/O errors.
*/
public static void saveChartAsJPEG(File file, JFreeChart chart,
int width, int height) throws IOException {
// defer argument checking...
saveChartAsJPEG(file, chart, width, height, null);
}
/**
* Saves a chart to a file in JPEG format.
*
* @param file the file ({@code null} not permitted).
* @param quality the JPEG quality setting.
* @param chart the chart ({@code null} not permitted).
* @param width the image width.
* @param height the image height.
*
* @throws IOException if there are any I/O errors.
*/
public static void saveChartAsJPEG(File file, float quality,
JFreeChart chart, int width, int height) throws IOException {
// defer argument checking...
saveChartAsJPEG(file, quality, chart, width, height, null);
}
/**
* Saves a chart to a file in JPEG format. This method allows you to pass
* in a {@link ChartRenderingInfo} object, to collect information about the
* chart dimensions/entities. You will need this info if you want to
* create an HTML image map.
*
* @param file the file name ({@code null} not permitted).
* @param chart the chart ({@code null} not permitted).
* @param width the image width.
* @param height the image height.
* @param info the chart rendering info ({@code null} permitted).
*
* @throws IOException if there are any I/O errors.
*/
public static void saveChartAsJPEG(File file, JFreeChart chart,
int width, int height, ChartRenderingInfo info) throws IOException {
Args.nullNotPermitted(file, "file");
Args.nullNotPermitted(chart, "chart");
OutputStream out = new BufferedOutputStream(new FileOutputStream(file));
try {
writeChartAsJPEG(out, chart, width, height, info);
}
finally {
out.close();
}
}
/**
* Saves a chart to a file in JPEG format. This method allows you to pass
* in a {@link ChartRenderingInfo} object, to collect information about the
* chart dimensions/entities. You will need this info if you want to
* create an HTML image map.
*
* @param file the file name ({@code null} not permitted).
* @param quality the quality setting.
* @param chart the chart ({@code null} not permitted).
* @param width the image width.
* @param height the image height.
* @param info the chart rendering info ({@code null} permitted).
*
* @throws IOException if there are any I/O errors.
*/
public static void saveChartAsJPEG(File file, float quality,
JFreeChart chart, int width, int height,
ChartRenderingInfo info) throws IOException {
Args.nullNotPermitted(file, "file");
Args.nullNotPermitted(chart, "chart");
OutputStream out = new BufferedOutputStream(new FileOutputStream(
file));
try {
writeChartAsJPEG(out, quality, chart, width, height, info);
}
finally {
out.close();
}
}
/**
* Writes a {@link BufferedImage} to an output stream in JPEG format.
*
* @param out the output stream ({@code null} not permitted).
* @param image the image ({@code null} not permitted).
*
* @throws IOException if there are any I/O errors.
*/
public static void writeBufferedImageAsJPEG(OutputStream out,
BufferedImage image) throws IOException {
// defer argument checking...
writeBufferedImageAsJPEG(out, 0.75f, image);
}
/**
* Writes a {@link BufferedImage} to an output stream in JPEG format.
*
* @param out the output stream ({@code null} not permitted).
* @param quality the image quality (0.0f to 1.0f).
* @param image the image ({@code null} not permitted).
*
* @throws IOException if there are any I/O errors.
*/
public static void writeBufferedImageAsJPEG(OutputStream out, float quality,
BufferedImage image) throws IOException {
EncoderUtil.writeBufferedImage(image, ImageFormat.JPEG, out, quality);
}
/**
* Writes a {@link BufferedImage} to an output stream in PNG format.
*
* @param out the output stream ({@code null} not permitted).
* @param image the image ({@code null} not permitted).
*
* @throws IOException if there are any I/O errors.
*/
public static void writeBufferedImageAsPNG(OutputStream out,
BufferedImage image) throws IOException {
EncoderUtil.writeBufferedImage(image, ImageFormat.PNG, out);
}
/**
* Writes a {@link BufferedImage} to an output stream in PNG format.
*
* @param out the output stream ({@code null} not permitted).
* @param image the image ({@code null} not permitted).
* @param encodeAlpha encode alpha?
* @param compression the compression level (0-9).
*
* @throws IOException if there are any I/O errors.
*/
public static void writeBufferedImageAsPNG(OutputStream out,
BufferedImage image, boolean encodeAlpha, int compression)
throws IOException {
EncoderUtil.writeBufferedImage(image, ImageFormat.PNG, out,
compression, encodeAlpha);
}
/**
* Encodes a {@link BufferedImage} to PNG format.
*
* @param image the image ({@code null} not permitted).
*
* @return A byte array in PNG format.
*
* @throws IOException if there is an I/O problem.
*/
public static byte[] encodeAsPNG(BufferedImage image) throws IOException {
return EncoderUtil.encode(image, ImageFormat.PNG);
}
/**
* Encodes a {@link BufferedImage} to PNG format.
*
* @param image the image ({@code null} not permitted).
* @param encodeAlpha encode alpha?
* @param compression the PNG compression level (0-9).
*
* @return The byte array in PNG format.
*
* @throws IOException if there is an I/O problem.
*/
public static byte[] encodeAsPNG(BufferedImage image, boolean encodeAlpha,
int compression) throws IOException {
return EncoderUtil.encode(image, ImageFormat.PNG, compression,
encodeAlpha);
}
/**
* Writes an image map to an output stream.
*
* @param writer the writer ({@code null} not permitted).
* @param name the map name ({@code null} not permitted).
* @param info the chart rendering info ({@code null} not permitted).
* @param useOverLibForToolTips whether to use OverLIB for tooltips
* (http://www.bosrup.com/web/overlib/).
*
* @throws IOException if there are any I/O errors.
*/
public static void writeImageMap(PrintWriter writer, String name,
ChartRenderingInfo info, boolean useOverLibForToolTips)
throws IOException {
ToolTipTagFragmentGenerator toolTipTagFragmentGenerator;
if (useOverLibForToolTips) {
toolTipTagFragmentGenerator
= new OverLIBToolTipTagFragmentGenerator();
}
else {
toolTipTagFragmentGenerator
= new StandardToolTipTagFragmentGenerator();
}
ImageMapUtils.writeImageMap(writer, name, info,
toolTipTagFragmentGenerator,
new StandardURLTagFragmentGenerator());
}
/**
* Writes an image map to the specified writer.
*
* @param writer the writer ({@code null} not permitted).
* @param name the map name ({@code null} not permitted).
* @param info the chart rendering info ({@code null} not permitted).
* @param toolTipTagFragmentGenerator a generator for the HTML fragment
* that will contain the tooltip text ({@code null} not permitted
* if {@code info} contains tooltip information).
* @param urlTagFragmentGenerator a generator for the HTML fragment that
* will contain the URL reference ({@code null} not permitted if
* {@code info} contains URLs).
*
* @throws IOException if there are any I/O errors.
*/
public static void writeImageMap(PrintWriter writer, String name,
ChartRenderingInfo info,
ToolTipTagFragmentGenerator toolTipTagFragmentGenerator,
URLTagFragmentGenerator urlTagFragmentGenerator)
throws IOException {
writer.println(ImageMapUtils.getImageMap(name, info,
toolTipTagFragmentGenerator, urlTagFragmentGenerator));
}
/**
* Creates an HTML image map. This method maps to
* {@link ImageMapUtils#getImageMap(String, ChartRenderingInfo,
* ToolTipTagFragmentGenerator, URLTagFragmentGenerator)}, using default
* generators.
*
* @param name the map name ({@code null} not permitted).
* @param info the chart rendering info ({@code null} not permitted).
*
* @return The map tag.
*/
public static String getImageMap(String name, ChartRenderingInfo info) {
return ImageMapUtils.getImageMap(name, info,
new StandardToolTipTagFragmentGenerator(),
new StandardURLTagFragmentGenerator());
}
/**
* Creates an HTML image map. This method maps directly to
* {@link ImageMapUtils#getImageMap(String, ChartRenderingInfo,
* ToolTipTagFragmentGenerator, URLTagFragmentGenerator)}.
*
* @param name the map name ({@code null} not permitted).
* @param info the chart rendering info ({@code null} not permitted).
* @param toolTipTagFragmentGenerator a generator for the HTML fragment
* that will contain the tooltip text ({@code null} not permitted
* if {@code info} contains tooltip information).
* @param urlTagFragmentGenerator a generator for the HTML fragment that
* will contain the URL reference ({@code null} not permitted if
* {@code info} contains URLs).
*
* @return The map tag.
*/
public static String getImageMap(String name, ChartRenderingInfo info,
ToolTipTagFragmentGenerator toolTipTagFragmentGenerator,
URLTagFragmentGenerator urlTagFragmentGenerator) {
return ImageMapUtils.getImageMap(name, info,
toolTipTagFragmentGenerator, urlTagFragmentGenerator);
}
}
jfree-jfreechart-cb8ff67/src/main/java/org/jfree/chart/HashUtils.java 0000664 0000000 0000000 00000024014 14636042355 0025626 0 ustar 00root root 0000000 0000000 /* ===========================================================
* JFreeChart : a free chart library for the Java(tm) platform
* ===========================================================
*
* (C) Copyright 2000-present, by David Gilbert and Contributors.
*
* Project Info: http://www.jfree.org/jfreechart/index.html
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* [Oracle and Java are registered trademarks of Oracle and/or its affiliates.
* Other names may be trademarks of their respective owners.]
*
* --------------
* HashUtils.java
* --------------
* (C) Copyright 2006-present, by David Gilbert;
*
* Original Author: David Gilbert;
* Contributor(s): -;
*
*/
package org.jfree.chart;
import java.awt.GradientPaint;
import java.awt.Paint;
import java.awt.Stroke;
import org.jfree.chart.util.BooleanList;
import org.jfree.chart.util.PaintList;
import org.jfree.chart.util.StrokeList;
/**
* Some utility methods for calculating hash codes.
*/
public class HashUtils {
/**
* Returns a hash code for a {@code Paint} instance. If
* {@code p} is {@code null}, this method returns zero.
*
* @param p the paint ({@code null} permitted).
*
* @return The hash code.
*/
public static int hashCodeForPaint(Paint p) {
if (p == null) {
return 0;
}
int result;
// handle GradientPaint as a special case
if (p instanceof GradientPaint) {
GradientPaint gp = (GradientPaint) p;
result = 193;
result = 37 * result + gp.getColor1().hashCode();
result = 37 * result + gp.getPoint1().hashCode();
result = 37 * result + gp.getColor2().hashCode();
result = 37 * result + gp.getPoint2().hashCode();
}
else {
// we assume that all other Paint instances implement equals() and
// hashCode()...of course that might not be true, but what can we
// do about it?
result = p.hashCode();
}
return result;
}
/**
* Returns a hash code for a {@code double[]} instance. If the array
* is {@code null}, this method returns zero.
*
* @param a the array ({@code null} permitted).
*
* @return The hash code.
*/
public static int hashCodeForDoubleArray(double[] a) {
if (a == null) {
return 0;
}
int result = 193;
long temp;
for (int i = 0; i < a.length; i++) {
temp = Double.doubleToLongBits(a[i]);
result = 29 * result + (int) (temp ^ (temp >>> 32));
}
return result;
}
/**
* Returns a hash value based on a seed value and the value of a boolean
* primitive.
*
* @param pre the seed value.
* @param b the boolean value.
*
* @return A hash value.
*/
public static int hashCode(int pre, boolean b) {
return 37 * pre + (b ? 0 : 1);
}
/**
* Returns a hash value based on a seed value and the value of an int
* primitive.
*
* @param pre the seed value.
* @param i the int value.
*
* @return A hash value.
*/
public static int hashCode(int pre, int i) {
return 37 * pre + i;
}
/**
* Returns a hash value based on a seed value and the value of a double
* primitive.
*
* @param pre the seed value.
* @param d the double value.
*
* @return A hash value.
*/
public static int hashCode(int pre, double d) {
long l = Double.doubleToLongBits(d);
return 37 * pre + (int) (l ^ (l >>> 32));
}
/**
* Returns a hash value based on a seed value and a paint instance.
*
* @param pre the seed value.
* @param p the paint ({@code null} permitted).
*
* @return A hash value.
*/
public static int hashCode(int pre, Paint p) {
return 37 * pre + hashCodeForPaint(p);
}
/**
* Returns a hash value based on a seed value and a stroke instance.
*
* @param pre the seed value.
* @param s the stroke ({@code null} permitted).
*
* @return A hash value.
*/
public static int hashCode(int pre, Stroke s) {
int h = (s != null ? s.hashCode() : 0);
return 37 * pre + h;
}
/**
* Returns a hash value based on a seed value and a string instance.
*
* @param pre the seed value.
* @param s the string ({@code null} permitted).
*
* @return A hash value.
*/
public static int hashCode(int pre, String s) {
int h = (s != null ? s.hashCode() : 0);
return 37 * pre + h;
}
/**
* Returns a hash value based on a seed value and a {@code Comparable}
* instance.
*
* @param pre the seed value.
* @param c the comparable ({@code null} permitted).
*
* @return A hash value.
*/
public static int hashCode(int pre, Comparable c) {
int h = (c != null ? c.hashCode() : 0);
return 37 * pre + h;
}
/**
* Returns a hash value based on a seed value and an {@code Object}
* instance.
*
* @param pre the seed value.
* @param obj the object ({@code null} permitted).
*
* @return A hash value.
*/
public static int hashCode(int pre, Object obj) {
int h = (obj != null ? obj.hashCode() : 0);
return 37 * pre + h;
}
/**
* Computes a hash code for a {@link BooleanList}. In the latest version
* of JCommon, the {@link BooleanList} class should implement the hashCode()
* method correctly, but we compute it here anyway so that we can work with
* older versions of JCommon (back to 1.0.0).
*
* @param pre the seed value.
* @param list the list ({@code null} permitted).
*
* @return The hash code.
*/
public static int hashCode(int pre, BooleanList list) {
if (list == null) {
return pre;
}
int result = 127;
int size = list.size();
result = HashUtils.hashCode(result, size);
// for efficiency, we just use the first, last and middle items to
// compute a hashCode...
if (size > 0) {
result = HashUtils.hashCode(result, list.getBoolean(0));
if (size > 1) {
result = HashUtils.hashCode(result,
list.getBoolean(size - 1));
if (size > 2) {
result = HashUtils.hashCode(result,
list.getBoolean(size / 2));
}
}
}
return 37 * pre + result;
}
/**
* Computes a hash code for a {@link PaintList}. In the latest version
* of JCommon, the {@link PaintList} class should implement the hashCode()
* method correctly, but we compute it here anyway so that we can work with
* older versions of JCommon (back to 1.0.0).
*
* @param pre the seed value.
* @param list the list ({@code null} permitted).
*
* @return The hash code.
*/
public static int hashCode(int pre, PaintList list) {
if (list == null) {
return pre;
}
int result = 127;
int size = list.size();
result = HashUtils.hashCode(result, size);
// for efficiency, we just use the first, last and middle items to
// compute a hashCode...
if (size > 0) {
result = HashUtils.hashCode(result, list.getPaint(0));
if (size > 1) {
result = HashUtils.hashCode(result,
list.getPaint(size - 1));
if (size > 2) {
result = HashUtils.hashCode(result,
list.getPaint(size / 2));
}
}
}
return 37 * pre + result;
}
/**
* Computes a hash code for a {@link StrokeList}. In the latest version
* of JCommon, the {@link StrokeList} class should implement the hashCode()
* method correctly, but we compute it here anyway so that we can work with
* older versions of JCommon (back to 1.0.0).
*
* @param pre the seed value.
* @param list the list ({@code null} permitted).
*
* @return The hash code.
*/
public static int hashCode(int pre, StrokeList list) {
if (list == null) {
return pre;
}
int result = 127;
int size = list.size();
result = HashUtils.hashCode(result, size);
// for efficiency, we just use the first, last and middle items to
// compute a hashCode...
if (size > 0) {
result = HashUtils.hashCode(result, list.getStroke(0));
if (size > 1) {
result = HashUtils.hashCode(result,
list.getStroke(size - 1));
if (size > 2) {
result = HashUtils.hashCode(result,
list.getStroke(size / 2));
}
}
}
return 37 * pre + result;
}
}
jfree-jfreechart-cb8ff67/src/main/java/org/jfree/chart/JFreeChart.java 0000664 0000000 0000000 00000161055 14636042355 0025706 0 ustar 00root root 0000000 0000000 /* ===========================================================
* JFreeChart : a free chart library for the Java(tm) platform
* ===========================================================
*
* (C) Copyright 2000-present, by David Gilbert and Contributors.
*
* Project Info: http://www.jfree.org/jfreechart/index.html
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* [Oracle and Java are registered trademarks of Oracle and/or its affiliates.
* Other names may be trademarks of their respective owners.]
*
* ---------------
* JFreeChart.java
* ---------------
* (C) Copyright 2000-present, by David Gilbert and Contributors.
*
* Original Author: David Gilbert;
* Contributor(s): Andrzej Porebski;
* David Li;
* Wolfgang Irler;
* Christian W. Zuckschwerdt;
* Klaus Rheinwald;
* Nicolas Brodu;
* Peter Kolb (patch 2603321);
* Tracy Hiltbrand (equals/hashCode comply with EqualsVerifier);
*
* NOTE: The above list of contributors lists only the people that have
* contributed to this source file (JFreeChart.java) - for a list of ALL
* contributors to the project, please see the README.md file.
*
*/
package org.jfree.chart;
import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Paint;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import javax.swing.UIManager;
import javax.swing.event.EventListenerList;
import org.jfree.chart.block.BlockParams;
import org.jfree.chart.block.EntityBlockResult;
import org.jfree.chart.block.LengthConstraintType;
import org.jfree.chart.block.RectangleConstraint;
import org.jfree.chart.entity.EntityCollection;
import org.jfree.chart.entity.JFreeChartEntity;
import org.jfree.chart.event.ChartChangeEvent;
import org.jfree.chart.event.ChartChangeListener;
import org.jfree.chart.event.ChartProgressEvent;
import org.jfree.chart.event.ChartProgressListener;
import org.jfree.chart.event.PlotChangeEvent;
import org.jfree.chart.event.PlotChangeListener;
import org.jfree.chart.event.TitleChangeEvent;
import org.jfree.chart.event.TitleChangeListener;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.Plot;
import org.jfree.chart.plot.PlotRenderingInfo;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.title.LegendTitle;
import org.jfree.chart.title.TextTitle;
import org.jfree.chart.title.Title;
import org.jfree.chart.ui.Align;
import org.jfree.chart.ui.Drawable;
import org.jfree.chart.ui.HorizontalAlignment;
import org.jfree.chart.ui.RectangleEdge;
import org.jfree.chart.ui.RectangleInsets;
import org.jfree.chart.ui.Size2D;
import org.jfree.chart.ui.VerticalAlignment;
import org.jfree.chart.util.PaintUtils;
import org.jfree.chart.util.Args;
import org.jfree.chart.util.SerialUtils;
import org.jfree.data.Range;
/**
* A chart class implemented using the Java 2D APIs. The current version
* supports bar charts, line charts, pie charts and xy plots (including time
* series data).
*
* JFreeChart coordinates several objects to achieve its aim of being able to
* draw a chart on a Java 2D graphics device: a list of {@link Title} objects
* (which often includes the chart's legend), a {@link Plot} and a
* {@link org.jfree.data.general.Dataset} (the plot in turn manages a
* domain axis and a range axis).
*
* You should use a {@link ChartPanel} to display a chart in a GUI.
*
* The {@link ChartFactory} class contains static methods for creating
* 'ready-made' charts.
*
* @see ChartPanel
* @see ChartFactory
* @see Title
* @see Plot
*/
public class JFreeChart implements Drawable, TitleChangeListener,
PlotChangeListener, Serializable, Cloneable {
/** For serialization. */
private static final long serialVersionUID = -3470703747817429120L;
/** The default font for titles. */
public static final Font DEFAULT_TITLE_FONT
= new Font("SansSerif", Font.BOLD, 18);
/** The default background color. */
public static final Paint DEFAULT_BACKGROUND_PAINT
= UIManager.getColor("Panel.background");
/** The default background image. */
public static final Image DEFAULT_BACKGROUND_IMAGE = null;
/** The default background image alignment. */
public static final int DEFAULT_BACKGROUND_IMAGE_ALIGNMENT = Align.FIT;
/** The default background image alpha. */
public static final float DEFAULT_BACKGROUND_IMAGE_ALPHA = 0.5f;
/**
* The key for a rendering hint that can suppress the generation of a
* shadow effect when drawing the chart. The hint value must be a
* Boolean.
*/
public static final RenderingHints.Key KEY_SUPPRESS_SHADOW_GENERATION
= new RenderingHints.Key(0) {
@Override
public boolean isCompatibleValue(Object val) {
return val instanceof Boolean;
}
};
/**
* Rendering hints that will be used for chart drawing. This should never
* be {@code null}.
*/
private transient RenderingHints renderingHints;
/** The chart id (optional, will be used by JFreeSVG export). */
private String id;
/** A flag that controls whether or not the chart border is drawn. */
private boolean borderVisible;
/** The stroke used to draw the chart border (if visible). */
private transient Stroke borderStroke;
/** The paint used to draw the chart border (if visible). */
private transient Paint borderPaint;
/** The padding between the chart border and the chart drawing area. */
private RectangleInsets padding;
/** The chart title (optional). */
private TextTitle title;
/**
* The chart subtitles (zero, one or many). This field should never be
* {@code null}.
*/
private List subtitles;
/** Draws the visual representation of the data. */
private Plot plot;
/** Paint used to draw the background of the chart. */
private transient Paint backgroundPaint;
/** An optional background image for the chart. */
private transient Image backgroundImage; // todo: not serialized yet
/** The alignment for the background image. */
private int backgroundImageAlignment = Align.FIT;
/** The alpha transparency for the background image. */
private float backgroundImageAlpha = 0.5f;
/** Storage for registered change listeners. */
private transient EventListenerList changeListeners;
/** Storage for registered progress listeners. */
private transient EventListenerList progressListeners;
/**
* A flag that can be used to enable/disable notification of chart change
* events.
*/
private boolean notify;
/**
* A flag that controls whether or not rendering hints that identify
* chart element should be added during rendering. This defaults to false
* and it should only be enabled if the output target will use the hints.
* JFreeSVG is one output target that supports these hints.
*/
private boolean elementHinting;
/**
* Creates a new chart based on the supplied plot. The chart will have
* a legend added automatically, but no title (although you can easily add
* one later).
*
* NOTE: if the plot is not an instance of {@link CategoryPlot}, then a
* {@code ClassCastException} is thrown.
*
* @return The plot.
*
* @see #getPlot()
*/
public CategoryPlot getCategoryPlot() {
return (CategoryPlot) this.plot;
}
/**
* Returns the plot cast as an {@link XYPlot}.
*
* NOTE: if the plot is not an instance of {@link XYPlot}, then a
* {@code ClassCastException} is thrown.
*
* @return The plot.
*
* @see #getPlot()
*/
public XYPlot getXYPlot() {
return (XYPlot) this.plot;
}
/**
* Returns a flag that indicates whether or not anti-aliasing is used when
* the chart is drawn.
*
* @return The flag.
*
* @see #setAntiAlias(boolean)
*/
public boolean getAntiAlias() {
Object val = this.renderingHints.get(RenderingHints.KEY_ANTIALIASING);
return RenderingHints.VALUE_ANTIALIAS_ON.equals(val);
}
/**
* Sets a flag that indicates whether or not anti-aliasing is used when the
* chart is drawn.
*
* Anti-aliasing usually improves the appearance of charts, but is slower.
*
* @param flag the new value of the flag.
*
* @see #getAntiAlias()
*/
public void setAntiAlias(boolean flag) {
Object hint = flag ? RenderingHints.VALUE_ANTIALIAS_ON
: RenderingHints.VALUE_ANTIALIAS_OFF;
this.renderingHints.put(RenderingHints.KEY_ANTIALIASING, hint);
fireChartChanged();
}
/**
* Returns the current value stored in the rendering hints table for
* {@link RenderingHints#KEY_TEXT_ANTIALIASING}.
*
* @return The hint value (possibly {@code null}).
*
* @see #setTextAntiAlias(Object)
*/
public Object getTextAntiAlias() {
return this.renderingHints.get(RenderingHints.KEY_TEXT_ANTIALIASING);
}
/**
* Sets the value in the rendering hints table for
* {@link RenderingHints#KEY_TEXT_ANTIALIASING} to either
* {@link RenderingHints#VALUE_TEXT_ANTIALIAS_ON} or
* {@link RenderingHints#VALUE_TEXT_ANTIALIAS_OFF}, then sends a
* {@link ChartChangeEvent} to all registered listeners.
*
* @param flag the new value of the flag.
*
* @see #getTextAntiAlias()
* @see #setTextAntiAlias(Object)
*/
public void setTextAntiAlias(boolean flag) {
if (flag) {
setTextAntiAlias(RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
}
else {
setTextAntiAlias(RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
}
}
/**
* Sets the value in the rendering hints table for
* {@link RenderingHints#KEY_TEXT_ANTIALIASING} and sends a
* {@link ChartChangeEvent} to all registered listeners.
*
* @param val the new value ({@code null} permitted).
*
* @see #getTextAntiAlias()
* @see #setTextAntiAlias(boolean)
*/
public void setTextAntiAlias(Object val) {
this.renderingHints.put(RenderingHints.KEY_TEXT_ANTIALIASING, val);
notifyListeners(new ChartChangeEvent(this));
}
/**
* Returns the paint used for the chart background.
*
* @return The paint (possibly {@code null}).
*
* @see #setBackgroundPaint(Paint)
*/
public Paint getBackgroundPaint() {
return this.backgroundPaint;
}
/**
* Sets the paint used to fill the chart background and sends a
* {@link ChartChangeEvent} to all registered listeners.
*
* @param paint the paint ({@code null} permitted).
*
* @see #getBackgroundPaint()
*/
public void setBackgroundPaint(Paint paint) {
if (this.backgroundPaint != null) {
if (!this.backgroundPaint.equals(paint)) {
this.backgroundPaint = paint;
fireChartChanged();
}
}
else {
if (paint != null) {
this.backgroundPaint = paint;
fireChartChanged();
}
}
}
/**
* Returns the background image for the chart, or {@code null} if
* there is no image.
*
* @return The image (possibly {@code null}).
*
* @see #setBackgroundImage(Image)
*/
public Image getBackgroundImage() {
return this.backgroundImage;
}
/**
* Sets the background image for the chart and sends a
* {@link ChartChangeEvent} to all registered listeners.
*
* @param image the image ({@code null} permitted).
*
* @see #getBackgroundImage()
*/
public void setBackgroundImage(Image image) {
if (this.backgroundImage != null) {
if (!this.backgroundImage.equals(image)) {
this.backgroundImage = image;
fireChartChanged();
}
}
else {
if (image != null) {
this.backgroundImage = image;
fireChartChanged();
}
}
}
/**
* Returns the background image alignment. Alignment constants are defined
* in the {@link Align} class.
*
* @return The alignment.
*
* @see #setBackgroundImageAlignment(int)
*/
public int getBackgroundImageAlignment() {
return this.backgroundImageAlignment;
}
/**
* Sets the background alignment. Alignment options are defined by the
* {@link org.jfree.chart.ui.Align} class.
*
* @param alignment the alignment.
*
* @see #getBackgroundImageAlignment()
*/
public void setBackgroundImageAlignment(int alignment) {
if (this.backgroundImageAlignment != alignment) {
this.backgroundImageAlignment = alignment;
fireChartChanged();
}
}
/**
* Returns the alpha-transparency for the chart's background image.
*
* @return The alpha-transparency.
*
* @see #setBackgroundImageAlpha(float)
*/
public float getBackgroundImageAlpha() {
return this.backgroundImageAlpha;
}
/**
* Sets the alpha-transparency for the chart's background image.
* Registered listeners are notified that the chart has been changed.
*
* @param alpha the alpha value.
*
* @see #getBackgroundImageAlpha()
*/
public void setBackgroundImageAlpha(float alpha) {
if (this.backgroundImageAlpha != alpha) {
this.backgroundImageAlpha = alpha;
fireChartChanged();
}
}
/**
* Returns a flag that controls whether or not change events are sent to
* registered listeners.
*
* @return A boolean.
*
* @see #setNotify(boolean)
*/
public boolean isNotify() {
return this.notify;
}
/**
* Sets a flag that controls whether or not listeners receive
* {@link ChartChangeEvent} notifications.
*
* @param notify a boolean.
*
* @see #isNotify()
*/
public void setNotify(boolean notify) {
this.notify = notify;
// if the flag is being set to true, there may be queued up changes...
if (notify) {
notifyListeners(new ChartChangeEvent(this));
}
}
/**
* Draws the chart on a Java 2D graphics device (such as the screen or a
* printer).
*
* This method is the focus of the entire JFreeChart library.
*
* @param g2 the graphics device.
* @param area the area within which the chart should be drawn.
*/
@Override
public void draw(Graphics2D g2, Rectangle2D area) {
draw(g2, area, null, null);
}
/**
* Draws the chart on a Java 2D graphics device (such as the screen or a
* printer). This method is the focus of the entire JFreeChart library.
*
* @param g2 the graphics device.
* @param area the area within which the chart should be drawn.
* @param info records info about the drawing (null means collect no info).
*/
public void draw(Graphics2D g2, Rectangle2D area, ChartRenderingInfo info) {
draw(g2, area, null, info);
}
/**
* Draws the chart on a Java 2D graphics device (such as the screen or a
* printer).
*
* This method is the focus of the entire JFreeChart library.
*
* @param g2 the graphics device.
* @param chartArea the area within which the chart should be drawn.
* @param anchor the anchor point (in Java2D space) for the chart
* ({@code null} permitted).
* @param info records info about the drawing (null means collect no info).
*/
public void draw(Graphics2D g2, Rectangle2D chartArea, Point2D anchor,
ChartRenderingInfo info) {
notifyListeners(new ChartProgressEvent(this, this,
ChartProgressEvent.DRAWING_STARTED, 0));
if (this.elementHinting) {
Map m = new HashMap
* This method is for convenience only.
*/
public void fireChartChanged() {
ChartChangeEvent event = new ChartChangeEvent(this);
notifyListeners(event);
}
/**
* Sends a {@link ChartChangeEvent} to all registered listeners.
*
* @param event information about the event that triggered the
* notification.
*/
protected void notifyListeners(ChartChangeEvent event) {
if (this.notify) {
Object[] listeners = this.changeListeners.getListenerList();
for (int i = listeners.length - 2; i >= 0; i -= 2) {
if (listeners[i] == ChartChangeListener.class) {
((ChartChangeListener) listeners[i + 1]).chartChanged(
event);
}
}
}
}
/**
* Registers an object for notification of progress events relating to the
* chart.
*
* @param listener the object being registered.
*
* @see #removeProgressListener(ChartProgressListener)
*/
public void addProgressListener(ChartProgressListener listener) {
this.progressListeners.add(ChartProgressListener.class, listener);
}
/**
* Deregisters an object for notification of changes to the chart.
*
* @param listener the object being deregistered.
*
* @see #addProgressListener(ChartProgressListener)
*/
public void removeProgressListener(ChartProgressListener listener) {
this.progressListeners.remove(ChartProgressListener.class, listener);
}
/**
* Sends a {@link ChartProgressEvent} to all registered listeners.
*
* @param event information about the event that triggered the
* notification.
*/
protected void notifyListeners(ChartProgressEvent event) {
Object[] listeners = this.progressListeners.getListenerList();
for (int i = listeners.length - 2; i >= 0; i -= 2) {
if (listeners[i] == ChartProgressListener.class) {
((ChartProgressListener) listeners[i + 1]).chartProgress(event);
}
}
}
/**
* Receives notification that a chart title has changed, and passes this
* on to registered listeners.
*
* @param event information about the chart title change.
*/
@Override
public void titleChanged(TitleChangeEvent event) {
event.setChart(this);
notifyListeners(event);
}
/**
* Receives notification that the plot has changed, and passes this on to
* registered listeners.
*
* @param event information about the plot change.
*/
@Override
public void plotChanged(PlotChangeEvent event) {
event.setChart(this);
notifyListeners(event);
}
/**
* Tests this chart for equality with another object.
*
* @param obj the object ({@code null} permitted).
*
* @return A boolean.
*/
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof JFreeChart)) {
return false;
}
JFreeChart that = (JFreeChart) obj;
if (!Objects.equals(this.renderingHints, that.renderingHints)) {
return false;
}
if (this.borderVisible != that.borderVisible) {
return false;
}
if (this.elementHinting != that.elementHinting) {
return false;
}
if (!Objects.equals(this.borderStroke, that.borderStroke)) {
return false;
}
if (!PaintUtils.equal(this.borderPaint, that.borderPaint)) {
return false;
}
if (!Objects.equals(this.padding, that.padding)) {
return false;
}
if (!Objects.equals(this.title, that.title)) {
return false;
}
if (!Objects.equals(this.subtitles, that.subtitles)) {
return false;
}
if (!Objects.equals(this.plot, that.plot)) {
return false;
}
if (!PaintUtils.equal(this.backgroundPaint, that.backgroundPaint)) {
return false;
}
if (!Objects.equals(this.backgroundImage, that.backgroundImage)) {
return false;
}
if (this.backgroundImageAlignment != that.backgroundImageAlignment) {
return false;
}
if (Float.floatToIntBits(this.backgroundImageAlpha) !=
Float.floatToIntBits(that.backgroundImageAlpha)) {
return false;
}
if (this.notify != that.notify) {
return false;
}
if (!Objects.equals(this.id, that.id)) {
return false;
}
return true;
}
@Override
public int hashCode() {
int hash = 7;
hash = 43 * hash + Objects.hashCode(this.renderingHints);
hash = 43 * hash + Objects.hashCode(this.id);
hash = 43 * hash + (this.borderVisible ? 1 : 0);
hash = 43 * hash + Objects.hashCode(this.borderStroke);
hash = 43 * hash + HashUtils.hashCodeForPaint(this.borderPaint);
hash = 43 * hash + Objects.hashCode(this.padding);
hash = 43 * hash + Objects.hashCode(this.title);
hash = 43 * hash + Objects.hashCode(this.subtitles);
hash = 43 * hash + Objects.hashCode(this.plot);
hash = 43 * hash + HashUtils.hashCodeForPaint(this.backgroundPaint);
hash = 43 * hash + Objects.hashCode(this.backgroundImage);
hash = 43 * hash + this.backgroundImageAlignment;
hash = 43 * hash + Float.floatToIntBits(this.backgroundImageAlpha);
hash = 43 * hash + (this.notify ? 1 : 0);
hash = 43 * hash + (this.elementHinting ? 1 : 0);
return hash;
}
/**
* Provides serialization support.
*
* @param stream the output stream.
*
* @throws IOException if there is an I/O error.
*/
private void writeObject(ObjectOutputStream stream) throws IOException {
stream.defaultWriteObject();
SerialUtils.writeStroke(this.borderStroke, stream);
SerialUtils.writePaint(this.borderPaint, stream);
SerialUtils.writePaint(this.backgroundPaint, stream);
}
/**
* Provides serialization support.
*
* @param stream the input stream.
*
* @throws IOException if there is an I/O error.
* @throws ClassNotFoundException if there is a classpath problem.
*/
private void readObject(ObjectInputStream stream)
throws IOException, ClassNotFoundException {
stream.defaultReadObject();
this.borderStroke = SerialUtils.readStroke(stream);
this.borderPaint = SerialUtils.readPaint(stream);
this.backgroundPaint = SerialUtils.readPaint(stream);
this.progressListeners = new EventListenerList();
this.changeListeners = new EventListenerList();
this.renderingHints = new RenderingHints(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
this.renderingHints.put(RenderingHints.KEY_STROKE_CONTROL,
RenderingHints.VALUE_STROKE_PURE);
// register as a listener with sub-components...
if (this.title != null) {
this.title.addChangeListener(this);
}
for (int i = 0; i < getSubtitleCount(); i++) {
getSubtitle(i).addChangeListener(this);
}
this.plot.addChangeListener(this);
}
/**
* Clones the object, and takes care of listeners.
* Note: caller shall register its own listeners on cloned graph.
*
* @return A clone.
*
* @throws CloneNotSupportedException if the chart is not cloneable.
*/
@Override
public Object clone() throws CloneNotSupportedException {
JFreeChart chart = (JFreeChart) super.clone();
chart.renderingHints = (RenderingHints) this.renderingHints.clone();
// private boolean borderVisible;
// private transient Stroke borderStroke;
// private transient Paint borderPaint;
if (this.title != null) {
chart.title = (TextTitle) this.title.clone();
chart.title.addChangeListener(chart);
}
chart.subtitles = new ArrayList<>();
for (int i = 0; i < getSubtitleCount(); i++) {
Title subtitle = (Title) getSubtitle(i).clone();
chart.subtitles.add(subtitle);
subtitle.addChangeListener(chart);
}
if (this.plot != null) {
chart.plot = (Plot) this.plot.clone();
chart.plot.addChangeListener(chart);
}
chart.progressListeners = new EventListenerList();
chart.changeListeners = new EventListenerList();
return chart;
}
}
jfree-jfreechart-cb8ff67/src/main/java/org/jfree/chart/LegendItem.java 0000664 0000000 0000000 00000110362 14636042355 0025741 0 ustar 00root root 0000000 0000000 /* ===========================================================
* JFreeChart : a free chart library for the Java(tm) platform
* ===========================================================
*
* (C) Copyright 2000-present, by David Gilbert and Contributors.
*
* Project Info: http://www.jfree.org/jfreechart/index.html
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* [Oracle and Java are registered trademarks of Oracle and/or its affiliates.
* Other names may be trademarks of their respective owners.]
*
* ---------------
* LegendItem.java
* ---------------
* (C) Copyright 2000-present, by David Gilbert and Contributors.
*
* Original Author: David Gilbert;
* Contributor(s): Andrzej Porebski;
* David Li;
* Wolfgang Irler;
* Luke Quinane;
* Tracy Hiltbrand (equals/hashCode comply with EqualsVerifier);
*
*/
package org.jfree.chart;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Paint;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.text.AttributedString;
import java.text.CharacterIterator;
import java.util.Objects;
import org.jfree.chart.text.AttributedStringUtils;
import org.jfree.chart.ui.GradientPaintTransformer;
import org.jfree.chart.ui.StandardGradientPaintTransformer;
import org.jfree.chart.util.PaintUtils;
import org.jfree.chart.util.Args;
import org.jfree.chart.util.PublicCloneable;
import org.jfree.chart.util.SerialUtils;
import org.jfree.chart.util.ShapeUtils;
import org.jfree.data.general.Dataset;
/**
* A temporary storage object for recording the properties of a legend item,
* without any consideration for layout issues.
*/
public class LegendItem implements Cloneable, Serializable {
/** For serialization. */
private static final long serialVersionUID = -797214582948827144L;
/**
* The dataset.
*/
private Dataset dataset;
/**
* The series key.
*/
private Comparable seriesKey;
/** The dataset index. */
private int datasetIndex;
/** The series index. */
private int series;
/** The label. */
private String label;
/**
* The label font ({@code null} is permitted).
*/
private Font labelFont;
/**
* The label paint ({@code null} is permitted).
*/
private transient Paint labelPaint;
/** The attributed label (if null, fall back to the regular label). */
private transient AttributedString attributedLabel;
/**
* The description (not currently used - could be displayed as a tool tip).
*/
private String description;
/** The tool tip text. */
private String toolTipText;
/** The url text. */
private String urlText;
/** A flag that controls whether or not the shape is visible. */
private boolean shapeVisible;
/** The shape. */
private transient Shape shape;
/** A flag that controls whether or not the shape is filled. */
private boolean shapeFilled;
/** The paint. */
private transient Paint fillPaint;
/**
* A gradient paint transformer.
*/
private GradientPaintTransformer fillPaintTransformer;
/** A flag that controls whether or not the shape outline is visible. */
private boolean shapeOutlineVisible;
/** The outline paint. */
private transient Paint outlinePaint;
/** The outline stroke. */
private transient Stroke outlineStroke;
/** A flag that controls whether or not the line is visible. */
private boolean lineVisible;
/** The line. */
private transient Shape line;
/** The stroke. */
private transient Stroke lineStroke;
/** The line paint. */
private transient Paint linePaint;
/**
* The shape must be non-null for a LegendItem - if no shape is required,
* use this.
*/
private static final Shape UNUSED_SHAPE = new Line2D.Float();
/**
* The stroke must be non-null for a LegendItem - if no stroke is required,
* use this.
*/
private static final Stroke UNUSED_STROKE = new BasicStroke(0.0f);
/**
* Creates a legend item with the specified label. The remaining
* attributes take default values.
*
* @param label the label ({@code null} not permitted).
*/
public LegendItem(String label) {
this(label, Color.BLACK);
}
/**
* Creates a legend item with the specified label and fill paint. The
* remaining attributes take default values.
*
* @param label the label ({@code null} not permitted).
* @param paint the paint ({@code null} not permitted).
*/
public LegendItem(String label, Paint paint) {
this(label, null, null, null, new Rectangle2D.Double(-4.0, -4.0, 8.0,
8.0), paint);
}
/**
* Creates a legend item with a filled shape. The shape is not outlined,
* and no line is visible.
*
* @param label the label ({@code null} not permitted).
* @param description the description ({@code null} permitted).
* @param toolTipText the tool tip text ({@code null} permitted).
* @param urlText the URL text ({@code null} permitted).
* @param shape the shape ({@code null} not permitted).
* @param fillPaint the paint used to fill the shape ({@code null}
* not permitted).
*/
public LegendItem(String label, String description,
String toolTipText, String urlText,
Shape shape, Paint fillPaint) {
this(label, description, toolTipText, urlText,
/* shape visible = */ true, shape,
/* shape filled = */ true, fillPaint,
/* shape outlined */ false, Color.BLACK, UNUSED_STROKE,
/* line visible */ false, UNUSED_SHAPE, UNUSED_STROKE,
Color.BLACK);
}
/**
* Creates a legend item with a filled and outlined shape.
*
* @param label the label ({@code null} not permitted).
* @param description the description ({@code null} permitted).
* @param toolTipText the tool tip text ({@code null} permitted).
* @param urlText the URL text ({@code null} permitted).
* @param shape the shape ({@code null} not permitted).
* @param fillPaint the paint used to fill the shape ({@code null}
* not permitted).
* @param outlineStroke the outline stroke ({@code null} not
* permitted).
* @param outlinePaint the outline paint ({@code null} not
* permitted).
*/
public LegendItem(String label, String description, String toolTipText,
String urlText, Shape shape, Paint fillPaint, Stroke outlineStroke,
Paint outlinePaint) {
this(label, description, toolTipText, urlText,
/* shape visible = */ true, shape,
/* shape filled = */ true, fillPaint,
/* shape outlined = */ true, outlinePaint, outlineStroke,
/* line visible */ false, UNUSED_SHAPE, UNUSED_STROKE,
Color.BLACK);
}
/**
* Creates a legend item using a line.
*
* @param label the label ({@code null} not permitted).
* @param description the description ({@code null} permitted).
* @param toolTipText the tool tip text ({@code null} permitted).
* @param urlText the URL text ({@code null} permitted).
* @param line the line ({@code null} not permitted).
* @param lineStroke the line stroke ({@code null} not permitted).
* @param linePaint the line paint ({@code null} not permitted).
*/
public LegendItem(String label, String description, String toolTipText,
String urlText, Shape line, Stroke lineStroke, Paint linePaint) {
this(label, description, toolTipText, urlText,
/* shape visible = */ false, UNUSED_SHAPE,
/* shape filled = */ false, Color.BLACK,
/* shape outlined = */ false, Color.BLACK, UNUSED_STROKE,
/* line visible = */ true, line, lineStroke, linePaint);
}
/**
* Creates a new legend item.
*
* @param label the label ({@code null} not permitted).
* @param description the description (not currently used,
* {@code null} permitted).
* @param toolTipText the tool tip text ({@code null} permitted).
* @param urlText the URL text ({@code null} permitted).
* @param shapeVisible a flag that controls whether or not the shape is
* displayed.
* @param shape the shape ({@code null} permitted).
* @param shapeFilled a flag that controls whether or not the shape is
* filled.
* @param fillPaint the fill paint ({@code null} not permitted).
* @param shapeOutlineVisible a flag that controls whether or not the
* shape is outlined.
* @param outlinePaint the outline paint ({@code null} not permitted).
* @param outlineStroke the outline stroke ({@code null} not
* permitted).
* @param lineVisible a flag that controls whether or not the line is
* visible.
* @param line the line.
* @param lineStroke the stroke ({@code null} not permitted).
* @param linePaint the line paint ({@code null} not permitted).
*/
public LegendItem(String label, String description,
String toolTipText, String urlText,
boolean shapeVisible, Shape shape,
boolean shapeFilled, Paint fillPaint,
boolean shapeOutlineVisible, Paint outlinePaint,
Stroke outlineStroke,
boolean lineVisible, Shape line,
Stroke lineStroke, Paint linePaint) {
Args.nullNotPermitted(label, "label");
Args.nullNotPermitted(fillPaint, "fillPaint");
Args.nullNotPermitted(lineStroke, "lineStroke");
Args.nullNotPermitted(outlinePaint, "outlinePaint");
Args.nullNotPermitted(outlineStroke, "outlineStroke");
this.label = label;
this.labelPaint = null;
this.attributedLabel = null;
this.description = description;
this.shapeVisible = shapeVisible;
this.shape = shape;
this.shapeFilled = shapeFilled;
this.fillPaint = fillPaint;
this.fillPaintTransformer = new StandardGradientPaintTransformer();
this.shapeOutlineVisible = shapeOutlineVisible;
this.outlinePaint = outlinePaint;
this.outlineStroke = outlineStroke;
this.lineVisible = lineVisible;
this.line = line;
this.lineStroke = lineStroke;
this.linePaint = linePaint;
this.toolTipText = toolTipText;
this.urlText = urlText;
}
/**
* Creates a legend item with a filled shape. The shape is not outlined,
* and no line is visible.
*
* @param label the label ({@code null} not permitted).
* @param description the description ({@code null} permitted).
* @param toolTipText the tool tip text ({@code null} permitted).
* @param urlText the URL text ({@code null} permitted).
* @param shape the shape ({@code null} not permitted).
* @param fillPaint the paint used to fill the shape ({@code null}
* not permitted).
*/
public LegendItem(AttributedString label, String description,
String toolTipText, String urlText,
Shape shape, Paint fillPaint) {
this(label, description, toolTipText, urlText,
/* shape visible = */ true, shape,
/* shape filled = */ true, fillPaint,
/* shape outlined = */ false, Color.BLACK, UNUSED_STROKE,
/* line visible = */ false, UNUSED_SHAPE, UNUSED_STROKE,
Color.BLACK);
}
/**
* Creates a legend item with a filled and outlined shape.
*
* @param label the label ({@code null} not permitted).
* @param description the description ({@code null} permitted).
* @param toolTipText the tool tip text ({@code null} permitted).
* @param urlText the URL text ({@code null} permitted).
* @param shape the shape ({@code null} not permitted).
* @param fillPaint the paint used to fill the shape ({@code null}
* not permitted).
* @param outlineStroke the outline stroke ({@code null} not
* permitted).
* @param outlinePaint the outline paint ({@code null} not
* permitted).
*/
public LegendItem(AttributedString label, String description,
String toolTipText, String urlText,
Shape shape, Paint fillPaint,
Stroke outlineStroke, Paint outlinePaint) {
this(label, description, toolTipText, urlText,
/* shape visible = */ true, shape,
/* shape filled = */ true, fillPaint,
/* shape outlined = */ true, outlinePaint, outlineStroke,
/* line visible = */ false, UNUSED_SHAPE, UNUSED_STROKE,
Color.BLACK);
}
/**
* Creates a legend item using a line.
*
* @param label the label ({@code null} not permitted).
* @param description the description ({@code null} permitted).
* @param toolTipText the tool tip text ({@code null} permitted).
* @param urlText the URL text ({@code null} permitted).
* @param line the line ({@code null} not permitted).
* @param lineStroke the line stroke ({@code null} not permitted).
* @param linePaint the line paint ({@code null} not permitted).
*/
public LegendItem(AttributedString label, String description,
String toolTipText, String urlText,
Shape line, Stroke lineStroke, Paint linePaint) {
this(label, description, toolTipText, urlText,
/* shape visible = */ false, UNUSED_SHAPE,
/* shape filled = */ false, Color.BLACK,
/* shape outlined = */ false, Color.BLACK, UNUSED_STROKE,
/* line visible = */ true, line, lineStroke, linePaint);
}
/**
* Creates a new legend item.
*
* @param label the label ({@code null} not permitted).
* @param description the description (not currently used,
* {@code null} permitted).
* @param toolTipText the tool tip text ({@code null} permitted).
* @param urlText the URL text ({@code null} permitted).
* @param shapeVisible a flag that controls whether or not the shape is
* displayed.
* @param shape the shape ({@code null} permitted).
* @param shapeFilled a flag that controls whether or not the shape is
* filled.
* @param fillPaint the fill paint ({@code null} not permitted).
* @param shapeOutlineVisible a flag that controls whether or not the
* shape is outlined.
* @param outlinePaint the outline paint ({@code null} not permitted).
* @param outlineStroke the outline stroke ({@code null} not
* permitted).
* @param lineVisible a flag that controls whether or not the line is
* visible.
* @param line the line ({@code null} not permitted).
* @param lineStroke the stroke ({@code null} not permitted).
* @param linePaint the line paint ({@code null} not permitted).
*/
public LegendItem(AttributedString label, String description,
String toolTipText, String urlText,
boolean shapeVisible, Shape shape,
boolean shapeFilled, Paint fillPaint,
boolean shapeOutlineVisible, Paint outlinePaint,
Stroke outlineStroke,
boolean lineVisible, Shape line, Stroke lineStroke,
Paint linePaint) {
Args.nullNotPermitted(label, "label");
Args.nullNotPermitted(fillPaint, "fillPaint");
Args.nullNotPermitted(lineStroke, "lineStroke");
Args.nullNotPermitted(line, "line");
Args.nullNotPermitted(linePaint, "linePaint");
Args.nullNotPermitted(outlinePaint, "outlinePaint");
Args.nullNotPermitted(outlineStroke, "outlineStroke");
this.label = characterIteratorToString(label.getIterator());
this.attributedLabel = label;
this.description = description;
this.shapeVisible = shapeVisible;
this.shape = shape;
this.shapeFilled = shapeFilled;
this.fillPaint = fillPaint;
this.fillPaintTransformer = new StandardGradientPaintTransformer();
this.shapeOutlineVisible = shapeOutlineVisible;
this.outlinePaint = outlinePaint;
this.outlineStroke = outlineStroke;
this.lineVisible = lineVisible;
this.line = line;
this.lineStroke = lineStroke;
this.linePaint = linePaint;
this.toolTipText = toolTipText;
this.urlText = urlText;
}
/**
* Returns a string containing the characters from the given iterator.
*
* @param iterator the iterator ({@code null} not permitted).
*
* @return A string.
*/
private String characterIteratorToString(CharacterIterator iterator) {
int endIndex = iterator.getEndIndex();
int beginIndex = iterator.getBeginIndex();
int count = endIndex - beginIndex;
if (count <= 0) {
return "";
}
char[] chars = new char[count];
int i = 0;
char c = iterator.first();
while (c != CharacterIterator.DONE) {
chars[i] = c;
i++;
c = iterator.next();
}
return new String(chars);
}
/**
* Returns the dataset.
*
* @return The dataset.
*
* @see #setDatasetIndex(int)
*/
public Dataset getDataset() {
return this.dataset;
}
/**
* Sets the dataset.
*
* @param dataset the dataset.
*/
public void setDataset(Dataset dataset) {
this.dataset = dataset;
}
/**
* Returns the dataset index for this legend item.
*
* @return The dataset index.
*
* @see #setDatasetIndex(int)
* @see #getDataset()
*/
public int getDatasetIndex() {
return this.datasetIndex;
}
/**
* Sets the dataset index for this legend item.
*
* @param index the index.
*
* @see #getDatasetIndex()
*/
public void setDatasetIndex(int index) {
this.datasetIndex = index;
}
/**
* Returns the series key.
*
* @return The series key.
*
* @see #setSeriesKey(Comparable)
*/
public Comparable getSeriesKey() {
return this.seriesKey;
}
/**
* Sets the series key.
*
* @param key the series key.
*/
public void setSeriesKey(Comparable key) {
this.seriesKey = key;
}
/**
* Returns the series index for this legend item.
*
* @return The series index.
*/
public int getSeriesIndex() {
return this.series;
}
/**
* Sets the series index for this legend item.
*
* @param index the index.
*/
public void setSeriesIndex(int index) {
this.series = index;
}
/**
* Returns the label.
*
* @return The label (never {@code null}).
*/
public String getLabel() {
return this.label;
}
/**
* Returns the label font.
*
* @return The label font (possibly {@code null}).
*/
public Font getLabelFont() {
return this.labelFont;
}
/**
* Sets the label font.
*
* @param font the font ({@code null} permitted).
*/
public void setLabelFont(Font font) {
this.labelFont = font;
}
/**
* Returns the paint used to draw the label.
*
* @return The paint (possibly {@code null}).
*/
public Paint getLabelPaint() {
return this.labelPaint;
}
/**
* Sets the paint used to draw the label.
*
* @param paint the paint ({@code null} permitted).
*/
public void setLabelPaint(Paint paint) {
this.labelPaint = paint;
}
/**
* Returns the attributed label.
*
* @return The attributed label (possibly {@code null}).
*/
public AttributedString getAttributedLabel() {
return this.attributedLabel;
}
/**
* Returns the description for the legend item.
*
* @return The description (possibly {@code null}).
*
* @see #setDescription(java.lang.String)
*/
public String getDescription() {
return this.description;
}
/**
* Sets the description for this legend item.
*
* @param text the description ({@code null} permitted).
*
* @see #getDescription()
*/
public void setDescription(String text) {
this.description = text;
}
/**
* Returns the tool tip text.
*
* @return The tool tip text (possibly {@code null}).
*
* @see #setToolTipText(java.lang.String)
*/
public String getToolTipText() {
return this.toolTipText;
}
/**
* Sets the tool tip text for this legend item.
*
* @param text the text ({@code null} permitted).
*
* @see #getToolTipText()
*/
public void setToolTipText(String text) {
this.toolTipText = text;
}
/**
* Returns the URL text.
*
* @return The URL text (possibly {@code null}).
*
* @see #setURLText(java.lang.String)
*/
public String getURLText() {
return this.urlText;
}
/**
* Sets the URL text.
*
* @param text the text ({@code null} permitted).
*
* @see #getURLText()
*/
public void setURLText(String text) {
this.urlText = text;
}
/**
* Returns a flag that indicates whether or not the shape is visible.
*
* @return A boolean.
*
* @see #setShapeVisible(boolean)
*/
public boolean isShapeVisible() {
return this.shapeVisible;
}
/**
* Sets the flag that controls whether or not the shape is visible.
*
* @param visible the new flag value.
*
* @see #isShapeVisible()
* @see #isLineVisible()
*/
public void setShapeVisible(boolean visible) {
this.shapeVisible = visible;
}
/**
* Returns the shape used to label the series represented by this legend
* item.
*
* @return The shape (never {@code null}).
*
* @see #setShape(java.awt.Shape)
*/
public Shape getShape() {
return this.shape;
}
/**
* Sets the shape for the legend item.
*
* @param shape the shape ({@code null} not permitted).
*
* @see #getShape()
*/
public void setShape(Shape shape) {
Args.nullNotPermitted(shape, "shape");
this.shape = shape;
}
/**
* Returns a flag that controls whether or not the shape is filled.
*
* @return A boolean.
*/
public boolean isShapeFilled() {
return this.shapeFilled;
}
/**
* Returns the fill paint.
*
* @return The fill paint (never {@code null}).
*/
public Paint getFillPaint() {
return this.fillPaint;
}
/**
* Sets the fill paint.
*
* @param paint the paint ({@code null} not permitted).
*/
public void setFillPaint(Paint paint) {
Args.nullNotPermitted(paint, "paint");
this.fillPaint = paint;
}
/**
* Returns the flag that controls whether or not the shape outline
* is visible.
*
* @return A boolean.
*/
public boolean isShapeOutlineVisible() {
return this.shapeOutlineVisible;
}
/**
* Returns the line stroke for the series.
*
* @return The stroke (never {@code null}).
*/
public Stroke getLineStroke() {
return this.lineStroke;
}
/**
* Sets the line stroke.
*
* @param stroke the stroke ({@code null} not permitted).
*/
public void setLineStroke(Stroke stroke) {
Args.nullNotPermitted(stroke, "stroke");
this.lineStroke = stroke;
}
/**
* Returns the paint used for lines.
*
* @return The paint (never {@code null}).
*/
public Paint getLinePaint() {
return this.linePaint;
}
/**
* Sets the line paint.
*
* @param paint the paint ({@code null} not permitted).
*/
public void setLinePaint(Paint paint) {
Args.nullNotPermitted(paint, "paint");
this.linePaint = paint;
}
/**
* Returns the outline paint.
*
* @return The outline paint (never {@code null}).
*/
public Paint getOutlinePaint() {
return this.outlinePaint;
}
/**
* Sets the outline paint.
*
* @param paint the paint ({@code null} not permitted).
*/
public void setOutlinePaint(Paint paint) {
Args.nullNotPermitted(paint, "paint");
this.outlinePaint = paint;
}
/**
* Returns the outline stroke.
*
* @return The outline stroke (never {@code null}).
*
* @see #setOutlineStroke(java.awt.Stroke)
*/
public Stroke getOutlineStroke() {
return this.outlineStroke;
}
/**
* Sets the outline stroke.
*
* @param stroke the stroke ({@code null} not permitted).
*
* @see #getOutlineStroke()
*/
public void setOutlineStroke(Stroke stroke) {
Args.nullNotPermitted(stroke, "stroke");
this.outlineStroke = stroke;
}
/**
* Returns a flag that indicates whether or not the line is visible.
*
* @return A boolean.
*
* @see #setLineVisible(boolean)
*/
public boolean isLineVisible() {
return this.lineVisible;
}
/**
* Sets the flag that controls whether or not the line shape is visible for
* this legend item.
*
* @param visible the new flag value.
*
* @see #isLineVisible()
*/
public void setLineVisible(boolean visible) {
this.lineVisible = visible;
}
/**
* Returns the line.
*
* @return The line (never {@code null}).
*
* @see #setLine(java.awt.Shape)
* @see #isLineVisible()
*/
public Shape getLine() {
return this.line;
}
/**
* Sets the line.
*
* @param line the line ({@code null} not permitted).
*
* @see #getLine()
*/
public void setLine(Shape line) {
Args.nullNotPermitted(line, "line");
this.line = line;
}
/**
* Returns the transformer used when the fill paint is an instance of
* {@code GradientPaint}.
*
* @return The transformer (never {@code null}).
*
* @see #setFillPaintTransformer(GradientPaintTransformer)
*/
public GradientPaintTransformer getFillPaintTransformer() {
return this.fillPaintTransformer;
}
/**
* Sets the transformer used when the fill paint is an instance of
* {@code GradientPaint}.
*
* @param transformer the transformer ({@code null} not permitted).
*
* @see #getFillPaintTransformer()
*/
public void setFillPaintTransformer(GradientPaintTransformer transformer) {
Args.nullNotPermitted(transformer, "transformer");
this.fillPaintTransformer = transformer;
}
/**
* Tests this item for equality with an arbitrary object.
*
* @param obj the object ({@code null} permitted).
*
* @return A boolean.
*/
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof LegendItem)) {
return false;
}
LegendItem that = (LegendItem) obj;
if (!Objects.equals(this.dataset, that.dataset)) {
return false;
}
if (!Objects.equals(this.seriesKey, that.seriesKey)) {
return false;
}
if (this.datasetIndex != that.datasetIndex) {
return false;
}
if (this.series != that.series) {
return false;
}
if (!Objects.equals(this.label, that.label)) {
return false;
}
if (!Objects.equals(this.labelFont, that.labelFont)) {
return false;
}
if (!Objects.equals(this.description, that.description)) {
return false;
}
if (!Objects.equals(this.toolTipText, that.toolTipText)) {
return false;
}
if (!Objects.equals(this.urlText, that.urlText)) {
return false;
}
if (this.shapeVisible != that.shapeVisible) {
return false;
}
if (this.shapeFilled != that.shapeFilled) {
return false;
}
if (!Objects.equals(this.fillPaintTransformer,
that.fillPaintTransformer)) {
return false;
}
if (!ShapeUtils.equal(this.shape, that.shape)) {
return false;
}
if (!PaintUtils.equal(this.fillPaint, that.fillPaint)) {
return false;
}
if (!AttributedStringUtils.equal(this.attributedLabel,
that.attributedLabel)) {
return false;
}
if (this.shapeOutlineVisible != that.shapeOutlineVisible) {
return false;
}
if (!Objects.equals(this.outlineStroke, that.outlineStroke)) {
return false;
}
if (!PaintUtils.equal(this.outlinePaint, that.outlinePaint)) {
return false;
}
if (!this.lineVisible == that.lineVisible) {
return false;
}
if (!ShapeUtils.equal(this.line, that.line)) {
return false;
}
if (!Objects.equals(this.lineStroke, that.lineStroke)) {
return false;
}
if (!PaintUtils.equal(this.linePaint, that.linePaint)) {
return false;
}
if (!Objects.equals(this.labelFont, that.labelFont)) {
return false;
}
if (!PaintUtils.equal(this.labelPaint, that.labelPaint)) {
return false;
}
return true;
}
@Override
public int hashCode() {
int hash = 7;
hash = 83 * hash + Objects.hashCode(this.dataset);
hash = 83 * hash + Objects.hashCode(this.seriesKey);
hash = 83 * hash + this.datasetIndex;
hash = 83 * hash + this.series;
hash = 83 * hash + Objects.hashCode(this.label);
hash = 83 * hash + Objects.hashCode(this.labelFont);
hash = 83 * hash + HashUtils.hashCodeForPaint(this.labelPaint);
hash = 83 * hash + Objects.hashCode(this.attributedLabel);
hash = 83 * hash + Objects.hashCode(this.description);
hash = 83 * hash + Objects.hashCode(this.toolTipText);
hash = 83 * hash + Objects.hashCode(this.urlText);
hash = 83 * hash + (this.shapeVisible ? 1 : 0);
hash = 83 * hash + Objects.hashCode(this.shape);
hash = 83 * hash + (this.shapeFilled ? 1 : 0);
hash = 83 * hash + HashUtils.hashCodeForPaint(this.fillPaint);
hash = 83 * hash + Objects.hashCode(this.fillPaintTransformer);
hash = 83 * hash + (this.shapeOutlineVisible ? 1 : 0);
hash = 83 * hash + HashUtils.hashCodeForPaint(this.outlinePaint);
hash = 83 * hash + Objects.hashCode(this.outlineStroke);
hash = 83 * hash + (this.lineVisible ? 1 : 0);
hash = 83 * hash + Objects.hashCode(this.line);
hash = 83 * hash + Objects.hashCode(this.lineStroke);
hash = 83 * hash + HashUtils.hashCodeForPaint(this.linePaint);
return hash;
}
/**
* Returns an independent copy of this object (except that the clone will
* still reference the same dataset as the original {@code LegendItem}).
*
* @return A clone.
*
* @throws CloneNotSupportedException if the legend item cannot be cloned.
*/
@Override
public Object clone() throws CloneNotSupportedException {
LegendItem clone = (LegendItem) super.clone();
if (this.seriesKey instanceof PublicCloneable) {
PublicCloneable pc = (PublicCloneable) this.seriesKey;
clone.seriesKey = (Comparable) pc.clone();
}
// FIXME: Clone the attributed string if it is not null
clone.shape = ShapeUtils.clone(this.shape);
if (this.fillPaintTransformer instanceof PublicCloneable) {
PublicCloneable pc = (PublicCloneable) this.fillPaintTransformer;
clone.fillPaintTransformer = (GradientPaintTransformer) pc.clone();
}
clone.line = ShapeUtils.clone(this.line);
return clone;
}
/**
* Provides serialization support.
*
* @param stream the output stream ({@code null} not permitted).
*
* @throws IOException if there is an I/O error.
*/
private void writeObject(ObjectOutputStream stream) throws IOException {
stream.defaultWriteObject();
SerialUtils.writeAttributedString(this.attributedLabel, stream);
SerialUtils.writeShape(this.shape, stream);
SerialUtils.writePaint(this.fillPaint, stream);
SerialUtils.writeStroke(this.outlineStroke, stream);
SerialUtils.writePaint(this.outlinePaint, stream);
SerialUtils.writeShape(this.line, stream);
SerialUtils.writeStroke(this.lineStroke, stream);
SerialUtils.writePaint(this.linePaint, stream);
SerialUtils.writePaint(this.labelPaint, stream);
}
/**
* Provides serialization support.
*
* @param stream the input stream ({@code null} not permitted).
*
* @throws IOException if there is an I/O error.
* @throws ClassNotFoundException if there is a classpath problem.
*/
private void readObject(ObjectInputStream stream)
throws IOException, ClassNotFoundException {
stream.defaultReadObject();
this.attributedLabel = SerialUtils.readAttributedString(stream);
this.shape = SerialUtils.readShape(stream);
this.fillPaint = SerialUtils.readPaint(stream);
this.outlineStroke = SerialUtils.readStroke(stream);
this.outlinePaint = SerialUtils.readPaint(stream);
this.line = SerialUtils.readShape(stream);
this.lineStroke = SerialUtils.readStroke(stream);
this.linePaint = SerialUtils.readPaint(stream);
this.labelPaint = SerialUtils.readPaint(stream);
}
}
jfree-jfreechart-cb8ff67/src/main/java/org/jfree/chart/LegendItemCollection.java 0000664 0000000 0000000 00000010717 14636042355 0027760 0 ustar 00root root 0000000 0000000 /* ===========================================================
* JFreeChart : a free chart library for the Java(tm) platform
* ===========================================================
*
* (C) Copyright 2000-present, by David Gilbert and Contributors.
*
* Project Info: http://www.jfree.org/jfreechart/index.html
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* [Oracle and Java are registered trademarks of Oracle and/or its affiliates.
* Other names may be trademarks of their respective owners.]
*
* -------------------------
* LegendItemCollection.java
* -------------------------
* (C) Copyright 2002-present, by David Gilbert.
*
* Original Author: David Gilbert;
* Contributor(s): Tracy Hiltbrand (equals/hashCode comply with EqualsVerifier);
*
*/
package org.jfree.chart;
import java.io.Serializable;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import org.jfree.chart.util.ObjectUtils;
/**
* A collection of legend items.
*/
public class LegendItemCollection implements Cloneable, Serializable {
/** For serialization. */
private static final long serialVersionUID = 1365215565589815953L;
/** Storage for the legend items. */
private List items;
/**
* Constructs a new legend item collection, initially empty.
*/
public LegendItemCollection() {
this.items = new java.util.ArrayList();
}
/**
* Adds a legend item to the collection.
*
* @param item the item to add.
*/
public void add(LegendItem item) {
this.items.add(item);
}
/**
* Adds the legend items from another collection to this collection.
*
* @param collection the other collection ({@code null} not
* permitted).
*/
public void addAll(LegendItemCollection collection) {
this.items.addAll(collection.items);
}
/**
* Returns a legend item from the collection.
*
* @param index the legend item index (zero-based).
*
* @return The legend item.
*/
public LegendItem get(int index) {
return (LegendItem) this.items.get(index);
}
/**
* Returns the number of legend items in the collection.
*
* @return The item count.
*/
public int getItemCount() {
return this.items.size();
}
/**
* Returns an iterator that provides access to all the legend items.
*
* @return An iterator.
*/
public Iterator iterator() {
return this.items.iterator();
}
/**
* Tests this collection for equality with an arbitrary object.
*
* @param obj the object ({@code null} permitted).
*
* @return A boolean.
*/
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof LegendItemCollection)) {
return false;
}
LegendItemCollection that = (LegendItemCollection) obj;
if (!Objects.equals(this.items, that.items)) {
return false;
}
return true;
}
@Override
public int hashCode() {
int hash = 7;
hash = 13 * hash + Objects.hashCode(this.items);
return hash;
}
/**
* Returns a clone of the collection.
*
* @return A clone.
*
* @throws CloneNotSupportedException if an item in the collection is not
* cloneable.
*/
@Override
public Object clone() throws CloneNotSupportedException {
LegendItemCollection clone = (LegendItemCollection) super.clone();
clone.items = (List) ObjectUtils.deepClone(this.items);
return clone;
}
}
jfree-jfreechart-cb8ff67/src/main/java/org/jfree/chart/LegendItemSource.java 0000664 0000000 0000000 00000003571 14636042355 0027125 0 ustar 00root root 0000000 0000000 /* ===========================================================
* JFreeChart : a free chart library for the Java(tm) platform
* ===========================================================
*
* (C) Copyright 2000-present, by David Gilbert and Contributors.
*
* Project Info: http://www.jfree.org/jfreechart/index.html
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* [Oracle and Java are registered trademarks of Oracle and/or its affiliates.
* Other names may be trademarks of their respective owners.]
*
* ---------------------
* LegendItemSource.java
* ---------------------
* (C) Copyright 2005-present, by David Gilbert and Contributors.
*
* Original Author: David Gilbert;
* Contributor(s): -;
*
*/
package org.jfree.chart;
/**
* A source of legend items. A {@link org.jfree.chart.title.LegendTitle} will
* maintain a list of sources (often just one) from which it obtains legend
* items.
*/
public interface LegendItemSource {
/**
* Returns a (possibly empty) collection of legend items.
*
* @return The legend item collection (never {@code null}).
*/
LegendItemCollection getLegendItems();
}
jfree-jfreechart-cb8ff67/src/main/java/org/jfree/chart/LegendRenderingOrder.java 0000664 0000000 0000000 00000007145 14636042355 0027760 0 ustar 00root root 0000000 0000000 /* ===========================================================
* JFreeChart : a free chart library for the Java(tm) platform
* ===========================================================
*
* (C) Copyright 2000-present, by David Gilbert and Contributors.
*
* Project Info: http://www.jfree.org/jfreechart/index.html
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* [Oracle and Java are registered trademarks of Oracle and/or its affiliates.
* Other names may be trademarks of their respective owners.]
*
* -------------------------
* LegendRenderingOrder.java
* -------------------------
* (C) Copyright 2004-present, by David Gilbert and Contributors.
*
* Original Author: Angel;
* Contributor(s): David Gilbert;
*
*/
package org.jfree.chart;
import java.io.ObjectStreamException;
import java.io.Serializable;
/**
* Represents the order for rendering legend items.
*/
public final class LegendRenderingOrder implements Serializable {
/** For serialization. */
private static final long serialVersionUID = -3832486612685808616L;
/** In order. */
public static final LegendRenderingOrder STANDARD
= new LegendRenderingOrder("LegendRenderingOrder.STANDARD");
/** In reverse order. */
public static final LegendRenderingOrder REVERSE
= new LegendRenderingOrder("LegendRenderingOrder.REVERSE");
/** The name. */
private String name;
/**
* Private constructor.
*
* @param name the name.
*/
private LegendRenderingOrder(String name) {
this.name = name;
}
/**
* Returns a string representing the object.
*
* @return The string.
*/
@Override
public String toString() {
return this.name;
}
/**
* Returns {@code true} if this object is equal to the specified
* object, and {@code false} otherwise.
*
* @param obj the other object.
*
* @return A boolean.
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof LegendRenderingOrder)) {
return false;
}
LegendRenderingOrder order = (LegendRenderingOrder) obj;
if (!this.name.equals(order.toString())) {
return false;
}
return true;
}
/**
* Ensures that serialization returns the unique instances.
*
* @return The object.
*
* @throws ObjectStreamException if there is a problem.
*/
private Object readResolve() throws ObjectStreamException {
if (this.equals(LegendRenderingOrder.STANDARD)) {
return LegendRenderingOrder.STANDARD;
}
else if (this.equals(LegendRenderingOrder.REVERSE)) {
return LegendRenderingOrder.REVERSE;
}
return null;
}
}
jfree-jfreechart-cb8ff67/src/main/java/org/jfree/chart/MouseWheelHandler.java 0000664 0000000 0000000 00000011541 14636042355 0027276 0 ustar 00root root 0000000 0000000 /* ===========================================================
* JFreeChart : a free chart library for the Java(tm) platform
* ===========================================================
*
* (C) Copyright 2000-present, by David Gilbert and Contributors.
*
* Project Info: http://www.jfree.org/jfreechart/index.html
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* [Oracle and Java are registered trademarks of Oracle and/or its affiliates.
* Other names may be trademarks of their respective owners.]
*
* ----------------------
* MouseWheelHandler.java
* ----------------------
* (C) Copyright 2009-present, by David Gilbert and Contributors.
*
* Original Author: David Gilbert;
* Contributor(s): Ulrich Voigt - patch 2686040;
* Jim Goodwin - bug fix;
*
*/
package org.jfree.chart;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.geom.Point2D;
import java.io.Serializable;
import org.jfree.chart.plot.PiePlot;
import org.jfree.chart.plot.Plot;
import org.jfree.chart.plot.PlotRenderingInfo;
import org.jfree.chart.plot.Zoomable;
/**
* A class that handles mouse wheel events for the {@link ChartPanel} class.
*/
public class MouseWheelHandler implements MouseWheelListener, Serializable {
/** The chart panel. */
private ChartPanel chartPanel;
/** The zoom factor. */
double zoomFactor;
/**
* Creates a new instance for the specified chart panel.
*
* @param chartPanel the chart panel ({@code null} not permitted).
*/
public MouseWheelHandler(ChartPanel chartPanel) {
this.chartPanel = chartPanel;
this.zoomFactor = 0.10;
this.chartPanel.addMouseWheelListener(this);
}
/**
* Returns the current zoom factor. The default value is 0.10 (ten
* percent).
*
* @return The zoom factor.
*
* @see #setZoomFactor(double)
*/
public double getZoomFactor() {
return this.zoomFactor;
}
/**
* Sets the zoom factor.
*
* @param zoomFactor the zoom factor.
*
* @see #getZoomFactor()
*/
public void setZoomFactor(double zoomFactor) {
this.zoomFactor = zoomFactor;
}
/**
* Handles a mouse wheel event from the underlying chart panel.
*
* @param e the event.
*/
@Override
public void mouseWheelMoved(MouseWheelEvent e) {
JFreeChart chart = this.chartPanel.getChart();
if (chart == null) {
return;
}
Plot plot = chart.getPlot();
if (plot instanceof Zoomable) {
Zoomable zoomable = (Zoomable) plot;
handleZoomable(zoomable, e);
}
else if (plot instanceof PiePlot) {
PiePlot pp = (PiePlot) plot;
pp.handleMouseWheelRotation(e.getWheelRotation());
}
}
/**
* Handle the case where a plot implements the {@link Zoomable} interface.
*
* @param zoomable the zoomable plot.
* @param e the mouse wheel event.
*/
private void handleZoomable(Zoomable zoomable, MouseWheelEvent e) {
// don't zoom unless the mouse pointer is in the plot's data area
ChartRenderingInfo info = this.chartPanel.getChartRenderingInfo();
PlotRenderingInfo pinfo = info.getPlotInfo();
Point2D p = this.chartPanel.translateScreenToJava2D(e.getPoint());
if (!pinfo.getDataArea().contains(p)) {
return;
}
Plot plot = (Plot) zoomable;
// do not notify while zooming each axis
boolean notifyState = plot.isNotify();
plot.setNotify(false);
int clicks = e.getWheelRotation();
double zf = 1.0 + this.zoomFactor;
if (clicks < 0) {
zf = 1.0 / zf;
}
if (chartPanel.isDomainZoomable()) {
zoomable.zoomDomainAxes(zf, pinfo, p, true);
}
if (chartPanel.isRangeZoomable()) {
zoomable.zoomRangeAxes(zf, pinfo, p, true);
}
plot.setNotify(notifyState); // this generates the change event too
}
}
jfree-jfreechart-cb8ff67/src/main/java/org/jfree/chart/OfflineRenderingChartPanel.java 0000664 0000000 0000000 00000044237 14636042355 0031115 0 ustar 00root root 0000000 0000000 /* ===========================================================
* JFreeChart : a free chart library for the Java(tm) platform
* ===========================================================
*
* (C) Copyright 2000-present, by David Gilbert and Contributors.
*
* Project Info: http://www.jfree.org/jfreechart/index.html
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* [Oracle and Java are registered trademarks of Oracle and/or its affiliates.
* Other names may be trademarks of their respective owners.]
*
* -------------------------------
* OfflineRenderingChartPanel.java
* -------------------------------
* (C) Copyright 2000-present, by Yuri Blankenstein and Contributors.
*
* Original Author: Yuri Blankenstein;
*/
package org.jfree.chart;
import java.awt.AlphaComposite;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.Rectangle;
import java.awt.Transparency;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import javax.swing.SwingWorker;
import org.jfree.chart.entity.EntityCollection;
import org.jfree.chart.plot.PlotRenderingInfo;
/**
* A {@link ChartPanel} that applies offline rendering, for better performance
* when navigating (i.e. panning / zooming) {@link JFreeChart charts} with lots
* of data.
*
* This chart panel uses a {@link SwingWorker} to perform the actual
* {@link JFreeChart} rendering. While rendering, a {@link Cursor#WAIT_CURSOR
* wait cursor} is visible and the current buffered image of the chart will be
* scaled and drawn to the screen. When - while rendering - another
* {@link #setRefreshBuffer(boolean) refresh} is requested, this will be either
* postponed until the current rendering is done or ignored when another refresh
* is requested.
*/
public class OfflineRenderingChartPanel extends ChartPanel {
private static final long serialVersionUID = -724633596883320084L;
/**
* Using enum state pattern to control the 'offline' rendering
*/
protected enum State {
IDLE {
@Override
protected State renderOffline(OfflineRenderingChartPanel panel,
OfflineChartRenderer renderer) {
// Start rendering offline
renderer.execute();
panel.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
return RENDERING;
}
@Override
protected State offlineRenderingDone(
OfflineRenderingChartPanel panel,
OfflineChartRenderer renderer) {
throw new IllegalStateException(
"offlineRenderingDone not expected in IDLE state");
}
},
RENDERING {
@Override
protected State renderOffline(OfflineRenderingChartPanel panel,
OfflineChartRenderer renderer) {
// We're already rendering, we'll start this renderer when we're
// finished. If another rendering is requested, this one will be
// ignored, see RE_RENDERING_PENDING. This gains a lot of speed
// as not all requested (intermediate) renderings are executed
// for large plots.
panel.pendingOfflineRenderer = renderer;
return RE_RENDERING_PENDING;
}
@Override
protected State offlineRenderingDone(
OfflineRenderingChartPanel panel,
OfflineChartRenderer renderer) {
// Offline rendering done, prepare the buffer and info for the
// next repaint and request it.
panel.currentChartBuffer = renderer.buffer;
panel.currentChartRenderingInfo = renderer.info;
panel.repaint();
panel.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
return IDLE;
}
},
RE_RENDERING_PENDING {
@Override
protected State renderOffline(OfflineRenderingChartPanel panel,
OfflineChartRenderer renderer) {
// We're already rendering, we'll start this renderer when we're
// finished.
panel.pendingOfflineRenderer = renderer;
return RE_RENDERING_PENDING;
}
@Override
protected State offlineRenderingDone(
OfflineRenderingChartPanel panel,
OfflineChartRenderer renderer) {
// Store the intermediate result, but do not actively repaint
// as this could trigger another RE_RENDERING_PENDING if i.e.
// the buffer-image-size of the pending renderer differs from
// the current buffer-image-size.
panel.currentChartBuffer = renderer.buffer;
panel.currentChartRenderingInfo = renderer.info;
// Immediately start rendering again to update the chart to the
// latest requested state.
panel.pendingOfflineRenderer.execute();
panel.pendingOfflineRenderer = null;
return RENDERING;
}
};
protected abstract State renderOffline(
final OfflineRenderingChartPanel panel,
final OfflineChartRenderer renderer);
protected abstract State offlineRenderingDone(
final OfflineRenderingChartPanel panel,
final OfflineChartRenderer renderer);
}
/** A buffer for the rendered chart. */
private transient BufferedImage currentChartBuffer = null;
private transient ChartRenderingInfo currentChartRenderingInfo = null;
/** A pending rendering for the chart. */
private transient OfflineChartRenderer pendingOfflineRenderer = null;
private State state = State.IDLE;
/**
* Constructs a double buffered JFreeChart panel that displays the specified
* chart.
*
* @param chart the chart.
*/
public OfflineRenderingChartPanel(JFreeChart chart) {
this(chart, DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_MINIMUM_DRAW_WIDTH,
DEFAULT_MINIMUM_DRAW_HEIGHT, DEFAULT_MAXIMUM_DRAW_WIDTH,
DEFAULT_MAXIMUM_DRAW_HEIGHT, true, // properties
true, // save
true, // print
true, // zoom
true // tooltips
);
}
/**
* Constructs a double buffered JFreeChart panel.
*
* @param chart the chart.
* @param properties a flag indicating whether or not the chart property
* editor should be available via the popup menu.
* @param save a flag indicating whether or not save options should be
* available via the popup menu.
* @param print a flag indicating whether or not the print option
* should be available via the popup menu.
* @param zoom a flag indicating whether or not zoom options should be
* added to the popup menu.
* @param tooltips a flag indicating whether or not tooltips should be
* enabled for the chart.
*/
public OfflineRenderingChartPanel(JFreeChart chart, boolean properties,
boolean save, boolean print, boolean zoom, boolean tooltips) {
this(chart, DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_MINIMUM_DRAW_WIDTH,
DEFAULT_MINIMUM_DRAW_HEIGHT, DEFAULT_MAXIMUM_DRAW_WIDTH,
DEFAULT_MAXIMUM_DRAW_HEIGHT, properties, save, print, zoom,
tooltips);
}
/**
* Constructs a double buffered JFreeChart panel.
*
* @param chart the chart.
* @param width the preferred width of the panel.
* @param height the preferred height of the panel.
* @param minimumDrawWidth the minimum drawing width.
* @param minimumDrawHeight the minimum drawing height.
* @param maximumDrawWidth the maximum drawing width.
* @param maximumDrawHeight the maximum drawing height.
* @param properties a flag indicating whether or not the chart
* property editor should be available via the
* popup menu.
* @param save a flag indicating whether or not save options
* should be available via the popup menu.
* @param print a flag indicating whether or not the print
* option should be available via the popup menu.
* @param zoom a flag indicating whether or not zoom options
* should be added to the popup menu.
* @param tooltips a flag indicating whether or not tooltips should
* be enabled for the chart.
*/
public OfflineRenderingChartPanel(JFreeChart chart, int width, int height,
int minimumDrawWidth, int minimumDrawHeight, int maximumDrawWidth,
int maximumDrawHeight, boolean properties, boolean save,
boolean print, boolean zoom, boolean tooltips) {
this(chart, width, height, minimumDrawWidth, minimumDrawHeight,
maximumDrawWidth, maximumDrawHeight, properties, true, save,
print, zoom, tooltips);
}
/**
* Constructs a double buffered JFreeChart panel.
*
* @param chart the chart.
* @param width the preferred width of the panel.
* @param height the preferred height of the panel.
* @param minimumDrawWidth the minimum drawing width.
* @param minimumDrawHeight the minimum drawing height.
* @param maximumDrawWidth the maximum drawing width.
* @param maximumDrawHeight the maximum drawing height.
* @param properties a flag indicating whether or not the chart
* property editor should be available via the
* popup menu.
* @param copy a flag indicating whether or not a copy option
* should be available via the popup menu.
* @param save a flag indicating whether or not save options
* should be available via the popup menu.
* @param print a flag indicating whether or not the print
* option should be available via the popup menu.
* @param zoom a flag indicating whether or not zoom options
* should be added to the popup menu.
* @param tooltips a flag indicating whether or not tooltips should
* be enabled for the chart.
*/
public OfflineRenderingChartPanel(JFreeChart chart, int width, int height,
int minimumDrawWidth, int minimumDrawHeight, int maximumDrawWidth,
int maximumDrawHeight, boolean properties, boolean copy,
boolean save, boolean print, boolean zoom, boolean tooltips) {
super(chart, width, height, minimumDrawWidth, minimumDrawHeight,
maximumDrawWidth, maximumDrawHeight, true, properties, copy,
save, print, zoom, tooltips);
}
@Override
protected BufferedImage paintChartToBuffer(Graphics2D g2,
Dimension bufferSize, Dimension chartSize, Point2D anchor,
ChartRenderingInfo info) {
synchronized (state) {
if (this.currentChartBuffer == null) {
// Rendering the first time, prepare an empty buffer and
// start rendering, no need for an additional state
this.currentChartBuffer = createChartBuffer(g2, bufferSize);
clearChartBuffer(currentChartBuffer);
setRefreshBuffer(true);
} else if ((this.currentChartBuffer.getWidth() != bufferSize.width)
|| (this.currentChartBuffer
.getHeight() != bufferSize.height)) {
setRefreshBuffer(true);
}
// do we need to redraw the buffer?
if (getRefreshBuffer()) {
setRefreshBuffer(false); // clear the flag
// Rendering is done offline, hence it requires a fresh buffer
// and rendering info
BufferedImage rendererBuffer = createChartBuffer(g2,
bufferSize);
ChartRenderingInfo rendererInfo = info;
if (rendererInfo != null) {
// As the chart will be re-rendered, the current chart
// entities cannot be trusted
final EntityCollection entityCollection =
rendererInfo.getEntityCollection();
if (entityCollection != null) {
entityCollection.clear();
}
// Offline rendering requires its own instance of
// ChartRenderingInfo, using clone if possible
try {
rendererInfo = rendererInfo.clone();
} catch (CloneNotSupportedException e) {
// Not expected
e.printStackTrace();
rendererInfo = new ChartRenderingInfo();
}
}
OfflineChartRenderer offlineRenderer = new OfflineChartRenderer(
getChart(), rendererBuffer, chartSize, anchor,
rendererInfo);
state = state.renderOffline(this, offlineRenderer);
}
// Copy the rendered ChartRenderingInfo into the passed info
// argument and mark that we have done so.
copyChartRenderingInfo(this.currentChartRenderingInfo, info);
this.currentChartRenderingInfo = info;
return this.currentChartBuffer;
}
}
private class OfflineChartRenderer extends SwingWorker
* Note that the {@link ChartFactory} class contains a range
* of static methods that will return ready-made charts, and often this
* is a more convenient way to create charts than using this constructor.
*
* @param plot the plot ({@code null} not permitted).
*/
public JFreeChart(Plot plot) {
this(null, null, plot, true);
}
/**
* Creates a new chart with the given title and plot. A default font
* ({@link #DEFAULT_TITLE_FONT}) is used for the title, and the chart will
* have a legend added automatically.
*
* Note that the {@link ChartFactory} class contains a range
* of static methods that will return ready-made charts, and often this
* is a more convenient way to create charts than using this constructor.
*
* @param title the chart title ({@code null} permitted).
* @param plot the plot ({@code null} not permitted).
*/
public JFreeChart(String title, Plot plot) {
this(title, JFreeChart.DEFAULT_TITLE_FONT, plot, true);
}
/**
* Creates a new chart with the given title and plot. The
* {@code createLegend} argument specifies whether or not a legend
* should be added to the chart.
*
* Note that the {@link ChartFactory} class contains a range
* of static methods that will return ready-made charts, and often this
* is a more convenient way to create charts than using this constructor.
*
* @param title the chart title ({@code null} permitted).
* @param titleFont the font for displaying the chart title
* ({@code null} permitted).
* @param plot controller of the visual representation of the data
* ({@code null} not permitted).
* @param createLegend a flag indicating whether or not a legend should
* be created for the chart.
*/
public JFreeChart(String title, Font titleFont, Plot plot,
boolean createLegend) {
Args.nullNotPermitted(plot, "plot");
this.id = null;
plot.setChart(this);
// create storage for listeners...
this.progressListeners = new EventListenerList();
this.changeListeners = new EventListenerList();
this.notify = true; // default is to notify listeners when the
// chart changes
this.renderingHints = new RenderingHints(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
// added the following hint because of
// http://stackoverflow.com/questions/7785082/
this.renderingHints.put(RenderingHints.KEY_STROKE_CONTROL,
RenderingHints.VALUE_STROKE_PURE);
this.borderVisible = false;
this.borderStroke = new BasicStroke(1.0f);
this.borderPaint = Color.BLACK;
this.padding = RectangleInsets.ZERO_INSETS;
this.plot = plot;
plot.addChangeListener(this);
this.subtitles = new ArrayList();
// create a legend, if requested...
if (createLegend) {
LegendTitle legend = new LegendTitle(this.plot);
legend.setMargin(new RectangleInsets(1.0, 1.0, 1.0, 1.0));
legend.setBackgroundPaint(Color.WHITE);
legend.setPosition(RectangleEdge.BOTTOM);
this.subtitles.add(legend);
legend.addChangeListener(this);
}
// add the chart title, if one has been specified...
if (title != null) {
if (titleFont == null) {
titleFont = DEFAULT_TITLE_FONT;
}
this.title = new TextTitle(title, titleFont);
this.title.addChangeListener(this);
}
this.backgroundPaint = DEFAULT_BACKGROUND_PAINT;
this.backgroundImage = DEFAULT_BACKGROUND_IMAGE;
this.backgroundImageAlignment = DEFAULT_BACKGROUND_IMAGE_ALIGNMENT;
this.backgroundImageAlpha = DEFAULT_BACKGROUND_IMAGE_ALPHA;
}
/**
* Returns the ID for the chart.
*
* @return The ID for the chart (possibly {@code null}).
*/
public String getID() {
return this.id;
}
/**
* Sets the ID for the chart.
*
* @param id the id ({@code null} permitted).
*/
public void setID(String id) {
this.id = id;
}
/**
* Returns the flag that controls whether or not rendering hints
* ({@link ChartHints#KEY_BEGIN_ELEMENT} and
* {@link ChartHints#KEY_END_ELEMENT}) that identify chart elements are
* added during rendering. The default value is {@code false}.
*
* @return A boolean.
*
* @see #setElementHinting(boolean)
*/
public boolean getElementHinting() {
return this.elementHinting;
}
/**
* Sets the flag that controls whether or not rendering hints
* ({@link ChartHints#KEY_BEGIN_ELEMENT} and
* {@link ChartHints#KEY_END_ELEMENT}) that identify chart elements are
* added during rendering.
*
* @param hinting the new flag value.
*
* @see #getElementHinting()
*/
public void setElementHinting(boolean hinting) {
this.elementHinting = hinting;
}
/**
* Returns the collection of rendering hints for the chart.
*
* @return The rendering hints for the chart (never {@code null}).
*
* @see #setRenderingHints(RenderingHints)
*/
public RenderingHints getRenderingHints() {
return this.renderingHints;
}
/**
* Sets the rendering hints for the chart. These will be added (using the
* {@code Graphics2D.addRenderingHints()} method) near the start of the
* {@code JFreeChart.draw()} method.
*
* @param renderingHints the rendering hints ({@code null} not permitted).
*
* @see #getRenderingHints()
*/
public void setRenderingHints(RenderingHints renderingHints) {
Args.nullNotPermitted(renderingHints, "renderingHints");
this.renderingHints = renderingHints;
fireChartChanged();
}
/**
* Returns a flag that controls whether or not a border is drawn around the
* outside of the chart.
*
* @return A boolean.
*
* @see #setBorderVisible(boolean)
*/
public boolean isBorderVisible() {
return this.borderVisible;
}
/**
* Sets a flag that controls whether or not a border is drawn around the
* outside of the chart.
*
* @param visible the flag.
*
* @see #isBorderVisible()
*/
public void setBorderVisible(boolean visible) {
this.borderVisible = visible;
fireChartChanged();
}
/**
* Returns the stroke used to draw the chart border (if visible).
*
* @return The border stroke.
*
* @see #setBorderStroke(Stroke)
*/
public Stroke getBorderStroke() {
return this.borderStroke;
}
/**
* Sets the stroke used to draw the chart border (if visible).
*
* @param stroke the stroke.
*
* @see #getBorderStroke()
*/
public void setBorderStroke(Stroke stroke) {
this.borderStroke = stroke;
fireChartChanged();
}
/**
* Returns the paint used to draw the chart border (if visible).
*
* @return The border paint.
*
* @see #setBorderPaint(Paint)
*/
public Paint getBorderPaint() {
return this.borderPaint;
}
/**
* Sets the paint used to draw the chart border (if visible).
*
* @param paint the paint.
*
* @see #getBorderPaint()
*/
public void setBorderPaint(Paint paint) {
this.borderPaint = paint;
fireChartChanged();
}
/**
* Returns the padding between the chart border and the chart drawing area.
*
* @return The padding (never {@code null}).
*
* @see #setPadding(RectangleInsets)
*/
public RectangleInsets getPadding() {
return this.padding;
}
/**
* Sets the padding between the chart border and the chart drawing area,
* and sends a {@link ChartChangeEvent} to all registered listeners.
*
* @param padding the padding ({@code null} not permitted).
*
* @see #getPadding()
*/
public void setPadding(RectangleInsets padding) {
Args.nullNotPermitted(padding, "padding");
this.padding = padding;
notifyListeners(new ChartChangeEvent(this));
}
/**
* Returns the main chart title. Very often a chart will have just one
* title, so we make this case simple by providing accessor methods for
* the main title. However, multiple titles are supported - see the
* {@link #addSubtitle(Title)} method.
*
* @return The chart title (possibly {@code null}).
*
* @see #setTitle(TextTitle)
*/
public TextTitle getTitle() {
return this.title;
}
/**
* Sets the main title for the chart and sends a {@link ChartChangeEvent}
* to all registered listeners. If you do not want a title for the
* chart, set it to {@code null}. If you want more than one title on
* a chart, use the {@link #addSubtitle(Title)} method.
*
* @param title the title ({@code null} permitted).
*
* @see #getTitle()
*/
public void setTitle(TextTitle title) {
if (this.title != null) {
this.title.removeChangeListener(this);
}
this.title = title;
if (title != null) {
title.addChangeListener(this);
}
fireChartChanged();
}
/**
* Sets the chart title and sends a {@link ChartChangeEvent} to all
* registered listeners. This is a convenience method that ends up calling
* the {@link #setTitle(TextTitle)} method. If there is an existing title,
* its text is updated, otherwise a new title using the default font is
* added to the chart. If {@code text} is {@code null} the chart
* title is set to {@code null}.
*
* @param text the title text ({@code null} permitted).
*
* @see #getTitle()
*/
public void setTitle(String text) {
if (text != null) {
if (this.title == null) {
setTitle(new TextTitle(text, JFreeChart.DEFAULT_TITLE_FONT));
} else {
this.title.setText(text);
}
}
else {
setTitle((TextTitle) null);
}
}
/**
* Adds a legend to the plot and sends a {@link ChartChangeEvent} to all
* registered listeners.
*
* @param legend the legend ({@code null} not permitted).
*
* @see #removeLegend()
*/
public void addLegend(LegendTitle legend) {
addSubtitle(legend);
}
/**
* Returns the legend for the chart, if there is one. Note that a chart
* can have more than one legend - this method returns the first.
*
* @return The legend (possibly {@code null}).
*
* @see #getLegend(int)
*/
public LegendTitle getLegend() {
return getLegend(0);
}
/**
* Returns the nth legend for a chart, or {@code null}.
*
* @param index the legend index (zero-based).
*
* @return The legend (possibly {@code null}).
*
* @see #addLegend(LegendTitle)
*/
public LegendTitle getLegend(int index) {
int seen = 0;
Iterator iterator = this.subtitles.iterator();
while (iterator.hasNext()) {
Title subtitle = (Title) iterator.next();
if (subtitle instanceof LegendTitle) {
if (seen == index) {
return (LegendTitle) subtitle;
}
else {
seen++;
}
}
}
return null;
}
/**
* Removes the first legend in the chart and sends a
* {@link ChartChangeEvent} to all registered listeners.
*
* @see #getLegend()
*/
public void removeLegend() {
removeSubtitle(getLegend());
}
/**
* Returns the list of subtitles for the chart.
*
* @return The subtitle list (possibly empty, but never {@code null}).
*
* @see #setSubtitles(List)
*/
public List getSubtitles() {
return new ArrayList(this.subtitles);
}
/**
* Sets the title list for the chart (completely replaces any existing
* titles) and sends a {@link ChartChangeEvent} to all registered
* listeners.
*
* @param subtitles the new list of subtitles ({@code null} not
* permitted).
*
* @see #getSubtitles()
*/
public void setSubtitles(List subtitles) {
if (subtitles == null) {
throw new NullPointerException("Null 'subtitles' argument.");
}
setNotify(false);
clearSubtitles();
Iterator iterator = subtitles.iterator();
while (iterator.hasNext()) {
Title t = (Title) iterator.next();
if (t != null) {
addSubtitle(t);
}
}
setNotify(true); // this fires a ChartChangeEvent
}
/**
* Returns the number of titles for the chart.
*
* @return The number of titles for the chart.
*
* @see #getSubtitles()
*/
public int getSubtitleCount() {
return this.subtitles.size();
}
/**
* Returns a chart subtitle.
*
* @param index the index of the chart subtitle (zero based).
*
* @return A chart subtitle.
*
* @see #addSubtitle(Title)
*/
public Title getSubtitle(int index) {
if ((index < 0) || (index >= getSubtitleCount())) {
throw new IllegalArgumentException("Index out of range.");
}
return (Title) this.subtitles.get(index);
}
/**
* Adds a chart subtitle, and notifies registered listeners that the chart
* has been modified.
*
* @param subtitle the subtitle ({@code null} not permitted).
*
* @see #getSubtitle(int)
*/
public void addSubtitle(Title subtitle) {
Args.nullNotPermitted(subtitle, "subtitle");
this.subtitles.add(subtitle);
subtitle.addChangeListener(this);
fireChartChanged();
}
/**
* Adds a subtitle at a particular position in the subtitle list, and sends
* a {@link ChartChangeEvent} to all registered listeners.
*
* @param index the index (in the range 0 to {@link #getSubtitleCount()}).
* @param subtitle the subtitle to add ({@code null} not permitted).
*/
public void addSubtitle(int index, Title subtitle) {
if (index < 0 || index > getSubtitleCount()) {
throw new IllegalArgumentException(
"The 'index' argument is out of range.");
}
Args.nullNotPermitted(subtitle, "subtitle");
this.subtitles.add(index, subtitle);
subtitle.addChangeListener(this);
fireChartChanged();
}
/**
* Clears all subtitles from the chart and sends a {@link ChartChangeEvent}
* to all registered listeners.
*
* @see #addSubtitle(Title)
*/
public void clearSubtitles() {
Iterator iterator = this.subtitles.iterator();
while (iterator.hasNext()) {
Title t = (Title) iterator.next();
t.removeChangeListener(this);
}
this.subtitles.clear();
fireChartChanged();
}
/**
* Removes the specified subtitle and sends a {@link ChartChangeEvent} to
* all registered listeners.
*
* @param title the title.
*
* @see #addSubtitle(Title)
*/
public void removeSubtitle(Title title) {
this.subtitles.remove(title);
fireChartChanged();
}
/**
* Returns the plot for the chart. The plot is a class responsible for
* coordinating the visual representation of the data, including the axes
* (if any).
*
* @return The plot.
*/
public Plot getPlot() {
return this.plot;
}
/**
* Returns the plot cast as a {@link CategoryPlot}.
*