Skip to content

Commit

Permalink
Merge pull request #659 from AustinShalit/osulacam-MinimizeSteps
Browse files Browse the repository at this point in the history
minimize steps
  • Loading branch information
AustinShalit authored Aug 11, 2016
2 parents 1e5fcd4 + 59f59f8 commit bbea07c
Show file tree
Hide file tree
Showing 7 changed files with 184 additions and 2 deletions.
17 changes: 17 additions & 0 deletions ui/src/main/java/edu/wpi/grip/ui/events/SetStepsExpandedEvent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package edu.wpi.grip.ui.events;

/**
* Toggles every steps' visibility.
*/
public class SetStepsExpandedEvent {

private final boolean expanded;

public SetStepsExpandedEvent(boolean expanded) {
this.expanded = expanded;
}

public boolean isExpanded() {
return expanded;
}
}
125 changes: 123 additions & 2 deletions ui/src/main/java/edu/wpi/grip/ui/pipeline/StepController.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,41 @@
import edu.wpi.grip.core.Step;
import edu.wpi.grip.core.sockets.InputSocket;
import edu.wpi.grip.core.sockets.OutputSocket;
import edu.wpi.grip.core.sockets.SocketHint;
import edu.wpi.grip.ui.Controller;
import edu.wpi.grip.ui.annotations.ParametrizedController;
import edu.wpi.grip.ui.components.ExceptionWitnessResponderButton;
import edu.wpi.grip.ui.dragging.StepDragService;
import edu.wpi.grip.ui.events.SetStepsExpandedEvent;
import edu.wpi.grip.ui.pipeline.input.InputSocketController;
import edu.wpi.grip.ui.pipeline.input.InputSocketControllerFactory;
import edu.wpi.grip.ui.util.ControllerMap;
import edu.wpi.grip.ui.util.StyleClassNameUtility;

import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import com.google.inject.assistedinject.Assisted;

import java.io.InputStream;
import java.util.Collection;

import java.util.function.Predicate;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.Labeled;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;

import javafx.util.Duration;
import javax.inject.Inject;

/**
Expand All @@ -40,7 +53,9 @@ public class StepController implements Controller {
private final OutputSocketController.Factory outputSocketControllerFactory;
private final ExceptionWitnessResponderButton.Factory exceptionWitnessResponderButtonFactory;
private final StepDragService stepDragService;
private final EventBus eventBus;
private final Step step;
private final BooleanProperty expanded = new SimpleBooleanProperty(true);
@FXML
private VBox root;
@FXML
Expand All @@ -53,21 +68,32 @@ public class StepController implements Controller {
private VBox inputs;
@FXML
private VBox outputs;
@FXML
private ImageView expandIcon;
@FXML
private Button expand;
private ControllerMap<InputSocketController, Node> inputSocketMapManager;
private ControllerMap<OutputSocketController, Node> outputSocketMapManager;

private static final Image UP_ARROW = new Image("/edu/wpi/grip/ui/icons/up.png");
private static final Image DOWN_ARROW = new Image("/edu/wpi/grip/ui/icons/down.png");
private static final Predicate<InputSocketController> interactiveInputSocketFilter
= i -> !i.getSocket().getSocketHint().getView().equals(SocketHint.View.NONE);

@Inject
StepController(Pipeline pipeline,
InputSocketControllerFactory inputSocketControllerFactory,
OutputSocketController.Factory outputSocketControllerFactory,
ExceptionWitnessResponderButton.Factory exceptionWitnessResponderButtonFactory,
StepDragService stepDragService,
EventBus eventBus,
@Assisted Step step) {
this.pipeline = pipeline;
this.inputSocketControllerFactory = inputSocketControllerFactory;
this.outputSocketControllerFactory = outputSocketControllerFactory;
this.exceptionWitnessResponderButtonFactory = exceptionWitnessResponderButtonFactory;
this.stepDragService = stepDragService;
this.eventBus = eventBus;
this.step = step;
}

Expand All @@ -82,6 +108,30 @@ private void initialize() {
new Image(InputStream.class.cast(icon))));
buttons.getChildren().add(0, exceptionWitnessResponderButtonFactory.create(step, "Step Error"));

if (step.getInputSockets().stream()
.allMatch(inputSocket -> inputSocket.getSocketHint().getView()
.equals(SocketHint.View.NONE))) {
expand.setManaged(false);
} else {
expandIcon.setImage(UP_ARROW);
expanded.addListener(((observable, oldValue, newValue) -> {
if (newValue) {
inputSocketMapManager.keySet().stream()
.filter(interactiveInputSocketFilter)
.forEach(this::fadeIn);
reopen();
expandIcon.setImage(UP_ARROW);
} else {
inputSocketMapManager.keySet().stream()
.filter(interactiveInputSocketFilter)
.filter(i -> i.getSocket().getConnections().isEmpty())
.forEach(this::fadeOut);
closeUp();
expandIcon.setImage(DOWN_ARROW);
}
}));
}

// Add a SocketControlView for each input socket and output socket
for (InputSocket<?> inputSocket : step.getInputSockets()) {
inputSocketMapManager.add(inputSocketControllerFactory.create(inputSocket));
Expand Down Expand Up @@ -142,6 +192,77 @@ private void moveStepRight() {
pipeline.moveStep(step, +1);
}

/**
* Clicking the arrow at the top of the step will cause the step to either expand or retract.
* Secondary clicking the arrow at the top of the step will cause all steps to either expand or
* retract.
*/
@FXML
private void toggleExpand(MouseEvent event) {
if (event.getButton().equals(MouseButton.PRIMARY)) {
expanded.set(!expanded.get());
} else if (event.getButton().equals(MouseButton.SECONDARY)) {
eventBus.post(new SetStepsExpandedEvent(!expanded.get()));
}
}

@Subscribe
public void setExpanded(SetStepsExpandedEvent event) {
expanded.set(event.isExpanded());
}

/**
* Makes an animation to make an input socket fade out over 0.1 seconds.
*
* @param input the input socket controller that will be faded out.
*/
private void fadeOut(InputSocketController input) {
DoubleProperty opacity = input.getRoot().opacityProperty();
Timeline fadeOut = new Timeline(
new KeyFrame(Duration.ZERO, new KeyValue(opacity, 1.0)),
new KeyFrame(new Duration(100), new KeyValue(opacity, 0.0)));
fadeOut.setOnFinished(event -> {
input.getRoot().setVisible(false);
input.getRoot().setManaged(false);
});
fadeOut.play();
}

/**
* Makes an animation to make an input socket fade in over 0.1 seconds.
*
* @param input the input socket controller that will be faded out.
*/
private void fadeIn(InputSocketController input) {
input.getRoot().setVisible(true);
DoubleProperty opacity = input.getRoot().opacityProperty();
Timeline fadeIn = new Timeline(
new KeyFrame(new Duration(100), new KeyValue(opacity, 1.0)));
fadeIn.setOnFinished(
event -> inputSocketMapManager.keySet().forEach(i -> input.getRoot().setManaged(true)));
fadeIn.play();
}

/**
* Makes an animation to make the input vbox slide closed over .25 seconds
*/
private void closeUp() {
Timeline animation = new Timeline(
new KeyFrame(Duration.seconds(0.25),
new KeyValue(inputs.prefHeightProperty(), 0)));
animation.play();
}

/**
* Makes an animation to make the input vbox slide open over .1 seconds
*/
private void reopen() {
Timeline animation = new Timeline(
new KeyFrame(Duration.seconds(0.1),
new KeyValue(inputs.prefHeightProperty(), inputs.getMaxHeight())));
animation.play();
}

/**
* Used for assisted injects. Guice will automatically create an instance of this interface so we
* can create step controllers. This lets us use injection with StepController even though it
Expand Down
4 changes: 4 additions & 0 deletions ui/src/main/resources/edu/wpi/grip/ui/GRIP.css
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,10 @@ Button.delete, Button.move-left, Button.move-right, .start-stoppable-button, .ex
-fx-pref-width: 2em;
}

.expand {
-fx-background-color: transparent;
}

VBox.sockets {
-fx-spacing: 0.5em;
}
Expand Down
Binary file added ui/src/main/resources/edu/wpi/grip/ui/icons/down.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added ui/src/main/resources/edu/wpi/grip/ui/icons/up.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions ui/src/main/resources/edu/wpi/grip/ui/pipeline/Step.fxml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,19 @@
</graphic>
</Label>
<Separator orientation="HORIZONTAL" />
<Button fx:id="expand" onMouseClicked="#toggleExpand" styleClass="expand"
maxWidth="Infinity" prefHeight="0" HBox.hgrow="ALWAYS">
<graphic>
<ImageView fx:id="expandIcon">
<fitHeight>
<DPIUtility fx:constant="SMALL_ICON_SIZE" />
</fitHeight>
</ImageView>
</graphic>
<tooltip>
<Tooltip text="Minimizes/Maximizes the inputs in the step"/>
</tooltip>
</Button>
<VBox fx:id="inputs" styleClass="sockets" />
<Separator orientation="HORIZONTAL" />
<VBox fx:id="outputs" styleClass="sockets" />
Expand Down
27 changes: 27 additions & 0 deletions ui/src/test/java/edu/wpi/grip/ui/pipeline/PipelineUITest.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import edu.wpi.grip.core.Pipeline;
import edu.wpi.grip.core.Step;
import edu.wpi.grip.core.SubtractionOperation;
import edu.wpi.grip.core.operations.composite.BlurOperation;
import edu.wpi.grip.core.operations.composite.DesaturateOperation;
import edu.wpi.grip.core.sockets.InputSocket;
import edu.wpi.grip.core.sockets.OutputSocket;
import edu.wpi.grip.core.util.MockExceptionWitness;
Expand Down Expand Up @@ -39,6 +41,7 @@
import javafx.stage.Stage;

import static junit.framework.Assert.assertEquals;
import static junit.framework.TestCase.assertTrue;
import static junit.framework.TestCase.fail;
import static org.testfx.api.FxAssert.verifyThat;
import static org.testfx.api.FxAssert.verifyThatIter;
Expand All @@ -49,6 +52,8 @@ public class PipelineUITest extends ApplicationTest {
private EventBus eventBus;
private OperationMetaData additionOperation;
private OperationMetaData subtractionOperation;
private OperationMetaData blurOperation;
private OperationMetaData desaturateOperation;
private PipelineController pipelineController;
private Pipeline pipeline;

Expand All @@ -66,6 +71,10 @@ public void start(Stage stage) {
AdditionOperation(isf, osf));
subtractionOperation = new OperationMetaData(SubtractionOperation.DESCRIPTION, () -> new
SubtractionOperation(isf, osf));
blurOperation = new OperationMetaData(BlurOperation.DESCRIPTION, () -> new
BlurOperation(isf, osf));
desaturateOperation = new OperationMetaData(DesaturateOperation.DESCRIPTION, () -> new
DesaturateOperation(isf, osf));
pipelineController = injector.getInstance(PipelineController.class);
final Scene scene = new Scene(TestAnnotationFXMLLoader.load(pipelineController), 800, 600);
stage.setScene(scene);
Expand Down Expand Up @@ -102,6 +111,24 @@ public void testConnectingTwoOperations() {

}

@Test
public void testMinimizeButton() {
Step desaturateStep = addOperation(1, desaturateOperation);
Step blurStep = addOperation(1, blurOperation);
assertTrue("blur input socket size is:" + blurStep.getInputSockets().size(),
blurStep.getInputSockets().size() > 0);

drag(StyleClassNameUtility.cssSelectorForOutputSocketHandleOn(desaturateStep), MouseButton
.PRIMARY).dropTo(StyleClassNameUtility.cssSelectorForInputSocketHandleOn(blurStep));

clickOn(".pipeline .blur-step .expand", MouseButton.PRIMARY);
clickOn(".pipeline .blur-step .expand", MouseButton.PRIMARY);

assertTrue("blur input socket size is:" + blurStep.getInputSockets().size(),
blurStep.getInputSockets().size() > 0);

}

@Test
public void testMoveOperation() {
final Step step1 = MockStep.createMockStepWithOperation();
Expand Down

0 comments on commit bbea07c

Please sign in to comment.