Merge branch 'C_keybindings' into 'master'

C keybindings

AC:
* All keybindings can be easily changed in the start screen
* Buttons are replacable on clicking on the current button assigned.
* When the current button assigned is clicked the text should turn "blank" and return to with text after a new button has been pressed or escape has been pressed.
* There cannot be more than one active replace button at a time.
* Reset to default should reset to the keys defined by the P.O (but with UP, DOWN instead of PG_UP, PG_DWN)
* Buttons should not save until the user exits with "save"

See merge request !35
main
Hamish Ball 8 years ago
commit 28d27a7b2b

@ -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);
}
}

@ -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.fxml.FXML;
import javafx.scene.chart.LineChart; import javafx.scene.chart.LineChart;
import javafx.scene.control.*; import javafx.scene.control.*;
import javafx.scene.control.Label;
import javafx.scene.input.KeyCode; import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent; import javafx.scene.input.KeyEvent;
import javafx.scene.layout.AnchorPane; import javafx.scene.layout.AnchorPane;
@ -23,7 +22,6 @@ import shared.model.Leg;
import visualiser.app.App; import visualiser.app.App;
import visualiser.gameController.ControllerClient; import visualiser.gameController.ControllerClient;
import visualiser.gameController.Keys.ControlKey; import visualiser.gameController.Keys.ControlKey;
import visualiser.gameController.Keys.KeyFactory;
import visualiser.model.*; import visualiser.model.*;
import java.io.IOException; import java.io.IOException;
@ -33,6 +31,7 @@ import java.util.ResourceBundle;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import static visualiser.app.App.keyFactory;
/** /**
@ -113,7 +112,7 @@ public class RaceController extends Controller {
@Override @Override
public void initialize(URL location, ResourceBundle resources) { public void initialize(URL location, ResourceBundle resources) {
KeyFactory keyFactory = KeyFactory.getFactory(); // KeyFactory keyFactory = KeyFactory.getFactory();
infoTableShow = true; infoTableShow = true;
// Initialise keyboard handler // Initialise keyboard handler

@ -1,5 +1,6 @@
package visualiser.Controllers; package visualiser.Controllers;
import javafx.event.EventHandler;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader; import javafx.fxml.FXMLLoader;
import javafx.scene.Parent; import javafx.scene.Parent;
@ -9,6 +10,7 @@ import javafx.scene.control.RadioButton;
import javafx.scene.layout.AnchorPane; import javafx.scene.layout.AnchorPane;
import javafx.stage.Modality; import javafx.stage.Modality;
import javafx.stage.Stage; import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import visualiser.app.App; import visualiser.app.App;
import java.io.IOException; 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 * Called when control button is pressed. New pop up window displaying controls
*/ */
public void controlBtnPressed(){ public void controlBtnPressed(){
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("/visualiser/scenes/controls.fxml"));
Parent layout;
try { 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); Scene scene = new Scene(layout);
Stage popupStage = new Stage(); Stage popupStage = new Stage();
popupStage.setResizable(false); popupStage.setResizable(false);
popupStage.setTitle("Game Controls"); popupStage.setTitle("Game Controls");
popupStage.initModality(Modality.WINDOW_MODAL); popupStage.initModality(Modality.WINDOW_MODAL);
popupStage.centerOnScreen();
popupStage.setScene(scene); 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){ } catch (Exception e){
e.printStackTrace(); e.printStackTrace();
} }

@ -3,7 +3,6 @@ package visualiser.app;
import javafx.animation.FadeTransition; import javafx.animation.FadeTransition;
import javafx.application.Application; import javafx.application.Application;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
import javafx.concurrent.Task; import javafx.concurrent.Task;
@ -15,7 +14,6 @@ import javafx.geometry.Rectangle2D;
import javafx.scene.Parent; import javafx.scene.Parent;
import javafx.scene.Scene; import javafx.scene.Scene;
import javafx.scene.control.Label; import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.ProgressBar; import javafx.scene.control.ProgressBar;
import javafx.scene.effect.DropShadow; import javafx.scene.effect.DropShadow;
import javafx.scene.image.Image; import javafx.scene.image.Image;
@ -29,19 +27,17 @@ import javafx.stage.StageStyle;
import javafx.stage.WindowEvent; import javafx.stage.WindowEvent;
import javafx.util.Duration; import javafx.util.Duration;
import visualiser.Controllers.MainController; import visualiser.Controllers.MainController;
import visualiser.gameController.Keys.KeyFactory;
import java.io.IOException;
public class App extends Application { public class App extends Application {
private static Stage stage; private static Stage stage;
private Pane splashLayout; private Pane splashLayout;
private ProgressBar loadProgress; private ProgressBar loadProgress;
private Label progressText; private Label progressText;
private static final int SPLASH_WIDTH = 676; private static final int SPLASH_WIDTH = 676;
private static final int SPLASH_HEIGHT = 227; private static final int SPLASH_HEIGHT = 227;
public static KeyFactory keyFactory = new KeyFactory();
public static App app; public static App app;
/** /**
@ -55,6 +51,9 @@ public class App extends Application {
@Override @Override
public void init() { public void init() {
// load the user's personalised key bindings
keyFactory.load();
ImageView splash = new ImageView(new Image( ImageView splash = new ImageView(new Image(
getClass().getClassLoader().getResourceAsStream("images/splashScreen.png") getClass().getClassLoader().getResourceAsStream("images/splashScreen.png")
)); ));

@ -3,10 +3,11 @@ package visualiser.gameController;
import javafx.animation.AnimationTimer; import javafx.animation.AnimationTimer;
import javafx.scene.Scene; import javafx.scene.Scene;
import visualiser.gameController.Keys.ControlKey; import visualiser.gameController.Keys.ControlKey;
import visualiser.gameController.Keys.KeyFactory;
import java.util.HashMap; import java.util.HashMap;
import static visualiser.app.App.keyFactory;
/** /**
* Class for checking what keys are currently being used * Class for checking what keys are currently being used
*/ */
@ -18,7 +19,7 @@ public class InputChecker {
* @param scene Scene the controller is to run in parallel with. * @param scene Scene the controller is to run in parallel with.
*/ */
public void runWithScene(Scene scene){ public void runWithScene(Scene scene){
KeyFactory keyFactory = KeyFactory.getFactory(); // KeyFactory keyFactory = KeyFactory.getFactory();
scene.setOnKeyPressed(event -> { scene.setOnKeyPressed(event -> {
String codeString = event.getCode().toString(); String codeString = event.getCode().toString();

@ -9,11 +9,9 @@ public class DownWindKey extends ControlKey {
/** /**
* Constructor for Control * Constructor for Control
* @param name name of the key
*
*/ */
public DownWindKey(String name) { public DownWindKey() {
super(name, BoatActionEnum.DOWNWIND); super("Downwind", BoatActionEnum.DOWNWIND);
} }
@Override @Override

@ -1,5 +1,8 @@
package visualiser.gameController.Keys; package visualiser.gameController.Keys;
import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.*;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -13,39 +16,108 @@ public class KeyFactory {
private Map<String, ControlKey> keyState; private Map<String, ControlKey> keyState;
/** /**
* Singleton instance to enforce consistent key state * Constructor for key state, set up initial state of each action.
*/ */
private static KeyFactory theFactory = new KeyFactory(); public KeyFactory() {
this.keyState = new HashMap<>();
keyState.put("Z", new ZoomInKey());
keyState.put("X", new ZoomOutKey());
keyState.put("SPACE", new VMGKey());
keyState.put("SHIFT", new SailsToggleKey());
keyState.put("ENTER", new TackGybeKey());
keyState.put("UP", new UpWindKey());
keyState.put("DOWN", new DownWindKey());
}
/** /**
* Singleton constructor for key state, set up initial state of each action. * Get the Control Key in charge of a key press
* @param key key pressed (String value of KeyCode)
* @return the Control Key behaviour of the key pressed.
*/ */
private KeyFactory() { public ControlKey getKey(String key){
this.keyState = new HashMap<>(); return keyState.get(key);
keyState.put("Z", new ZoomInKey("Zoom In")); }
keyState.put("X", new ZoomOutKey("Zoom Out"));
keyState.put("SPACE", new VMGKey("VMG")); public Map<String, ControlKey> getKeyState() {
keyState.put("SHIFT", new SailsToggleKey("Toggle Sails")); return keyState;
keyState.put("ENTER", new TackGybeKey("Tack/Gybe")); }
keyState.put("UP", new UpWindKey("Upwind"));
keyState.put("DOWN", new DownWindKey("Downwind")); public void setKeyState(Map<String, ControlKey> keyState) {
this.keyState = keyState;
} }
/** /**
* Get singleton instance of KeyFactory to interact with key state * Update the key bound to a particular command in the keystate.
* @return automatically constructed KeyFactory * @param newKey the new key value for the command
* @param command the command to be updated
*/ */
public static KeyFactory getFactory() { public void updateKey(String newKey, String command){
return theFactory; ControlKey controlKey = null;
String oldKey = null;
for (Map.Entry<String, ControlKey> entry : keyState.entrySet()) {
// if this is the correct command
if (entry.getValue().toString()==command){
controlKey = entry.getValue();
oldKey = entry.getKey();
}
}
keyState.remove(oldKey, controlKey);
keyState.put(newKey, controlKey);
} }
/** /**
* Get the Control Key in charge of a key press * Persistently saves the keybindings the user has set.
* @param key key pressed (String value of KeyCode)
* @return the Control Key behaviour of the key pressed.
*/ */
public ControlKey getKey(String key){ public void save(){
return keyState.get(key); try {
// open the filestream and write to it
FileOutputStream fos = new FileOutputStream(
System.getProperty("user.dir")+
"/settings/keyBindings.xml");
XMLEncoder xmlEncoder = new XMLEncoder(fos);
xmlEncoder.writeObject(this.keyState);
xmlEncoder.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
/**
* Loads the persistently saved keybindings the user has set.
*/
public void load(){
try {
// access settings folder, create if it doesn't exist
File settingsFolder = new File(
System.getProperty("user.dir")+"/settings");
if (!settingsFolder.exists()){
settingsFolder.mkdir();
}
// access keybindings xml file, create if it doesn't exist
File savedFile = new File(
settingsFolder+"/keyBindings.xml");
if (!savedFile.exists()){
savedFile.createNewFile();
FileOutputStream fos = new FileOutputStream(savedFile);
XMLEncoder xmlEncoder = new XMLEncoder(fos);
xmlEncoder.writeObject(this.keyState);
xmlEncoder.close();
}
// load the saved settings into the game
InputStream is = new FileInputStream(savedFile);
XMLDecoder xmlDecoder = new XMLDecoder(is);
Map<String, ControlKey> savedKeyState
= (Map<String, ControlKey>)xmlDecoder.readObject();
xmlDecoder.close();
this.keyState = savedKeyState;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} }
} }

@ -10,11 +10,9 @@ public class SailsToggleKey extends ControlKey {
/** /**
* Constructor for Control * Constructor for Control
* @param name name of the key
*
*/ */
public SailsToggleKey(String name) { public SailsToggleKey() {
super(name, BoatActionEnum.NOT_A_STATUS); super("Toggle Sails", BoatActionEnum.NOT_A_STATUS);
} }
/** /**

@ -9,11 +9,9 @@ public class TackGybeKey extends ControlKey {
/** /**
* Constructor for Control * Constructor for Control
* @param name name of the key
*
*/ */
public TackGybeKey(String name) { public TackGybeKey() {
super(name, BoatActionEnum.TACK_GYBE); super("Tack/Gybe", BoatActionEnum.TACK_GYBE);
} }
@Override @Override

@ -9,11 +9,9 @@ public class UpWindKey extends ControlKey {
/** /**
* Constructor for Control * Constructor for Control
* @param name name of the key
*
*/ */
public UpWindKey(String name) { public UpWindKey() {
super(name, BoatActionEnum.UPWIND); super("Upwind", BoatActionEnum.UPWIND);
} }
@Override @Override

@ -1,6 +1,5 @@
package visualiser.gameController.Keys; package visualiser.gameController.Keys;
import javafx.scene.input.KeyCode;
import network.Messages.Enums.BoatActionEnum; import network.Messages.Enums.BoatActionEnum;
/** /**
@ -10,11 +9,9 @@ public class VMGKey extends ControlKey{
/** /**
* Constructor for Control * Constructor for Control
*
* @param name name of the key
*/ */
public VMGKey(String name) { public VMGKey() {
super(name, BoatActionEnum.AUTO_PILOT); super("VMG", BoatActionEnum.AUTO_PILOT);
} }
@Override @Override

@ -5,8 +5,8 @@ package visualiser.gameController.Keys;
*/ */
public class ZoomInKey extends ControlKey { public class ZoomInKey extends ControlKey {
public ZoomInKey(String name) { public ZoomInKey() {
super(name); super("Zoom In");
} }
@Override @Override

@ -7,11 +7,9 @@ public class ZoomOutKey extends ControlKey{
/** /**
* Constructor for Control * Constructor for Control
* @param name name of the key
*
*/ */
public ZoomOutKey(String name) { public ZoomOutKey() {
super(name); super("Zoom Out");
} }
@Override @Override

@ -0,0 +1,45 @@
.list-view .list-cell {
-fx-cell-size: 40;
-fx-font-family: "Tahoma";
-fx-background-color: #fffff0;
-fx-alignment: center;
}
.list-view .list-cell:even {
-fx-background-color: #ffffdc;
}
.list-view .list-cell:selected {
-fx-background-color: #f9e5c3;
-fx-font-family: "Comic Sans MS";
-fx-font-weight: bold;
-fx-font-size: 18;
}
.button {
-fx-background-color: linear-gradient(#acdeff 50%, #a9c8ff 100%);
-fx-background-radius: 4px;
-fx-border-radius: 4px;
-fx-text-fill: #242d35;
-fx-font-size: 12px;
-fx-font-family: "Courier New";
-fx-border-color: #a9c8ff;
}
.button:focused {
-fx-background-color: white;
-fx-border-color: #0056bd;
}
#anchor {
-fx-background-color: #fdfac3;
}
#menu{
-fx-background-color: linear-gradient(#acdeff 50%, #a9c8ff 100%);
-fx-background-radius: 4px;
-fx-border-radius: 4px;
-fx-text-fill: #242d35;
-fx-font-size: 12px;
-fx-font-family: "Verdana";
-fx-border-color: #a9c8ff;
}

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>
<AnchorPane id="anchor" fx:id="anchor" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="471.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="visualiser.Controllers.KeyBindingsController">
<children>
<Label fx:id="lblTitle" layoutX="172.0" layoutY="14.0" text="Key Bindings">
<font>
<Font name="Comic Sans MS" size="44.0" />
</font>
</Label>
<Button id="menu" fx:id="btnCancel" layoutX="430.0" layoutY="428.0"
mnemonicParsing="false" onAction="#cancel" prefWidth="160.0" text="Cancel" AnchorPane.bottomAnchor="18.0" AnchorPane.rightAnchor="20.0" />
<ListView fx:id="lstControl" focusTraversable="false" layoutX="27.0" layoutY="88.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="322.0" prefWidth="150.0" />
<ListView fx:id="lstKey" focusTraversable="false" layoutX="176.0" layoutY="88.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="322.0" prefWidth="150.0" />
<ListView fx:id="lstDescription" focusTraversable="false" layoutX="325.0" layoutY="88.0" prefHeight="322.0" prefWidth="250.0" />
<Button id="menu" fx:id="btnSave" layoutX="220.0" layoutY="428.0" mnemonicParsing="false" onAction="#save" prefWidth="160.0" text="Save" AnchorPane.bottomAnchor="18.0" />
<Button id="menu" fx:id="btnReset" layoutX="20.0" layoutY="428.0" mnemonicParsing="false" onAction="#reset" prefWidth="160.0" text="Reset to Default" AnchorPane.bottomAnchor="18.0" AnchorPane.leftAnchor="20.0" />
</children>
</AnchorPane>

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.text.Text?>
<Pane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="100.0" prefWidth="300.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="visualiser.Controllers.NotificationController">
<children>
<Button fx:id="btnOk" layoutX="110.0" layoutY="65.0" mnemonicParsing="false" onAction="#ok" prefWidth="80.0" text="Ok" />
<Text fx:id="txtMessage" fill="RED" layoutY="23.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Warning!" textAlignment="CENTER" wrappingWidth="300.0">
<font>
<Font name="System Bold" size="14.0" />
</font>
</Text>
<Label fx:id="lblDescription" alignment="CENTER" layoutY="36.0" prefHeight="17.0" prefWidth="300.0" textAlignment="CENTER" />
</children>
</Pane>
Loading…
Cancel
Save