Skip to content

Commit 9bffdfc

Browse files
committed
Make the source controls a factory
1 parent 77cf189 commit 9bffdfc

File tree

11 files changed

+197
-154
lines changed

11 files changed

+197
-154
lines changed

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

Lines changed: 0 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import java.io.IOException;
66
import java.util.Optional;
77
import java.util.Properties;
8-
import java.util.concurrent.TimeoutException;
98

109
/**
1110
* Base class for an input into the pipeline.
@@ -46,52 +45,4 @@ public final OutputSocket[] getOutputSockets() {
4645
* @see #getProperties()
4746
*/
4847
public abstract void createFromProperties(EventBus eventBus, Properties properties) throws IOException;
49-
50-
/**
51-
* Starts this source.
52-
* A source whose {@link #canStopAndStart()} returns true can also be stopped and started and stopped multiple times.
53-
*
54-
* @return The source object that created the camera
55-
* @throws IOException If the source fails to be started
56-
*/
57-
public <T extends Source> T start(EventBus eventBus) throws IOException {
58-
start();
59-
eventBus.register(this);
60-
return (T) this;
61-
}
62-
63-
/**
64-
* Any method that overrides this method should post a {@link edu.wpi.grip.core.events.SourceStartedEvent}
65-
* to the {@link EventBus} if is successfully starts.
66-
* @throws IOException If the source fails to be started
67-
*/
68-
protected abstract void start() throws IOException;
69-
70-
/**
71-
* Stops this source.
72-
* This will stop the source publishing new socket values after this method returns.
73-
* A source whose {@link #canStopAndStart()} returns true can also be stopped and started and stopped multiple times.
74-
*
75-
* Any method that overrides this method should post a {@link edu.wpi.grip.core.events.SourceStoppedEvent}
76-
* to the {@link EventBus} if is successfully stops.
77-
*
78-
* @return The source that was stopped
79-
* @throws TimeoutException if the thread running the source fails to stop.
80-
* @throws IOException If there is a problem stopping the Source
81-
*/
82-
public void stop() throws TimeoutException, IOException { /* no op */ }
83-
84-
/**
85-
* Used to indicate if the source is running or stopped
86-
*
87-
* @return true if this source is running
88-
*/
89-
public abstract boolean isRunning();
90-
91-
/**
92-
* Used to flag to the UI if this source should have the start/stop button displayed
93-
*
94-
* @return true if this source can be restarted once created
95-
*/
96-
public abstract boolean canStopAndStart();
9748
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package edu.wpi.grip.core;
2+
3+
4+
import com.google.common.eventbus.EventBus;
5+
6+
import java.io.IOException;
7+
import java.util.concurrent.TimeoutException;
8+
9+
/**
10+
* A Source that can be stopped and started multiple times.
11+
*/
12+
public abstract class StopStartSource extends Source {
13+
14+
/**
15+
* Starts this source.
16+
*
17+
* @return The source object that created the camera
18+
* @throws IOException If the source fails to be started
19+
*/
20+
public <T extends Source> T start(EventBus eventBus) throws IOException {
21+
start();
22+
eventBus.register(this);
23+
return (T) this;
24+
}
25+
26+
/**
27+
* Any method that overrides this method should post a {@link edu.wpi.grip.core.events.SourceStartedEvent}
28+
* to the {@link EventBus} if is successfully starts.
29+
* @throws IOException If the source fails to be started
30+
*/
31+
protected abstract void start() throws IOException;
32+
33+
/**
34+
* Stops this source.
35+
* This will stop the source publishing new socket values after this method returns.
36+
*
37+
* Any method that overrides this method should post a {@link edu.wpi.grip.core.events.SourceStoppedEvent}
38+
* to the {@link EventBus} if is successfully stops.
39+
*
40+
* @return The source that was stopped
41+
* @throws TimeoutException if the thread running the source fails to stop.
42+
* @throws IOException If there is a problem stopping the Source
43+
*/
44+
public abstract void stop() throws TimeoutException, IOException;
45+
46+
/**
47+
* Used to indicate if the source is running or stopped
48+
*
49+
* @return true if this source is running
50+
*/
51+
public abstract boolean isRunning();
52+
}

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

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
import edu.wpi.grip.core.OutputSocket;
99
import edu.wpi.grip.core.SocketHint;
1010
import edu.wpi.grip.core.SocketHints;
11-
import edu.wpi.grip.core.Source;
1211
import edu.wpi.grip.core.events.UnexpectedThrowableEvent;
12+
import edu.wpi.grip.core.StopStartSource;
1313
import edu.wpi.grip.core.events.SourceRemovedEvent;
1414
import edu.wpi.grip.core.events.SourceStartedEvent;
1515
import edu.wpi.grip.core.events.SourceStoppedEvent;
@@ -29,7 +29,7 @@
2929
* Provides a way to generate a constantly updated {@link Mat} from a camera
3030
*/
3131
@XStreamAlias(value = "grip:Camera")
32-
public class CameraSource extends Source {
32+
public class CameraSource extends StopStartSource {
3333

3434
private final static String DEVICE_NUMBER_PROPERTY = "deviceNumber";
3535
private final static String ADDRESS_PROPERTY = "address";
@@ -227,11 +227,6 @@ public boolean isRunning() {
227227
}
228228
}
229229

230-
@Override
231-
public boolean canStopAndStart() {
232-
return true;
233-
}
234-
235230
@Subscribe
236231
public void onSourceRemovedEvent(SourceRemovedEvent event) throws TimeoutException {
237232
if (event.getSource() == this) {

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

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ public class ImageFileSource extends Source {
3333
private final SocketHint<Mat> imageOutputHint = SocketHints.Inputs.createMatSocketHint("Image", true);
3434
private OutputSocket<Mat> outputSocket;
3535
private EventBus eventBus;
36-
private boolean started = false;
3736

3837
/**
3938
* @param eventBus The event bus for the pipeline.
@@ -84,20 +83,6 @@ public void createFromProperties(EventBus eventBus, Properties properties) throw
8483
this.initialize(eventBus, path);
8584
}
8685

87-
protected void start() throws IOException {
88-
this.started = true;
89-
loadImage(this.path);
90-
}
91-
92-
@Override
93-
public boolean isRunning() {
94-
return this.started;
95-
}
96-
97-
@Override
98-
public boolean canStopAndStart() {
99-
return false;
100-
}
10186

10287
/**
10388
* Loads the image and posts an update to the {@link EventBus}

core/src/test/java/edu/wpi/grip/core/sources/ImageFileSourceTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public void setUp() throws URISyntaxException {
3232
public void testLoadImageToMat() throws IOException {
3333
// Given above setup
3434
// When
35-
final ImageFileSource fileSource = new ImageFileSource(eventBus, this.imageFile).start(eventBus);
35+
final ImageFileSource fileSource = new ImageFileSource(eventBus, this.imageFile);
3636
OutputSocket<Mat> outputSocket = fileSource.getOutputSockets()[0];
3737

3838
// Then
@@ -45,7 +45,7 @@ public void testLoadImageToMat() throws IOException {
4545

4646
@Test(expected = IOException.class)
4747
public void testReadInTextFile() throws IOException {
48-
final ImageFileSource fileSource = new ImageFileSource(eventBus, this.textFile).start(eventBus);
48+
final ImageFileSource fileSource = new ImageFileSource(eventBus, this.textFile);
4949
OutputSocket<Mat> outputSocket = fileSource.getOutputSockets()[0];
5050
assertTrue("No matrix should have been returned.", outputSocket.getValue().get().empty());
5151
}
@@ -54,7 +54,7 @@ public void testReadInTextFile() throws IOException {
5454
public void testReadInFileWithoutExtension() throws MalformedURLException, IOException {
5555
final File testFile = new File("temp" + File.separator +"fdkajdl3eaf");
5656

57-
final ImageFileSource fileSource = new ImageFileSource(eventBus, testFile).start(eventBus);
57+
final ImageFileSource fileSource = new ImageFileSource(eventBus, testFile);
5858
OutputSocket<Mat> outputSocket = fileSource.getOutputSockets()[0];
5959
assertTrue("No matrix should have been returned.", outputSocket.getValue().get().empty());
6060
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public AddSourceView(EventBus eventBus) {
5858
// Add a new source for each image .
5959
imageFiles.forEach(file -> {
6060
try {
61-
eventBus.post(new SourceAddedEvent(new ImageFileSource(eventBus, file).start(eventBus)));
61+
eventBus.post(new SourceAddedEvent(new ImageFileSource(eventBus, file)));
6262
} catch (IOException e) {
6363
eventBus.post(new UnexpectedThrowableEvent(e, "Tried to create an invalid source"));
6464
}
Lines changed: 3 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,18 @@
11
package edu.wpi.grip.ui.pipeline;
22

33
import com.google.common.eventbus.EventBus;
4-
import com.google.common.eventbus.Subscribe;
54
import edu.wpi.grip.core.OutputSocket;
65
import edu.wpi.grip.core.Source;
7-
import edu.wpi.grip.core.events.FatalErrorEvent;
86
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;
7+
import edu.wpi.grip.ui.pipeline.source.SourceControlsViewFactory;
138
import javafx.collections.ObservableList;
149
import javafx.fxml.FXML;
1510
import javafx.fxml.FXMLLoader;
16-
import javafx.scene.control.ContentDisplay;
1711
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;
2312
import javafx.scene.layout.HBox;
24-
import javafx.scene.layout.Priority;
2513
import javafx.scene.layout.VBox;
2614

2715
import java.io.IOException;
28-
import java.util.concurrent.TimeoutException;
2916

3017
/**
3118
* A JavaFX control that represents a {@link Source}. <code>SourceView</code>s are somewhat analogous to
@@ -34,8 +21,6 @@
3421
*/
3522
public class SourceView extends VBox {
3623

37-
private static final Image startImage = new Image(SourceView.class.getResourceAsStream("/edu/wpi/grip/ui/icons/start.png"));
38-
private static final Image stopImage = new Image(SourceView.class.getResourceAsStream("/edu/wpi/grip/ui/icons/stop.png"));
3924

4025
@FXML
4126
private Label name;
@@ -44,10 +29,7 @@ public class SourceView extends VBox {
4429
private VBox sockets;
4530

4631
@FXML
47-
private ToggleButton startStopButton;
48-
49-
@FXML
50-
private Tooltip startStopTooltip;
32+
private HBox controls;
5133

5234
private final EventBus eventBus;
5335
private final Source source;
@@ -65,41 +47,9 @@ public SourceView(EventBus eventBus, Source source) {
6547
throw new RuntimeException(e);
6648
}
6749

68-
6950
this.name.setText(source.getName());
7051

71-
if (!source.canStopAndStart()) startStopButton.setVisible(false);
72-
else {
73-
HBox.setHgrow(startStopButton, Priority.NEVER);
74-
startStopButton.setContentDisplay(ContentDisplay.RIGHT);
75-
76-
startStopButton.addEventFilter(MouseEvent.MOUSE_RELEASED, (event) -> {
77-
event.consume();
78-
if (!startStopButton.isSelected()) try {
79-
source.start(eventBus);
80-
// If this fails then an SourceStartedEvent will not be posted
81-
} catch (IOException e) {
82-
eventBus.post(new FatalErrorEvent(e));
83-
}
84-
else try {
85-
source.stop();
86-
// If this fails then an SourceStoppedEvent will not be posted
87-
} catch (TimeoutException | IOException e) {
88-
eventBus.post(new FatalErrorEvent(e));
89-
}
90-
});
91-
startStopButton.selectedProperty().addListener((o, oldV, newV) -> {
92-
final String stopCameraText = "Stop Camera";
93-
final String startCameraText = "Start Camera";
94-
final ImageView icon = newV ? new ImageView(stopImage) : new ImageView(startImage);
95-
icon.setFitHeight(DPIUtility.MINI_ICON_SIZE);
96-
icon.setFitWidth(DPIUtility.MINI_ICON_SIZE);
97-
startStopButton.setGraphic(icon);
98-
startStopTooltip.setText(newV ? stopCameraText : startCameraText);
99-
startStopButton.setAccessibleText(newV ? stopCameraText : startCameraText);
100-
});
101-
startStopButton.setSelected(source.isRunning());
102-
}
52+
controls.getChildren().add(SourceControlsViewFactory.createSourceControlsView(eventBus, source));
10353

10454
for (OutputSocket<?> socket : source.getOutputSockets()) {
10555
this.sockets.getChildren().add(new OutputSocketView(eventBus, socket));
@@ -125,22 +75,4 @@ public void delete() {
12575
this.eventBus.post(new SourceRemovedEvent(this.getSource()));
12676
}
12777

128-
129-
@Subscribe
130-
public void onSourceStarted(SourceStartedEvent event) {
131-
if (source == event.getSource()) {
132-
Platform.runLater(() -> {
133-
startStopButton.setSelected(true);
134-
});
135-
}
136-
}
137-
138-
@Subscribe
139-
public void onSourceStopped(SourceStoppedEvent event) {
140-
if (source == event.getSource()) {
141-
Platform.runLater(() -> {
142-
startStopButton.setSelected(false);
143-
});
144-
}
145-
}
14678
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package edu.wpi.grip.ui.pipeline.source;
2+
3+
import javafx.scene.layout.HBox;
4+
5+
public abstract class SourceControlsView<T> extends HBox {
6+
7+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package edu.wpi.grip.ui.pipeline.source;
2+
3+
import com.google.common.eventbus.EventBus;
4+
import edu.wpi.grip.core.Source;
5+
import edu.wpi.grip.core.StopStartSource;
6+
7+
public class SourceControlsViewFactory {
8+
private SourceControlsViewFactory() { /* no op */ }
9+
10+
public static <T> SourceControlsView<T> createSourceControlsView(EventBus eventBus, Source source) {
11+
if (source instanceof StopStartSource) {
12+
return (SourceControlsView<T>) new StopStartSourceControlsView(eventBus, (StopStartSource) source);
13+
} else {
14+
return new SourceControlsView() {};
15+
}
16+
}
17+
}

0 commit comments

Comments
 (0)