- Stuck on animation timer not running #story[778]main
parent
a584400e24
commit
3326da4f5d
@ -1,33 +0,0 @@
|
||||
package seng302.Controllers;
|
||||
|
||||
import javafx.fxml.Initializable;
|
||||
import seng302.App;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
/**
|
||||
* Controller parent for app controllers.
|
||||
* Created by fwy13 on 15/03/2017.
|
||||
*/
|
||||
public abstract class Controller implements Initializable {
|
||||
protected MainController parent;
|
||||
|
||||
/**
|
||||
* Sets the parent of the application
|
||||
*
|
||||
* @param parent controller
|
||||
*/
|
||||
public void setParent(MainController parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialisation class that is run on start up.
|
||||
*
|
||||
* @param location resources location
|
||||
* @param resources resources bundle
|
||||
*/
|
||||
@Override
|
||||
public abstract void initialize(URL location, ResourceBundle resources);
|
||||
}
|
||||
@ -1,42 +0,0 @@
|
||||
package seng302.Controllers;
|
||||
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.SplitPane;
|
||||
import javafx.scene.layout.AnchorPane;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import seng302.RaceDataSource;
|
||||
import seng302.RaceXMLReader;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
/**
|
||||
* Created by fwy13 on 15/03/2017.
|
||||
*/
|
||||
public class MainController extends Controller {
|
||||
@FXML StartController startController;
|
||||
@FXML RaceController raceController;
|
||||
|
||||
public void beginRace(int scaleFactor, RaceDataSource raceData) {
|
||||
raceController.startRace(scaleFactor, raceData);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Main Controller for the applications will house the menu and the displayed pane.
|
||||
*
|
||||
* @param location of resources
|
||||
* @param resources bundle
|
||||
*/
|
||||
@Override
|
||||
public void initialize(URL location, ResourceBundle resources) {
|
||||
startController.setParent(this);
|
||||
raceController.setParent(this);
|
||||
AnchorPane.setTopAnchor(startController.startWrapper(), 0.0);
|
||||
AnchorPane.setBottomAnchor(startController.startWrapper(), 0.0);
|
||||
AnchorPane.setLeftAnchor(startController.startWrapper(), 0.0);
|
||||
AnchorPane.setRightAnchor(startController.startWrapper(), 0.0);
|
||||
}
|
||||
}
|
||||
@ -1,227 +0,0 @@
|
||||
package seng302.Controllers;
|
||||
|
||||
|
||||
import javafx.beans.property.ReadOnlyObjectWrapper;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import org.xml.sax.SAXException;
|
||||
import seng302.Model.*;
|
||||
import seng302.RaceDataSource;
|
||||
import seng302.RaceXMLReader;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
/**
|
||||
* Created by fwy13 on 15/03/2017.
|
||||
*/
|
||||
public class RaceController extends Controller {
|
||||
@FXML
|
||||
GridPane canvasBase;
|
||||
|
||||
//user saved data for annotation display
|
||||
private ArrayList<Boolean> presetAnno;
|
||||
|
||||
ResizableRaceCanvas raceMap;
|
||||
@FXML
|
||||
SplitPane race;
|
||||
@FXML
|
||||
CheckBox showFPS;
|
||||
|
||||
@FXML
|
||||
CheckBox showBoatPath;
|
||||
@FXML
|
||||
CheckBox showAnnotations;
|
||||
@FXML
|
||||
Label timer;
|
||||
@FXML
|
||||
Label FPS;
|
||||
@FXML
|
||||
Label timeZone;
|
||||
|
||||
@FXML
|
||||
CheckBox showName;
|
||||
@FXML
|
||||
CheckBox showAbbrev;
|
||||
@FXML
|
||||
CheckBox showSpeed;
|
||||
@FXML
|
||||
Button saveAnno;
|
||||
@FXML
|
||||
Button showSetAnno;
|
||||
|
||||
@FXML
|
||||
TableView<BoatInRace> boatInfoTable;
|
||||
@FXML
|
||||
TableColumn<BoatInRace, String> boatPlacingColumn;
|
||||
@FXML
|
||||
TableColumn<BoatInRace, String> boatTeamColumn;
|
||||
@FXML
|
||||
TableColumn<BoatInRace, String> boatMarkColumn;
|
||||
@FXML
|
||||
TableColumn<BoatInRace, String> boatSpeedColumn;
|
||||
|
||||
/**
|
||||
* Updates the ResizableRaceCanvas (raceMap) with most recent data
|
||||
*
|
||||
* @param boats boats that are to be displayed in the race
|
||||
* @see ResizableRaceCanvas
|
||||
*/
|
||||
public void updateMap(ObservableList<BoatInRace> boats) {
|
||||
raceMap.setBoats(boats);
|
||||
raceMap.update();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the array listened by the TableView (boatInfoTable) that displays the boat information.
|
||||
*
|
||||
* @param race Race to listen to.
|
||||
*/
|
||||
public void setInfoTable(Race race) {
|
||||
//boatInfoTable.getItems().clear();
|
||||
boatInfoTable.setItems(race.getStartingBoats());
|
||||
|
||||
boatTeamColumn.setCellValueFactory(cellData -> cellData.getValue().getName());
|
||||
boatSpeedColumn.setCellValueFactory(cellData -> cellData.getValue().getVelocityProp());
|
||||
boatMarkColumn.setCellValueFactory(cellData -> cellData.getValue().getCurrentLegName());
|
||||
boatPlacingColumn.setCellValueFactory(cellData -> cellData.getValue().positionProperty());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void initialize(URL location, ResourceBundle resources) {
|
||||
//listener for fps
|
||||
showFPS.selectedProperty().addListener((ov, old_val, new_val) -> {
|
||||
if (showFPS.isSelected()) {
|
||||
FPS.setVisible(true);
|
||||
} else {
|
||||
FPS.setVisible(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes and runs the race, based on the user's chosen scale factor
|
||||
* Currently uses an example racecourse
|
||||
*
|
||||
* @param scaleFactor scale value of race
|
||||
*/
|
||||
public void startRace(int scaleFactor, RaceDataSource raceData) {
|
||||
ConstantVelocityRace newRace = new ConstantVelocityRace(raceData, this, scaleFactor);
|
||||
newRace.initialiseBoats();
|
||||
|
||||
raceMap = new ResizableRaceCanvas(raceData);
|
||||
raceMap.setMouseTransparent(true);
|
||||
raceMap.widthProperty().bind(canvasBase.widthProperty());
|
||||
raceMap.heightProperty().bind(canvasBase.heightProperty());
|
||||
raceMap.setBoats(newRace.getStartingBoats());
|
||||
raceMap.setRaceBoundaries(raceData.getBoundary());
|
||||
raceMap.drawRaceMap();
|
||||
raceMap.setVisible(true);
|
||||
|
||||
canvasBase.getChildren().add(raceMap);
|
||||
race.setVisible(true);
|
||||
|
||||
//Initialize save annotation array, fps listener, and annotation listeners
|
||||
//timezone
|
||||
RaceClock raceClock = new RaceClock(raceData.getMark());
|
||||
timeZone.setText(raceClock.getTimeZone());
|
||||
initializeFPS();
|
||||
initializeAnnotations();
|
||||
|
||||
new Thread((newRace)).start();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the value for the race clock label
|
||||
*
|
||||
* @param time time that the label will be updated to
|
||||
*/
|
||||
public void setTimer(String time) {
|
||||
timer.setText(time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value for the fps label
|
||||
*
|
||||
* @param fps fps that the label will be updated to
|
||||
*/
|
||||
public void setFrames(String fps) {
|
||||
FPS.setText((fps));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up FPS display at bottom of screen
|
||||
*/
|
||||
private void initializeFPS() {
|
||||
showFPS.setVisible(true);
|
||||
showFPS.selectedProperty().addListener((ov, old_val, new_val) -> {
|
||||
if (showFPS.isSelected()) {
|
||||
FPS.setVisible(true);
|
||||
} else {
|
||||
FPS.setVisible(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up boat annotations
|
||||
*/
|
||||
private void initializeAnnotations() {
|
||||
presetAnno = new ArrayList<>();
|
||||
//listener for annotation
|
||||
showAnnotations.selectedProperty().addListener((ov, old_val, new_val) -> {
|
||||
raceMap.toggleAnnotations();
|
||||
raceMap.update();
|
||||
});
|
||||
//listener for show name in annotation
|
||||
showName.selectedProperty().addListener((ov, old_val, new_val) -> {
|
||||
raceMap.toggleAnnoName();
|
||||
raceMap.update();
|
||||
});
|
||||
//listener for show abbreviation for annotation
|
||||
showAbbrev.selectedProperty().addListener((ov, old_val, new_val) -> {
|
||||
raceMap.toggleAnnoAbbrev();
|
||||
raceMap.update();
|
||||
});
|
||||
|
||||
//listener for show boat path for annotation
|
||||
showBoatPath.selectedProperty().addListener((ov, old_val, new_val) -> {
|
||||
raceMap.toggleBoatPath();
|
||||
raceMap.update();
|
||||
});
|
||||
//listener to show speed for annotation
|
||||
showSpeed.selectedProperty().addListener((ov, old_val, new_val) -> {
|
||||
raceMap.toggleAnnoSpeed();
|
||||
raceMap.update();
|
||||
});
|
||||
//listener to save currently selected annotation
|
||||
saveAnno.setOnAction(event -> {
|
||||
presetAnno.clear();
|
||||
presetAnno.add(showName.isSelected());
|
||||
presetAnno.add(showAbbrev.isSelected());
|
||||
presetAnno.add(showSpeed.isSelected());
|
||||
presetAnno.add(showBoatPath.isSelected());
|
||||
});
|
||||
//listener to show saved annotation
|
||||
showSetAnno.setOnAction(event -> {
|
||||
if (presetAnno.size() > 0) {
|
||||
showName.setSelected(presetAnno.get(0));
|
||||
showAbbrev.setSelected(presetAnno.get(1));
|
||||
showSpeed.setSelected(presetAnno.get(2));
|
||||
showBoatPath.setSelected(presetAnno.get(3));
|
||||
raceMap.update();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -1,159 +0,0 @@
|
||||
package seng302.Controllers;
|
||||
|
||||
import javafx.animation.AnimationTimer;
|
||||
import javafx.application.Platform;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.TableColumn;
|
||||
import javafx.scene.control.TableView;
|
||||
import javafx.scene.control.cell.PropertyValueFactory;
|
||||
import javafx.scene.layout.AnchorPane;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import org.xml.sax.SAXException;
|
||||
import seng302.Model.BoatInRace;
|
||||
import seng302.Model.RaceClock;
|
||||
import seng302.RaceDataSource;
|
||||
import seng302.RaceXMLReader;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
/**
|
||||
* Created by esa46 on 6/04/17.
|
||||
*/
|
||||
public class StartController extends Controller {
|
||||
|
||||
@FXML private GridPane start;
|
||||
@FXML private AnchorPane startWrapper;
|
||||
|
||||
@FXML private TableView<BoatInRace> boatNameTable;
|
||||
@FXML private TableColumn<BoatInRace, String> boatNameColumn;
|
||||
@FXML private TableColumn<BoatInRace, String> boatCodeColumn;
|
||||
@FXML private Label timeZoneTime;
|
||||
@FXML private Label timer;
|
||||
@FXML private int PRERACE_TIME = 15000;
|
||||
|
||||
@FXML Button oneMinButton;
|
||||
@FXML Button fiveMinButton;
|
||||
@FXML Button fifteenMinButton;
|
||||
|
||||
private RaceClock raceClock;
|
||||
|
||||
private RaceDataSource raceData;
|
||||
|
||||
/**
|
||||
* Begins the race with a scale factor of 15
|
||||
*/
|
||||
public void startRace1Min() {
|
||||
startRace(15);
|
||||
}
|
||||
|
||||
/**
|
||||
* Begins the race with a scale factor of 3
|
||||
*/
|
||||
public void startRace5Min() {
|
||||
startRace(3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Begins the race with a scale factor of 1
|
||||
*/
|
||||
public void startRaceNoScaling() {
|
||||
startRace(1);
|
||||
}
|
||||
|
||||
private void startRace(int raceScale){
|
||||
|
||||
oneMinButton.setDisable(true);
|
||||
fiveMinButton.setDisable(true);
|
||||
fifteenMinButton.setDisable(true);
|
||||
countdownTimer(raceScale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(URL location, ResourceBundle resources){
|
||||
raceData = null;
|
||||
try {
|
||||
raceData = new RaceXMLReader("raceXML/bermuda_AC35.xml");
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (SAXException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ParserConfigurationException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
initialiseTables();
|
||||
}
|
||||
|
||||
public AnchorPane startWrapper(){
|
||||
return startWrapper;
|
||||
}
|
||||
|
||||
private void initialiseTables() {
|
||||
List<BoatInRace> boats = raceData.getBoats();
|
||||
ObservableList<BoatInRace> observableBoats = FXCollections.observableArrayList(boats);
|
||||
|
||||
boatNameTable.setItems(observableBoats);
|
||||
boatNameColumn.setCellValueFactory(cellData -> cellData.getValue().getName());
|
||||
boatCodeColumn.setCellValueFactory(new PropertyValueFactory<>("abbrev"));
|
||||
//timezone
|
||||
raceClock = new RaceClock(raceData.getMark());
|
||||
timeZoneTime.textProperty().bind(raceClock.timeProperty());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Updates the calculated time to the timer label
|
||||
*
|
||||
* @param time The calculated time from calcTimer() method
|
||||
*/
|
||||
protected void updateTime(String time) {
|
||||
Platform.runLater(() -> {
|
||||
timer.setText(time);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Countdown timer until race starts. Use PRERACE_TIME to set countdown duration.
|
||||
*/
|
||||
protected void countdownTimer(int scaleFactor) {
|
||||
new AnimationTimer() {
|
||||
long currentTime = System.currentTimeMillis();
|
||||
long startTime = currentTime + (PRERACE_TIME/scaleFactor);
|
||||
long minutes;
|
||||
long currentTimeInSeconds;
|
||||
long remainingSeconds;
|
||||
long hours;
|
||||
long timeLeft;
|
||||
|
||||
@Override
|
||||
public void handle(long arg0) {
|
||||
timeLeft = startTime - currentTime;
|
||||
if (timeLeft <= 0) {
|
||||
updateTime("Race is starting...");
|
||||
stop();
|
||||
parent.beginRace(scaleFactor, raceData);
|
||||
startWrapper.setVisible(false);
|
||||
|
||||
} else {
|
||||
currentTimeInSeconds = (timeLeft*scaleFactor) / 1000;
|
||||
minutes = currentTimeInSeconds / 60;
|
||||
remainingSeconds = currentTimeInSeconds % 60;
|
||||
hours = minutes / 60;
|
||||
minutes = minutes % 60;
|
||||
updateTime(String.format("Race Clock: -%02d:%02d:%02d", hours, minutes, remainingSeconds));
|
||||
raceClock.updateTime();
|
||||
|
||||
}
|
||||
currentTime = System.currentTimeMillis();
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,40 +0,0 @@
|
||||
package seng302;
|
||||
|
||||
/**
|
||||
* Graph Coordinate that is to be displayed on the Canvas
|
||||
* Created by cbt24 on 15/03/17.
|
||||
*/
|
||||
public class GraphCoordinate {
|
||||
private int x;
|
||||
private int y;
|
||||
|
||||
/**
|
||||
* Constructor method.
|
||||
*
|
||||
* @param x X coordinate.
|
||||
* @param y Y coordinate.
|
||||
*/
|
||||
public GraphCoordinate(int x, int y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the X coordinate.
|
||||
*
|
||||
* @return x axis Coordinate.
|
||||
*/
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Y coordinate.
|
||||
*
|
||||
* @return y axis Coordinate.
|
||||
*/
|
||||
public int getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,410 +0,0 @@
|
||||
package seng302.Model;
|
||||
|
||||
|
||||
import javafx.scene.canvas.Canvas;
|
||||
import javafx.scene.canvas.GraphicsContext;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.paint.Paint;
|
||||
import javafx.scene.transform.Rotate;
|
||||
import seng302.*;
|
||||
import seng302.Controllers.RaceController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This creates a JavaFX Canvas that is fills it's parent.
|
||||
* Cannot be downsized.
|
||||
* Created by fwy13 on 17/03/17.
|
||||
*/
|
||||
public class ResizableRaceCanvas extends Canvas {
|
||||
private GraphicsContext gc;
|
||||
private RaceMap map;
|
||||
private List<BoatInRace> boats;
|
||||
private boolean raceAnno = true;
|
||||
private boolean annoName = true;
|
||||
private boolean annoAbbrev = true;
|
||||
private boolean annoSpeed = true;
|
||||
private boolean annoPath = true;
|
||||
private ArrayList<GPSCoordinate> raceBoundaries;
|
||||
double[] xpoints = {}, ypoints = {};
|
||||
|
||||
public ResizableRaceCanvas(RaceDataSource raceData) {
|
||||
gc = this.getGraphicsContext2D();
|
||||
// Redraw canvas when size changes.
|
||||
widthProperty().addListener(evt -> drawRaceMap());
|
||||
heightProperty().addListener(evt -> drawRaceMap());
|
||||
|
||||
double lat1 = raceData.getMapTopLeft().getLatitude();
|
||||
double long1 = raceData.getMapTopLeft().getLongitude();
|
||||
double lat2 = raceData.getMapBottomRight().getLatitude();
|
||||
double long2 = raceData.getMapBottomRight().getLongitude();
|
||||
setMap(new RaceMap(lat1, long1, lat2, long2, (int) getWidth(), (int) getHeight()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the boats that are to be displayed in this race.
|
||||
*
|
||||
* @param boats in race
|
||||
*/
|
||||
public void setBoats(List<BoatInRace> boats) {
|
||||
this.boats = boats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the RaceMap that the RaceCanvas is to be displaying for.
|
||||
*
|
||||
* @param map race map
|
||||
*/
|
||||
public void setMap(RaceMap map) {
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the mark of a race as a circle.
|
||||
*
|
||||
* @param graphCoordinate Latitude and Logintude in GraphCoordinate that it is to be displayed as.
|
||||
* @param paint Colour the mark is to be coloured.
|
||||
* @see GraphCoordinate
|
||||
* @see Color
|
||||
* @see Paint
|
||||
*/
|
||||
public void displayMark(GraphCoordinate graphCoordinate, Paint paint) {
|
||||
double d = 25;
|
||||
gc.setFill(paint);
|
||||
gc.fillOval(graphCoordinate.getX() - (d / 2), graphCoordinate.getY() - (d / 2), d, d);
|
||||
}
|
||||
|
||||
public void displayBoat(BoatInRace boat, double angle) {
|
||||
GraphCoordinate pos = this.map.convertGPS(boat.getCurrentPosition());
|
||||
Paint paint = boat.getColour();
|
||||
|
||||
double[] x = {pos.getX() - 6, pos.getX(), pos.getX() + 6};
|
||||
double[] y = {pos.getY() + 12, pos.getY() - 12, pos.getY() + 12};
|
||||
gc.setFill(paint);
|
||||
|
||||
gc.save();
|
||||
rotate(angle, pos.getX(), pos.getY());
|
||||
gc.fillPolygon(x, y, 3);
|
||||
gc.restore();
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a line on the map with rectangles on the starting and ending point of the line.
|
||||
*
|
||||
* @param graphCoordinateA Starting Point of the line in GraphCoordinate.
|
||||
* @param graphCoordinateB End Point of the line in GraphCoordinate.
|
||||
* @param paint Colour the line is to coloured.
|
||||
* @see GraphCoordinate
|
||||
* @see Color
|
||||
* @see Paint
|
||||
*/
|
||||
private void displayLine(GraphCoordinate graphCoordinateA, GraphCoordinate graphCoordinateB, Paint paint) {
|
||||
gc.setStroke(paint);
|
||||
gc.setFill(paint);
|
||||
gc.fillOval(graphCoordinateA.getX() - 3, graphCoordinateA.getY() - 3, 6, 6);
|
||||
gc.fillOval(graphCoordinateB.getX() - 3, graphCoordinateB.getY() - 3, 6, 6);
|
||||
gc.strokeLine(graphCoordinateA.getX(), graphCoordinateA.getY(), graphCoordinateB.getX(), graphCoordinateB.getY());
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a point on the Canvas
|
||||
*
|
||||
* @param graphCoordinate Coordinate that the point is to be displayed at.
|
||||
* @param paint Colour that the boat is to be coloured.
|
||||
* @see GraphCoordinate
|
||||
* @see Paint
|
||||
* @see Color
|
||||
*/
|
||||
private void displayPoint(GraphCoordinate graphCoordinate, Paint paint) {
|
||||
gc.setFill(paint);
|
||||
gc.fillOval(graphCoordinate.getX(), graphCoordinate.getY(), 10, 10);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Displays an arrow on the Canvas
|
||||
*
|
||||
* @param coordinate Coordinate that the arrow is to be displayed at.
|
||||
* @param angle Angle that the arrow is to be facing in degrees 0 degrees = North (Up).
|
||||
* @see GraphCoordinate
|
||||
*/
|
||||
private void displayArrow(GraphCoordinate coordinate, int angle) {
|
||||
gc.save();
|
||||
rotate(angle, coordinate.getX(), coordinate.getY());
|
||||
gc.setFill(Color.BLACK);
|
||||
gc.fillPolygon(new double[]{coordinate.getX() - 12, coordinate.getX() - 6, coordinate.getX(), coordinate.getX() - 4, coordinate.getX() - 4, coordinate.getX() - 8, coordinate.getX() - 8},
|
||||
new double[]{coordinate.getY() - 5, coordinate.getY() - 20, coordinate.getY() - 5, coordinate.getY() - 5, coordinate.getY() + 20, coordinate.getY() + 20, coordinate.getY() - 5},
|
||||
7);
|
||||
gc.restore();
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotates things on the canvas Note: this must be called in between gc.save() and gc.restore() else they will rotate everything
|
||||
*
|
||||
* @param angle Bearing angle to rotate at in degrees
|
||||
* @param px Pivot point x of rotation.
|
||||
* @param py Pivot point y of rotation.
|
||||
*/
|
||||
private void rotate(double angle, double px, double py) {
|
||||
Rotate r = new Rotate(angle, px, py);
|
||||
gc.setTransform(r.getMxx(), r.getMyx(), r.getMxy(), r.getMyy(), r.getTx(), r.getTy());
|
||||
}
|
||||
|
||||
/**
|
||||
* Display given name and speed of boat at a graph coordinate
|
||||
*
|
||||
* @param name name of the boat
|
||||
* @param abbrev abbreviation of the boat name
|
||||
* @param speed speed of the boat
|
||||
* @param coordinate coordinate the text appears
|
||||
*/
|
||||
private void displayText(String name, String abbrev, double speed, GraphCoordinate coordinate) {
|
||||
String text = "";
|
||||
//Check name toggle value
|
||||
if (annoName){
|
||||
text += String.format("%s ", name);
|
||||
}
|
||||
//Check abbreviation toggle value
|
||||
if (annoAbbrev){
|
||||
text += String.format("%s ", abbrev);
|
||||
}
|
||||
//Check speed toggle value
|
||||
if (annoSpeed){
|
||||
text += String.format("%.2fkn", speed);
|
||||
}
|
||||
//String text = String.format("%s, %2$.2fkn", name, speed);
|
||||
long xCoord = coordinate.getX() + 20;
|
||||
long yCoord = coordinate.getY();
|
||||
if (xCoord + (text.length() * 7) >= getWidth()) {
|
||||
xCoord -= text.length() * 7;
|
||||
}
|
||||
if (yCoord - (text.length() * 2) <= 0) {
|
||||
yCoord += 30;
|
||||
}
|
||||
gc.fillText(text, xCoord, yCoord);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws race map with up to date data.
|
||||
*/
|
||||
public void update() {
|
||||
this.drawRaceMap();
|
||||
this.updateBoats();
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw boundary of the race.
|
||||
*/
|
||||
public void drawBoundaries() {
|
||||
if (this.raceBoundaries == null) {
|
||||
return;
|
||||
}
|
||||
gc.setFill(Color.AQUA);
|
||||
setRaceBoundCoordinates();
|
||||
gc.fillPolygon(xpoints, ypoints, xpoints.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws the Race Map
|
||||
*/
|
||||
public void drawRaceMap() {
|
||||
|
||||
double width = getWidth();
|
||||
double height = getHeight();
|
||||
|
||||
gc.clearRect(0, 0, width, height);
|
||||
|
||||
if (map == null) {
|
||||
return;//TODO this should return a exception in the future
|
||||
}
|
||||
this.map.setHeight((int) height);
|
||||
this.map.setWidth((int) width);
|
||||
|
||||
//finish line
|
||||
gc.setLineWidth(2);
|
||||
drawBoundaries();
|
||||
GraphCoordinate finishLineCoord1 = this.map.convertGPS(Constants.finishLineMarker1);
|
||||
GraphCoordinate finishLineCoord2 = this.map.convertGPS(Constants.finishLineMarker2);
|
||||
displayLine(finishLineCoord1, finishLineCoord2, Color.DARKRED);
|
||||
//marks
|
||||
GraphCoordinate markCoord = this.map.convertGPS(Constants.mark1);
|
||||
GraphCoordinate windwardGate1 = this.map.convertGPS(Constants.windwardGate1);
|
||||
GraphCoordinate windwardGate2 = this.map.convertGPS(Constants.windwardGate2);
|
||||
GraphCoordinate leewardGate1 = this.map.convertGPS(Constants.leewardGate1);
|
||||
GraphCoordinate leewardGate2 = this.map.convertGPS(Constants.leewardGate2);
|
||||
displayMark(markCoord, Color.GOLD);
|
||||
displayLine(windwardGate1, windwardGate2, Color.DARKCYAN);
|
||||
displayLine(leewardGate1, leewardGate2, Color.DARKVIOLET);
|
||||
//start line
|
||||
GraphCoordinate startline1 = this.map.convertGPS(Constants.startLineMarker1);
|
||||
GraphCoordinate startline2 = this.map.convertGPS(Constants.startLineMarker2);
|
||||
|
||||
displayLine(startline1, startline2, Color.GREEN);
|
||||
|
||||
updateBoats();
|
||||
|
||||
//display wind direction arrow - specify origin point and angle - angle now set to random angle
|
||||
displayArrow(new GraphCoordinate((int) getWidth() - 40, 40), 150);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a boat at a certain GPSCoordinate
|
||||
*
|
||||
* @param colour Colour to colour boat.
|
||||
* @param gpsCoordinates GPScoordinate that the boat is to be drawn at.
|
||||
* @see GPSCoordinate
|
||||
* @see Color
|
||||
*/
|
||||
public void drawBoat(Color colour, GPSCoordinate gpsCoordinates) {
|
||||
GraphCoordinate graphCoordinate = this.map.convertGPS(gpsCoordinates);
|
||||
displayPoint(graphCoordinate, colour);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle the raceAnno value
|
||||
*/
|
||||
public void toggleAnnotations() {
|
||||
if (raceAnno) {
|
||||
raceAnno = false;
|
||||
} else {
|
||||
raceAnno = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle name display in annotation
|
||||
*/
|
||||
public void toggleAnnoName() {
|
||||
if (annoName) {
|
||||
annoName = false;
|
||||
} else {
|
||||
annoName = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void toggleBoatPath() {
|
||||
if (annoPath) {
|
||||
annoPath = false;
|
||||
} else {
|
||||
annoPath = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle abbreviation display in annotation
|
||||
*/
|
||||
public void toggleAnnoAbbrev() {
|
||||
if (annoAbbrev) {
|
||||
annoAbbrev = false;
|
||||
} else {
|
||||
annoAbbrev = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle speed display in annotation
|
||||
*/
|
||||
public void toggleAnnoSpeed() {
|
||||
if (annoSpeed) {
|
||||
annoSpeed = false;
|
||||
} else {
|
||||
annoSpeed = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws boats while race in progress, when leg heading is set.
|
||||
*/
|
||||
public void updateBoats() {
|
||||
if (boats != null) {
|
||||
for (BoatInRace boat : boats) {
|
||||
boolean finished = boat.getCurrentLeg().getName().equals("Finish") || boat.getCurrentLeg().getName().equals("DNF");
|
||||
boolean isStart = boat.isStarted();
|
||||
if (!finished && isStart) {
|
||||
displayBoat(boat, boat.getHeading());
|
||||
GraphCoordinate wakeFrom = this.map.convertGPS(boat.getCurrentPosition());
|
||||
GraphCoordinate wakeTo = this.map.convertGPS(boat.getWake());
|
||||
displayLine(wakeFrom, wakeTo, boat.getColour());
|
||||
} else if (!isStart) {
|
||||
displayBoat(boat, boat.getHeading());
|
||||
} else {
|
||||
displayBoat(boat, 0);
|
||||
}
|
||||
|
||||
if (raceAnno)
|
||||
displayText(boat.toString(), boat.getAbbrev(), boat.getVelocity(), this.map.convertGPS(boat.getCurrentPosition()));
|
||||
|
||||
if(boat.isTrackVisible()) drawTrack(boat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws all track points for a given boat. Colour is set by boat, opacity by track point.
|
||||
* @param boat whose track is displayed
|
||||
* @see seng302.Model.TrackPoint
|
||||
*/
|
||||
private void drawTrack(BoatInRace boat) {
|
||||
if (annoPath && raceAnno) {
|
||||
for (TrackPoint point : boat.getTrack()) {
|
||||
GraphCoordinate scaledCoordinate = this.map.convertGPS(point.getCoordinate());
|
||||
Color boatColour = boat.getColour();
|
||||
gc.setFill(new Color(boatColour.getRed(), boatColour.getGreen(), boatColour.getBlue(), point.getAlpha()));
|
||||
gc.fillOval(scaledCoordinate.getX(), scaledCoordinate.getY(), 5, 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setRaceBoundaries(List<GPSCoordinate> boundaries) {
|
||||
this.raceBoundaries = new ArrayList<>();
|
||||
for (GPSCoordinate bound : boundaries) {
|
||||
raceBoundaries.add(bound);
|
||||
}
|
||||
setRaceBoundCoordinates();
|
||||
}
|
||||
|
||||
public void setRaceBoundCoordinates() {
|
||||
xpoints = new double[this.raceBoundaries.size()];
|
||||
ypoints = new double[this.raceBoundaries.size()];
|
||||
for (int i = 0; i < raceBoundaries.size(); i++) {
|
||||
GraphCoordinate coord = map.convertGPS(raceBoundaries.get(i));
|
||||
xpoints[i] = coord.getX();
|
||||
ypoints[i] = coord.getY();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Canvas to resizable.
|
||||
*
|
||||
* @return That the Canvas is resizable.
|
||||
*/
|
||||
@Override
|
||||
public boolean isResizable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the preferred width of the Canvas
|
||||
*
|
||||
* @param width of canvas
|
||||
* @return Returns the width of the Canvas
|
||||
*/
|
||||
@Override
|
||||
public double prefWidth(double width) {
|
||||
return getWidth();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the preferred height of the Canvas
|
||||
*
|
||||
* @param height of canvas
|
||||
* @return Returns the height of the Canvas
|
||||
*/
|
||||
@Override
|
||||
public double prefHeight(double height) {
|
||||
return getHeight();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,69 +0,0 @@
|
||||
package seng302;
|
||||
|
||||
/**
|
||||
* Created by cbt24 on 15/03/17.
|
||||
*/
|
||||
public class RaceMap {
|
||||
private double x1, x2, y1, y2;
|
||||
private int width, height;
|
||||
|
||||
/**
|
||||
* Constructor Method.
|
||||
*
|
||||
* @param x1 Longitude of the top left point.
|
||||
* @param y1 Latitude of the top left point.
|
||||
* @param x2 Longitude of the top right point.
|
||||
* @param y2 Latitude of the top right point.
|
||||
* @param width width that the Canvas the race is to be drawn on is.
|
||||
* @param height height that the Canvas the race is to be drawn on is.
|
||||
*/
|
||||
public RaceMap(double y1, double x1, double y2, double x2, int height, int width) {
|
||||
this.x1 = x1;
|
||||
this.x2 = x2;
|
||||
this.y1 = y1;
|
||||
this.y2 = y2;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts GPS coordinates to coordinates for container
|
||||
*
|
||||
* @param lat GPS latitude
|
||||
* @param lon GPS longitude
|
||||
* @return GraphCoordinate (pair of doubles)
|
||||
* @see GraphCoordinate
|
||||
*/
|
||||
public GraphCoordinate convertGPS(double lat, double lon) {
|
||||
int difference = Math.abs(width - height);
|
||||
int size = width;
|
||||
if (width > height) {
|
||||
size = height;
|
||||
return new GraphCoordinate((int) ((size * (lon - x1) / (x2 - x1)) + difference / 2), (int) (size - (size * (lat - y1) / (y2 - y1))));
|
||||
} else {
|
||||
return new GraphCoordinate((int) (size * (lon - x1) / (x2 - x1)), (int) ((size - (size * (lat - y1) / (y2 - y1))) + difference / 2));
|
||||
}
|
||||
|
||||
//return new GraphCoordinate((int) (width * (lon - x1) / (x2 - x1)), (int) (height - (height * (lat - y1) / (y2 - y1))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the GPS Coordinate to GraphCoordinates
|
||||
*
|
||||
* @param coordinate GPSCoordinate representation of Latitude and Longitude.
|
||||
* @return GraphCoordinate that the GPS is coordinates are to be displayed on the map.
|
||||
* @see GraphCoordinate
|
||||
* @see GPSCoordinate
|
||||
*/
|
||||
public GraphCoordinate convertGPS(GPSCoordinate coordinate) {
|
||||
return convertGPS(coordinate.getLatitude(), coordinate.getLongitude());
|
||||
}
|
||||
|
||||
public void setWidth(int width) {
|
||||
this.width = width;
|
||||
}
|
||||
|
||||
public void setHeight(int height) {
|
||||
this.height = height;
|
||||
}
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
|
||||
<?import java.lang.*?>
|
||||
<?import javafx.geometry.*?>
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.*?>
|
||||
<?import javafx.scene.layout.*?>
|
||||
<?import javafx.scene.text.*?>
|
||||
|
||||
<AnchorPane fx:id="main" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="seng302.Controllers.MainController">
|
||||
<children>
|
||||
<fx:include source="race.fxml" fx:id="race"/>
|
||||
<fx:include source="start.fxml" fx:id="start"/>
|
||||
</children>
|
||||
</AnchorPane>
|
||||
@ -1,85 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import java.lang.*?>
|
||||
<?import javafx.geometry.*?>
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.*?>
|
||||
<?import javafx.scene.layout.*?>
|
||||
<?import javafx.scene.text.*?>
|
||||
|
||||
<SplitPane fx:id="race" dividerPositions="0.7" visible="false" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="seng302.Controllers.RaceController">
|
||||
<items>
|
||||
<GridPane fx:id="canvasBase">
|
||||
<columnConstraints>
|
||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
|
||||
</rowConstraints>
|
||||
<children>
|
||||
<Pane prefHeight="200.0" prefWidth="400.0" GridPane.halignment="LEFT" GridPane.valignment="TOP">
|
||||
<children>
|
||||
<Accordion>
|
||||
<panes>
|
||||
<TitledPane animated="false" text="Annotation Control">
|
||||
<content>
|
||||
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="240.0" prefWidth="200.0">
|
||||
<children>
|
||||
<CheckBox fx:id="showBoatPath" mnemonicParsing="false" selected="true" text="Show Boat Paths" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="104.0" />
|
||||
<CheckBox fx:id="showAnnotations" layoutX="-2.0" layoutY="14.0" mnemonicParsing="false" selected="true" text="Show Annotations" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="0.0" />
|
||||
<CheckBox fx:id="showName" layoutY="39.0" mnemonicParsing="false" selected="true" text="Show Boat Name" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="26.0" />
|
||||
<CheckBox fx:id="showAbbrev" layoutY="61.0" mnemonicParsing="false" selected="true" text="Show Boat Abbreviation" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="52.0" />
|
||||
<CheckBox fx:id="showSpeed" layoutY="90.0" mnemonicParsing="false" selected="true" text="Show Boat Speed" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="78.0" />
|
||||
<Button fx:id="saveAnno" layoutX="11.0" layoutY="106.0" maxWidth="154.0" mnemonicParsing="false" prefWidth="154.0" text="Save Annotation" AnchorPane.topAnchor="130.0" />
|
||||
<Button fx:id="showSetAnno" layoutX="11.0" layoutY="139.0" mnemonicParsing="false" text="Show Set Annotation" AnchorPane.topAnchor="160.0" />
|
||||
</children>
|
||||
</AnchorPane>
|
||||
</content>
|
||||
</TitledPane>
|
||||
<TitledPane animated="false" text="FPS Control">
|
||||
<content>
|
||||
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
|
||||
<children>
|
||||
<CheckBox fx:id="showFPS" layoutX="-14.0" layoutY="13.0" mnemonicParsing="false" selected="true" text="Show FPS" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="0.0" />
|
||||
</children>
|
||||
</AnchorPane>
|
||||
</content>
|
||||
</TitledPane>
|
||||
</panes>
|
||||
</Accordion>
|
||||
</children>
|
||||
</Pane>
|
||||
<Label fx:id="timer" layoutX="45.0" layoutY="146.0" maxHeight="20.0" text="0:0" AnchorPane.bottomAnchor="0.0" AnchorPane.rightAnchor="0.0" GridPane.halignment="RIGHT" GridPane.valignment="BOTTOM">
|
||||
<font>
|
||||
<Font name="System Bold" size="15.0" />
|
||||
</font>
|
||||
</Label>
|
||||
<Label fx:id="FPS" text="FPS: 0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" GridPane.halignment="LEFT" GridPane.valignment="BOTTOM">
|
||||
<font>
|
||||
<Font name="System Bold" size="15.0" />
|
||||
</font>
|
||||
</Label>
|
||||
<Label fx:id="timeZone" text="Label" GridPane.halignment="RIGHT" GridPane.valignment="BOTTOM">
|
||||
<GridPane.margin>
|
||||
<Insets bottom="20.0" />
|
||||
</GridPane.margin>
|
||||
<font>
|
||||
<Font name="System Bold" size="15.0" />
|
||||
</font>
|
||||
</Label>
|
||||
</children>
|
||||
</GridPane>
|
||||
<AnchorPane layoutX="450.0" minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="200.0" GridPane.columnIndex="1">
|
||||
<children>
|
||||
<TableView fx:id="boatInfoTable" layoutX="-2.0" prefHeight="600.0" prefWidth="264.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="-2.0" AnchorPane.rightAnchor="-62.0" AnchorPane.topAnchor="0.0">
|
||||
<columns>
|
||||
<TableColumn fx:id="boatPlacingColumn" prefWidth="50.0" text="Place" />
|
||||
<TableColumn fx:id="boatTeamColumn" prefWidth="100.0" text="Team" />
|
||||
<TableColumn fx:id="boatMarkColumn" prefWidth="130.0" text="Mark" />
|
||||
<TableColumn fx:id="boatSpeedColumn" prefWidth="75.0" text="Speed" />
|
||||
</columns>
|
||||
</TableView>
|
||||
</children>
|
||||
</AnchorPane>
|
||||
</items>
|
||||
</SplitPane>
|
||||
@ -1,58 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.control.TableColumn?>
|
||||
<?import javafx.scene.control.TableView?>
|
||||
<?import javafx.scene.layout.AnchorPane?>
|
||||
<?import javafx.scene.layout.ColumnConstraints?>
|
||||
<?import javafx.scene.layout.GridPane?>
|
||||
<?import javafx.scene.layout.RowConstraints?>
|
||||
<?import javafx.scene.text.Font?>
|
||||
<?import javafx.scene.text.Text?>
|
||||
|
||||
<AnchorPane fx:id="startWrapper" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="seng302.Controllers.StartController">
|
||||
<children>
|
||||
<GridPane fx:id="start" prefHeight="600.0" prefWidth="780.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
||||
<columnConstraints>
|
||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="1.7976931348623157E308" prefWidth="200.0" />
|
||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="372.0" minWidth="10.0" prefWidth="200.0" />
|
||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="394.0" minWidth="10.0" prefWidth="250.0" />
|
||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="416.0" minWidth="10.0" prefWidth="200.0" />
|
||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="1.7976931348623157E308" prefWidth="200.0" />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints maxHeight="241.0" minHeight="10.0" prefHeight="116.5" vgrow="SOMETIMES" />
|
||||
<RowConstraints maxHeight="383.0" minHeight="10.0" prefHeight="257.5" vgrow="SOMETIMES" />
|
||||
<RowConstraints maxHeight="369.0" minHeight="10.0" prefHeight="50.5" vgrow="SOMETIMES" />
|
||||
<RowConstraints maxHeight="369.0" minHeight="10.0" prefHeight="38.0" vgrow="SOMETIMES" />
|
||||
<RowConstraints maxHeight="191.5" minHeight="10.0" prefHeight="53.5" vgrow="SOMETIMES" />
|
||||
<RowConstraints maxHeight="191.5" minHeight="10.0" prefHeight="82.0" vgrow="SOMETIMES" />
|
||||
</rowConstraints>
|
||||
<children>
|
||||
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="Welcome to RaceVision" GridPane.columnSpan="5" GridPane.halignment="CENTER">
|
||||
<font>
|
||||
<Font size="36.0" />
|
||||
</font>
|
||||
</Text>
|
||||
<Button maxWidth="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#startRace1Min" prefWidth="100.0" fx:id="oneMinButton" text="1 Minute" GridPane.columnIndex="1" GridPane.halignment="RIGHT" GridPane.rowIndex="4">
|
||||
<GridPane.margin>
|
||||
<Insets />
|
||||
</GridPane.margin>
|
||||
</Button>
|
||||
<Button maxWidth="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#startRaceNoScaling" prefWidth="100.0" fx:id="fifteenMinButton" text="15 Minutes" GridPane.columnIndex="3" GridPane.halignment="LEFT" GridPane.rowIndex="4" />
|
||||
<Button maxWidth="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#startRace5Min" prefWidth="100.0" fx:id="fiveMinButton" text="5 Minutes" GridPane.columnIndex="2" GridPane.halignment="CENTER" GridPane.rowIndex="4" />
|
||||
<Label text="Select Race Duration:" GridPane.columnIndex="2" GridPane.halignment="CENTER" GridPane.rowIndex="3" />
|
||||
<TableView fx:id="boatNameTable" prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1" GridPane.columnSpan="3" GridPane.rowIndex="1">
|
||||
<columns>
|
||||
<TableColumn fx:id="boatNameColumn" prefWidth="360.0" style="-fx-font-size: 16;" text="Team Name" />
|
||||
<TableColumn fx:id="boatCodeColumn" prefWidth="133.0" style="-fx-font-size: 16;" text="Code" />
|
||||
</columns>
|
||||
</TableView>
|
||||
<Label fx:id="timeZoneTime" contentDisplay="CENTER" text="timeZoneTime" GridPane.columnIndex="2" GridPane.halignment="CENTER" GridPane.rowIndex="2" GridPane.valignment="CENTER" />
|
||||
<Label fx:id="timer" text=" " GridPane.columnIndex="2" GridPane.halignment="CENTER" GridPane.rowIndex="5" />
|
||||
</children>
|
||||
</GridPane>
|
||||
</children>
|
||||
</AnchorPane>
|
||||
Loading…
Reference in new issue