Merge branch 'master' into story77

# Conflicts:
#	racevisionGame/src/main/java/mock/app/Event.java
#	racevisionGame/src/main/java/visualiser/Controllers/HostController.java
#	racevisionGame/src/main/java/visualiser/model/View3D.java
This commit is contained in:
hba56
2017-09-08 17:28:17 +12:00
79 changed files with 2957 additions and 663 deletions
@@ -71,8 +71,10 @@ public class FinishController extends Controller {
//Winner label.
raceWinnerLabel.setText("Winner: "+ boatNameColumn.getCellObservableValue(0).getValue());
raceWinnerLabel.setWrapText(true);
if (boats.size() > 0) {
raceWinnerLabel.setText("Winner: " + boatNameColumn.getCellObservableValue(0).getValue());
raceWinnerLabel.setWrapText(true);
}
}
@@ -0,0 +1,247 @@
package visualiser.Controllers;
import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ListView;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import visualiser.gameController.Keys.ControlKey;
import visualiser.gameController.Keys.KeyFactory;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import static visualiser.app.App.keyFactory;
/**
* Controller for the scene used to display and update current key bindings.
*/
public class KeyBindingsController {
private @FXML Button btnSave;
private @FXML Button btnCancel;
private @FXML Button btnReset;
private @FXML ListView lstControl;
private @FXML ListView lstKey;
private @FXML ListView lstDescription;
private @FXML AnchorPane anchor;
private KeyFactory newKeyFactory;
private Boolean changed = false; // keyBindings have been modified
private Button currentButton = null; // last button clicked
public void initialize(){
// create new key factory to modify, keeping the existing one safe
newKeyFactory = copyExistingFactory();
initializeTable();
populateTable();
setKeyListener();
}
/**
* Sets up table before populating it.
* Set up includes headings, CSS styling and modifying default properties.
*/
public void initializeTable(){
// set the headings for each column
lstKey.getItems().add("Key");
lstControl.getItems().add("Command");
lstDescription.getItems().add("Description");
lstKey.getSelectionModel().select(0);
lstControl.getSelectionModel().select(0);
lstDescription.getSelectionModel().select(0);
// add CSS stylesheet once the scene has been created
lstKey.sceneProperty().addListener((obs, oldScene, newScene) -> {
if (newScene != null) {
newScene.getStylesheets().add("/css/keyBindings.css");
}
});
// stop the columns from being selectable, so only the buttons are
lstKey.getSelectionModel().selectedItemProperty()
.addListener((observable, oldvalue, newValue) ->
Platform.runLater(() ->
lstKey.getSelectionModel().select(0)));
lstDescription.getSelectionModel().selectedItemProperty()
.addListener((observable, oldvalue, newValue) ->
Platform.runLater(() ->
lstDescription.getSelectionModel().select(0)));
lstControl.getSelectionModel().selectedItemProperty()
.addListener((observable, oldvalue, newValue) ->
Platform.runLater(() ->
lstControl.getSelectionModel().select(0)));
}
/**
* Populates the table with commands and their key binding details.
*/
public void populateTable(){
// add each command to the table
for (Map.Entry<String, ControlKey> entry : newKeyFactory.getKeyState().entrySet()) {
// create button for command
Button button = new Button(entry.getKey());
button.setMinWidth(120);
button.setId(entry.getValue().toString());
button.setOnAction(e -> currentButton = button);
// display details for command in table
lstControl.getItems().add(entry.getValue());
lstKey.getItems().add(button);
lstDescription.getItems().add(entry.getValue().getProtocolCode());
}
}
/**
* Makes a copy of the {@link KeyFactory} that does not modify the original.
* @return new keyfactory to be modified
*/
public KeyFactory copyExistingFactory(){
newKeyFactory = new KeyFactory();
Map<String, ControlKey> oldKeyState = keyFactory.getKeyState();
Map<String, ControlKey> newKeyState = new HashMap<>();
// copy over commands and their keys
for (Map.Entry<String, ControlKey> entry : oldKeyState.entrySet()){
newKeyState.put(entry.getKey(), entry.getValue());
}
newKeyFactory.setKeyState(newKeyState);
return newKeyFactory;
}
/**
* Creates a listener for the base anchorpane for key presses.
* It updates the current key bindings of the {@link KeyFactory} if
* required.
*/
public void setKeyListener(){
anchor.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
// if esc, cancel current button click
if (event.getCode() == KeyCode.ESCAPE){
btnCancel.requestFocus();
currentButton = null;
}
// if a button was clicked
else if (currentButton != null) {
// check if a button is already mapped to this key
for (int i = 1; i < lstKey.getItems().size(); i++) {
Button button = (Button)lstKey.getItems().get(i);
// update buttons text and remove key binding from command
if (button.getText().equals(event.getCode().toString())) {
button.setText("");
newKeyFactory.updateKey(button.getId(), button.getId());
}
}
// update text on the button
currentButton.setText(event.getCode().toString());
// update the control key
newKeyFactory.updateKey(event.getCode().toString(),
currentButton.getId());
// remove current button selection
currentButton = null;
changed = true;
btnCancel.requestFocus();
}
event.consume();
});
}
/**
* Cancel and exits the key bindings menu. Changes are not forced to be
* saved or fixed if invalid, and instead are defaulted back to the last
* successful saved state.
*/
public void cancel(){
((Stage)btnCancel.getScene().getWindow()).close();
}
/**
* Resets all key bindings to the built-in defaults.
*/
public void reset(){
lstKey.getItems().clear();
lstControl.getItems().clear();
lstDescription.getItems().clear();
newKeyFactory = new KeyFactory();
initializeTable();
populateTable();
changed = true;
}
/**
* Replace existing {@link KeyFactory} with the modified key bindings.
*/
public void save(){
if (isFactoryValid()) {
keyFactory = newKeyFactory;
newKeyFactory = new KeyFactory();
changed = false;
keyFactory.save(); // save persistently
loadNotification("Key bindings were successfully saved.", false);
} else {
loadNotification("One or more key bindings are missing. " +
"Failed to save.", true);
}
}
/**
* Checks the {@link KeyFactory} being modified is valid and that no
* commands are missing a key binding.
* @return True if valid, false if invalid
*/
public Boolean isFactoryValid(){
for (Map.Entry<String, ControlKey> entry : newKeyFactory.getKeyState().entrySet
()) {
if (entry.getKey().toString()==entry.getValue().toString()){
return false;
}
}
return true;
}
/**
* Method used to stop a user from exiting key bindings without saving
* their changes to the {@link KeyFactory}.
* @param we {@link WindowEvent} close request to be consumed if settings
* have not been successfully saved.
*/
public void onExit(WindowEvent we){
// if modified KeyFactory hasn't been saved
if (changed){
loadNotification("Please cancel or save your changes before exiting" +
".", true);
we.consume();
}
}
/**
* Loads a popup window giving confirmation/warning of user activity.
* @param message the message to be displayed to the user
* @param warning true if the message to be displayed is due to user error
*/
public void loadNotification(String message, Boolean warning){
Parent root = null;
FXMLLoader loader = new FXMLLoader(getClass().getResource
("/visualiser/scenes/notification.fxml"));
try {
root = loader.load();
} catch (IOException e) {
e.printStackTrace();
}
NotificationController controller = loader.getController();
Stage stage = new Stage();
stage.setScene(new Scene(root));
stage.centerOnScreen();
stage.initModality(Modality.APPLICATION_MODAL);
stage.show();
// displays given message in the window
controller.setMessage(message, warning);
}
}
@@ -51,6 +51,7 @@ public class MainController extends Controller {
* Transitions from the StartController screen (displays pre-race information) to the RaceController (displays the actual race).
* @param visualiserRace The object modelling the race.
* @param controllerClient Socket Client that manipulates the controller.
* @param isHost if the client is the host of a race or not.
*/
public void beginRace(VisualiserRaceEvent visualiserRace, ControllerClient controllerClient, Boolean isHost) {
raceController.startRace(visualiserRace, controllerClient, isHost);
@@ -0,0 +1,35 @@
package visualiser.Controllers;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.paint.Color;
import javafx.scene.text.Text;
import javafx.stage.Stage;
/**
* Controller for a popup notification regarding user activity.
*/
public class NotificationController {
private @FXML Label lblDescription;
private @FXML Text txtMessage;
/**
* Closes the popup window once clicked.
*/
public void ok(){
((Stage)lblDescription.getScene().getWindow()).close();
}
/**
* Displays the appropriate popup notification.
* @param message message for the user
* @param warning if true warning text shown, if false success text shown
*/
public void setMessage(String message, Boolean warning){
lblDescription.setText(message);
if (!warning){
txtMessage.setText("Success!");
txtMessage.setFill(Color.GREEN);
}
}
}
@@ -10,7 +10,6 @@ import javafx.collections.transformation.SortedList;
import javafx.fxml.FXML;
import javafx.scene.chart.LineChart;
import javafx.scene.control.*;
import javafx.scene.control.Label;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.AnchorPane;
@@ -23,7 +22,6 @@ import shared.model.Leg;
import visualiser.app.App;
import visualiser.gameController.ControllerClient;
import visualiser.gameController.Keys.ControlKey;
import visualiser.gameController.Keys.KeyFactory;
import visualiser.model.*;
import java.io.IOException;
@@ -33,6 +31,7 @@ import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import static visualiser.app.App.keyFactory;
/**
@@ -113,7 +112,7 @@ public class RaceController extends Controller {
@Override
public void initialize(URL location, ResourceBundle resources) {
KeyFactory keyFactory = KeyFactory.getFactory();
// KeyFactory keyFactory = KeyFactory.getFactory();
infoTableShow = true;
// Initialise keyboard handler
@@ -356,7 +355,7 @@ public class RaceController extends Controller {
private void initialiseRaceCanvas(VisualiserRaceEvent race) {
//Create canvas.
raceCanvas = new ResizableRaceCanvas(race);
raceCanvas = new ResizableRaceCanvas(race.getVisualiserRaceState());
//Set properties.
raceCanvas.setMouseTransparent(true);
@@ -1,5 +1,6 @@
package visualiser.Controllers;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
@@ -9,6 +10,7 @@ import javafx.scene.control.RadioButton;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import visualiser.app.App;
import java.io.IOException;
@@ -87,18 +89,26 @@ public class TitleController extends Controller {
* Called when control button is pressed. New pop up window displaying controls
*/
public void controlBtnPressed(){
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("/visualiser/scenes/controls.fxml"));
Parent layout;
try {
layout = loader.load();
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("/visualiser/scenes/keyBindings.fxml"));
Parent layout = loader.load();
Scene scene = new Scene(layout);
Stage popupStage = new Stage();
popupStage.setResizable(false);
popupStage.setTitle("Game Controls");
popupStage.initModality(Modality.WINDOW_MODAL);
popupStage.centerOnScreen();
popupStage.setScene(scene);
popupStage.showAndWait();
popupStage.show();
KeyBindingsController controller = loader.getController();
popupStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
public void handle(WindowEvent we) {
if (we.getEventType() == WindowEvent.WINDOW_CLOSE_REQUEST) {
controller.onExit(we);
}
}
});
} catch (Exception e){
e.printStackTrace();
}