aboutsummaryrefslogtreecommitdiffstats
path: root/src/jcgp/gui/handlers/NodeHandlers.java
blob: b413a620edfb8d07b47c25c4bacf5f24eabcf5b6 (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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
package jcgp.gui.handlers;

import javafx.event.EventHandler;
import javafx.scene.input.MouseDragEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import jcgp.backend.population.Gene;
import jcgp.gui.GUI;
import jcgp.gui.constants.Position;
import jcgp.gui.population.ChromosomePane;
import jcgp.gui.population.GUIConnection;
import jcgp.gui.population.GUIGene;
import jcgp.gui.population.GUIGene.GUIGeneState;
import jcgp.gui.population.GUINode;

/**
 * Holds the handlers that define the behaviour of {@code GUINode}.
 * <br><br>
 * The handlers are instantiated here statically and added to {@code GUINode}
 * instances using {@code NodeHandlers.addHandlers(...)}. This guarantees that
 * all nodes behave the same way without instantiating a new set of handlers for
 * each node instance.
 * 
 * @author Eduardo Pedroni
 *
 */
public final class NodeHandlers {

	/**
	 * Private constructor to prevent instantiation.
	 */
	private NodeHandlers() {}

	/**
	 * Set the node to {@code GUIGeneState.HOVER} state, and set its immediate connections to {@code GUIGeneState.EXTENDED_HOVER}.
	 */
	private static EventHandler<MouseEvent> mouseEnteredHandler = new EventHandler<MouseEvent>() {
		@Override
		public void handle(MouseEvent event) {
			// acquire the source, we can safely cast it to GUINode
			GUINode source = (GUINode) event.getSource();

			source.setState(GUIGeneState.HOVER);
			for (int i = 0; i < GUI.resources.arity(); i++) {
				((GUIGene) ((Gene) source.getNode().getConnection(i)).getGUIObject()).setState(GUIGeneState.EXTENDED_HOVER);
			}
		}
	};

	/**
	 * Set the node and its immediate connections to {@code GUIGeneState.NEUTRAL} state.
	 */
	private static EventHandler<MouseEvent> mouseExitedHandler = new EventHandler<MouseEvent>() {
		@Override
		public void handle(MouseEvent event) {
			// acquire the source, we can safely cast it to GUINode
			GUINode source = (GUINode) event.getSource();

			if (Target.getSourceMutable() != source) {
				source.setState(GUIGeneState.NEUTRAL);
				for (int i = 0; i < GUI.resources.arity(); i++) {
					((GUIGene) ((Gene) source.getNode().getConnection(i)).getGUIObject()).setState(GUIGeneState.NEUTRAL);
				}
			}
		}
	};

	private static EventHandler<MouseEvent> socketDragDetected = new EventHandler<MouseEvent>() {
		@Override
		public void handle(MouseEvent event) {
			// it's safe to assume that the source is the socket
			((GUINode) ((Circle) event.getSource()).getParent()).startFullDrag();
		}
	};

	private static EventHandler<MouseEvent> socketMousePressedHandler = new EventHandler<MouseEvent>() {
		@Override
		public void handle(MouseEvent event) {
			// it's safe to assume that the source is the socket
			Target.start((Circle) event.getSource());
		}
	};

	private static EventHandler<MouseEvent> socketMouseDraggedHandler = new EventHandler<MouseEvent>() {
		@Override
		public void handle(MouseEvent event) {
			// this can only happen after a press, so we know Target is up-to-date
			if (!Target.isProspecting()) {
				GUINode node = (GUINode) Target.getSourceMutable();
				Line line = Target.getConnectionLine();
				line.setEndX(event.getX() + node.getLayoutX());
				line.setEndY(event.getY() + node.getLayoutY());
			}

		}
	};

	private static EventHandler<MouseEvent> socketMouseReleasedHandler = new EventHandler<MouseEvent>() {
		@Override
		public void handle(MouseEvent event) {

			GUINode node = (GUINode) ((Circle) event.getSource()).getParent();
			int connectionId = Integer.valueOf(((Circle) event.getSource()).getId());

			Position.connect(node.getLines()[connectionId], (GUIGene) ((Gene) node.getNode().getConnection(connectionId)).getGUIObject());
		}
	};

	private static EventHandler<MouseDragEvent> dragEnteredHandler = new EventHandler<MouseDragEvent>() {
		@Override
		public void handle(MouseDragEvent event) {
			// acquire the source, we can safely cast it to GUINode
			GUINode source = (GUINode) event.getSource();
			if (Target.getCurrentConnection() == source) {
				source.setState(GUIGeneState.NEUTRAL_TARGET);
				// we are now prospecting
				Target.setProspecting(true);
				Position.connect(Target.getConnectionLine(), source);
			} else if (ChromosomePane.isAllowed(Target.getSourceMutable(), (GUIConnection) source)) {
				source.setState(GUIGeneState.GOOD_TARGET);
				// we are now prospecting
				Target.setProspecting(true);
				Position.connect(Target.getConnectionLine(), source);
			} else {
				source.setState(GUIGeneState.BAD_TARGET);
			}
		}
	};

	private static EventHandler<MouseDragEvent> dragExitedHandler = new EventHandler<MouseDragEvent>() {
		@Override
		public void handle(MouseDragEvent event) {
			// acquire the source, we can safely cast it to GUINode
			GUINode source = (GUINode) event.getSource();
			source.setState(GUIGeneState.NEUTRAL);
			
			// no longer prospecting
			Target.setProspecting(false);
		}
	};

	/**
	 * Adds all handlers to the specified node.
	 * 
	 * @param node the {@code GUINode} to which the handlers will be added.
	 */
	public static void addHandlers(GUINode node) {
		node.addEventHandler(MouseEvent.MOUSE_ENTERED, mouseEnteredHandler);
		node.addEventHandler(MouseEvent.MOUSE_EXITED, mouseExitedHandler);

		node.addEventHandler(MouseDragEvent.MOUSE_DRAG_ENTERED, dragEnteredHandler);
		node.addEventHandler(MouseDragEvent.MOUSE_DRAG_EXITED, dragExitedHandler);

		Circle[] sockets = node.getSockets();
		for (int s = 0; s < sockets.length; s++) {

			sockets[s].addEventFilter(MouseEvent.DRAG_DETECTED, socketDragDetected);
			sockets[s].addEventHandler(MouseEvent.MOUSE_PRESSED, socketMousePressedHandler);
			sockets[s].addEventHandler(MouseEvent.MOUSE_DRAGGED, socketMouseDraggedHandler);
			sockets[s].addEventHandler(MouseEvent.MOUSE_RELEASED, socketMouseReleasedHandler);
		}
	}
}