diff --git a/src/main/java/seng302/App.java b/src/main/java/seng302/App.java index df036566..3625db47 100644 --- a/src/main/java/seng302/App.java +++ b/src/main/java/seng302/App.java @@ -62,7 +62,8 @@ public class App extends Application { } //Change the StreamReceiver in this else block to change the default data source. else{ - sr = new StreamReceiver("localhost", 4949, "RaceStream"); +// sr = new StreamReceiver("localhost", 4949, "RaceStream"); + sr = new StreamReceiver("livedata.americascup.com", 4941, "RaceStream"); } sr.start(); diff --git a/src/main/java/seng302/controllers/RaceController.java b/src/main/java/seng302/controllers/RaceController.java index d0ea0d42..e5e95d59 100644 --- a/src/main/java/seng302/controllers/RaceController.java +++ b/src/main/java/seng302/controllers/RaceController.java @@ -25,7 +25,7 @@ public class RaceController { String teamsConfigFile = "/config/teams.xml"; try { - race = createRace(raceConfigFile, teamsConfigFile); + race = createRace(raceConfigFile, teamsConfigFile); //These config files arent actually used } catch (Exception e) { System.out.println("There was an error creating the race."); } diff --git a/src/main/java/seng302/controllers/RaceViewController.java b/src/main/java/seng302/controllers/RaceViewController.java index aa09d9d1..22c96f13 100644 --- a/src/main/java/seng302/controllers/RaceViewController.java +++ b/src/main/java/seng302/controllers/RaceViewController.java @@ -2,13 +2,14 @@ package seng302.controllers; import javafx.animation.KeyFrame; import javafx.animation.Timeline; -import javafx.beans.value.ChangeListener; -import javafx.beans.value.ObservableValue; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.CheckBox; +import javafx.scene.control.ComboBox; import javafx.scene.control.Slider; import javafx.scene.layout.AnchorPane; import javafx.scene.layout.Pane; @@ -50,6 +51,8 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel @FXML private Button selectAnnotationBtn; @FXML + private ComboBox boatSelectionComboBox; + @FXML private CanvasController includedCanvasController; private ArrayList startingBoats = new ArrayList<>(); @@ -57,26 +60,27 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel private Timeline timerTimeline; private Race race; private Stage stage; + private ImportantAnnotationsState importantAnnotations; + private Yacht selectedBoat; public void initialize() { // Load a default important annotation state importantAnnotations = new ImportantAnnotationsState(); + //Initialise race controller RaceController raceController = new RaceController(); raceController.initializeRace(); race = raceController.getRace(); - for (Yacht boat : race.getBoats()) { - startingBoats.add(boat); - } + startingBoats = new ArrayList<>(Arrays.asList(race.getBoats())); includedCanvasController.setup(this); includedCanvasController.initializeCanvas(); - initializeTimer(); - initializeSettings(); - initialiseWindDirection(); - initialisePositionVBox(); + initializeUpdateTimer(); + initialiseFPSCheckBox(); + initialiseAnnotationSlider(); + initialiseBoatSelectionComboBox(); includedCanvasController.timer.start(); selectAnnotationBtn.setOnAction(event -> { @@ -86,7 +90,6 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel /** * The important annotations have been changed, update this view - * * @param importantAnnotationsState The current state of the selected annotations */ public void importantAnnotationsChanged(ImportantAnnotationsState importantAnnotationsState) { @@ -110,7 +113,7 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel // Load FXML and set CSS fxmlLoader .setLocation(getClass().getResource("/views/importantAnnotationSelectView.fxml")); - Scene scene = new Scene(fxmlLoader.load(), 469, 270); + Scene scene = new Scene(fxmlLoader.load(), 469, 248); scene.getStylesheets().add(getClass().getResource("/css/master.css").toString()); stage.initStyle(StageStyle.UNDECORATED); @@ -124,18 +127,14 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel } } - private void initializeSettings() { + + private void initialiseFPSCheckBox() { displayFps = true; + toggleFps.selectedProperty().addListener( + (observable, oldValue, newValue) -> displayFps = !displayFps); + } - toggleFps.selectedProperty().addListener(new ChangeListener() { - @Override - public void changed(ObservableValue observable, Boolean oldValue, - Boolean newValue) { - displayFps = !displayFps; - } - }); - - //SLIDER STUFF BELOW + private void initialiseAnnotationSlider() { annotationSlider.setLabelFormatter(new StringConverter() { @Override public String toString(Double n) { @@ -143,12 +142,9 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel return "None"; } if (n == 1) { - return "Low"; - } - if (n == 2) { return "Important"; } - if (n == 3) { + if (n == 2) { return "All"; } @@ -160,15 +156,13 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel switch (s) { case "None": return 0d; - case "Low": - return 1d; case "Important": - return 2d; + return 1d; case "All": - return 3d; + return 2d; default: - return 3d; + return 2d; } } }); @@ -176,22 +170,27 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel annotationSlider.valueProperty().addListener((obs, oldval, newVal) -> setAnnotations((int) annotationSlider.getValue())); - annotationSlider.setValue(3); + annotationSlider.setValue(2); } - private void initializeTimer() { + + /** + * Initalises a timer which updates elements of the RaceView such as wind direction, boat + * orderings etc.. which are dependent on the info from the stream parser constantly. + * Updates of each of these attributes are called ONCE EACH SECOND + */ + private void initializeUpdateTimer() { timerTimeline = new Timeline(); timerTimeline.setCycleCount(Timeline.INDEFINITE); // Run timer update every second timerTimeline.getKeyFrames().add( new KeyFrame(Duration.seconds(1), event -> { - if (StreamParser.isRaceFinished()) { - timerLabel.setFill(Color.RED); - timerLabel.setText("Race Finished!"); - } else { - timerLabel.setText(currentTimer()); - } + updateRaceTime(); + updateWindDirection(); + updateOrder(); + updateBoatSelectionComboBox(); + }) ); @@ -199,54 +198,45 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel timerTimeline.playFromStart(); } - private void initialiseWindDirection() { - Timeline windDirTimeline = new Timeline(); - windDirTimeline.setCycleCount(Timeline.INDEFINITE); - windDirTimeline.getKeyFrames().add( - new KeyFrame(Duration.seconds(1), - event -> { - windDirectionText - .setText(String.format("%.1f°", StreamParser.getWindDirection())); - windArrowText.setRotate(StreamParser.getWindDirection()); - }) - ); - windDirTimeline.playFromStart(); - } - - private void initialisePositionVBox() { - - Timeline posVBoxTimeline = new Timeline(); - posVBoxTimeline.setCycleCount(Timeline.INDEFINITE); - posVBoxTimeline.getKeyFrames().add( - new KeyFrame(Duration.seconds(1), - event -> { - showOrder(); - }) - ); - posVBoxTimeline.playFromStart(); - - } /** - * Display the list of boats in the order they finished the race + * Updates the wind direction arrow and text as from info from the StreamParser */ - private void loadRaceResultView() { - FXMLLoader loader = new FXMLLoader(getClass().getResource("/views/FinishView.fxml")); - loader.setController(new RaceResultController(race)); + private void updateWindDirection() { + windDirectionText.setText(String.format("%.1f°", StreamParser.getWindDirection())); + windArrowText.setRotate(StreamParser.getWindDirection()); + } - try { - contentAnchorPane.getChildren().removeAll(); - contentAnchorPane.getChildren().clear(); - contentAnchorPane.getChildren().addAll((Pane) loader.load()); - } catch (javafx.fxml.LoadException e) { - System.err.println(e.getCause()); - } catch (IOException e) { - System.err.println(e); + /** + * Updates the clock for the race + */ + private void updateRaceTime() { + if (StreamParser.isRaceFinished()) { + timerLabel.setFill(Color.RED); + timerLabel.setText("Race Finished!"); + } else { + timerLabel.setText(getTimeSinceStartOfRace()); } } - private void showOrder() { + + /** + * Grabs the boats currently in the race as from the StreamParser and sets them to be selectable + * in the boat selection combo box + */ + private void updateBoatSelectionComboBox() { + ObservableList observableBoats = FXCollections + .observableArrayList(StreamParser.getBoatsPos().values()); + boatSelectionComboBox.setItems(observableBoats); + } + + + /** + * Updates the order of the boats as from the StreamParser and sets them in the boat order + * section + */ + private void updateOrder() { positionVbox.getChildren().clear(); positionVbox.getChildren().removeAll(); positionVbox.getStylesheets().add(getClass().getResource("/css/master.css").toString()); @@ -269,6 +259,44 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel } } + + /** + * Initialised the combo box with any boats currently in the race and adds the required listener + * for the combobox to take action upon selection + */ + private void initialiseBoatSelectionComboBox() { + updateBoatSelectionComboBox(); + boatSelectionComboBox.valueProperty().addListener((observable, oldValue, newValue) -> { + //This listener is fired whenever the combo box changes. This means when the values are updated + //We dont want to set the selected value if the values are updated but nothing clicked (null) + if (newValue != null && newValue != selectedBoat) { + Yacht thisYacht = (Yacht) newValue; + setSelectedBoat(thisYacht); + } + }); + } + + + /** + * Display the list of boats in the order they finished the race + */ + private void loadRaceResultView() { + FXMLLoader loader = new FXMLLoader(getClass().getResource("/views/FinishView.fxml")); + loader.setController(new RaceResultController(race)); + + try { + contentAnchorPane.getChildren().removeAll(); + contentAnchorPane.getChildren().clear(); + contentAnchorPane.getChildren().addAll((Pane) loader.load()); + + } catch (javafx.fxml.LoadException e) { + System.err.println(e.getCause()); + } catch (IOException e) { + System.err.println(e); + } + } + + /** * Convert seconds to a string of the format mm:ss * @@ -282,7 +310,7 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel return String.format("%02d:%02d", time / 60, time % 60); } - private String currentTimer() { + private String getTimeSinceStartOfRace() { String timerString = "0:00"; if (StreamParser.getTimeSinceStart() > 0) { String timerMinute = Long.toString(StreamParser.getTimeSinceStart() / 60); @@ -302,13 +330,6 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel return timerString; } - public void stopTimer() { - timerTimeline.stop(); - } - - public void startTimer() { - timerTimeline.play(); - } public boolean isDisplayFps() { return displayFps; @@ -318,13 +339,9 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel return race; } - public ArrayList getStartingBoats() { - return startingBoats; - } /** * Display the important annotations for a specific BoatGroup - * * @param bg The boat group to set the annotations for */ private void setBoatGroupImportantAnnotations(BoatGroup bg) { @@ -381,22 +398,8 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel } } break; - // Low Annotations - case 1: - for (RaceObject ro : includedCanvasController.getRaceObjects()) { - if (ro instanceof BoatGroup) { - BoatGroup bg = (BoatGroup) ro; - bg.setTeamNameObjectVisible(true); - bg.setVelocityObjectVisible(false); - bg.setEstTimeToNextMarkObjectVisible(false); - bg.setLegTimeObjectVisible(false); - bg.setLineGroupVisible(false); - bg.setWakeVisible(false); - } - } - break; // Important Annotations - case 2: + case 1: for (RaceObject ro : includedCanvasController.getRaceObjects()) { if (ro instanceof BoatGroup) { BoatGroup bg = (BoatGroup) ro; @@ -405,7 +408,7 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel } break; // All Annotations - case 3: + case 2: for (RaceObject ro : includedCanvasController.getRaceObjects()) { if (ro instanceof BoatGroup) { BoatGroup bg = (BoatGroup) ro; @@ -421,6 +424,28 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel } } + + /** + * Sets all the annotations of the selected boat to be visible and all others to be hidden + * + * @param yacht The yacht for which we want to view all annotations + */ + private void setSelectedBoat(Yacht yacht) { + for (RaceObject ro : includedCanvasController.getRaceObjects()) { + if (ro instanceof BoatGroup) { + BoatGroup bg = (BoatGroup) ro; + //We need to iterate over all race groups to get the matching boat group belonging to this boat if we + //are to toggle its annotations, there is no other backwards knowledge of a yacht to its boatgroup. + if (bg.getBoat().getHullID().equals(yacht.getHullID())) { + bg.setIsSelected(true); + selectedBoat = yacht; + } else { + bg.setIsSelected(false); + } + } + } + } + void setStage(Stage stage) { this.stage = stage; } diff --git a/src/main/java/seng302/models/BoatGroup.java b/src/main/java/seng302/models/BoatGroup.java index e07c57ee..bea2f04b 100644 --- a/src/main/java/seng302/models/BoatGroup.java +++ b/src/main/java/seng302/models/BoatGroup.java @@ -49,6 +49,7 @@ public class BoatGroup extends RaceObject { private Text estTimeToNextMarkObject; private Text legTimeObject; private Wake wake; + private boolean isSelected = true; //Boats annotations are visible by default at the start //Handles boat moving when connecting to a stream private boolean setToInitialLocation = false; private boolean destinationSet; @@ -61,8 +62,8 @@ public class BoatGroup extends RaceObject { /** * Creates a BoatGroup with the default triangular boat polygon. * - * @param boat The boat that the BoatGroup will represent. Must contain an ID which will be used - * to tell which BoatGroup to update. + * @param boat The boat that the BoatGroup will represent. Must contain an ID which will be used + * to tell which BoatGroup to update. * @param color The colour of the boat polygon and the trailing line. */ public BoatGroup(Yacht boat, Color color) { @@ -74,11 +75,11 @@ public class BoatGroup extends RaceObject { * Creates a BoatGroup with the boat being the default polygon. The head of the boat should be * at point (0,0). * - * @param boat The boat that the BoatGroup will represent. Must contain an ID which will be used - * to tell which BoatGroup to update. - * @param color The colour of the boat polygon and the trailing line. + * @param boat The boat that the BoatGroup will represent. Must contain an ID which will be used + * to tell which BoatGroup to update. + * @param color The colour of the boat polygon and the trailing line. * @param points An array of co-ordinates x1,y1,x2,y2,x3,y3... that will make up the boat - * polygon. + * polygon. */ public BoatGroup(Yacht boat, Color color, double... points) { this.boat = boat; @@ -88,23 +89,26 @@ public class BoatGroup extends RaceObject { /** * Creates the javafx objects that will be the in the group by default. * - * @param color The colour of the boat polygon and the trailing line. + * @param color The colour of the boat polygon and the trailing line. * @param points An array of co-ordinates x1,y1,x2,y2,x3,y3... that will make up the boat - * polygon. + * polygon. */ private void initChildren(Color color, double... points) { boatPoly = new Polygon(points); boatPoly.setFill(color); + boatPoly.setOnMouseEntered(event -> boatPoly.setFill(Color.FLORALWHITE)); + boatPoly.setOnMouseExited(event -> boatPoly.setFill(color)); + boatPoly.setOnMouseClicked(event -> setIsSelected(!isSelected)); teamNameObject = new Text(boat.getShortName()); velocityObject = new Text(String.valueOf(boat.getVelocity())); DateFormat format = new SimpleDateFormat("mm:ss"); String timeToNextMark = format - .format(boat.getEstimateTimeAtNextMark() - StreamParser.getCurrentTimeLong()); + .format(boat.getEstimateTimeAtNextMark() - StreamParser.getCurrentTimeLong()); estTimeToNextMarkObject = new Text("Next mark: " + timeToNextMark); if (boat.getMarkRoundingTime() != null) { String elapsedTime = format - .format(StreamParser.getCurrentTimeLong() - boat.getMarkRoundingTime()); + .format(StreamParser.getCurrentTimeLong() - boat.getMarkRoundingTime()); legTimeObject = new Text("Last mark: " + elapsedTime); } else { legTimeObject = new Text("Last mark: -"); @@ -122,7 +126,7 @@ public class BoatGroup extends RaceObject { estTimeToNextMarkObject.setX(ESTTIMETONEXTMARK_X_OFFSET); estTimeToNextMarkObject.setY(ESTTIMETONEXTMARK_Y_OFFSET); estTimeToNextMarkObject - .relocate(estTimeToNextMarkObject.getX(), estTimeToNextMarkObject.getY()); + .relocate(estTimeToNextMarkObject.getX(), estTimeToNextMarkObject.getY()); legTimeObject.setX(LEGTIME_X_OFFSET); legTimeObject.setY(LEGTIME_Y_OFFSET); @@ -130,8 +134,8 @@ public class BoatGroup extends RaceObject { wake = new Wake(0, -BOAT_HEIGHT); super.getChildren() - .addAll(teamNameObject, velocityObject, boatPoly, estTimeToNextMarkObject, - legTimeObject); + .addAll(teamNameObject, velocityObject, boatPoly, estTimeToNextMarkObject, + legTimeObject); } /** @@ -141,9 +145,9 @@ public class BoatGroup extends RaceObject { */ private void initChildren(Color color) { initChildren(color, - -BOAT_WIDTH / 2, BOAT_HEIGHT / 2, - 0.0, -BOAT_HEIGHT / 2, - BOAT_WIDTH / 2, BOAT_HEIGHT / 2); + -BOAT_WIDTH / 2, BOAT_HEIGHT / 2, + 0.0, -BOAT_HEIGHT / 2, + BOAT_WIDTH / 2, BOAT_HEIGHT / 2); } /** @@ -172,8 +176,8 @@ public class BoatGroup extends RaceObject { /** * Moves the boat and its children annotations to coordinates specified * - * @param x The X coordinate to move the boat to - * @param y The Y coordinate to move the boat to + * @param x The X coordinate to move the boat to + * @param y The Y coordinate to move the boat to * @param rotation The heading in degrees from north the boat should rotate to. */ public void moveTo(double x, double y, double rotation) { @@ -207,7 +211,7 @@ public class BoatGroup extends RaceObject { * Updates the position of all graphics in the BoatGroup based off of the given time interval. * * @param timeInterval The interval, in milliseconds, the boat should update it's position based - * on. + * on. */ public void updatePosition(long timeInterval) { //Calculate the movement of the boat. @@ -222,13 +226,13 @@ public class BoatGroup extends RaceObject { distanceTravelled = 0; if (lastPoint != null) { Line l = new Line( - lastPoint.getX(), - lastPoint.getY(), - boatPoly.getLayoutX(), - boatPoly.getLayoutY() + lastPoint.getX(), + lastPoint.getY(), + boatPoly.getLayoutX(), + boatPoly.getLayoutY() ); l.getStrokeDashArray().setAll(3d, 7d); - l.setStroke(boatPoly.getFill()); + l.setStroke(boat.getColour()); lineGroup.getChildren().add(l); } if (destinationSet) { //Only begin drawing after the first destination is set @@ -244,11 +248,11 @@ public class BoatGroup extends RaceObject { * * @param newXValue The X co-ordinate the boat needs to move to. * @param newYValue The Y co-ordinate the boat needs to move to. - * @param rotation Rotation to move graphics to. - * @param raceIds RaceID of the object to move. + * @param rotation Rotation to move graphics to. + * @param raceIds RaceID of the object to move. */ public void setDestination(double newXValue, double newYValue, double rotation, - double groundSpeed, int... raceIds) { + double groundSpeed, int... raceIds) { if (hasRaceId(raceIds)) { if (setToInitialLocation) { destinationSet = true; @@ -277,18 +281,18 @@ public class BoatGroup extends RaceObject { wakeGenerationDelay--; } else { wake.setRotationalVelocity(rotationalVelocity, rotationalGoal, - boat.getVelocity()); + boat.getVelocity()); } velocityObject.setText(String.format("%.2f m/s", boat.getVelocity())); DateFormat format = new SimpleDateFormat("mm:ss"); // estimate time to next mark String timeToNextMark = format - .format(boat.getEstimateTimeAtNextMark() - StreamParser.getCurrentTimeLong()); + .format(boat.getEstimateTimeAtNextMark() - StreamParser.getCurrentTimeLong()); estTimeToNextMarkObject.setText("Next mark: " + timeToNextMark); // elapsed time if (boat.getMarkRoundingTime() != null) { String elapsedTime = format - .format(StreamParser.getCurrentTimeLong() - boat.getMarkRoundingTime()); + .format(StreamParser.getCurrentTimeLong() - boat.getMarkRoundingTime()); legTimeObject.setText("Last mark: " + elapsedTime); } else { legTimeObject.setText("Last mark: -"); @@ -307,10 +311,10 @@ public class BoatGroup extends RaceObject { setCallCount = 5; if (lastPoint != null) { Line l = new Line( - lastPoint.getX(), - lastPoint.getY(), - newXValue, - newYValue + lastPoint.getX(), + lastPoint.getY(), + newXValue, + newYValue ); l.getStrokeDashArray().setAll(3d, 7d); l.setStroke(boatPoly.getFill()); @@ -324,16 +328,16 @@ public class BoatGroup extends RaceObject { } public void setDestination(double newXValue, double newYValue, double groundSpeed, - int... raceIDs) { + int... raceIDs) { destinationSet = true; if (hasRaceId(raceIDs)) { double rotation = Math.abs( - Math.toDegrees( - Math.atan( - (newYValue - boatPoly.getLayoutY()) / (newXValue - boatPoly.getLayoutX()) + Math.toDegrees( + Math.atan( + (newYValue - boatPoly.getLayoutY()) / (newXValue - boatPoly.getLayoutX()) + ) ) - ) ); setDestination(newXValue, newYValue, rotation, groundSpeed, raceIDs); } @@ -349,6 +353,10 @@ public class BoatGroup extends RaceObject { wake.rotate(rotationalGoal); } + public void paintBoat(Color color) { + boatPoly.setFill(color); + } + public void setTeamNameObjectVisible(Boolean visible) { teamNameObject.setVisible(visible); } @@ -377,6 +385,24 @@ public class BoatGroup extends RaceObject { return boat; } + /** + * This function sets the boats isSelected property AS WELL as actually acting upon the value of + * that selection. (Painting or not painting annotations) + * + * @param isSelected A Boolean indicating whether or not the boat is selected + */ + public void setIsSelected(Boolean isSelected) { + this.isSelected = isSelected; + setTeamNameObjectVisible(isSelected); + setVelocityObjectVisible(isSelected); + setLineGroupVisible(isSelected); + setWakeVisible(isSelected); + setEstTimeToNextMarkObjectVisible(isSelected); + setLegTimeObjectVisible(isSelected); + // TODO: 17/05/17 wmu16 - this should iterate over some list of annotations which we should make to easily make extensible +// paintBoat((isSelected) ? Color.WHITE : boat.getColour()); + } + /** * Returns true if this BoatGroup contains at least one of the given IDs. * @@ -435,4 +461,9 @@ public class BoatGroup extends RaceObject { } }); } + + @Override + public String toString() { + return boat.toString(); + } } diff --git a/src/main/java/seng302/models/Yacht.java b/src/main/java/seng302/models/Yacht.java index e21384f9..23ba616a 100644 --- a/src/main/java/seng302/models/Yacht.java +++ b/src/main/java/seng302/models/Yacht.java @@ -166,4 +166,9 @@ public class Yacht { public void setMarkRoundingTime(Long markRoundingTime) { this.markRoundingTime = markRoundingTime; } + + @Override + public String toString() { + return boatName; + } } diff --git a/src/main/java/seng302/models/mark/MarkGroup.java b/src/main/java/seng302/models/mark/MarkGroup.java index 29931e01..d58f3b78 100644 --- a/src/main/java/seng302/models/mark/MarkGroup.java +++ b/src/main/java/seng302/models/mark/MarkGroup.java @@ -1,6 +1,7 @@ package seng302.models.mark; import javafx.geometry.Point2D; +import javafx.scene.CacheHint; import javafx.scene.Node; import javafx.scene.paint.Color; import javafx.scene.shape.Circle; diff --git a/src/main/java/seng302/models/parsers/StreamParser.java b/src/main/java/seng302/models/parsers/StreamParser.java index 63019c3d..ef35a7ff 100644 --- a/src/main/java/seng302/models/parsers/StreamParser.java +++ b/src/main/java/seng302/models/parsers/StreamParser.java @@ -24,7 +24,6 @@ import java.util.concurrent.PriorityBlockingQueue; * and parsed in by turning the byte arrays into useful data. There are two public static hashmaps * that are threadsafe so the visualiser can always access the latest speed and position available * Created by kre39 on 23/04/17. - * */ public class StreamParser extends Thread{ diff --git a/src/main/resources/css/master.css b/src/main/resources/css/master.css index 81661bfe..8223fc00 100644 --- a/src/main/resources/css/master.css +++ b/src/main/resources/css/master.css @@ -128,6 +128,24 @@ Table -fx-border-style: none; } + +/** +Combo Box + */ + +.combo-box-base { + -fx-background-color: #119796; + -fx-text-fill: white; +} + +.combo-box-popup .list-view .list-cell:hover { + -fx-text-fill: white; +} + +.combo-box .cell:selected { + -fx-text-fill: white; +} + /** Remove scroll bars */ diff --git a/src/main/resources/views/RaceView.fxml b/src/main/resources/views/RaceView.fxml index 32d6f710..cfb36f23 100644 --- a/src/main/resources/views/RaceView.fxml +++ b/src/main/resources/views/RaceView.fxml @@ -56,9 +56,11 @@ - +