package org.eclipse.iee.web.renderer; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Graphics2D; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.io.IOException; import java.io.OutputStream; import java.io.StringReader; import java.io.Writer; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.imageio.ImageIO; import org.eclipse.iee.core.IResultContainer; import org.eclipse.iee.core.utils.ArrayUtils; import org.eclipse.iee.pad.formula.image.FormulaImageRenderer; import org.eclipse.iee.pad.graph.GraphPart; import org.eclipse.iee.pad.graph.model.GraphElement; import org.eclipse.iee.pad.graph.model.GraphModel; import org.jfree.chart.ChartFactory; import org.jfree.chart.JFreeChart; import org.jfree.chart.plot.PlotOrientation; import org.jfree.chart.plot.XYPlot; import org.jfree.chart.renderer.xy.XYItemRenderer; import org.jfree.data.general.DatasetChangeEvent; import org.jfree.data.xy.AbstractXYDataset; import org.jfree.data.xy.XYDataset; import org.jfree.ui.RectangleInsets; import org.jfree.util.PaintUtilities; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; import org.osgi.service.component.annotations.ReferencePolicy; @Component public class GraphHTMLRenderer implements IHTMLRenderer<GraphPart> { private FormulaImageRenderer formulaImageRenderer; @Override public void renderPad(GraphPart pad, IHTMLRendererContext context) throws IOException { Writer writer = context.getWriter(); GraphModel model = pad.getModel(); writer.append("<table>").append("<tr>").append("<td>"); List<GraphElement> elements = model.getElements(); for (int i = 0; i < elements.size(); i++) { writer.append("<div>"); writer.append("<img src='").append(context.createResourceURL(pad.getId(), "formula/" + i, new HashMap<String, String>())).append("' />"); writer.append("</div>"); } writer.append("</td>").append("<td>"); writer.append("<img src='").append(context.createResourceURL(pad.getId(), "graph", new HashMap<String, String>())).append("' />"); writer.append("</td>").append("</tr>"); writer.append("<tr>").append("<td>").append("</td>").append("<td style='text-align:center'>"); writer.append("<img src='").append(context.createResourceURL(pad.getId(), "variables", new HashMap<String, String>())).append("' />"); writer.append("</td>").append("</tr>").append("</table>"); } @Override public void renderResource(GraphPart pad, String resourceId, IResourceRenderContext context) throws IOException { if (resourceId.startsWith("formula/")) { String nStr = resourceId.replace("formula/", ""); int number = Integer.parseInt(nStr); GraphModel model = pad.getModel(); List<GraphElement> elements = model.getElements(); GraphElement graphElement = elements.get(number); BufferedImage image = formulaImageRenderer.getFormulaImage(graphElement.getFunction(), java.awt.Color.black, null); writeImage(context, image); } else if ("graph".equals(resourceId)) { IResultContainer resultContainer = context.getResultContainer(); Map<Integer, double[][]> parseResult = parseResult(resultContainer.getResult(pad.getId())); JFreeChart chart = createChart(pad.getModel(), parseResult); BufferedImage image = new BufferedImage(720, 300, BufferedImage.TYPE_4BYTE_ABGR); Graphics2D graphics = image.createGraphics(); chart.draw(graphics, new Rectangle2D.Double(0, 0, 720, 300)); writeImage(context, image); } else if ("variables".equals(resourceId)) { GraphModel model = pad.getModel(); StringBuilder sb = new StringBuilder(); for (String variable : model.getVariables()) { if (sb.length() > 0) { sb.append(","); } sb.append(variable); } BufferedImage image = formulaImageRenderer.getFormulaImage(sb.toString(), java.awt.Color.black, null); writeImage(context, image); } } private void writeImage(IResourceRenderContext context, BufferedImage image) throws IOException { context.setContentType("image/png"); OutputStream outputStream = context.getOutputStream(); ImageIO.write(image, "png", outputStream); } private JFreeChart createChart(GraphModel model, Map<Integer, double[][]> results) { XYDataset dataset = createDataset(results, model); JFreeChart chart = ChartFactory.createXYLineChart(null, null, null, dataset, PlotOrientation.HORIZONTAL, false, false, false); chart.setBackgroundPaint(Color.white); chart.setBorderVisible(true); chart.setBorderPaint(Color.BLACK); XYPlot plot = (XYPlot) chart.getPlot(); plot.setOrientation(PlotOrientation.VERTICAL); plot.setBackgroundPaint(Color.lightGray); plot.setDomainGridlinePaint(Color.white); plot.setRangeGridlinePaint(Color.white); plot.setAxisOffset(new RectangleInsets(5.0, 5.0, 5.0, 5.0)); plot.getRangeAxis().setFixedDimension(15.0); XYItemRenderer renderer = plot.getRenderer(); renderer.setSeriesPaint(0, Color.black); if (model.getMaxX() != null && model.getMinX() != null) { plot.getDomainAxis().setRange(model.getMinX(), model.getMaxX()); } else { plot.getDomainAxis().setAutoRange(true); } if (model.getMaxY() != null && model.getMinY() != null) { plot.getRangeAxis().setRange(model.getMinY(), model.getMaxY()); } else { plot.getRangeAxis().setAutoRange(true); } List<GraphElement> elements = model.getElements(); for (int i = 0; i < elements.size(); i++) { GraphElement element = elements.get(i); String color = element.getColor(); if (color == null) { color = PaintUtilities.colorToString((Color) plot.getDrawingSupplier().getNextPaint()); } renderer.setSeriesPaint(i, PaintUtilities.stringToColor(color)); int width = element.getWidth(); if (width < 1) { width = 1; } renderer.setSeriesStroke(i, new BasicStroke(width)); } plot.datasetChanged(new DatasetChangeEvent(this, dataset)); return chart; } public Map<Integer, double[][]> parseResult(String result) { Map<Integer, double[][]> results = new HashMap<>(); double[][][] parseTrippleArray; try { parseTrippleArray = ArrayUtils.parseTrippleArray(new StringReader(result)); for (int i = 0; i < parseTrippleArray.length; i++) { results.put(i, parseTrippleArray[i]); } } catch (IOException e) { e.printStackTrace(); } return results; } public XYDataset createDataset(final Map<Integer, double[][]> results, final GraphModel model) { XYDataset dataset = new AbstractXYDataset() { private static final long serialVersionUID = 1L; @Override public Number getY(int arg0, int arg1) { return getResult(arg0)[arg1][1]; } @Override public Number getX(int arg0, int arg1) { return getResult(arg0)[arg1][0]; } @Override public int getItemCount(int arg0) { return getResult(arg0).length; } @Override public Comparable<Integer> getSeriesKey(int arg0) { return Integer.valueOf(arg0); } @Override public int getSeriesCount() { return model.getElements().size(); } private double[][] getResult(int number) { double[][] ds = results.get(Integer.valueOf(number)); if (ds == null) { return new double[0][]; } return ds; } }; return dataset; } @Reference(unbind = "unbindFormulaImageRenderer", policy = ReferencePolicy.DYNAMIC) public void bindFormulaImageRenderer(FormulaImageRenderer renderer) { formulaImageRenderer = renderer; } public void unbindFormulaImageRenderer(FormulaImageRenderer renderer) { formulaImageRenderer = null; } }