package com.kodcu.service.extension.chart; import com.kodcu.config.ExtensionConfigBean; import com.kodcu.controller.ApplicationController; import com.kodcu.other.Current; import com.kodcu.other.IOHelper; import com.kodcu.service.ThreadService; import javafx.embed.swing.SwingFXUtils; import javafx.geometry.Side; import javafx.scene.Node; import javafx.scene.SnapshotParameters; import javafx.scene.chart.Axis; import javafx.scene.chart.CategoryAxis; import javafx.scene.chart.NumberAxis; import javafx.scene.chart.XYChart; import javafx.scene.image.WritableImage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.awt.image.BufferedImage; import java.util.*; /** * Created by usta on 31.03.2015. */ public abstract class XYChartBuilderService extends ChartBuilderService { private final ThreadService threadService; private final Current current; private final ApplicationController controller; private final ExtensionConfigBean extensionConfigBean; private final Logger logger = LoggerFactory.getLogger(XYChartBuilderService.class); public XYChartBuilderService(ThreadService threadService, Current current, ApplicationController controller, ExtensionConfigBean extensionConfigBean) { super(threadService, current, controller); this.threadService = threadService; this.current = current; this.controller = controller; this.extensionConfigBean = extensionConfigBean; } @Override public void chartBuild(String chartContent, String imagesDir, String imageTarget, Map<String, String> optMap) throws Exception { try { super.chartBuild(chartContent, imagesDir, imageTarget, optMap); } catch (InterruptedException e) { throw e; } logger.debug("Chart extension is started for {}", imageTarget); String[] split = chartContent.split("\\r?\\n"); List<String> lines = Arrays.asList(split); List colors = new ArrayList<>(); XYChart xyChart = createXYChart(); int scale = extensionConfigBean.getDefaultImageScale(); xyChart.setScaleX(scale); xyChart.setScaleY(scale); xyChart.setScaleZ(scale); XYChart.Series series = new XYChart.Series(); Axis xAxis = xyChart.getXAxis(); Axis yAxis = xyChart.getYAxis(); xAxis.setTickLabelsVisible(true); xAxis.setAnimated(false); xAxis.setTickLabelGap(10); yAxis.setTickLabelsVisible(true); yAxis.setAnimated(false); yAxis.setTickLabelGap(10); for (String line : lines) { if (line.trim().startsWith("//")) { series = new XYChart.Series(); series.setName(line.trim().substring(2)); } String[] parts = line.split(","); if (parts.length < 2) continue; Object name = null; // try first double Object value = null; // try first double Object color = null; // try first double if (parts.length == 3) { color = parts[2]; colors.add(color); xyChart.setStyle("-fx-bar-fill: " + color + ";"); } if (xAxis instanceof NumberAxis) { name = Double.valueOf(parts[0]); } if (yAxis instanceof NumberAxis) { value = Double.valueOf(parts[1]); } if (xAxis instanceof CategoryAxis) { name = String.valueOf(parts[0]); } if (yAxis instanceof CategoryAxis) { value = String.valueOf(parts[1]); } series.getData().add(new XYChart.Data(name, value)); if (!xyChart.getData().contains(series)) xyChart.getData().add(series); } for (int i = 0; i < colors.size(); i++) { Object color = colors.get(i); if (Objects.isNull(color)) continue; Set<Node> nodes1 = xyChart.lookupAll(".default-color" + i + ".chart-bar"); Set<Node> nodes2 = xyChart.lookupAll(".default-color" + i + ".chart-pie"); for (Node node : nodes1) { node.setStyle("-fx-bar-fill: " + color + ";"); } for (Node node : nodes2) { node.setStyle("-fx-bar-fill: " + color + ";"); } } if (Objects.nonNull(optMap.get("legend"))) { try { xyChart.setLegendSide(Side.valueOf(optMap.get("legend").toUpperCase())); } catch (RuntimeException e) { xyChart.setLegendVisible(false); } } if (Objects.nonNull(optMap.get("title"))) xyChart.setTitle(optMap.get("title")); if (Objects.nonNull(optMap.get("title-side"))) { xyChart.setTitleSide(Side.valueOf(optMap.get("title-side").toUpperCase())); } Set<Node> nodes = xyChart.lookupAll(".chart-title"); for (Node node : nodes) { String titleColor = Objects.isNull(optMap.get("title-color")) ? "#000" : optMap.get("title-color"); String titleSize = Objects.isNull(optMap.get("title-size")) ? "1.6em" : optMap.get("title-size"); node.setStyle(String.format("-fx-text-fill: %s; -fx-font-size: %s;", titleColor, titleSize)); } if (Objects.nonNull(optMap.get("x-label"))) xAxis.setLabel(optMap.get("x-label")); if (Objects.nonNull(optMap.get("y-label"))) yAxis.setLabel(optMap.get("y-label")); if (Objects.nonNull(optMap.get("x-label-rotation"))) xAxis.setTickLabelRotation(Double.parseDouble(optMap.get("x-label-rotation"))); if (Objects.nonNull(optMap.get("y-label-rotation"))) yAxis.setTickLabelRotation(Double.parseDouble(optMap.get("y-label-rotation"))); if (Objects.nonNull(optMap.get("show-labels"))) { Boolean value = Boolean.valueOf(optMap.get("show-labels")); xAxis.setTickLabelsVisible(value); yAxis.setTickLabelsVisible(value); } if (Objects.nonNull(optMap.get("show-x-label"))) { xAxis.setTickLabelsVisible(Boolean.valueOf(optMap.get("show-x-labels"))); } if (Objects.nonNull(optMap.get("show-y-label"))) { yAxis.setTickLabelsVisible(Boolean.valueOf(optMap.get("show-y-labels"))); } if (Objects.nonNull(optMap.get("label-gap"))) { xAxis.setTickLabelGap(Double.valueOf(optMap.get("label-gap"))); yAxis.setTickLabelGap(Double.valueOf(optMap.get("label-gap"))); } if (Objects.nonNull(optMap.get("x-label-gap"))) { xAxis.setTickLabelGap(Double.valueOf(optMap.get("x-label-gap"))); } if (Objects.nonNull(optMap.get("y-label-gap"))) { yAxis.setTickLabelGap(Double.valueOf(optMap.get("y-label-gap"))); } if (Objects.nonNull(optMap.get("x-side"))) { xAxis.setSide(Side.valueOf(optMap.get("x-side").toUpperCase())); } if (Objects.nonNull(optMap.get("y-side"))) { yAxis.setSide(Side.valueOf(optMap.get("y-side").toUpperCase())); } xyChart.setLayoutX(-10000); xyChart.setLayoutY(-10000); controller.getRootAnchor().getChildren().add(xyChart); WritableImage writableImage = xyChart.snapshot(new SnapshotParameters(), null); controller.getRootAnchor().getChildren().remove(xyChart); BufferedImage bufferedImage = SwingFXUtils.fromFXImage(writableImage, null); IOHelper.createDirectories(currentRoot.resolve(imagesDir)); IOHelper.imageWrite(bufferedImage, "png", imagePath.toFile()); logger.debug("Chart extension is ended for {}", imageTarget); controller.clearImageCache(imagePath); } protected abstract XYChart createXYChart(); }