I am working on making a screen recorder in JavaFX and one utility that is mandatory in the screen recorder is to let the user define how much area to record.
I m
Thanks @Alexander.Berg for providing this utility class (1st version). It helped me to get the desired functionality for my Undecorated Stage.
However, I have few queries regarding some points:
I tried to modify your code to address all the above queries. Please find below the updated ResizeHelper. I am only trying to simplify the things a bit further. Once again thanks for providing the code and letting me to think with a starting point.
import javafx.event.EventHandler;
import javafx.event.EventType;
import javafx.scene.Cursor;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.stage.Stage;
/**
* Helper class to set the resizing implementation for any given undecorated stage.
*/
public class ResizeHelper {
/**
* Handler to process the resizing of the the given stage.
*/
static class ResizeHandler implements EventHandler {
/** Space to consider around the stage border for resizing */
private static final int BORDER = 10;
/** Stage to which the handler is implemented */
private final Stage stage;
/** Current cursor reference to the scene */
private Cursor cursor = Cursor.DEFAULT;
/** X position of the drag start */
private double startX = 0;
/** Y position of the drag start */
private double startY = 0;
/**
* Constructor.
*
* @param stageTmp Stage to which resizing to be set.
*/
public ResizeHandler(final Stage stageTmp) {
stage = stageTmp;
}
@Override
public void handle(final MouseEvent event) {
final EventType extends MouseEvent> eventType = event.getEventType();
final Scene scene = stage.getScene();
final double mouseEventX = event.getSceneX();
final double mouseEventY = event.getSceneY();
final double sceneWidth = scene.getWidth();
final double sceneHeight = scene.getHeight();
if (MouseEvent.MOUSE_MOVED.equals(eventType)) {
setCursor(mouseEventX, mouseEventY, sceneWidth, sceneHeight);
scene.setCursor(cursor);
} else if (MouseEvent.MOUSE_PRESSED.equals(eventType)) {
startX = stage.getWidth() - mouseEventX;
startY = stage.getHeight() - mouseEventY;
consumeEventIfNotDefaultCursor(event);
} else if (MouseEvent.MOUSE_DRAGGED.equals(eventType) && !Cursor.DEFAULT.equals(cursor)) {
consumeEventIfNotDefaultCursor(event);
if (!Cursor.W_RESIZE.equals(cursor) && !Cursor.E_RESIZE.equals(cursor)) {
processVerticalDrag(event);
}
if (!Cursor.N_RESIZE.equals(cursor) && !Cursor.S_RESIZE.equals(cursor)) {
processHorizontalDrag(event);
}
}
}
/**
* Consumes the mouse event if the cursor is not the DEFAULT cursor.
*
* @param event MouseEvent instance.
*/
private void consumeEventIfNotDefaultCursor(final MouseEvent event) {
if (!cursor.equals(Cursor.DEFAULT)) {
event.consume();
}
}
/**
* Processes the horizontal drag movement and resizes the window width.
*
* @param event MouseEvent instance.
*/
private void processHorizontalDrag(final MouseEvent event) {
final double minWidth =
stage.getMinWidth() > BORDER * 2 ? stage.getMinWidth() : BORDER * 2;
final double mouseEventX = event.getSceneX();
if (Cursor.NW_RESIZE.equals(cursor)
|| Cursor.W_RESIZE.equals(cursor)
|| Cursor.SW_RESIZE.equals(cursor)) {
if (stage.getWidth() > minWidth || mouseEventX < 0) {
stage.setWidth(stage.getX() - event.getScreenX() + stage.getWidth());
stage.setX(event.getScreenX());
}
} else if (stage.getWidth() > minWidth || mouseEventX + startX - stage.getWidth() > 0) {
stage.setWidth(mouseEventX + startX);
}
}
/**
* Processes the vertical drag movement and resizes the window height.
*
* @param event MouseEvent instance.
*/
private void processVerticalDrag(final MouseEvent event) {
final double minHeight =
stage.getMinHeight() > BORDER * 2 ? stage.getMinHeight() : BORDER * 2;
final double mouseEventY = event.getSceneY();
if (Cursor.NW_RESIZE.equals(cursor)
|| Cursor.N_RESIZE.equals(cursor)
|| Cursor.NE_RESIZE.equals(cursor)) {
if (stage.getHeight() > minHeight || mouseEventY < 0) {
stage.setHeight(stage.getY() - event.getScreenY() + stage.getHeight());
stage.setY(event.getScreenY());
}
} else if (stage.getHeight() > minHeight || mouseEventY + startY - stage.getHeight() > 0) {
stage.setHeight(mouseEventY + startY);
}
}
/**
* Determines and sets the appropriate cursor based on the mouse position in relative to scene bounds.
*
* @param mouseEventX X position of mouse in the scene.
* @param mouseEventY Y position of mouse in the scene.
* @param sceneWidth Width of the scene.
* @param sceneHeight Height of the scene.
*/
private void setCursor(final double mouseEventX, final double mouseEventY, final double sceneWidth,
final double sceneHeight) {
final Cursor cursor1;
if (mouseEventX < BORDER && mouseEventY < BORDER) {
cursor1 = Cursor.NW_RESIZE;
} else if (mouseEventX < BORDER && mouseEventY > sceneHeight - BORDER) {
cursor1 = Cursor.SW_RESIZE;
} else if (mouseEventX > sceneWidth - BORDER && mouseEventY < BORDER) {
cursor1 = Cursor.NE_RESIZE;
} else if (mouseEventX > sceneWidth - BORDER && mouseEventY > sceneHeight - BORDER) {
cursor1 = Cursor.SE_RESIZE;
} else if (mouseEventX < BORDER) {
cursor1 = Cursor.W_RESIZE;
} else if (mouseEventX > sceneWidth - BORDER) {
cursor1 = Cursor.E_RESIZE;
} else if (mouseEventY < BORDER) {
cursor1 = Cursor.N_RESIZE;
} else if (mouseEventY > sceneHeight - BORDER) {
cursor1 = Cursor.S_RESIZE;
} else {
cursor1 = Cursor.DEFAULT;
}
cursor = cursor1;
}
}
/**
* Constructor.
*
*/
private ResizeHelper() {
}
/**
* Adds the resize handler to the provided stage.
*
* @param stage Stage to which the resizing should be implemented.
*/
public static void addResizeHandler(final Stage stage) {
ResizeHandler resizeHandler = new ResizeHandler(stage);
stage.setMinHeight(stage.getHeight());
stage.setMinWidth(stage.getWidth());
stage.setMaxHeight(stage.getMaxHeight());
stage.setMaxWidth(stage.getMaxWidth());
stage.getScene().addEventFilter(MouseEvent.ANY, resizeHandler);
}
}