Files
ErhaCam/src/main/java/id/co/gtc/erhacam/AutoCloseAlert.java
2025-10-03 11:00:51 +07:00

390 lines
13 KiB
Java

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<String> 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<String> 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<String> onClose){
List<Image> 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<String> 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<String> 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;
}
}