package jcgp.gui.dragresize;
import javafx.event.EventHandler;
import javafx.scene.Cursor;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Region;
import jcgp.gui.constants.Constants;
/**
* This class adds horizontal drag resize functionality to any
* arbitrary region provided. This is done by using the static
* method {@code makeDragResizable()}.
*
* This is based on a class by Andrew Till found on:
* http://andrewtill.blogspot.co.uk/2012/12/dragging-to-resize-javafx-region.html
*
*/
public class HorizontalDragResize {
private boolean dragging = false;
private final Region region;
/**
* For internal use only, creates an instance of the actual
* resizer used.
*
* @param region the region to make resizable.
*/
private HorizontalDragResize(Region region) {
this.region = region;
}
/**
* Makes the specified region drag resizable.
* This particular implementation only creates a resize
* click-and-drag area on the left side of the region.
* The resize area is defined by {@code GUI.RESIZE_MARGIN}.
*
* @param region the region to make resizable.
*/
public static void makeDragResizable(final Region region) {
// make the instance, this actually performs the resizing
final HorizontalDragResize dr = new HorizontalDragResize(region);
// set mouse listeners
region.setOnMousePressed(new EventHandler() {
@Override
public void handle(MouseEvent event) {
dr.mousePressed(event);
}
});
region.setOnMouseDragged(new EventHandler() {
@Override
public void handle(MouseEvent event) {
dr.mouseDragged(event);
}
});
region.setOnMouseMoved(new EventHandler() {
@Override
public void handle(MouseEvent event) {
dr.mouseMoved(event);
}
});
region.setOnMouseReleased(new EventHandler() {
@Override
public void handle(MouseEvent event) {
dr.mouseReleased();
}
});
}
/**
* If the press happened in the resize area, raise the drag flag.
*
* @param event the associated mouse event.
*/
private void mousePressed(MouseEvent event) {
if(isInDraggableZone(event)) {
dragging = true;
}
}
/**
* If drag flag is high, resize the region to match the mouse position.
*
* @param event the associated mouse event.
*/
private void mouseDragged(MouseEvent event) {
if(dragging) {
double newWidth = region.getWidth() - event.getX();
if (newWidth >= region.getMinWidth()) {
region.setPrefWidth(newWidth);
} else {
region.setPrefWidth(region.getMinWidth());
}
}
}
/**
* Change the cursor if the mouse position overlaps with the resize area.
*
* @param event the associated mouse event.
*/
private void mouseMoved(MouseEvent event) {
if(isInDraggableZone(event) || dragging) {
region.setCursor(Cursor.H_RESIZE);
} else {
region.setCursor(Cursor.DEFAULT);
}
}
/**
* Finish resizing.
*/
private void mouseReleased() {
dragging = false;
region.setCursor(Cursor.DEFAULT);
}
/**
* Assert whether the mouse cursor is in the draggable area defined by {@code GUI.RESIZE_MARGIN}.
*
* @param event the associated mouse event.
* @return true if the mouse position is in the draggable area.
*/
private boolean isInDraggableZone(MouseEvent event) {
return event.getX() < (Constants.RESIZE_MARGIN);
}
}