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

com.cedarsoft.exceptions.handling.notification.FxBalloonDialog.kt Maven / Gradle / Ivy

There is a newer version: 8.9.2
Show newest version
package com.cedarsoft.exceptions.handling.notification

import com.cedarsoft.exceptions.handling.Messages
import com.cedarsoft.unit.other.px
import de.jensd.fx.glyphs.fontawesome.FontAwesomeIcon
import de.jensd.fx.glyphs.fontawesome.FontAwesomeIconView
import javafx.beans.binding.Bindings
import javafx.event.EventHandler
import javafx.geometry.VPos
import javafx.scene.Node
import javafx.scene.control.ButtonType
import javafx.scene.control.Dialog
import javafx.scene.control.DialogPane
import javafx.scene.control.Hyperlink
import javafx.scene.image.ImageView
import javafx.scene.text.Text
import javafx.stage.Modality
import javafx.stage.StageStyle
import org.tbee.javafx.scene.layout.MigPane
import java.util.concurrent.Callable

/**
 * Java fx based notification balloon
 * @author Johannes Schneider ([[email protected]](mailto:[email protected]))
 */
abstract class FxBalloonDialog(notification: Notification) : Dialog() {
  init {
    initModality(Modality.NONE)
    initStyle(StageStyle.UNDECORATED)
    isResizable = true

    //Add a custom dialog pane to remove the button bar
    dialogPane = object : DialogPane() {
      override fun createButtonBar(): Node? {
        return null;
      }
    }
    dialogPane.stylesheets.add(javaClass.getResource("FxBalloonDialog.css").toExternalForm())
    dialogPane.styleClass.add("balloon-dialog")

    dialogPane.header = null

    val contentPane = MigPane("fill, wrap 2, insets 0", "[][grow,fill]", "[fill][fill,grow][fill]")
    contentPane.styleClass.add("pane")
    dialogPane.content = contentPane

    //Icon
    val imageView = ImageView()
    imageView.styleClass.add("icon")
    contentPane.add(imageView)

    //Headline
    val headline = Text(notification.title)
    headline.styleClass.add("headline")
    contentPane.getChildren().add(headline);

    contentPane.add(Text(notification.message), "span, wrap")

    //Details link
    val detailsCallback = notification.detailsCallback
    if (detailsCallback != null) {
      val detailsLink = Hyperlink(Messages.get("details"))
      detailsLink.styleClass.add("details-link")
      contentPane.add(detailsLink, "alignx right, span")

      detailsLink.layoutX = 20.0
      detailsLink.layoutY = 20.0

      detailsLink.onAction = EventHandler {
        closeBalloon()
        detailsCallback.detailsClicked(notification)
      }
    }

    //Close icon
    run {
      val iconView = FontAwesomeIconView(FontAwesomeIcon.TIMES_CIRCLE_ALT)
      iconView.styleClass.add("close-icon")

      iconView.isManaged = false
      iconView.glyphSize = 18
      contentPane.children.add(iconView)

      iconView.y = 0.0
      iconView.textOrigin = VPos.TOP
      @px val closeIconWidth = iconView.boundsInLocal.width
      iconView.xProperty().bind(Bindings.createDoubleBinding(Callable { dialogPane.width - closeIconWidth }, dialogPane.widthProperty()))

      iconView.onMouseClickedProperty().setValue(EventHandler { closeBalloon() })
    }
//
//    //Workaround to fix size
//    if (SystemInfo.isLinux()) {
//      Platform.runLater {
//        val boundsInLocal = dialogPane.boundsInLocal
//        dialogPane.scene.window.width = boundsInLocal.width
//        dialogPane.scene.window.height = boundsInLocal.height
////        dialogPane.scene.window.width = boundsInLocal.width + 15
////        dialogPane.scene.window.height = boundsInLocal.height + 15
//      }
//    }
//    dialogPane.autosize()
//    dialogPane.scene.window.sizeToScene()
  }

  /**
   * Is called when the balloon should be closed
   */
  abstract fun closeBalloon()
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy