Skip to content

Commit 9b53dc3

Browse files
committed
Merge branch 'MinimizeSteps' of https://github.com/osulacam/GRIP into osulacam-MinimizeSteps
2 parents e91bb8b + 3409330 commit 9b53dc3

File tree

6 files changed

+161
-2
lines changed

6 files changed

+161
-2
lines changed

ui/src/main/java/edu/wpi/grip/ui/pipeline/StepController.java

Lines changed: 117 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import edu.wpi.grip.core.Step;
55
import edu.wpi.grip.core.sockets.InputSocket;
66
import edu.wpi.grip.core.sockets.OutputSocket;
7+
import edu.wpi.grip.core.sockets.SocketHint;
78
import edu.wpi.grip.ui.Controller;
89
import edu.wpi.grip.ui.annotations.ParametrizedController;
910
import edu.wpi.grip.ui.components.ExceptionWitnessResponderButton;
@@ -16,16 +17,26 @@
1617
import com.google.inject.assistedinject.Assisted;
1718

1819
import java.io.InputStream;
20+
import java.util.ArrayList;
1921
import java.util.Collection;
22+
import java.util.List;
2023

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;
2131
import javafx.fxml.FXML;
2232
import javafx.scene.Node;
33+
import javafx.scene.control.Button;
2334
import javafx.scene.control.Labeled;
2435
import javafx.scene.image.Image;
2536
import javafx.scene.image.ImageView;
2637
import javafx.scene.layout.HBox;
2738
import javafx.scene.layout.VBox;
28-
39+
import javafx.util.Duration;
2940
import javax.inject.Inject;
3041

3142
/**
@@ -41,6 +52,8 @@ public class StepController implements Controller {
4152
private final ExceptionWitnessResponderButton.Factory exceptionWitnessResponderButtonFactory;
4253
private final StepDragService stepDragService;
4354
private final Step step;
55+
private final List<InputSocketController> inputSockets;
56+
private boolean expanded = true;
4457
@FXML
4558
private VBox root;
4659
@FXML
@@ -53,6 +66,10 @@ public class StepController implements Controller {
5366
private VBox inputs;
5467
@FXML
5568
private VBox outputs;
69+
@FXML
70+
private ImageView expandIcon;
71+
@FXML
72+
private Button expand;
5673
private ControllerMap<InputSocketController, Node> inputSocketMapManager;
5774
private ControllerMap<OutputSocketController, Node> outputSocketMapManager;
5875

@@ -69,6 +86,7 @@ public class StepController implements Controller {
6986
this.exceptionWitnessResponderButtonFactory = exceptionWitnessResponderButtonFactory;
7087
this.stepDragService = stepDragService;
7188
this.step = step;
89+
inputSockets = new ArrayList<>();
7290
}
7391

7492
@FXML
@@ -82,9 +100,21 @@ private void initialize() {
82100
new Image(InputStream.class.cast(icon))));
83101
buttons.getChildren().add(0, exceptionWitnessResponderButtonFactory.create(step, "Step Error"));
84102

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+
85111
// Add a SocketControlView for each input socket and output socket
86112
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+
}
88118
}
89119

90120
for (OutputSocket<?> outputSocket : step.getOutputSockets()) {
@@ -142,6 +172,91 @@ private void moveStepRight() {
142172
pipeline.moveStep(step, +1);
143173
}
144174

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+
145260
/**
146261
* Used for assisted injects. Guice will automatically create an instance of this interface so we
147262
* can create step controllers. This lets us use injection with StepController even though it

ui/src/main/resources/edu/wpi/grip/ui/GRIP.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,10 @@ Button.delete, Button.move-left, Button.move-right, .start-stoppable-button, .ex
122122
-fx-pref-width: 2em;
123123
}
124124

125+
.expand {
126+
-fx-background-color: transparent;
127+
}
128+
125129
VBox.sockets {
126130
-fx-spacing: 0.5em;
127131
}
237 Bytes
Loading
231 Bytes
Loading

ui/src/main/resources/edu/wpi/grip/ui/pipeline/Step.fxml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,19 @@
7979
</graphic>
8080
</Label>
8181
<Separator orientation="HORIZONTAL" />
82+
<Button fx:id="expand" onMouseClicked="#expand" styleClass="expand"
83+
maxWidth="Infinity" prefHeight="0" HBox.hgrow="ALWAYS">
84+
<graphic>
85+
<ImageView fx:id="expandIcon">
86+
<fitHeight>
87+
<DPIUtility fx:constant="SMALL_ICON_SIZE" />
88+
</fitHeight>
89+
</ImageView>
90+
</graphic>
91+
<tooltip>
92+
<Tooltip text="Minimizes/Maximizes the inputs in the step"/>
93+
</tooltip>
94+
</Button>
8295
<VBox fx:id="inputs" styleClass="sockets" />
8396
<Separator orientation="HORIZONTAL" />
8497
<VBox fx:id="outputs" styleClass="sockets" />

ui/src/test/java/edu/wpi/grip/ui/pipeline/PipelineUITest.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
import edu.wpi.grip.core.Pipeline;
88
import edu.wpi.grip.core.Step;
99
import edu.wpi.grip.core.SubtractionOperation;
10+
import edu.wpi.grip.core.operations.composite.BlurOperation;
11+
import edu.wpi.grip.core.operations.composite.DesaturateOperation;
1012
import edu.wpi.grip.core.sockets.InputSocket;
1113
import edu.wpi.grip.core.sockets.OutputSocket;
1214
import edu.wpi.grip.core.util.MockExceptionWitness;
@@ -39,6 +41,7 @@
3941
import javafx.stage.Stage;
4042

4143
import static junit.framework.Assert.assertEquals;
44+
import static junit.framework.TestCase.assertTrue;
4245
import static junit.framework.TestCase.fail;
4346
import static org.testfx.api.FxAssert.verifyThat;
4447
import static org.testfx.api.FxAssert.verifyThatIter;
@@ -49,6 +52,8 @@ public class PipelineUITest extends ApplicationTest {
4952
private EventBus eventBus;
5053
private OperationMetaData additionOperation;
5154
private OperationMetaData subtractionOperation;
55+
private OperationMetaData blurOperation;
56+
private OperationMetaData desaturateOperation;
5257
private PipelineController pipelineController;
5358
private Pipeline pipeline;
5459

@@ -66,6 +71,10 @@ public void start(Stage stage) {
6671
AdditionOperation(isf, osf));
6772
subtractionOperation = new OperationMetaData(SubtractionOperation.DESCRIPTION, () -> new
6873
SubtractionOperation(isf, osf));
74+
blurOperation = new OperationMetaData(BlurOperation.DESCRIPTION, () -> new
75+
BlurOperation(isf, osf));
76+
desaturateOperation = new OperationMetaData(DesaturateOperation.DESCRIPTION, () -> new
77+
DesaturateOperation(isf, osf));
6978
pipelineController = injector.getInstance(PipelineController.class);
7079
final Scene scene = new Scene(TestAnnotationFXMLLoader.load(pipelineController), 800, 600);
7180
stage.setScene(scene);
@@ -102,6 +111,24 @@ public void testConnectingTwoOperations() {
102111

103112
}
104113

114+
@Test
115+
public void testMinimizeButton() {
116+
Step desaturateStep = addOperation(1, desaturateOperation);
117+
Step blurStep = addOperation(1, blurOperation);
118+
assertTrue("blur input socket size is:" + blurStep.getInputSockets().size(),
119+
blurStep.getInputSockets().size() > 0);
120+
121+
drag(StyleClassNameUtility.cssSelectorForOutputSocketHandleOn(desaturateStep), MouseButton
122+
.PRIMARY).dropTo(StyleClassNameUtility.cssSelectorForInputSocketHandleOn(blurStep));
123+
124+
clickOn(".pipeline .blur-step .expand", MouseButton.PRIMARY);
125+
clickOn(".pipeline .blur-step .expand", MouseButton.PRIMARY);
126+
127+
assertTrue("blur input socket size is:" + blurStep.getInputSockets().size(),
128+
blurStep.getInputSockets().size() > 0);
129+
130+
}
131+
105132
@Test
106133
public void testMoveOperation() {
107134
final Step step1 = MockStep.createMockStepWithOperation();

0 commit comments

Comments
 (0)