Java tutorial
/* * JasperReports - Free Java Reporting Library. * Copyright (C) 2001 - 2019 TIBCO Software Inc. All rights reserved. * http://www.jaspersoft.com * * Unless you have purchased a commercial license agreement from Jaspersoft, * the following license terms apply: * * This program is part of JasperReports. * * JasperReports 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 3 of the License, or * (at your option) any later version. * * JasperReports 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 JasperReports. If not, see <http://www.gnu.org/licenses/>. */ package net.sf.jasperreports.charts.util; import java.awt.Graphics2D; import java.awt.geom.Rectangle2D; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.StringTokenizer; import org.jfree.chart.ChartRenderingInfo; import org.jfree.chart.JFreeChart; import org.jfree.chart.axis.NumberAxis; import org.jfree.chart.axis.NumberTickUnit; import org.jfree.chart.axis.TickUnit; import org.jfree.chart.axis.TickUnitSource; import org.jfree.chart.axis.TickUnits; import org.jfree.chart.entity.ChartEntity; import org.jfree.chart.entity.EntityCollection; import org.jfree.data.Range; import net.sf.jasperreports.charts.ChartTheme; import net.sf.jasperreports.charts.ChartThemeBundle; import net.sf.jasperreports.engine.DefaultJasperReportsContext; import net.sf.jasperreports.engine.JRException; import net.sf.jasperreports.engine.JRPrintHyperlink; import net.sf.jasperreports.engine.JRPrintImageArea; import net.sf.jasperreports.engine.JRPrintImageAreaHyperlink; import net.sf.jasperreports.engine.JRPropertiesUtil; import net.sf.jasperreports.engine.JRRuntimeException; import net.sf.jasperreports.engine.JasperReportsContext; import net.sf.jasperreports.engine.fill.DefaultChartTheme; import net.sf.jasperreports.engine.util.JRSingletonCache; /** * @author Teodor Danciu (teodord@users.sourceforge.net) */ public final class ChartUtil { public static final String EXCEPTION_MESSAGE_KEY_CHART_THEME_NOT_FOUND = "charts.util.chart.theme.not.found"; public static final String EXCEPTION_MESSAGE_KEY_RENDERER_FACTORY_NOT_SPECIFIED = "charts.util.renderer.factory.not.specified"; /** * */ private static final JRSingletonCache<ChartRenderableFactory> CHART_RENDERABLE_FACTORY_CACHE = new JRSingletonCache<ChartRenderableFactory>( ChartRenderableFactory.class); protected static final double AUTO_TICK_UNIT_THRESHOLD = 1e12; protected static final double AUTO_TICK_UNIT_FACTOR = 1000d; private JasperReportsContext jasperReportsContext; /** * */ private ChartUtil(JasperReportsContext jasperReportsContext) { this.jasperReportsContext = jasperReportsContext; } /** * */ private static ChartUtil getDefaultInstance()//FIXMECONTEXT check this use of this { return new ChartUtil(DefaultJasperReportsContext.getInstance()); } /** * */ public static ChartUtil getInstance(JasperReportsContext jasperReportsContext) { return new ChartUtil(jasperReportsContext); } /** * */ public static List<JRPrintImageAreaHyperlink> getImageAreaHyperlinks(JFreeChart chart, ChartHyperlinkProvider chartHyperlinkProvider, Graphics2D grx, Rectangle2D renderingArea)// throws JRException { List<JRPrintImageAreaHyperlink> areaHyperlinks = null; if (chartHyperlinkProvider != null && chartHyperlinkProvider.hasHyperlinks()) { ChartRenderingInfo renderingInfo = new ChartRenderingInfo(); if (grx == null) { chart.createBufferedImage((int) renderingArea.getWidth(), (int) renderingArea.getHeight(), renderingInfo); } else { chart.draw(grx, renderingArea, renderingInfo); } EntityCollection entityCollection = renderingInfo.getEntityCollection(); if (entityCollection != null && entityCollection.getEntityCount() > 0) { areaHyperlinks = new ArrayList<JRPrintImageAreaHyperlink>(entityCollection.getEntityCount()); for (@SuppressWarnings("unchecked") Iterator<ChartEntity> it = entityCollection.iterator(); it.hasNext();) { ChartEntity entity = it.next(); JRPrintHyperlink printHyperlink = chartHyperlinkProvider.getEntityHyperlink(entity); if (printHyperlink != null) { JRPrintImageArea area = getImageArea(entity); JRPrintImageAreaHyperlink areaHyperlink = new JRPrintImageAreaHyperlink(); areaHyperlink.setArea(area); areaHyperlink.setHyperlink(printHyperlink); areaHyperlinks.add(areaHyperlink); } } } } return areaHyperlinks; } private static JRPrintImageArea getImageArea(ChartEntity entity) { JRPrintImageArea area = new JRPrintImageArea(); area.setShape(JRPrintImageArea.getShape(entity.getShapeType())); int[] coordinates = getCoordinates(entity); if (coordinates != null) { area.setCoordinates(coordinates); } return area; } private static int[] getCoordinates(ChartEntity entity) { int[] coordinates = null; String shapeCoords = entity.getShapeCoords(); if (shapeCoords != null && shapeCoords.length() > 0) { StringTokenizer tokens = new StringTokenizer(shapeCoords, ","); coordinates = new int[tokens.countTokens()]; int idx = 0; while (tokens.hasMoreTokens()) { String coord = tokens.nextToken(); coordinates[idx] = Integer.parseInt(coord); ++idx; } } return coordinates; } /** * */ public ChartTheme getTheme(String themeName) { if (themeName == null) { return new DefaultChartTheme(); } List<ChartThemeBundle> themeBundles = jasperReportsContext.getExtensions(ChartThemeBundle.class); for (Iterator<ChartThemeBundle> it = themeBundles.iterator(); it.hasNext();) { ChartThemeBundle bundle = it.next(); ChartTheme chartTheme = bundle.getChartTheme(themeName); if (chartTheme != null) { return chartTheme; } } throw new JRRuntimeException(EXCEPTION_MESSAGE_KEY_CHART_THEME_NOT_FOUND, new Object[] { themeName }); } /** * */ public ChartRenderableFactory getChartRenderableFactory(String renderType) { String factoryClass = JRPropertiesUtil.getInstance(jasperReportsContext) .getProperty(ChartRenderableFactory.PROPERTY_CHART_RENDERER_FACTORY_PREFIX + renderType); if (factoryClass == null) { throw new JRRuntimeException(EXCEPTION_MESSAGE_KEY_RENDERER_FACTORY_NOT_SPECIFIED, new Object[] { renderType }); } try { return CHART_RENDERABLE_FACTORY_CACHE.getCachedInstance(factoryClass); } catch (JRException e) { throw new JRRuntimeException(e); } } public TickUnitSource createIntegerTickUnits(Locale locale) { DecimalFormatSymbols formatSymbols = DecimalFormatSymbols.getInstance(locale); // copied from NumberAxis.createIntegerTickUnits() to preserve backward behaviour TickUnits units = new TickUnits(); DecimalFormat df0 = new DecimalFormat("0", formatSymbols); DecimalFormat df1 = new DecimalFormat("#,##0", formatSymbols); units.add(new NumberTickUnit(1, df0)); units.add(new NumberTickUnit(2, df0)); units.add(new NumberTickUnit(5, df0)); units.add(new NumberTickUnit(10, df0)); units.add(new NumberTickUnit(20, df0)); units.add(new NumberTickUnit(50, df0)); units.add(new NumberTickUnit(100, df0)); units.add(new NumberTickUnit(200, df0)); units.add(new NumberTickUnit(500, df0)); units.add(new NumberTickUnit(1000, df1)); units.add(new NumberTickUnit(2000, df1)); units.add(new NumberTickUnit(5000, df1)); units.add(new NumberTickUnit(10000, df1)); units.add(new NumberTickUnit(20000, df1)); units.add(new NumberTickUnit(50000, df1)); units.add(new NumberTickUnit(100000, df1)); units.add(new NumberTickUnit(200000, df1)); units.add(new NumberTickUnit(500000, df1)); units.add(new NumberTickUnit(1000000, df1)); units.add(new NumberTickUnit(2000000, df1)); units.add(new NumberTickUnit(5000000, df1)); units.add(new NumberTickUnit(10000000, df1)); units.add(new NumberTickUnit(20000000, df1)); units.add(new NumberTickUnit(50000000, df1)); units.add(new NumberTickUnit(100000000, df1)); units.add(new NumberTickUnit(200000000, df1)); units.add(new NumberTickUnit(500000000, df1)); units.add(new NumberTickUnit(1000000000, df1)); units.add(new NumberTickUnit(2000000000, df1)); units.add(new NumberTickUnit(5000000000.0, df1)); units.add(new NumberTickUnit(10000000000.0, df1)); // adding further values by default because 1E10 is not enough for some people // using getNumberInstance because that's what NumberAxis.createIntegerTickUnits does units.add(new NumberTickUnit(20000000000L, df1)); units.add(new NumberTickUnit(50000000000L, df1)); units.add(new NumberTickUnit(100000000000L, df1)); units.add(new NumberTickUnit(200000000000L, df1)); units.add(new NumberTickUnit(500000000000L, df1)); units.add(new NumberTickUnit(1000000000000L, df1)); units.add(new NumberTickUnit(2000000000000L, df1)); units.add(new NumberTickUnit(5000000000000L, df1)); units.add(new NumberTickUnit(10000000000000L, df1)); units.add(new NumberTickUnit(20000000000000L, df1)); units.add(new NumberTickUnit(50000000000000L, df1)); units.add(new NumberTickUnit(100000000000000L, df1)); units.add(new NumberTickUnit(200000000000000L, df1)); units.add(new NumberTickUnit(500000000000000L, df1)); units.add(new NumberTickUnit(1000000000000000L, df1)); units.add(new NumberTickUnit(2000000000000000L, df1)); units.add(new NumberTickUnit(5000000000000000L, df1)); units.add(new NumberTickUnit(10000000000000000L, df1)); units.add(new NumberTickUnit(20000000000000000L, df1)); units.add(new NumberTickUnit(50000000000000000L, df1)); units.add(new NumberTickUnit(100000000000000000L, df1)); units.add(new NumberTickUnit(200000000000000000L, df1)); units.add(new NumberTickUnit(500000000000000000L, df1)); units.add(new NumberTickUnit(1000000000000000000L, df1)); units.add(new NumberTickUnit(2000000000000000000L, df1)); units.add(new NumberTickUnit(5000000000000000000L, df1)); return units; } public TickUnitSource createStandardTickUnits(Locale locale) { DecimalFormatSymbols formatSymbols = DecimalFormatSymbols.getInstance(locale); //copied from NumberAxis.createStandardTickUnits() to preserve backward behaviour TickUnits units = new TickUnits(); DecimalFormat df0 = new DecimalFormat("0.00000000", formatSymbols); DecimalFormat df1 = new DecimalFormat("0.0000000", formatSymbols); DecimalFormat df2 = new DecimalFormat("0.000000", formatSymbols); DecimalFormat df3 = new DecimalFormat("0.00000", formatSymbols); DecimalFormat df4 = new DecimalFormat("0.0000", formatSymbols); DecimalFormat df5 = new DecimalFormat("0.000", formatSymbols); DecimalFormat df6 = new DecimalFormat("0.00", formatSymbols); DecimalFormat df7 = new DecimalFormat("0.0", formatSymbols); DecimalFormat df8 = new DecimalFormat("#,##0", formatSymbols); //these two are probably not needed DecimalFormat df9 = new DecimalFormat("#,###,##0", formatSymbols); DecimalFormat df10 = new DecimalFormat("#,###,###,##0", formatSymbols); // we can add the units in any order, the TickUnits collection will // sort them... units.add(new NumberTickUnit(0.0000001, df1)); units.add(new NumberTickUnit(0.000001, df2)); units.add(new NumberTickUnit(0.00001, df3)); units.add(new NumberTickUnit(0.0001, df4)); units.add(new NumberTickUnit(0.001, df5)); units.add(new NumberTickUnit(0.01, df6)); units.add(new NumberTickUnit(0.1, df7)); units.add(new NumberTickUnit(1, df8)); units.add(new NumberTickUnit(10, df8)); units.add(new NumberTickUnit(100, df8)); units.add(new NumberTickUnit(1000, df8)); units.add(new NumberTickUnit(10000, df8)); units.add(new NumberTickUnit(100000, df8)); units.add(new NumberTickUnit(1000000, df9)); units.add(new NumberTickUnit(10000000, df9)); units.add(new NumberTickUnit(100000000, df9)); units.add(new NumberTickUnit(1000000000, df10)); units.add(new NumberTickUnit(10000000000.0, df10)); units.add(new NumberTickUnit(100000000000.0, df10)); units.add(new NumberTickUnit(0.00000025, df0)); units.add(new NumberTickUnit(0.0000025, df1)); units.add(new NumberTickUnit(0.000025, df2)); units.add(new NumberTickUnit(0.00025, df3)); units.add(new NumberTickUnit(0.0025, df4)); units.add(new NumberTickUnit(0.025, df5)); units.add(new NumberTickUnit(0.25, df6)); units.add(new NumberTickUnit(2.5, df7)); units.add(new NumberTickUnit(25, df8)); units.add(new NumberTickUnit(250, df8)); units.add(new NumberTickUnit(2500, df8)); units.add(new NumberTickUnit(25000, df8)); units.add(new NumberTickUnit(250000, df8)); units.add(new NumberTickUnit(2500000, df9)); units.add(new NumberTickUnit(25000000, df9)); units.add(new NumberTickUnit(250000000, df9)); units.add(new NumberTickUnit(2500000000.0, df10)); units.add(new NumberTickUnit(25000000000.0, df10)); units.add(new NumberTickUnit(250000000000.0, df10)); units.add(new NumberTickUnit(0.0000005, df1)); units.add(new NumberTickUnit(0.000005, df2)); units.add(new NumberTickUnit(0.00005, df3)); units.add(new NumberTickUnit(0.0005, df4)); units.add(new NumberTickUnit(0.005, df5)); units.add(new NumberTickUnit(0.05, df6)); units.add(new NumberTickUnit(0.5, df7)); units.add(new NumberTickUnit(5L, df8)); units.add(new NumberTickUnit(50L, df8)); units.add(new NumberTickUnit(500L, df8)); units.add(new NumberTickUnit(5000L, df8)); units.add(new NumberTickUnit(50000L, df8)); units.add(new NumberTickUnit(500000L, df8)); units.add(new NumberTickUnit(5000000L, df9)); units.add(new NumberTickUnit(50000000L, df9)); units.add(new NumberTickUnit(500000000L, df9)); units.add(new NumberTickUnit(5000000000L, df10)); units.add(new NumberTickUnit(50000000000L, df10)); units.add(new NumberTickUnit(500000000000L, df10)); // adding further values by default because 5E11 is not enough for some people units.add(new NumberTickUnit(1000000000000L, df8)); units.add(new NumberTickUnit(2500000000000L, df8)); units.add(new NumberTickUnit(5000000000000L, df8)); units.add(new NumberTickUnit(10000000000000L, df8)); units.add(new NumberTickUnit(25000000000000L, df8)); units.add(new NumberTickUnit(50000000000000L, df8)); units.add(new NumberTickUnit(100000000000000L, df8)); units.add(new NumberTickUnit(250000000000000L, df8)); units.add(new NumberTickUnit(500000000000000L, df8)); units.add(new NumberTickUnit(1000000000000000L, df8)); units.add(new NumberTickUnit(2500000000000000L, df8)); units.add(new NumberTickUnit(5000000000000000L, df8)); units.add(new NumberTickUnit(10000000000000000L, df8)); units.add(new NumberTickUnit(25000000000000000L, df8)); units.add(new NumberTickUnit(50000000000000000L, df8)); units.add(new NumberTickUnit(100000000000000000L, df8)); units.add(new NumberTickUnit(250000000000000000L, df8)); units.add(new NumberTickUnit(500000000000000000L, df8)); units.add(new NumberTickUnit(1000000000000000000L, df8)); units.add(new NumberTickUnit(2500000000000000000L, df8)); units.add(new NumberTickUnit(5000000000000000000L, df8)); return units; } public void setAutoTickUnit(NumberAxis numberAxis) { if (numberAxis.isAutoTickUnitSelection()) { Range range = numberAxis.getRange(); if (range.getLength() >= AUTO_TICK_UNIT_THRESHOLD) { // this is a workaround for a floating point error makes JFreeChart // select tick units that are too small when the values are very large double autoSize = range.getLength() / AUTO_TICK_UNIT_THRESHOLD; TickUnit unit = numberAxis.getStandardTickUnits().getCeilingTickUnit(autoSize); numberAxis.setTickUnit((NumberTickUnit) unit, false, false); } } } }