diff --git a/src/main/java/name/nathanmcrae/numbersstation/AddPrefixController.java b/src/main/java/name/nathanmcrae/numbersstation/AddPrefixController.java new file mode 100644 index 0000000..8ffcc21 --- /dev/null +++ b/src/main/java/name/nathanmcrae/numbersstation/AddPrefixController.java @@ -0,0 +1,145 @@ + package name.nathanmcrae.numbersstation; + + import java.lang.StringBuilder; + import javafx.application.Platform; + import javafx.fxml.FXML; + import javafx.scene.control.Button; + import javafx.scene.control.TextField; + import javafx.stage.Stage; + import javafx.scene.input.KeyCode; + import javafx.scene.input.KeyEvent; + + public class AddPrefixController { + @FXML + private TextField prefixField; + + @FXML + private Button okButton; + + @FXML + private Button cancelButton; + + private int digitsPerGroup; + private MainSettingsController mainSettingsController; + + public void setDigitsPerGroup(int newDigitsPerGroup) { + digitsPerGroup = newDigitsPerGroup; + } + + public void setMainSettingsController(MainSettingsController mainSettingsController) { + this.mainSettingsController = mainSettingsController; + } + + @FXML + private void initialize() { + okButton.setOnAction(event -> handleOkButtonPress()); + cancelButton.setOnAction(event -> handleCancelButtonPress()); + + // Set focus on the text field when the window is shown + Platform.runLater(() -> prefixField.requestFocus()); + + // Add event filter to handle Enter key press + prefixField.addEventFilter(KeyEvent.ANY, event -> { + if (event.getCode() == KeyCode.ENTER) { + handleOkButtonPress(); + event.consume(); + } + + int cursorPosition = prefixField.getCaretPosition(); + + String character = event.getCharacter(); + KeyCode code = event.getCode(); + + String str = event.getText(); + + // Consume the event to block the default behavior + if (!(code == KeyCode.DOWN || + code == KeyCode.END || + code == KeyCode.HOME || + code == KeyCode.LEFT || + code == KeyCode.PAGE_DOWN || + code == KeyCode.PAGE_UP || + code == KeyCode.RIGHT || + code == KeyCode.UP)) { + event.consume(); + } + + if (event.getEventType() == KeyEvent.KEY_PRESSED && + (code == KeyCode.BACK_SPACE || + code == KeyCode.DELETE)) { + + String newText = prefixField.getText(); + if (code == KeyCode.BACK_SPACE) { + newText = (newText.substring(0, cursorPosition - 1) + newText.substring(cursorPosition)).replaceAll(" ", ""); + } + else if (code == KeyCode.DELETE) { + newText = (newText.substring(0, cursorPosition) + newText.substring(cursorPosition + 1)).replaceAll(" ", ""); + } + + StringBuilder sb = new StringBuilder(); + + for (int i = 0; i < newText.length(); i++) { + sb.append(newText.charAt(i)); + if ((i + 1) % (digitsPerGroup) == 0) { + sb.append(' '); + } + } + + prefixField.setText(sb.toString()); + if (code == KeyCode.BACK_SPACE) { + prefixField.positionCaret(cursorPosition - 1); + } else if (code == KeyCode.DELETE) { + prefixField.positionCaret(cursorPosition); + } + } + + if (event.getEventType() == KeyEvent.KEY_PRESSED && + (code == KeyCode.DIGIT0 || + code == KeyCode.DIGIT1 || + code == KeyCode.DIGIT2 || + code == KeyCode.DIGIT3 || + code == KeyCode.DIGIT4 || + code == KeyCode.DIGIT5 || + code == KeyCode.DIGIT6 || + code == KeyCode.DIGIT7 || + code == KeyCode.DIGIT8 || + code == KeyCode.DIGIT9)) { + + String newText = prefixField.getText().substring(0, cursorPosition) + str + prefixField.getText().substring(cursorPosition); + newText = newText.replaceAll(" ", ""); + + StringBuilder sb = new StringBuilder(); + + for (int i = 0; i < newText.length(); i++) { + sb.append(newText.charAt(i)); + if ((i + 1) % (digitsPerGroup) == 0) { + sb.append(' '); + } + } + + prefixField.setText(sb.toString()); + if (prefixField.getText().charAt(cursorPosition) == ' ') { + cursorPosition++; + } + prefixField.positionCaret(cursorPosition + 1); + } + }); + } + + private void handleOkButtonPress() { + String prefix = prefixField.getText(); + if (prefix != null && !prefix.isEmpty()) { + mainSettingsController.addPrefix(prefix.replaceAll(" ", "")); + closeWindow(); + } + } + + private void handleCancelButtonPress() { + closeWindow(); + } + + private void closeWindow() { + Stage stage = (Stage) okButton.getScene().getWindow(); + stage.close(); + } + } diff --git a/src/main/java/name/nathanmcrae/numbersstation/AddPrefixView.fxml b/src/main/java/name/nathanmcrae/numbersstation/AddPrefixView.fxml new file mode 100644 index 0000000..6160948 --- /dev/null +++ b/src/main/java/name/nathanmcrae/numbersstation/AddPrefixView.fxml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import javafx.scene.control.Button?> +<?import javafx.scene.control.Label?> +<?import javafx.scene.control.TextField?> +<?import javafx.scene.layout.AnchorPane?> +<?import javafx.scene.layout.VBox?> + +<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="92.0" prefWidth="312.0" xmlns="http://javafx.com/javafx/23.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="name.nathanmcrae.numbersstation.AddPrefixController"> + <children> + <AnchorPane prefHeight="200.0" prefWidth="312.0"> + <children> + <Button fx:id="okButton" layoutX="89.0" layoutY="67.0" mnemonicParsing="false" prefHeight="25.0" prefWidth="65.0" text="OK" AnchorPane.bottomAnchor="15.0" AnchorPane.rightAnchor="89.0" /> + <Button fx:id="cancelButton" layoutX="169.0" layoutY="67.0" mnemonicParsing="false" prefHeight="25.0" prefWidth="65.0" text="Cancel" AnchorPane.bottomAnchor="15.0" AnchorPane.rightAnchor="9.0" /> + <Label layoutX="14.0" layoutY="14.0" text="Enter a message prefix / identifier:" /> + <TextField fx:id="prefixField" layoutX="203.0" layoutY="10.0" prefHeight="25.0" prefWidth="105.0" AnchorPane.leftAnchor="203.0" AnchorPane.rightAnchor="10.0" /> + </children> + </AnchorPane> + </children> +</VBox> diff --git a/src/main/java/name/nathanmcrae/numbersstation/MainSettingsController.java b/src/main/java/name/nathanmcrae/numbersstation/MainSettingsController.java index cc7e242..d33a42b 100644 --- a/src/main/java/name/nathanmcrae/numbersstation/MainSettingsController.java +++ b/src/main/java/name/nathanmcrae/numbersstation/MainSettingsController.java @@ -21,8 +21,10 @@ import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.event.Event; import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; import javafx.scene.control.CheckBox; import javafx.scene.control.DatePicker; +import javafx.scene.control.ListCell; import javafx.scene.control.ListView; import javafx.scene.control.RadioButton; import javafx.scene.control.Spinner; @@ -33,7 +35,11 @@ import javafx.scene.control.ToggleGroup; import javafx.scene.input.KeyEvent; import javafx.scene.input.KeyCode; import javafx.scene.Node; +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.stage.Modality; import javafx.stage.Stage; +import javafx.util.Callback; public class MainSettingsController { private IntegerProperty digitsPerGroup = new SimpleIntegerProperty(); @@ -278,19 +284,59 @@ public class MainSettingsController { stage.setUserData(false); } }); + + prefixListView.setCellFactory(new Callback<ListView<String>, ListCell<String>>() { + @Override + public ListCell<String> call(ListView<String> listView) { + return new ListCell<String>() { + @Override + protected void updateItem(String item, boolean empty) { + super.updateItem(item, empty); + if (empty || item == null) { + setText(null); + } else { + + String newText = item.replaceAll(" ", ""); + StringBuilder sb = new StringBuilder(); + + for (int i = 0; i < newText.length(); i++) { + sb.append(newText.charAt(i)); + if ((i + 1) % (digitsPerGroup.get()) == 0) { + sb.append(' '); + } + } + setText(sb.toString()); + } + } + }; + } + }); } @FXML private void handleAddPrefixButtonPress() { - TextInputDialog dialog = new TextInputDialog(); - dialog.setTitle("New prefix"); - dialog.setHeaderText("Add a new prefix"); - dialog.setContentText("Enter a message prefix / identifier:"); + try { + FXMLLoader loader = new FXMLLoader(getClass().getResource("AddPrefixView.fxml")); + Parent root = loader.load(); - Optional<String> result = dialog.showAndWait(); - result.ifPresent(prefix -> { + AddPrefixController controller = loader.getController(); + controller.setMainSettingsController(this); + controller.setDigitsPerGroup(settings.getDigitsPerGroup()); + + Stage stage = new Stage(); + stage.setTitle("New prefix"); + stage.setScene(new Scene(root)); + stage.initModality(Modality.APPLICATION_MODAL); + stage.showAndWait(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void addPrefix(String prefix) { + if (!(prefix == null || prefix.isEmpty())) { prefixListView.getItems().add(prefix); - }); + } } @FXML