4
4
import edu .wpi .grip .core .Step ;
5
5
import edu .wpi .grip .core .sockets .InputSocket ;
6
6
import edu .wpi .grip .core .sockets .OutputSocket ;
7
+ import edu .wpi .grip .core .sockets .SocketHint ;
7
8
import edu .wpi .grip .ui .Controller ;
8
9
import edu .wpi .grip .ui .annotations .ParametrizedController ;
9
10
import edu .wpi .grip .ui .components .ExceptionWitnessResponderButton ;
16
17
import com .google .inject .assistedinject .Assisted ;
17
18
18
19
import java .io .InputStream ;
20
+ import java .util .ArrayList ;
19
21
import java .util .Collection ;
22
+ import java .util .List ;
20
23
24
+ import javafx .animation .KeyFrame ;
25
+ import javafx .animation .KeyValue ;
26
+ import javafx .animation .Timeline ;
27
+ import javafx .animation .TimelineBuilder ;
28
+ import javafx .beans .property .DoubleProperty ;
29
+ import javafx .event .ActionEvent ;
30
+ import javafx .event .EventHandler ;
21
31
import javafx .fxml .FXML ;
22
32
import javafx .scene .Node ;
33
+ import javafx .scene .control .Button ;
23
34
import javafx .scene .control .Labeled ;
24
35
import javafx .scene .image .Image ;
25
36
import javafx .scene .image .ImageView ;
26
37
import javafx .scene .layout .HBox ;
27
38
import javafx .scene .layout .VBox ;
28
-
39
+ import javafx . util . Duration ;
29
40
import javax .inject .Inject ;
30
41
31
42
/**
@@ -41,6 +52,8 @@ public class StepController implements Controller {
41
52
private final ExceptionWitnessResponderButton .Factory exceptionWitnessResponderButtonFactory ;
42
53
private final StepDragService stepDragService ;
43
54
private final Step step ;
55
+ private final List <InputSocketController > inputSockets ;
56
+ private boolean expanded = true ;
44
57
@ FXML
45
58
private VBox root ;
46
59
@ FXML
@@ -53,6 +66,10 @@ public class StepController implements Controller {
53
66
private VBox inputs ;
54
67
@ FXML
55
68
private VBox outputs ;
69
+ @ FXML
70
+ private ImageView expandIcon ;
71
+ @ FXML
72
+ private Button expand ;
56
73
private ControllerMap <InputSocketController , Node > inputSocketMapManager ;
57
74
private ControllerMap <OutputSocketController , Node > outputSocketMapManager ;
58
75
@@ -69,6 +86,7 @@ public class StepController implements Controller {
69
86
this .exceptionWitnessResponderButtonFactory = exceptionWitnessResponderButtonFactory ;
70
87
this .stepDragService = stepDragService ;
71
88
this .step = step ;
89
+ inputSockets = new ArrayList <>();
72
90
}
73
91
74
92
@ FXML
@@ -82,9 +100,21 @@ private void initialize() {
82
100
new Image (InputStream .class .cast (icon ))));
83
101
buttons .getChildren ().add (0 , exceptionWitnessResponderButtonFactory .create (step , "Step Error" ));
84
102
103
+ if (step .getInputSockets ().stream ()
104
+ .allMatch (inputSocket -> inputSocket .getSocketHint ().getView ()
105
+ .equals (SocketHint .View .NONE ))) {
106
+ expand .setManaged (false );
107
+ } else {
108
+ expandIcon .setImage (new Image ("/edu/wpi/grip/ui/icons/up.png" ));
109
+ }
110
+
85
111
// Add a SocketControlView for each input socket and output socket
86
112
for (InputSocket <?> inputSocket : step .getInputSockets ()) {
87
- inputSocketMapManager .add (inputSocketControllerFactory .create (inputSocket ));
113
+ InputSocketController tempSocket = inputSocketControllerFactory .create (inputSocket );
114
+ inputSocketMapManager .add (tempSocket );
115
+ if (!inputSocket .getSocketHint ().getView ().equals (SocketHint .View .NONE )) {
116
+ inputSockets .add (tempSocket );
117
+ }
88
118
}
89
119
90
120
for (OutputSocket <?> outputSocket : step .getOutputSockets ()) {
@@ -142,6 +172,91 @@ private void moveStepRight() {
142
172
pipeline .moveStep (step , +1 );
143
173
}
144
174
175
+ @ FXML
176
+ private void expand () {
177
+ if (expanded ) {
178
+ for (InputSocketController input : inputSockets ) {
179
+ inputs .setMaxHeight (inputs .getHeight ());
180
+ inputs .setPrefHeight (inputs .getHeight ());
181
+ if (input .getSocket ().getConnections ().isEmpty ()) {
182
+ fadeOut (input );
183
+ }
184
+ }
185
+ closeUp ();
186
+ expandIcon .setImage (new Image ("/edu/wpi/grip/ui/icons/down.png" ));
187
+ expanded = false ;
188
+ } else {
189
+ for (InputSocketController input : inputSockets ) {
190
+ fadeIn (input );
191
+ }
192
+ reopen ();
193
+ expandIcon .setImage (new Image ("/edu/wpi/grip/ui/icons/up.png" ));
194
+ expanded = true ;
195
+ }
196
+
197
+ }
198
+
199
+ /**
200
+ * Makes an animation to make an input socket fade out over 0.1 seconds.
201
+ *
202
+ * @param input the input socket controller that will be faded out.
203
+ */
204
+ private void fadeOut (InputSocketController input ) {
205
+ DoubleProperty opacity = input .getRoot ().opacityProperty ();
206
+ Timeline fadeOut = new Timeline (
207
+ new KeyFrame (Duration .ZERO , new KeyValue (opacity , 1.0 )),
208
+ new KeyFrame (new Duration (100 ), new KeyValue (opacity , 0.0 )));
209
+ fadeOut .setOnFinished (new EventHandler <ActionEvent >() {
210
+ @ Override
211
+ public void handle (ActionEvent event ) {
212
+ input .getRoot ().setVisible (false );
213
+ input .getRoot ().setManaged (false );
214
+ }
215
+ });
216
+ fadeOut .play ();
217
+ }
218
+
219
+ /**
220
+ * Makes an animation to make an input socket fade in over 0.1 seconds.
221
+ *
222
+ * @param input the input socket controller that will be faded out.
223
+ */
224
+ private void fadeIn (InputSocketController input ) {
225
+ input .getRoot ().setVisible (true );
226
+ DoubleProperty opacity = input .getRoot ().opacityProperty ();
227
+ Timeline fadeIn = new Timeline (
228
+ new KeyFrame (new Duration (100 ), new KeyValue (opacity , 1.0 )));
229
+ fadeIn .setOnFinished (new EventHandler <ActionEvent >() {
230
+ @ Override
231
+ public void handle (ActionEvent event ) {
232
+ for (InputSocketController input : inputSockets ) {
233
+ input .getRoot ().setManaged (true );
234
+ }
235
+ }
236
+ });
237
+ fadeIn .play ();
238
+ }
239
+
240
+ /**
241
+ * Makes an animation to make the input vbox slide closed over .25 seconds
242
+ */
243
+ private void closeUp () {
244
+ Timeline animation = TimelineBuilder .create ().cycleCount (1 ).keyFrames (
245
+ new KeyFrame (Duration .seconds (0.25 ),
246
+ new KeyValue (inputs .prefHeightProperty (), 0 ))).build ();
247
+ animation .play ();
248
+ }
249
+
250
+ /**
251
+ * Makes an animation to make the input vbox slide open over .1 seconds
252
+ */
253
+ private void reopen () {
254
+ Timeline animation = TimelineBuilder .create ().cycleCount (1 ).keyFrames (
255
+ new KeyFrame (Duration .seconds (0.1 ),
256
+ new KeyValue (inputs .prefHeightProperty (), inputs .getMaxHeight ()))).build ();
257
+ animation .play ();
258
+ }
259
+
145
260
/**
146
261
* Used for assisted injects. Guice will automatically create an instance of this interface so we
147
262
* can create step controllers. This lets us use injection with StepController even though it
0 commit comments