package com.alexhulbert.icewind.gui;
import java.awt.image.BufferedImage;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.*;
import javafx.beans.property.*;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.embed.swing.SwingFXUtils;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.*;
import javafx.scene.Cursor;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.effect.*;
import javafx.scene.image.*;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;
public class Frosty {
private boolean enabled = false;
private int blurAmount = 0;
private final ImageView background = new ImageView();
private final StackPane layout = new StackPane();
private final StackPane root = new StackPane();
private final Rectangle shadow = new Rectangle();
private Stage stage;
private Rectangle smoke;
private DropShadow beFocused;
private DropShadow beUnfocused;
private boolean focusing = true;
private boolean tmpFocus = false;
private Scene scene;
private static final java.awt.Dimension screen = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
private BufferedImage desktop;
private boolean capturing = false;
public void setBlur(int amount) {
blurAmount = amount;
beFocused = new DropShadow(BlurType.THREE_PASS_BOX, Color.BLACK, 15, 0.1, 0, 0);
beUnfocused = new DropShadow(BlurType.THREE_PASS_BOX, Color.DARKGREY, 15, 0, 0, 0);
BoxBlur bb = new BoxBlur(amount, amount, 3);
//beFocused.setInput(bb); background.setEffect(beFocused);
//beUnfocused.setInput(bb); background.setEffect(beUnfocused);
//bb.setInput(beFocused);
background.setEffect(bb);
shadow.setEffect(beFocused);
}
public void setEnabled(boolean enable, boolean real) {
if (enable) {
layout.setStyle("-fx-background-color: null");
behind(
(int) stage.getX(),
(int) stage.getY(),
(int) stage.getWidth(),
(int) stage.getHeight()
);
} else {
layout.setStyle("-fx-background-color: white");
background.setImage(null);
}
enabled = (!real && enabled) || (real && enable);
}
public int getBlur() {
return blurAmount;
}
public Scene getScene() {
return scene;
}
public Frosty(final Stage stage, Pane parent, Node content) {
enabled = Options.fancyBlur;
this.stage = stage;
root.getChildren().setAll(shadow, layout);
java.awt.Rectangle fullScreen = new java.awt.Rectangle(0, 0, screen.width, screen.height);
java.awt.Robot robot = null;
try {
robot = new java.awt.Robot();
} catch (java.awt.AWTException ex) {
}
desktop = robot.createScreenCapture(fullScreen);
if (enabled) {
layout.getChildren().setAll(background, content);
layout.setStyle("-fx-background-color: null");
} else {
layout.setStyle("-fx-background-color: white");
}
parent.getChildren().add(root);
Scene scene = new Scene(
parent,
1000, 600,
Color.TRANSPARENT
);
stage.setScene(scene);
stage.show();
//stage.setHeight(600);
//stage.setWidth(800);
Platform.setImplicitExit(false);
scene.setOnMouseClicked(new EventHandler<MouseEvent>() {
public void handle(MouseEvent event) {
if (event.getClickCount() == 2) //Platform.exit();
{
//setEnabled(!enabled, true);
stage.toBack();
}
}
});
smoke = makeSmoke(stage);
behind(
(int) stage.getX(),
(int) stage.getY(),
(int) stage.getWidth(),
(int) stage.getHeight()
);
setBlur(25);
makeDraggable(stage, layout);
stage.focusedProperty().addListener(new ChangeListener<Boolean>() {
@Override
public void changed(ObservableValue<? extends Boolean> ov, Boolean t, Boolean t1) {
focusing = t1;
if (enabled) {
if (focusing) {
capture();
} else {
setEnabled(false, false);
tmpFocus = true;
}
}
}
});
}
private void capture() {
final double realX = stage.getX();
final double realY = stage.getY();
if (capturing || realX >= screen.width || realY >= screen.height) {
return;
}
capturing = true;
//stage.toBack();
Timeline pause = new Timeline(new KeyFrame(Duration.millis(0), new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
stage.setX(screen.width);
stage.setY(screen.height);
}
}));
pause.getKeyFrames().add(new KeyFrame(Duration.millis(5), new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
java.awt.Rectangle fullScreen = new java.awt.Rectangle(0, 0, screen.width, screen.height);
java.awt.Robot robot = null;
try {
robot = new java.awt.Robot();
} catch (java.awt.AWTException ex) {
}
desktop = robot.createScreenCapture(fullScreen);
}
}));
pause.getKeyFrames().add(new KeyFrame(Duration.millis(10), new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
stage.setX(realX);
stage.setY(realY);
//stage.toFront();
capturing = false;
}
}));
pause.play();
}
private void behind(final int x, final int y, final int w, final int h) {
if (!enabled || capturing) {
return;
}
if (w == 0 || h == 0) {
return;
}
if (x >= 0 && y >= 0 && (w+x) <= screen.width && (h+y) <= screen.height) {
background.setImage(SwingFXUtils.toFXImage(desktop.getSubimage(x, y, w, h), null));
} else {
BufferedImage unpadded = desktop.getSubimage(0, 0, Math.min(w + x, screen.width) - x, Math.min(h + y, screen.height) - y);
BufferedImage newImage = new BufferedImage(w, h, unpadded.getType());
java.awt.Graphics tmpGraphics = newImage.getGraphics();
tmpGraphics.setColor(java.awt.Color.white);
tmpGraphics.fillRect(0, 0, w, h);
tmpGraphics.drawImage(unpadded, -1*Math.min(0, x), -1*Math.min(0, y), null);
tmpGraphics.dispose();
background.setImage(SwingFXUtils.toFXImage(newImage, null));
}
}
// create some content to be displayed on top of the frozen glass panel.
private Label createContent() {
Label label = new Label("Create a new question for drop shadow effects.\n\nDrag to move\n\nDouble click to close");
//label.setPadding(new Insets(10));
label.setStyle("-fx-font-size: 15px; -fx-text-fill: green;");
label.setMaxWidth(250);
label.setWrapText(true);
return label;
}
// makes a stage draggable using a given node.
public void makeDraggable(final Stage stage, final Node byNode) {
final Delta dragDelta = new Delta();
byNode.setOnMousePressed(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent mouseEvent) {
if (Options.graphicsLevel < 3) {
layout.setStyle("-fx-background-color: white");
}
// record a delta distance for the drag and drop operation.
dragDelta.x = stage.getX() - mouseEvent.getScreenX();
dragDelta.y = stage.getY() - mouseEvent.getScreenY();
byNode.setCursor(Cursor.MOVE);
}
});
final BooleanProperty inDrag = new SimpleBooleanProperty(false);
byNode.setOnMouseReleased(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent me) {
byNode.setCursor(Cursor.HAND);
if (Options.graphicsLevel < 3) {
behind(
(int) stage.getX(),
(int) stage.getY(),
(int) stage.getWidth(),
(int) stage.getHeight()
);
layout.getChildren().set(
0,
background
);
}
inDrag.set(false);
}
});
byNode.setOnMouseDragged(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent mouseEvent) {
double nex = mouseEvent.getScreenX() + dragDelta.x;
double ney = mouseEvent.getScreenY() + dragDelta.y;
stage.setX(nex);
stage.setY(ney);
if (Options.graphicsLevel >= 3) {
behind(
(int) nex,
(int) ney,
(int) stage.getWidth(),
(int) stage.getHeight()
);
} else {
layout.getChildren().set(
0,
makeSmoke(stage)
);
}
inDrag.set(true);
}
});
byNode.setOnMouseEntered(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent mouseEvent) {
if (!mouseEvent.isPrimaryButtonDown()) {
byNode.setCursor(Cursor.HAND);
}
}
});
byNode.setOnMouseExited(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent mouseEvent) {
if (!mouseEvent.isPrimaryButtonDown()) {
byNode.setCursor(Cursor.DEFAULT);
}
}
});
}
private javafx.scene.shape.Rectangle makeSmoke(Stage stage) {
javafx.scene.shape.Rectangle rect = new javafx.scene.shape.Rectangle(
stage.getWidth(),
stage.getHeight(),
Color.WHITESMOKE.deriveColor(
0, 1, 1, 0.08
)
);
return rect;
}
/**
* records relative x and y co-ordinates.
*/
private class Delta {
double x, y;
}
}