aboutsummaryrefslogtreecommitdiffstats
path: root/src/jcgp/gui/dragresize/HorizontalDragResize.java
blob: e88eafd7d9aa6bb21fcf7f20c908101b8746934f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
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()}.
 * <br><br>
 * 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<MouseEvent>() {
			@Override
			public void handle(MouseEvent event) {
		        dr.mousePressed(event);
			}
		});
		region.setOnMouseDragged(new EventHandler<MouseEvent>() {
			@Override
			public void handle(MouseEvent event) {
				dr.mouseDragged(event);
			}
		});
		region.setOnMouseMoved(new EventHandler<MouseEvent>() {
			@Override
			public void handle(MouseEvent event) {
				dr.mouseMoved(event);
			}
		});
		region.setOnMouseReleased(new EventHandler<MouseEvent>() {
			@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);
	}

}