com.metaeffekt.artifact.analysis.utils.JFreeChartUtils Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2021-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.metaeffekt.artifact.analysis.utils;
import org.apache.batik.dom.GenericDOMImplementation;
import org.apache.batik.svggen.SVGGraphics2D;
import org.apache.batik.svggen.SVGGraphics2DIOException;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.StandardChartTheme;
import org.jfree.chart.annotations.XYAnnotation;
import org.jfree.chart.annotations.XYTextAnnotation;
import org.jfree.chart.axis.*;
import org.jfree.chart.block.Block;
import org.jfree.chart.block.BlockContainer;
import org.jfree.chart.block.LabelBlock;
import org.jfree.chart.labels.PieSectionLabelGenerator;
import org.jfree.chart.labels.StandardPieSectionLabelGenerator;
import org.jfree.chart.plot.*;
import org.jfree.chart.renderer.AbstractRenderer;
import org.jfree.chart.renderer.category.CategoryItemRenderer;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.chart.title.*;
import org.jfree.chart.util.Args;
import org.jfree.data.general.DefaultPieDataset;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.io.File;
import java.io.FileNotFoundException;
import java.text.DecimalFormat;
import java.util.List;
public abstract class JFreeChartUtils {
private final static Logger LOG = LoggerFactory.getLogger(JFreeChartUtils.class);
/**
* Writes a JFreeChart into a svg file.
*
* @param chart The chart to write.
* @param file The file to write the svg into.
* @param height The height of the svg.
* @param width The width of the svg.
* @throws SVGGraphics2DIOException If the file failed to write.
* @throws FileNotFoundException If the parent directory does not exist and cannot be created.
*/
public static void writeGraphToFile(JFreeChart chart, File file, int width, int height) throws SVGGraphics2DIOException, FileNotFoundException {
if (!file.getParentFile().exists() && !file.getParentFile().mkdirs()) {
throw new FileNotFoundException("Parent directory of file [" + file.getAbsolutePath() + "] does not exist and cannot be created for writing chart");
} else if (file.isDirectory()) {
throw new IllegalArgumentException("Expected file, got directory for writing chart to [" + file.getAbsolutePath() + "]");
}
final DOMImplementation svgDOM = GenericDOMImplementation.getDOMImplementation();
final Document document = svgDOM.createDocument(null, "svg", null);
final SVGGraphics2D svgGenerator = new SVGGraphics2D(document);
svgGenerator.setSVGCanvasSize(new Dimension(width, height));
// render chart as SVG 2D Graphics object
chart.draw(svgGenerator, new Rectangle2D.Double(0, 0, width, height), null);
svgGenerator.stream(file.getAbsolutePath());
}
public static void applyDefaultForLineChartAxis(CategoryAxis axis) {
axis.setCategoryLabelPositions(CategoryLabelPositions.UP_45);
axis.setMaximumCategoryLabelWidthRatio(1.3f);
axis.setLowerMargin(0);
axis.setUpperMargin(0);
}
public static void applyDefaultForPieChartPlot(PiePlot> plot) {
plot.setLabelGenerator(null);
//plot.setShadowPaint(new Color(0, 0, 0, 0));
plot.setDefaultSectionOutlinePaint(Color.WHITE);
plot.setDefaultSectionOutlineStroke(new BasicStroke(1));
}
public static > void addPieChartData(DefaultPieDataset dataset, PiePlot> plot, T key, Number value, Color color) {
dataset.setValue(key, value);
plot.setSectionPaint(key, color);
}
public static > void addPieChartDataIfNotZero(DefaultPieDataset dataset, PiePlot> plot, T key, Number value, Color color) {
if (value.doubleValue() == 0) return;
dataset.setValue(key, value);
plot.setSectionPaint(key, color);
}
public static void setTransparentBackground(JFreeChart chart) {
if (chart != null) {
chart.setBackgroundPaint(null);
if (chart.getPlot() != null) chart.getPlot().setBackgroundPaint(null);
if (chart.getLegend() != null) chart.getLegend().setBackgroundPaint(null);
if (chart.getTitle() != null) chart.getTitle().setBackgroundPaint(null);
}
}
public static void removeChartOutline(JFreeChart chart) {
if (chart != null && chart.getPlot() != null) {
chart.getPlot().setOutlinePaint(null);
}
}
public static void setPieChartLabelGenerator(JFreeChart chart, boolean pieSectionKey, boolean absoluteValue, boolean percentageValue, Color backgroundPaint, Color foregroundPaint) {
if (chart != null && chart.getPlot() instanceof PiePlot>) {
PiePlot> plot = (PiePlot>) chart.getPlot();
StringBuilder format = new StringBuilder();
if (pieSectionKey) {
format.append("{0}");
if (absoluteValue || percentageValue) {
format.append(":");
}
}
if (absoluteValue) {
format.append(" {1}");
}
if (percentageValue) {
if (absoluteValue) {
format.append(" ({2})");
} else {
format.append(" {2}");
}
}
PieSectionLabelGenerator gen = new StandardPieSectionLabelGenerator(format.toString(), new DecimalFormat("0"), new DecimalFormat("0%"));
plot.setLabelGenerator(gen);
if (backgroundPaint != null) {
plot.setLabelBackgroundPaint(backgroundPaint);
}
if (foregroundPaint != null) {
plot.setLabelPaint(foregroundPaint);
}
}
}
public static void setFont(JFreeChart chart, Font font) {
setFont(chart, font, -1, -1, -1, -1);
}
public static void setFont(JFreeChart chart, Font font, int extraLarge, int large, int regular, int small) {
StandardChartTheme fontApplierTheme = createFontApplierTheme();
fontApplierTheme.setExtraLargeFont(font.deriveFont(Font.BOLD, extraLarge == -1 ? 20 : extraLarge));
fontApplierTheme.setLargeFont(font.deriveFont(Font.BOLD, large == -1 ? 14 : large));
fontApplierTheme.setRegularFont(font.deriveFont(Font.PLAIN, regular == -1 ? 12 : regular));
fontApplierTheme.setSmallFont(font.deriveFont(Font.PLAIN, small == -1 ? 10 : small));
fontApplierTheme.apply(chart);
}
private static StandardChartTheme createFontApplierTheme() {
return new StandardChartTheme("FontApplier") {
@Override
public void apply(JFreeChart chart) {
TextTitle title = chart.getTitle();
if (title != null) {
title.setFont(this.getExtraLargeFont());
}
int subtitleCount = chart.getSubtitleCount();
for (int i = 0; i < subtitleCount; i++) {
applyToTitle(chart.getSubtitle(i));
}
// now process the plot if there is one
Plot plot = chart.getPlot();
if (plot != null) {
applyToPlot(plot);
}
}
@Override
protected void applyToTitle(Title title) {
if (title instanceof TextTitle) {
TextTitle tt = (TextTitle) title;
tt.setFont(this.getLargeFont());
} else if (title instanceof LegendTitle) {
LegendTitle lt = (LegendTitle) title;
lt.setItemFont(this.getRegularFont());
if (lt.getWrapper() != null) {
applyToBlockContainer(lt.getWrapper());
}
} else if (title instanceof PaintScaleLegend) {
PaintScaleLegend psl = (PaintScaleLegend) title;
ValueAxis axis = psl.getAxis();
if (axis != null) {
applyToValueAxis(axis);
}
} else if (title instanceof CompositeTitle) {
CompositeTitle ct = (CompositeTitle) title;
BlockContainer bc = ct.getContainer();
List> blocks = bc.getBlocks();
for (Object block : blocks) {
Block b = (Block) block;
if (b instanceof Title) {
applyToTitle((Title) b);
}
}
}
}
@Override
protected void applyToBlockContainer(BlockContainer bc) {
for (Object o : bc.getBlocks()) {
Block b = (Block) o;
applyToBlock(b);
}
}
@Override
protected void applyToBlock(Block b) {
if (b instanceof Title) {
applyToTitle((Title) b);
} else if (b instanceof LabelBlock) {
LabelBlock lb = (LabelBlock) b;
lb.setFont(this.getRegularFont());
}
}
@Override
protected void applyToPlot(Plot plot) {
Args.nullNotPermitted(plot, "plot");
if (plot instanceof PiePlot) {
applyToPiePlot((PiePlot>) plot);
} else if (plot instanceof MultiplePiePlot) {
applyToMultiplePiePlot((MultiplePiePlot) plot);
} else if (plot instanceof CategoryPlot) {
applyToCategoryPlot((CategoryPlot) plot);
} else if (plot instanceof XYPlot) {
applyToXYPlot((XYPlot) plot);
} else if (plot instanceof FastScatterPlot) {
applyToFastScatterPlot((FastScatterPlot) plot);
} else if (plot instanceof MeterPlot) {
applyToMeterPlot((MeterPlot) plot);
} else if (plot instanceof ThermometerPlot) {
applyToThermometerPlot((ThermometerPlot) plot);
} else if (plot instanceof SpiderWebPlot) {
applyToSpiderWebPlot((SpiderWebPlot) plot);
} else if (plot instanceof PolarPlot) {
applyToPolarPlot((PolarPlot) plot);
}
}
@Override
protected void applyToPiePlot(PiePlot plot) {
plot.setLabelFont(this.getRegularFont());
}
@Override
protected void applyToMultiplePiePlot(MultiplePiePlot plot) {
apply(plot.getPieChart());
}
@Override
protected void applyToCategoryPlot(CategoryPlot plot) {
// process all domain axes
int domainAxisCount = plot.getDomainAxisCount();
for (int i = 0; i < domainAxisCount; i++) {
CategoryAxis axis = plot.getDomainAxis(i);
if (axis != null) {
applyToCategoryAxis(axis);
}
}
// process all range axes
int rangeAxisCount = plot.getRangeAxisCount();
for (int i = 0; i < rangeAxisCount; i++) {
ValueAxis axis = plot.getRangeAxis(i);
if (axis != null) {
applyToValueAxis(axis);
}
}
// process all renderers
int rendererCount = plot.getRendererCount();
for (int i = 0; i < rendererCount; i++) {
CategoryItemRenderer r = plot.getRenderer(i);
if (r != null) {
applyToCategoryItemRenderer(r);
}
}
if (plot instanceof CombinedDomainCategoryPlot) {
CombinedDomainCategoryPlot cp = (CombinedDomainCategoryPlot) plot;
for (Object o : cp.getSubplots()) {
CategoryPlot subplot = (CategoryPlot) o;
if (subplot != null) {
applyToPlot(subplot);
}
}
}
if (plot instanceof CombinedRangeCategoryPlot) {
CombinedRangeCategoryPlot cp = (CombinedRangeCategoryPlot) plot;
for (Object o : cp.getSubplots()) {
CategoryPlot subplot = (CategoryPlot) o;
if (subplot != null) {
applyToPlot(subplot);
}
}
}
}
@Override
protected void applyToXYPlot(XYPlot plot) {
// process all domain axes
int domainAxisCount = plot.getDomainAxisCount();
for (int i = 0; i < domainAxisCount; i++) {
ValueAxis axis = plot.getDomainAxis(i);
if (axis != null) {
applyToValueAxis(axis);
}
}
// process all range axes
int rangeAxisCount = plot.getRangeAxisCount();
for (int i = 0; i < rangeAxisCount; i++) {
ValueAxis axis = plot.getRangeAxis(i);
if (axis != null) {
applyToValueAxis(axis);
}
}
// process all renderers
int rendererCount = plot.getRendererCount();
for (int i = 0; i < rendererCount; i++) {
XYItemRenderer r = plot.getRenderer(i);
if (r != null) {
applyToXYItemRenderer(r);
}
}
// process all annotations
for (Object o : plot.getAnnotations()) {
XYAnnotation a = (XYAnnotation) o;
applyToXYAnnotation(a);
}
if (plot instanceof CombinedDomainXYPlot) {
CombinedDomainXYPlot cp = (CombinedDomainXYPlot) plot;
for (Object o : cp.getSubplots()) {
XYPlot subplot = (XYPlot) o;
if (subplot != null) {
applyToPlot(subplot);
}
}
}
if (plot instanceof CombinedRangeXYPlot) {
CombinedRangeXYPlot cp = (CombinedRangeXYPlot) plot;
for (Object o : cp.getSubplots()) {
XYPlot subplot = (XYPlot) o;
if (subplot != null) {
applyToPlot(subplot);
}
}
}
}
@Override
protected void applyToFastScatterPlot(FastScatterPlot plot) {
ValueAxis xAxis = plot.getDomainAxis();
if (xAxis != null) {
applyToValueAxis(xAxis);
}
ValueAxis yAxis = plot.getRangeAxis();
if (yAxis != null) {
applyToValueAxis(yAxis);
}
}
@Override
protected void applyToPolarPlot(PolarPlot plot) {
plot.setAngleLabelFont(this.getRegularFont());
ValueAxis axis = plot.getAxis();
if (axis != null) {
applyToValueAxis(axis);
}
}
@Override
protected void applyToSpiderWebPlot(SpiderWebPlot plot) {
plot.setLabelFont(this.getRegularFont());
}
@Override
protected void applyToMeterPlot(MeterPlot plot) {
plot.setValueFont(this.getLargeFont());
plot.setTickLabelFont(this.getRegularFont());
}
@Override
protected void applyToThermometerPlot(ThermometerPlot plot) {
plot.setValueFont(this.getLargeFont());
ValueAxis axis = plot.getRangeAxis();
if (axis != null) {
applyToValueAxis(axis);
}
}
@Override
protected void applyToCategoryAxis(CategoryAxis axis) {
axis.setLabelFont(this.getLargeFont());
axis.setTickLabelFont(this.getRegularFont());
if (axis instanceof SubCategoryAxis) {
SubCategoryAxis sca = (SubCategoryAxis) axis;
sca.setSubLabelFont(this.getRegularFont());
}
}
@Override
protected void applyToValueAxis(ValueAxis axis) {
axis.setLabelFont(this.getLargeFont());
axis.setTickLabelFont(this.getRegularFont());
if (axis instanceof SymbolAxis) {
applyToSymbolAxis((SymbolAxis) axis);
}
if (axis instanceof PeriodAxis) {
applyToPeriodAxis((PeriodAxis) axis);
}
}
@Override
protected void applyToSymbolAxis(SymbolAxis axis) {
}
@Override
protected void applyToPeriodAxis(PeriodAxis axis) {
PeriodAxisLabelInfo[] info = axis.getLabelInfo();
for (int i = 0; i < info.length; i++) {
PeriodAxisLabelInfo e = info[i];
PeriodAxisLabelInfo n = new PeriodAxisLabelInfo(e.getPeriodClass(),
e.getDateFormat(), e.getPadding(), this.getRegularFont(),
this.getTickLabelPaint(), e.getDrawDividers(),
e.getDividerStroke(), e.getDividerPaint());
info[i] = n;
}
axis.setLabelInfo(info);
}
@Override
protected void applyToAbstractRenderer(AbstractRenderer renderer) {
}
@Override
protected void applyToCategoryItemRenderer(CategoryItemRenderer renderer) {
Args.nullNotPermitted(renderer, "renderer");
if (renderer instanceof AbstractRenderer) {
applyToAbstractRenderer((AbstractRenderer) renderer);
}
renderer.setDefaultItemLabelFont(this.getRegularFont());
}
@Override
protected void applyToXYItemRenderer(XYItemRenderer renderer) {
Args.nullNotPermitted(renderer, "renderer");
if (renderer instanceof AbstractRenderer) {
applyToAbstractRenderer((AbstractRenderer) renderer);
}
renderer.setDefaultItemLabelFont(this.getRegularFont());
}
@Override
protected void applyToXYAnnotation(XYAnnotation annotation) {
Args.nullNotPermitted(annotation, "annotation");
if (annotation instanceof XYTextAnnotation) {
XYTextAnnotation xyta = (XYTextAnnotation) annotation;
xyta.setFont(this.getSmallFont());
}
}
};
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy