Skip to content

Commit 59aa466

Browse files
committed
Sources can now be stopped and started from the UI
1 parent 0e2660b commit 59aa466

File tree

9 files changed

+148
-15
lines changed

9 files changed

+148
-15
lines changed

core/src/main/java/edu/wpi/grip/core/Source.java

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,38 @@ public <T extends Source> T start(EventBus eventBus) throws IOException {
5151
final T source = (T) start();
5252
eventBus.register(source);
5353
return source;
54-
};
54+
}
5555

56+
/**
57+
* Starts this source.
58+
* A source whose {@link #isRestartable()} returns true can also be stopped and started and stopped multiple times.
59+
*
60+
* @return The source object that created the camera
61+
* @throws IOException If the source fails to be started
62+
*/
5663
protected abstract Source start() throws IOException;
5764

65+
/**
66+
* Stops this source.
67+
* This will stop the source publishing new socket values after this method returns.
68+
* A source whose {@link #isRestartable()} returns true can also be stopped and started and stopped multiple times.
69+
*
70+
* @return The source that was stopped
71+
* @throws Exception
72+
*/
5873
public abstract Source stop() throws Exception;
5974

75+
/**
76+
* Used to indicate if the source is running or stopped
77+
*
78+
* @return true if this source is running
79+
*/
6080
public abstract boolean isRunning();
81+
82+
/**
83+
* Used to flag to the UI if this source should have the start/stop button displayed
84+
*
85+
* @return true if this source can be restarted once created
86+
*/
87+
public abstract boolean isRestartable();
6188
}

core/src/main/java/edu/wpi/grip/core/sources/CameraSource.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@ private void initialize(EventBus eventBus, FrameGrabber frameGrabber, String nam
8383
this.frameOutputSocket = new OutputSocket<>(eventBus, imageOutputHint);
8484
this.frameRateOutputSocket = new OutputSocket<>(eventBus, frameRateOutputHint);
8585
this.grabber = frameGrabber;
86-
eventBus.register(this);
8786
}
8887

8988
@Override
@@ -230,11 +229,16 @@ public boolean isRunning() {
230229
}
231230
}
232231

232+
@Override
233+
public boolean isRestartable() {
234+
return true;
235+
}
236+
233237
@Subscribe
234238
public void onSourceRemovedEvent(SourceRemovedEvent event) throws TimeoutException {
235239
if (event.getSource() == this) {
236240
try {
237-
this.stop();
241+
if (this.isRunning()) this.stop();
238242
} finally {
239243
this.eventBus.unregister(this);
240244
}

core/src/main/java/edu/wpi/grip/core/sources/ImageFileSource.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,11 @@ public boolean isRunning() {
102102
return this.started;
103103
}
104104

105+
@Override
106+
public boolean isRestartable() {
107+
return false;
108+
}
109+
105110
/**
106111
* Loads the image and posts an update to the {@link EventBus}
107112
*
362 Bytes
Loading
188 Bytes
Loading

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

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,27 @@
11
package edu.wpi.grip.ui.pipeline;
22

33
import com.google.common.eventbus.EventBus;
4+
import com.google.common.eventbus.Subscribe;
45
import edu.wpi.grip.core.OutputSocket;
56
import edu.wpi.grip.core.Source;
7+
import edu.wpi.grip.core.events.FatalErrorEvent;
68
import edu.wpi.grip.core.events.SourceRemovedEvent;
9+
import edu.wpi.grip.core.events.SourceStartedEvent;
10+
import edu.wpi.grip.core.events.SourceStoppedEvent;
11+
import edu.wpi.grip.ui.util.DPIUtility;
12+
import javafx.application.Platform;
713
import javafx.collections.ObservableList;
814
import javafx.fxml.FXML;
915
import javafx.fxml.FXMLLoader;
16+
import javafx.scene.control.ContentDisplay;
1017
import javafx.scene.control.Label;
18+
import javafx.scene.control.ToggleButton;
19+
import javafx.scene.control.Tooltip;
20+
import javafx.scene.image.Image;
21+
import javafx.scene.image.ImageView;
22+
import javafx.scene.input.MouseEvent;
23+
import javafx.scene.layout.HBox;
24+
import javafx.scene.layout.Priority;
1125
import javafx.scene.layout.VBox;
1226

1327
import java.io.IOException;
@@ -19,12 +33,21 @@
1933
*/
2034
public class SourceView extends VBox {
2135

36+
private static final Image startImage = new Image(SourceView.class.getResourceAsStream("/edu/wpi/grip/ui/icons/start.png"));
37+
private static final Image stopImage = new Image(SourceView.class.getResourceAsStream("/edu/wpi/grip/ui/icons/stop.png"));
38+
2239
@FXML
2340
private Label name;
2441

2542
@FXML
2643
private VBox sockets;
2744

45+
@FXML
46+
private ToggleButton startStopButton;
47+
48+
@FXML
49+
private Tooltip startStopTooltip;
50+
2851
private final EventBus eventBus;
2952
private final Source source;
3053

@@ -41,11 +64,45 @@ public SourceView(EventBus eventBus, Source source) {
4164
throw new RuntimeException(e);
4265
}
4366

67+
4468
this.name.setText(source.getName());
4569

70+
if (!source.isRestartable()) startStopButton.setVisible(false);
71+
else {
72+
HBox.setHgrow(startStopButton, Priority.NEVER);
73+
startStopButton.setContentDisplay(ContentDisplay.RIGHT);
74+
75+
startStopButton.addEventFilter(MouseEvent.MOUSE_RELEASED, (event) -> {
76+
event.consume();
77+
if (!startStopButton.isSelected()) try {
78+
source.start(eventBus);
79+
} catch (IOException e) {
80+
eventBus.post(new FatalErrorEvent(e));
81+
}
82+
else try {
83+
source.stop();
84+
} catch (Exception e) {
85+
eventBus.post(new FatalErrorEvent(e));
86+
}
87+
});
88+
startStopButton.selectedProperty().addListener((o, oldV, newV) -> {
89+
final String stopCameraText = "Stop Camera";
90+
final String startCameraText = "Start Camera";
91+
final ImageView icon = newV ? new ImageView(stopImage) : new ImageView(startImage);
92+
icon.setFitHeight(DPIUtility.MINI_ICON_SIZE);
93+
icon.setFitWidth(DPIUtility.MINI_ICON_SIZE);
94+
startStopButton.setGraphic(icon);
95+
startStopTooltip.setText(newV ? stopCameraText : startCameraText);
96+
startStopButton.setAccessibleText(newV ? stopCameraText : startCameraText);
97+
});
98+
startStopButton.setSelected(source.isRunning());
99+
}
100+
46101
for (OutputSocket<?> socket : source.getOutputSockets()) {
47102
this.sockets.getChildren().add(new OutputSocketView(eventBus, socket));
48103
}
104+
105+
eventBus.register(this);
49106
}
50107

51108
public Source getSource() {
@@ -64,4 +121,23 @@ public ObservableList<OutputSocketView> getOutputSockets() {
64121
public void delete() {
65122
this.eventBus.post(new SourceRemovedEvent(this.getSource()));
66123
}
124+
125+
126+
@Subscribe
127+
public void onSourceStarted(SourceStartedEvent event) {
128+
if (source == event.getSource()) {
129+
Platform.runLater(() -> {
130+
startStopButton.setSelected(true);
131+
});
132+
}
133+
}
134+
135+
@Subscribe
136+
public void onSourceStopped(SourceStoppedEvent event) {
137+
if (source == event.getSource()) {
138+
Platform.runLater(() -> {
139+
startStopButton.setSelected(false);
140+
});
141+
}
142+
}
67143
}

ui/src/main/java/edu/wpi/grip/ui/util/DPIUtility.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ public class DPIUtility {
1313
public final static double FONT_SIZE = 11.0 * (isManualHiDPI() ? HIDPI_SCALE : 1.0);
1414
public final static double SMALL_ICON_SIZE = 16.0 * (isManualHiDPI() ? HIDPI_SCALE : 1.0);
1515
public final static double LARGE_ICON_SIZE = 48.0 * (isManualHiDPI() ? HIDPI_SCALE : 1.0);
16+
public final static double MINI_ICON_SIZE = SMALL_ICON_SIZE / 2.0;
1617
public final static double STROKE_WIDTH = 2.0 * (isManualHiDPI() ? HIDPI_SCALE : 1.0);
1718

1819
private static boolean isManualHiDPI() {

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ Button.add-source {
123123
-fx-spacing: 0.5em;
124124
}
125125

126-
Button.delete, Button.move-left, Button.move-right {
126+
Button.delete, Button.move-left, Button.move-right, Button.start-stop {
127127
-fx-padding: 0.2em 0.8em;
128128
-fx-font-weight: bold;
129129
-fx-font-color: -fx-dark-color;
@@ -181,6 +181,10 @@ VBox.sockets {
181181
-fx-padding: 0.5em;
182182
}
183183

184+
.source-header-box {
185+
-fx-padding: 0 0 0.5em 0;
186+
}
187+
184188
.preview-box {
185189
-fx-spacing: 0.5em;
186190
}
Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,32 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22

3-
<?import javafx.scene.control.Button?>
4-
<?import javafx.scene.control.Label?>
5-
<?import javafx.scene.layout.VBox?>
6-
<fx:root type="javafx.scene.layout.VBox" xmlns="http://javafx.com/javafx/null"
7-
xmlns:fx="http://javafx.com/fxml/1" styleClass="source">
3+
<?import javafx.scene.control.*?>
4+
<?import javafx.scene.layout.*?>
5+
<fx:root styleClass="source" type="javafx.scene.layout.VBox" xmlns="http://javafx.com/javafx/8.0.40"
6+
xmlns:fx="http://javafx.com/fxml/1">
87
<children>
9-
<Label fx:id="name" styleClass="source-name">
10-
<graphic>
11-
<Button text="" styleClass="delete" onMouseClicked="#delete"/>
12-
</graphic>
13-
</Label>
14-
<VBox fx:id="sockets" styleClass="sockets"/>
8+
<BorderPane VBox.vgrow="NEVER">
9+
<top>
10+
<HBox alignment="CENTER" spacing="2.0" styleClass="source-header-box" BorderPane.alignment="CENTER">
11+
<Button onMouseClicked="#delete" styleClass="delete" text=""/>
12+
<Label fx:id="name" styleClass="source-name"/>
13+
<Pane HBox.hgrow="ALWAYS"/>
14+
<ToggleButton fx:id="startStopButton" styleClass="start-stop" contentDisplay="RIGHT"
15+
mnemonicParsing="false"
16+
HBox.hgrow="NEVER">
17+
<tooltip>
18+
<Tooltip fx:id="startStopTooltip"/>
19+
</tooltip>
20+
</ToggleButton>
21+
</HBox>
22+
</top>
23+
<center>
24+
<VBox fx:id="sockets" styleClass="sockets" BorderPane.alignment="CENTER">
25+
<children>
26+
<Separator orientation="HORIZONTAL"/>
27+
</children>
28+
</VBox>
29+
</center>
30+
</BorderPane>
1531
</children>
1632
</fx:root>

0 commit comments

Comments
 (0)