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

it.unibo.tuprolog.ui.gui.GraphRenderView.kt Maven / Gradle / Ivy

package it.unibo.tuprolog.ui.gui

import javafx.application.Platform
import javafx.fxml.FXML
import javafx.fxml.FXMLLoader
import javafx.scene.control.Button
import javafx.scene.control.Label
import javafx.scene.control.ProgressBar
import javafx.scene.control.TextArea
import javafx.scene.image.Image
import javafx.scene.image.ImageView
import javafx.scene.input.Clipboard
import javafx.scene.input.ClipboardContent
import javafx.scene.layout.BorderPane
import javafx.scene.layout.VBox
import javafx.scene.paint.Color
import javafx.stage.FileChooser
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.IOException
import java.util.concurrent.CompletableFuture

class GraphRenderView(
    private val dotGraph: String,
) : VBox() {
    companion object {
        private const val FXML = "GraphRenderView.fxml"
    }

    init {
        val loader = FXMLLoader(GraphRenderView::class.java.getResource(FXML))
        loader.setController(this)
        loader.setRoot(this)

        try {
            loader.load()
        } catch (e: IOException) {
            throw IllegalStateException(e)
        }

        btnCopy.setOnAction { this.copyToClipboard() }
        btnRender.setOnAction { this.renderToImage() }
        btnSave.setOnAction { this.saveToFile() }
        btnSave.isVisible = false
        imageView.isVisible = false
        textArea.text = dotGraph
        btnRender.isDisable = !GraphvizRenderer.isAvailable

        if (!GraphvizRenderer.isReady) {
            showMessage(
                "The image renderer is still initializing...\n" +
                    "Close and reopen this panel in few seconds.",
                true,
            )
        } else if (!GraphvizRenderer.isAvailable) {
            showMessage(
                "The image renderer is not available.\n" +
                    "Please check the docs at: https://github.com/nidi3/graphviz-java",
                true,
            )
        } else {
            showMessage("The image rendered is ready.", false)
        }
    }

    @FXML
    lateinit var btnCopy: Button

    @FXML
    lateinit var btnRender: Button

    @FXML
    lateinit var btnSave: Button

    @FXML
    lateinit var textArea: TextArea

    @FXML
    lateinit var imageView: ImageView

    @FXML
    lateinit var labelMsg: Label

    @FXML
    lateinit var progressBar: ProgressBar

    private var imageBytes: ByteArray? = null

    private fun copyToClipboard() {
        val clipboard: Clipboard = Clipboard.getSystemClipboard()
        val content = ClipboardContent()
        content.putString(dotGraph)
        content.putHtml(dotGraph)
        clipboard.setContent(content)
        showMessage("Text has been copied to clipboard.", false)
    }

    private fun renderToImage() {
        if (!GraphvizRenderer.isAvailable) {
            return
        }

        progressBar.isVisible = true
        showMessage("Rendering graph image...", false)
        this.let {
            CompletableFuture.supplyAsync {
                val outputStream = ByteArrayOutputStream()
                GraphvizRenderer.renderAsPNG(dotGraph, outputStream)
                imageBytes = outputStream.toByteArray()

                Platform.runLater {
                    imageView.image = Image(ByteArrayInputStream(imageBytes))
                    imageView.isVisible = true
                    btnSave.isVisible = true
                    progressBar.isVisible = false
                    hideMessage()
                    it.scene.window.sizeToScene()
                }
            }
        }
    }

    private fun saveToFile() {
        imageBytes?.let {
            if (imageView.isVisible) {
                val fileChooser = FileChooser()
                fileChooser.title = "Save Image"
                fileChooser.extensionFilters.addAll(
                    FileChooser.ExtensionFilter("PNG image file", "*.png"),
                    FileChooser.ExtensionFilter("All files", "*.*"),
                )
                fileChooser.initialFileName = "bdd-${System.currentTimeMillis()}.png"
                val file = fileChooser.showSaveDialog(scene.window)
                showMessage("Saving image to file...", false)
                file?.writeBytes(it)
                showMessage("File saved successfully.", false)
            }
        }
    }

    private fun showMessage(
        text: String,
        error: Boolean,
    ) {
        labelMsg.text = text
        labelMsg.textFill = Color.color(if (error) 1.0 else 0.0, 0.0, 0.0)
        labelMsg.isVisible = true
    }

    private fun hideMessage() {
        labelMsg.isVisible = false
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy