Skip to content

Commit 31f9ac6

Browse files
committed
Merge pull request #197 from PaulaRudy/previewOrder
Preview order functionality complete
2 parents f8409f5 + 64d317e commit 31f9ac6

File tree

3 files changed

+206
-18
lines changed

3 files changed

+206
-18
lines changed

ui/src/main/java/edu/wpi/grip/ui/MainWindowView.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,9 @@ public MainWindowView(final EventBus eventBus) {
5757

5858
this.eventBus = eventBus;
5959

60-
this.previews = new PreviewsView(eventBus);
6160
this.palette = new PaletteView(eventBus, new Palette(this.eventBus));
6261
this.pipeline = new PipelineView(eventBus, new Pipeline(this.eventBus));
62+
this.previews = new PreviewsView(eventBus, pipeline);//Pass the pipeline to the PreviewsView to allow proper ordering of the previews
6363

6464
this.topPane.getItems().addAll(previews, palette);
6565
this.bottomPane.setContent(pipeline);

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,7 @@ private OutputSocketView findOutputSocketView(OutputSocket socket) {
156156
/**
157157
* @return The {@link SourceView} that corresponds with the given source
158158
*/
159-
160-
private SourceView findSourceView(Source source) {
159+
public SourceView findSourceView(Source source) {
161160
for (SourceView sourceView : this.getSources()) {
162161
if (sourceView.getSource() == source) {
163162
return sourceView;
@@ -170,7 +169,7 @@ private SourceView findSourceView(Source source) {
170169
/**
171170
* @return The {@link StepView} that corresponds with the given step
172171
*/
173-
private StepView findStepView(Step step) {
172+
public StepView findStepView(Step step) {
174173
for (StepView stepView : this.getSteps()) {
175174
if (stepView.getStep() == step) {
176175
return stepView;

ui/src/main/java/edu/wpi/grip/ui/preview/PreviewsView.java

Lines changed: 203 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,13 @@
33
import com.google.common.eventbus.EventBus;
44
import com.google.common.eventbus.Subscribe;
55
import edu.wpi.grip.core.OutputSocket;
6+
import edu.wpi.grip.core.Source;
7+
import edu.wpi.grip.core.Step;
68
import edu.wpi.grip.core.events.SocketPreviewChangedEvent;
9+
import edu.wpi.grip.core.events.StepMovedEvent;
10+
import edu.wpi.grip.ui.pipeline.PipelineView;
11+
import edu.wpi.grip.ui.pipeline.StepView;
12+
import edu.wpi.grip.ui.pipeline.source.SourceView;
713
import javafx.application.Platform;
814
import javafx.fxml.FXML;
915
import javafx.fxml.FXMLLoader;
@@ -13,6 +19,7 @@
1319
import java.io.IOException;
1420
import java.util.ArrayList;
1521
import java.util.List;
22+
import java.util.Stack;
1623

1724
import static com.google.common.base.Preconditions.checkNotNull;
1825

@@ -28,12 +35,15 @@ public class PreviewsView extends VBox {
2835

2936
private final EventBus eventBus;
3037
private final List<OutputSocket<?>> previewedSockets;
38+
private final PipelineView pipeline;//This is used to determine the order the previews are shown in.
3139

32-
public PreviewsView(EventBus eventBus) {
40+
public PreviewsView(EventBus eventBus, PipelineView pipeline) {
3341
checkNotNull(eventBus);
42+
checkNotNull(pipeline);
3443

3544
this.eventBus = eventBus;
3645
this.previewedSockets = new ArrayList<>();
46+
this.pipeline = pipeline;
3747

3848
try {
3949
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("Previews.fxml"));
@@ -47,25 +57,204 @@ public PreviewsView(EventBus eventBus) {
4757
this.eventBus.register(this);
4858
}
4959

60+
/**
61+
* This function is called when a step moves in the pipeline to adjust the positions of any open previews it has
62+
* to reflect the new order of the pipeline.
63+
*/
64+
@Subscribe
65+
public synchronized void onPreviewOrderChanged(StepMovedEvent event) {
66+
Platform.runLater(() -> {//Run this function on the main gui thread
67+
final Step movedStep = event.getStep(); //The step whose position in the pipeline has changed
68+
final int distanceMoved = event.getDistance(); //The number of indices (positive or negative) the step has been moved by
69+
final int numberOfSourcePreviews = getNumbOfSourcePreviews();//The number of previews opened that are displaying sources (NOT steps)
70+
71+
final OutputSocket<?>[] socketsMovedArray = movedStep.getOutputSockets();//Grab all the output sockets of the step that has moved
72+
73+
//Find the rightmost and leftmost position in the previews of the previewed sockets of the step that has moved
74+
int rightmostIndex = 0; //Set to minimum possible value so that the first index will overwrite it
75+
int leftmostIndex = this.previewedSockets.size();//Set to maximum possible value so that the first index will overwrite it
76+
77+
Stack<OutputSocket<?>> previewedMovedSockets = new Stack<OutputSocket<?>>();//This will hold the sockets of the step that was moved that are open for preview
78+
79+
for (OutputSocket<?> i : socketsMovedArray) {
80+
if (this.previewedSockets.indexOf(i) != -1) {//If this socket is previewed
81+
previewedMovedSockets.push(i);
82+
83+
if (rightmostIndex < this.previewedSockets.indexOf(i)) {
84+
rightmostIndex = this.previewedSockets.indexOf(i);
85+
}
86+
87+
if (leftmostIndex > this.previewedSockets.indexOf(i)) {
88+
leftmostIndex = this.previewedSockets.indexOf(i);
89+
}
90+
91+
}
92+
}
93+
94+
//Deal with each previewed socket from the step that was moved in turn
95+
while (previewedMovedSockets.size() != 0) { //While there are still sockets to deal with on the stack
96+
OutputSocket<?> current = previewedMovedSockets.pop();//Grab the top socket on the stack
97+
int oldIndex = this.previewedSockets.indexOf(current);//Get the index of this preview so we can remove the correct entry
98+
99+
int newLocation = 0;//This will hold the new index in the list of previewed sockets for this socket
100+
101+
if (distanceMoved < 0) { //If the step moved left....
102+
newLocation = leftmostIndex + distanceMoved; //Calculate the new index from the leftmost previewed socket of this step
103+
} else { //The step must have moved right....
104+
newLocation = rightmostIndex + distanceMoved;//So calculate the new index from the rightmost previewed socket of this step
105+
}
106+
107+
if (newLocation < numberOfSourcePreviews) {//If the new calculated index would put it in the midst of source previews
108+
newLocation = numberOfSourcePreviews;//Make the index the location of the first non-source preview
109+
} else { //The new index is the current location of another step (NOT a source)
110+
111+
//So we need to make sure that we jump over GROUPS of previews associated with the SAME step as a unit
112+
int count = 0;//This will hold the number of previews open from the same step in sequence, starting from the new location and going in the direction we are moving
113+
114+
if (distanceMoved < 0) {//If the step moved left....
115+
OutputSocket<?> nextSocketInDirection = this.previewedSockets.get(newLocation);//Grab the socket whose preview is open at the new location
116+
boolean zeroReached = false;//We will set this to true if we reach the beginning of the list of previews (there are no source previews open)
117+
while ((!zeroReached) &&
118+
((nextSocketInDirection.getStep().isPresent())
119+
&& (nextSocketInDirection.getStep().get() == this.previewedSockets.get(newLocation).getStep().get()))) { //While we haven't reached the beginning of the list of previews, the socket at this location is a socket from a step, and it is the SAME step as the step of the socket at the new location...
120+
count++;
121+
if ((newLocation - count) > 0) {//If we haven't reached the beginning of the list of open previews...
122+
nextSocketInDirection = this.previewedSockets.get(newLocation - count);//Grab the next previewed socket to examine in the direction we are moving
123+
} else {
124+
zeroReached = true;//Mark that we've reached the beginning of the list of previews so we know to stop looking for more
125+
}
126+
}
127+
newLocation = newLocation - (count - 1);//Since the first compare of the while loop will always be true, we subract one from the count when we use it to adjust newLocation
128+
129+
} else {//The step must have moved right....
130+
while ((newLocation + count < this.previewedSockets.size())
131+
&& (this.previewedSockets.get(newLocation + count).getStep().get() == this.previewedSockets.get(newLocation).getStep().get())) { //While there are still previewed sockets to examine, and the socket being examined is one from the SAME step of the socket at the new location....
132+
count++;
133+
}
134+
newLocation = newLocation + (count - 1);//Since the first compare of the while loop will always be true, we subract one from the count when we use it to adjust newLocation
135+
}
136+
}
137+
138+
//Remove this socket from the old point in the previews
139+
this.previewedSockets.remove(oldIndex);
140+
this.eventBus.unregister(this.previewBox.getChildren().remove(oldIndex));
141+
142+
if (newLocation > this.previewedSockets.size()) {//If the new index is now too big for the list of previews
143+
newLocation = this.previewedSockets.size();//Make it so it will be added to the end of the list of previews
144+
}
145+
this.previewedSockets.add(newLocation, current);//...add it to the correct location in the list of previews open
146+
this.previewBox.getChildren().add(newLocation, SocketPreviewViewFactory.createPreviewView(this.eventBus, current));//...and display it in the correct location in the list of previews open
147+
}
148+
});
149+
}
150+
151+
/**
152+
* This function is called when a preview button is pushed/triggered
153+
*/
50154
@Subscribe
51155
public synchronized void onSocketPreviewChanged(SocketPreviewChangedEvent event) {
52-
Platform.runLater(() -> {
53-
final OutputSocket<?> socket = event.getSocket();
54-
55-
if (socket.isPreviewed()) {
56-
// If the socket was just set as previewed, add it to the list of previewed sockets and add a new view for it.
57-
if (!this.previewedSockets.contains(socket)) {
58-
this.previewedSockets.add(socket);
59-
this.previewBox.getChildren().add(SocketPreviewViewFactory.createPreviewView(this.eventBus, socket));
156+
Platform.runLater(() -> {//Run this function on the main gui thread
157+
158+
final OutputSocket<?> socket = event.getSocket(); //The socket whose preview has changed
159+
160+
if (socket.isPreviewed()) {// If the socket was just set as previewed, add it to the list of previewed sockets and add a new view for it.
161+
162+
if (!this.previewedSockets.contains(socket)) {//If the socket is not already previewed...
163+
164+
if (socket.getStep().isPresent()) { //If this is a socket associated with a pipeline step (IE NOT a source)....
165+
166+
//Find the appropriate index to add this preview with...
167+
int indexInPreviews = getIndexInPreviewsOfAStepSocket(socket);
168+
169+
this.previewedSockets.add(indexInPreviews, socket);//...use this index to add it to the correct location in the list of previews open
170+
this.previewBox.getChildren().add(indexInPreviews, SocketPreviewViewFactory.createPreviewView(this.eventBus, socket));//...and display it in the correct location in the list of previews open in the gui
171+
172+
} else {//This is a socket associated with a source and not a pipeline step...
173+
174+
//Find the appropriate index to add this preview with.
175+
int indexInSourcePreviews = getIndexInPreviewsOfASourceSocket(socket);
176+
177+
this.previewedSockets.add(indexInSourcePreviews, socket);//Add the preview to the appropriate place in the list of previewed sockets
178+
this.previewBox.getChildren().add(indexInSourcePreviews, SocketPreviewViewFactory.createPreviewView(this.eventBus, socket));//Display the preview in the appropriate place
179+
}
60180
}
61-
} else {
62-
// If the socket was just set as not previewed, remove both it and the corresponding control
63-
int index = this.previewedSockets.indexOf(socket);
64-
if (index != -1) {
181+
} else {//The socket was already previewed, so the user must be requesting to not show this preview (remove both it and the corresponding control)
182+
183+
int index = this.previewedSockets.indexOf(socket);//Get the index of this preview so we can remove the correct entry
184+
if (index != -1) {//False when the preview isn't currently displayed
65185
this.previewedSockets.remove(index);
66186
this.eventBus.unregister(this.previewBox.getChildren().remove(index));
67187
}
68188
}
69189
});
70190
}
71-
}
191+
192+
/**
193+
* Find the correct index in the displayed previews for a socket associated with a source (NOT a step socket)
194+
* by comparing the indices in the pipeline.
195+
* Made to be called in {@link PreviewsView#onSocketPreviewChanged}
196+
*
197+
* @param socket An output socket associated with a source (NOT a step)
198+
* @return The correct index (an int) in the list of displayed previews for the given <code>socket</code>
199+
* @see PreviewsView#onSocketPreviewChanged(SocketPreviewChangedEvent)
200+
*/
201+
private int getIndexInPreviewsOfASourceSocket(OutputSocket<?> socket) {
202+
final Source socketSource = socket.getSource().get();//The source socket associated with the socket whose preview has changed
203+
final SourceView sourceView = this.pipeline.findSourceView(socketSource);//The gui object that displays the socketSource
204+
int indexOfSource = this.pipeline.getSources().indexOf(sourceView); //The index of the source that has the socket in the pipeline
205+
206+
//Start with the first socket in the list of previewed sockets
207+
int indexInSourcePreviews = 0;
208+
//Find the correct index in the displayed source previews by comparing the indices
209+
while (((this.previewedSockets.size() > indexInSourcePreviews)//If there are previews still to be examined AND
210+
&& (this.previewedSockets.get(indexInSourcePreviews).getSource().isPresent()))//AND If the preview at this index is a source...
211+
&& ((this.pipeline.getSources().indexOf(this.pipeline.findSourceView(this.previewedSockets.get(indexInSourcePreviews).getSource().get()))) < indexOfSource)) {//AND the preview at this index is a source with an index in the list of sources less than this source
212+
indexInSourcePreviews++;
213+
}
214+
return indexInSourcePreviews;
215+
}
216+
217+
/**
218+
* Find the correct index in the displayed previews for a socket associated with a step (NOT a source socket)
219+
* by comparing the indices in the pipeline, starting with the first non-source preview displayed.
220+
* Made to be called in {@link PreviewsView#onSocketPreviewChanged}
221+
*
222+
* @param socket An output socket associated with a step (NOT a source)
223+
* @return The correct index in the list of displayed previews for the given <code>socket</code>
224+
* @see PreviewsView#onSocketPreviewChanged(SocketPreviewChangedEvent)
225+
*/
226+
private int getIndexInPreviewsOfAStepSocket(OutputSocket<?> socket) {
227+
int numbOfSourcePreviews = getNumbOfSourcePreviews();//Count how many *source* previews (not *step* previews) are currently displayed
228+
229+
final Step socketStep = socket.getStep().get();//The pipeline step associated with the socket whose preview has changed
230+
final StepView stepView = this.pipeline.findStepView(socketStep);//The gui object that displays the socketStep
231+
int indexOfStep = this.pipeline.getSteps().indexOf(stepView); //The index of the step that has the socket in the pipeline
232+
233+
//Start at the first non-source socket in the list of previewed sockets
234+
int indexInPreviews = numbOfSourcePreviews;
235+
236+
while ((this.previewedSockets.size() > indexInPreviews)//While there are sockets in the list of previewed sockets yet to be examined
237+
&& ((this.pipeline.getSteps().indexOf(this.pipeline.findStepView(this.previewedSockets.get(indexInPreviews).getStep().get()))) < indexOfStep)) {//...AND the socket at this index in the list of displayed sockets has an index in the pipeline less than the socket passed in as "socket"
238+
indexInPreviews++;
239+
}
240+
return indexInPreviews;
241+
}
242+
243+
/**
244+
* Counts how many source previews (NOT step previews) are currently displayed.
245+
* Called in {@link PreviewsView#getIndexInPreviewsOfAStepSocket} and {@link PreviewsView#onPreviewOrderChanged(StepMovedEvent)}
246+
*
247+
* @return The number of source (NOT step) previews that are currently displayed
248+
* @see PreviewsView#getIndexInPreviewsOfAStepSocket(OutputSocket)
249+
* @see PreviewsView#onPreviewOrderChanged(StepMovedEvent)
250+
*/
251+
private int getNumbOfSourcePreviews() {
252+
//Start at the beginning of the list.
253+
int numbOfSourcePreviews = 0;
254+
while ((this.previewedSockets.size() > numbOfSourcePreviews) //While there are still previews to examine
255+
&& (!this.previewedSockets.get(numbOfSourcePreviews).getStep().isPresent())) { //If this is a source...
256+
numbOfSourcePreviews++;
257+
}
258+
return numbOfSourcePreviews;
259+
}
260+
}

0 commit comments

Comments
 (0)