package id.co.gtc.erhacam; import javafx.animation.KeyFrame; import javafx.animation.PauseTransition; import javafx.animation.Timeline; import javafx.application.Platform; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.Scene; import javafx.scene.control.Label; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.*; import javafx.scene.paint.Color; import javafx.scene.shape.Circle; import javafx.stage.*; import javafx.util.Duration; import org.tinylog.Logger; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; import static Config.SomeCodes.*; public class AutoCloseAlert { private static Stage currentAlertStage; public static String shownTitle = ""; public static String shownContent = ""; public static String shownHeader = ""; public static Image shownBanner = null; public static Image banner_01; public static Image banner_02; private static Circle Cam1; private static Circle Cam2; private static Circle Cam3; private static Circle Cam4; private static Circle Cam5; public static void init(){ String f_01 = ExtractResource("/IU photoboth-01.jpg"); //System.out.println("Banner 01 extracted as file: "+f_01); String f_02 = ExtractResource("/IU photoboth-02.jpg"); //System.out.println("Banner 02 extracted as file: "+f_02); banner_01 = LoadImage(f_01); if (banner_01!=null) System.out.println("Banner 01 loaded"); else System.out.println("Banner 01 not loaded"); banner_02 = LoadImage(f_02); if (banner_02!=null) System.out.println("Banner 02 loaded"); else System.out.println("Banner 02 not loaded"); Cam1 = new Circle(10, Color.RED); Cam2 = new Circle(10, Color.RED); Cam3 = new Circle(10, Color.RED); if (!DermiesMode){ Cam4 = new Circle(10, Color.RED); Cam5 = new Circle(10, Color.RED); } } public static void ChangeCamStatus(int id, boolean active){ Circle x = switch (id){ case 1 -> Cam1; case 2 -> Cam2; case 3 -> Cam3; case 4 -> DermiesMode? null: Cam4; case 5 -> DermiesMode ? null : Cam5; default -> null; }; if (x!=null){ if (active){ x.setFill(Color.GREEN); } else { x.setFill(Color.RED); } } } /** * Close the current alert if it is shown */ public static void close(){ if (currentAlertStage!=null){ try { closeStage(currentAlertStage); } catch (InterruptedException e) { Logger.error("Error closing alert stage: " + e.getMessage()); } currentAlertStage = null; } clear(); } /** * Show an alert with a title, header, content, and automatically close after a few seconds * If called several times, the previous alert will be closed before showing a new one * @param title the title of the alert * @param header the header of the alert * @param content the content of the alert * @param seconds the number of seconds before the alert is closed, or put 0 to keep it open * @param onClose What to do after auto close */ public static void show(String title, String header, String content, int seconds, Consumer onClose) { if (Platform.isFxApplicationThread()){ Stage alertStage = _showtext(title, header, content); closeAlertStage(seconds, onClose, alertStage); } else { Platform.runLater(()->{ Stage alertStage = _showtext(title, header, content); closeAlertStage(seconds, onClose, alertStage); }); } } /** * Show a banner image * @param b1 Image to show * @param seconds the number of seconds before the alert is closed, or put 0 to keep it open * @param onClose What to do after auto close */ public static void showbanner(Image b1, int seconds, Consumer onClose){ if (Platform.isFxApplicationThread()){ Stage alertStage = _showbanner(b1); closeAlertStage(seconds, onClose, alertStage); } else { Platform.runLater(()->{ Stage alertStage = _showbanner(b1); closeAlertStage(seconds, onClose, alertStage); }); } } public static void showpictures(String[] pictures, int seconds, Consumer onClose){ List images = new ArrayList<>(); if (pictures != null){ for(String pp : pictures){ Image ii = LoadImage(pp); if (ii!=null) images.add(ii); } } if (!images.isEmpty()){ Image[] source = images.toArray(new Image[0]); if (Platform.isFxApplicationThread()){ _showpictures(source, seconds, onClose); } else { Platform.runLater(()-> _showpictures(source,seconds, onClose)); } } } private static void _showpictures(Image[] pictures, int seconds, Consumer onClose){ close(); Stage alertStage = new Stage(); alertStage.initModality(Modality.APPLICATION_MODAL); alertStage.initStyle(StageStyle.UTILITY); alertStage.setAlwaysOnTop(true); alertStage.setResizable(false); int width = (int) Screen.getPrimary().getBounds().getWidth(); int height = (int) Screen.getPrimary().getBounds().getHeight(); HBox hbox = new HBox(); hbox.setAlignment(Pos.CENTER); int fitwidth = width / pictures.length; for(Image i : pictures){ ImageView iv = new ImageView(i); iv.setPreserveRatio(true); iv.setFitHeight(height); iv.setFitWidth(fitwidth); hbox.getChildren().add(iv); } BorderPane borderPane = new BorderPane(); borderPane.setCenter(hbox); alertStage.setScene(new Scene(borderPane, width, height)); alertStage.centerOnScreen(); Timeline timeline = new Timeline(); timeline.getKeyFrames().add(new KeyFrame(Duration.seconds(0), event -> alertStage.show())); timeline.getKeyFrames().add(new KeyFrame(Duration.seconds(seconds* (pictures.length)), event -> { try { closeStage(alertStage); } catch (InterruptedException e) { Logger.error("Error closing alert stage: " + e.getMessage()); } //alertStage.close(); if (currentAlertStage == alertStage) { currentAlertStage = null; } if (onClose!=null) onClose.accept(shownTitle); clear(); })); timeline.play(); currentAlertStage = alertStage; shownTitle = ""; shownContent = ""; shownHeader = ""; shownBanner = null; } private static Stage _showbanner(Image image){ close(); Stage alertStage = new Stage(); alertStage.initModality(Modality.APPLICATION_MODAL); alertStage.initStyle(StageStyle.UTILITY); alertStage.setAlwaysOnTop(true); alertStage.setResizable(false); int width = (int) Screen.getPrimary().getBounds().getWidth(); int height = (int) Screen.getPrimary().getBounds().getHeight(); BorderPane borderPane = new BorderPane(); StackPane stackPane = new StackPane(); if (image!=null){ ImageView imageView = new ImageView(image); imageView.setPreserveRatio(true); imageView.setFitWidth(width); imageView.setSmooth(true); stackPane.getChildren().add(imageView); } HBox CamStatus = DermiesMode ? new HBox(30, Cam1, Cam2, Cam3) : new HBox(30, Cam1, Cam2, Cam3, Cam4, Cam5); CamStatus.setMinHeight(60); CamStatus.setAlignment(Pos.CENTER); VBox vBox = new VBox(CamStatus); vBox.setAlignment(Pos.BOTTOM_CENTER); stackPane.getChildren().add(vBox); borderPane.setCenter(stackPane); alertStage.setScene(new Scene(borderPane, width, height)); alertStage.centerOnScreen(); alertStage.show(); currentAlertStage = alertStage; shownBanner = image; CamStatus.prefWidthProperty().bind(currentAlertStage.widthProperty()); shownTitle = ""; shownContent = ""; shownHeader = ""; return alertStage; } /** * Create an alert with a title, header, and content * @param title the title * @param header the header * @param content the content * @return the alert stage */ private static Stage _showtext(String title, String header, String content){ // close previous alert before showing a new one close(); Stage alertStage = new Stage(); alertStage.initModality(Modality.APPLICATION_MODAL); alertStage.initStyle(StageStyle.UTILITY); alertStage.setAlwaysOnTop(true); alertStage.setResizable(false); double screenwidth = Screen.getPrimary().getBounds().getWidth(); double screenheight = Screen.getPrimary().getBounds().getHeight(); double height = screenheight/4.0; double width = height * 21.0/9.0; VBox root = new VBox(10); root.setPadding(new Insets(12)); root.setPrefSize(width, height); root.setAlignment(Pos.CENTER); if (ValidString(header)){ Label headerLabel = new Label(header); headerLabel.setStyle("-fx-font-weight: bold; -fx-font-size: 28px;"); headerLabel.setWrapText(true); headerLabel.setMinHeight(height*0.25); headerLabel.setMaxWidth(Double.MAX_VALUE); headerLabel.prefWidthProperty().bind(root.widthProperty()); root.getChildren().add(headerLabel); } if (ValidString(content)){ Label contentLabel = new Label(content); contentLabel.setWrapText(true); contentLabel.setStyle("-fx-font-size: 24px;"); contentLabel.setMinHeight(height*0.75); contentLabel.setMaxWidth(Double.MAX_VALUE); contentLabel.prefWidthProperty().bind(root.widthProperty()); VBox.setVgrow(contentLabel, Priority.ALWAYS); contentLabel.setAlignment(Pos.TOP_CENTER); root.getChildren().add(contentLabel); } Scene scene = new Scene(root); alertStage.setScene(scene); alertStage.setTitle(title); double x = screenwidth/2 - width/2; double y = screenheight - height - 10; alertStage.setX(x); alertStage.setY(y); alertStage.show(); currentAlertStage = alertStage; shownHeader = ValidString(header) ? header : ""; shownContent = ValidString(content) ? content : ""; shownTitle = ValidString(title) ? title : ""; shownBanner = null; return alertStage; } /** * Close the alert after a few seconds * @param seconds the number of seconds before the alert is closed, if 0, the alert will not be closed * @param onClose What to do after auto close * @param alertStage the alert stage to be closed */ private static void closeAlertStage(int seconds, Consumer onClose, Stage alertStage) { if (seconds>0){ PauseTransition delay = new PauseTransition(Duration.seconds(seconds)); delay.setOnFinished(e -> { try { closeStage(alertStage); } catch (InterruptedException err) { Logger.error("Error closing alert stage: " + err.getMessage()); } //alertStage.close(); if (currentAlertStage == alertStage) { currentAlertStage = null; } if (onClose!=null) onClose.accept(shownTitle); clear(); } ); delay.play(); } } private static Image LoadImage(String filename){ if (ValidFile(filename)){ try{ return new Image(Paths.get(filename).toUri().toString()); } catch (Exception e){ Logger.error("Error loading image: " + filename+", Message: "+e.getMessage()); } } else Logger.error("LoadImage: Invalid file: " + filename); return null; } private static void clear(){ shownTitle = ""; shownContent = ""; shownHeader = ""; shownBanner= null; } }