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; } }