All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.d3x.morpheus.viz.jfree.JFChartBase Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2014-2018 D3X Systems - All Rights Reserved
 *
 * 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.d3x.morpheus.viz.jfree;

import java.awt.*;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Base64;
import java.util.Optional;
import javax.swing.JFrame;

import org.jfree.chart.ChartMouseListener;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.Plot;
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.ui.RectangleEdge;
import org.jfree.ui.RectangleInsets;

import com.d3x.morpheus.viz.chart.Chart;
import com.d3x.morpheus.viz.chart.ChartException;
import com.d3x.morpheus.viz.chart.ChartLabel;
import com.d3x.morpheus.viz.chart.ChartLegend;
import com.d3x.morpheus.viz.chart.ChartOptions;
import com.d3x.morpheus.viz.chart.ChartTheme;
import com.d3x.morpheus.viz.js.JsCode;

/**
 * A convenience base class for building various types of chart types
 *
 * @param 

the plot type * * @author Xavier Witdouck * *

This is open source software released under the Apache 2.0 License

*/ abstract class JFChartBase

implements Chart

, ChartMouseListener { private P plot; private JFreeChart freeChart; private ChartPanel chartPanel; private ChartOptions options; /** * Constructor * @param plot the plot for this chart * @param legend true to enable legend */ JFChartBase(P plot, boolean legend) { this.plot = plot; this.freeChart = new JFreeChart(null, new Font("Arial", Font.PLAIN, 4), underlying(plot), legend); this.freeChart.setBackgroundPaint(Color.WHITE); this.chartPanel = new ChartPanel(freeChart); this.chartPanel.setMouseZoomable(true); this.chartPanel.setRefreshBuffer(true); this.chartPanel.addChartMouseListener(this); this.options = new ChartOptions.Default(); } /** * Returns the JFreeChart plot object from the Morpheus Plot adapter * @param plot the Morpheus plot adapter * @return the JFreeChart plot */ private Plot underlying(P plot) { if (plot instanceof JFXyPlot) { return ((JFXyPlot)plot).underlying(); } else if (plot instanceof JFCatPlot) { return ((JFCatPlot) plot).underlying(); } else if (plot instanceof JFPiePlot) { return ((JFPiePlot) plot).underlying(); } else { throw new IllegalArgumentException("Unsupported plot type: " + plot); } } /** * Returns a reference to the chart panel * @return the JFreeChart chart panel */ ChartPanel chartPanel() { return chartPanel; } /** * Returns the JFreeChart reference for this chart * @return the JFreeChart reference */ JFreeChart freeChart() { return freeChart; } @Override public P plot() { return plot; } @Override public ChartLabel title() { return new TitleAdapter(freeChart, false); } @Override public ChartLabel subtitle() { return new TitleAdapter(freeChart, true); } @Override public ChartLegend legend() { return new LegendAdapter(freeChart); } @Override public ChartOptions options() { return options; } @Override() public ChartTheme theme() { return new ThemeAdapter(); } @Override public Chart show() { return show(1024, 600); } @Override public Chart show(int width, int height) { final JFrame frame = new JFrame(); frame.getContentPane().setLayout(new BorderLayout(0, 0)); frame.getContentPane().add(chartPanel, BorderLayout.CENTER); frame.getContentPane().setBackground(Color.WHITE); frame.pack(); frame.setSize(width, height); frame.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); frame.setVisible(true); return this; } @Override public Chart writerPng(File file, int width, int height, boolean transparent) { BufferedOutputStream os = null; try { File parent = file.getParentFile(); if (parent != null && !parent.exists()) { if (!parent.mkdirs()) { System.err.printf("Unable to create directory for %s", file.getAbsolutePath()); } } os = new BufferedOutputStream(new FileOutputStream(file)); writerPng(os, width, height, transparent); return this; } catch (Exception ex) { throw new ChartException(ex.getMessage(), ex); } finally { try { if (os != null) { os.flush(); os.close(); } } catch (Exception ex) { ex.printStackTrace(); } } } @Override public Chart writerPng(OutputStream os, int width, int height, boolean transparent) { try { if (transparent) { freeChart().setBackgroundPaint(new Color(255, 255, 255, 0)); freeChart().setBackgroundImageAlpha(0.0f); freeChart().getPlot().setBackgroundPaint( new Color(255, 255, 255, 0) ); freeChart().getPlot().setBackgroundImageAlpha(0f); } ChartUtilities.writeChartAsPNG(os, freeChart, width, height, transparent, 0); return this; } catch (Exception ex) { throw new ChartException(ex.getMessage(), ex); } finally { try { if (os != null) { os.flush(); os.close(); } } catch (Exception ex) { ex.printStackTrace(); } } } @Override public void accept(JsCode jsCode, String functionName, String divId) { try { final String base64Image = toBase64Image(); jsCode.newFunction(functionName, func -> { func.write("var divElement = document.getElementById('%s');", divId); func.newLine().write("var imageElement = document.createElement('img');"); func.newLine().write("imageElement.setAttribute('src', 'data:image/png;base64, %s');", base64Image); func.newLine().write("imageElement.setAttribute('alt', 'Embedded Chart');"); func.newLine().write("imageElement.setAttribute('class', 'chart');"); func.newLine().write("divElement.appendChild(imageElement);"); }); } catch (IOException ex) { throw new ChartException("Failed to generate base64 image of chart", ex); } } /** * Returns a base64 encoded string of a PNG image generated from this chart * @return the base64 encoded image * @throws IOException if there is an I/O exception */ String toBase64Image() throws IOException { final double width = this.options().getPreferredSize().map(Dimension::getWidth).orElse(700d); final double height = this.options().getPreferredSize().map(Dimension::getHeight).orElse(400d); final ByteArrayOutputStream baos = new ByteArrayOutputStream(); this.writerPng(baos, (int)width, (int)height, true); final byte[] imageBytes = baos.toByteArray(); final Base64.Encoder encoder = Base64.getEncoder(); final byte[] base64 = encoder.encode(imageBytes); return new String(base64); } /** * A JFreeChart ChartLabel adapter for the chart title */ private class TitleAdapter implements ChartLabel { private JFreeChart chart; private boolean subtitle; /** * Constructor * @param chart the chart reference * @param subtitle true if this represents a subtitle */ private TitleAdapter(JFreeChart chart, boolean subtitle) { this.chart = chart; this.subtitle = subtitle; } @Override public ChartLabel withText(String text) { this.getTitle().setText(text); return this; } @Override public ChartLabel withColor(Color color) { this.getTitle().setPaint(color); return this; } @Override public ChartLabel withFont(Font font) { this.getTitle().setFont(font); return this; } /** * Returns the title for the chart * @return the chart title */ private TextTitle getTitle() { if (subtitle) { if (chart.getSubtitleCount() > 0) { for (int i=0; i { x.setPaint(darkColor); x.setBackgroundPaint(lightColor); }); Optional.ofNullable(freeChart().getSubtitle(0)).ifPresent(x -> { if (x instanceof TextTitle) { ((TextTitle)x).setBackgroundPaint(lightColor); ((TextTitle)x).setPaint(darkColor); } }); Optional.ofNullable(freeChart().getLegend()).ifPresent(x -> { x.setBackgroundPaint(lightColor); x.setItemPaint(darkColor); }); final Plot plot = freeChart().getPlot(); if (plot instanceof XYPlot) { final XYPlot xyPlot = (XYPlot)plot; xyPlot.setBackgroundPaint(lightColor); xyPlot.setDomainGridlinesVisible(true); xyPlot.setRangeGridlinesVisible(true); xyPlot.setDomainGridlinePaint(Color.DARK_GRAY); xyPlot.setRangeGridlinePaint(Color.DARK_GRAY); for (int i=0; i { x.setPaint(lightColor); x.setBackgroundPaint(darkColor); }); Optional.ofNullable(freeChart().getSubtitle(0)).ifPresent(x -> { if (x instanceof TextTitle) { ((TextTitle)x).setBackgroundPaint(darkColor); ((TextTitle)x).setPaint(lightColor); } }); Optional.ofNullable(freeChart().getLegend()).ifPresent(x -> { x.setBackgroundPaint(darkColor); x.setItemPaint(lightColor); }); final Plot plot = freeChart().getPlot(); if (plot instanceof XYPlot) { final XYPlot xyPlot = (XYPlot)plot; xyPlot.setBackgroundPaint(darkColor); xyPlot.setDomainGridlinesVisible(true); xyPlot.setRangeGridlinesVisible(true); xyPlot.setDomainGridlinePaint(Color.LIGHT_GRAY); xyPlot.setRangeGridlinePaint(Color.LIGHT_GRAY); for (int i=0; i





© 2015 - 2024 Weber Informatics LLC | Privacy Policy