package seng302.visualiser.controllers.dialogs; import com.jfoenix.controls.JFXButton; import com.jfoenix.controls.JFXToggleButton; import java.net.URL; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.ResourceBundle; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.input.KeyEvent; import seng302.model.GameKeyBind; import seng302.model.KeyAction; import seng302.visualiser.GameClient; import seng302.visualiser.controllers.ViewManager; public class KeyBindingDialogController implements Initializable { //--------FXML BEGIN--------// @FXML private Label keyBindingDialogHeader; @FXML private Label closeLabel; @FXML private JFXButton zoomInbtn; @FXML private JFXButton zoomOutBtn; @FXML private JFXButton vmgBtn; @FXML private JFXButton sailInOutBtn; @FXML private JFXButton tackGybeBtn; @FXML private JFXButton upwindBtn; @FXML private JFXButton downwindBtn; @FXML private JFXButton resetBtn; @FXML private Label upwindLabel; @FXML private Label downwindLabel; @FXML private JFXToggleButton turningToggle; @FXML private JFXButton viewButton; @FXML private JFXButton rightButton; @FXML private JFXButton leftButton; @FXML private JFXButton forwardButton; @FXML private JFXButton backwardButton; //---------FXML END---------// private GameKeyBind gameKeyBind; private List buttons = new ArrayList<>(); private Map buttonActionMap; private GameClient gameClient; // to send turning mode packet @Override public void initialize(URL location, ResourceBundle resources) { gameKeyBind = GameKeyBind.getInstance(); buttons = new ArrayList<>(); Collections.addAll(buttons, zoomInbtn, zoomOutBtn, vmgBtn, sailInOutBtn, tackGybeBtn, upwindBtn, downwindBtn, viewButton, rightButton, leftButton, forwardButton, backwardButton); bindButtonWithAction(); loadKeyBind(); buttons.forEach(button -> { button.setOnMouseEntered(event -> mouseEnter(button)); button.setOnMousePressed(event -> buttonPressed(button)); button.setOnMouseExited(event -> mouseExit(button)); button.setOnKeyPressed(event -> keyPressed(event, button)); }); turningToggle.setOnMouseClicked(event -> toggleTurningMode()); resetBtn.setOnMouseClicked(event -> { gameKeyBind.setToDefault(); loadKeyBind(); showSnackBar("All keys reset!", false); }); closeLabel.setOnMouseClicked(event -> ViewManager.getInstance().closeKeyBindingDialog()); } /** * Set buttons' label according to GameKeyBind settings */ private void loadKeyBind() { buttons.forEach( button -> button .setText(gameKeyBind.getKeyCode(buttonActionMap.get(button)).getName())); turningToggle.setSelected(gameKeyBind.isContinuouslyTurning()); if (gameKeyBind.isContinuouslyTurning()) { upwindLabel.setText("ClOCKWISE TURNING"); downwindLabel.setText("ANTICLOCKWISE TURNING"); } else { upwindLabel.setText("UPWIND"); downwindLabel.setText("DOWNWIND"); } } /** * Bind buttons with specific action in a map. */ private void bindButtonWithAction() { buttonActionMap = new HashMap<>(); for (int i = 0; i < 12; i++) { buttonActionMap.put(buttons.get(i), KeyAction.getType(i + 1)); } } /** * Prompt success / failure message for reassigning key action */ private void showSnackBar(String message, Boolean isWarning) { ViewManager.getInstance().showSnackbar(message, isWarning); } /** * When a mouse enters the button, the color and font size should change to highlight * @param button */ private void mouseEnter(Button button) { button.setStyle("" + "-fx-background-color: -fx-pp-theme-color;" + "-fx-text-fill: -fx-pp-front-color;" + "-fx-font-size: 15;"); } /** * Prompt "press key..." to inform users assign a new key bind by pressing a key * @param button */ private void buttonPressed(Button button) { button.setText("PRESS KEY..."); } /** * When mouse leaves the button, return the button to the normal state in terms of text, * color and font size * @param button */ private void mouseExit(Button button) { button.setText(GameKeyBind.getInstance().getKeyCode(buttonActionMap.get(button)).getName()); button.setStyle("" + "-fx-background-color: -fx-pp-front-color; " + "-fx-text-fill: -fx-pp-theme-color; " + "-fx-font-size: 13;"); keyBindingDialogHeader.requestFocus(); } /** * When a key is pressed, check if the new binding conflicts to any existed settings, if not * assign the selected action with the new key binding to GameKeyBind. * @param event * @param button */ private void keyPressed(KeyEvent event, Button button) { event.consume(); KeyAction buttonAction = buttonActionMap.get(button); if (gameKeyBind.bindKeyToAction(event.getCode(), buttonAction)) { showSnackBar(button.getId() + " is set to " + event.getCode().getName(), false); button.setText(gameKeyBind.getKeyCode(buttonAction).getName()); } else { loadKeyBind(); showSnackBar(event.getCode().getName() + " is already in use", true); } } /** * When the turning mode is toggled, update gameKeyBind and send out packet to notify the server */ private void toggleTurningMode() { gameKeyBind.toggleTurningMode(); gameClient.sendToggleTurningModePacket(); loadKeyBind(); } public void setGameClient(GameClient gameClient) { this.gameClient = gameClient; } }