Compare commits

...

8 Commits

Author SHA1 Message Date
c5e0b41dab Flesh out station selection
Also, save selected station in settings. So that the application opens
with the most recently used station.
2025-01-05 22:53:53 -08:00
36b2c51787 Store StationSettings directly in ListView 2025-01-05 13:25:51 -08:00
4d1aa1842a Add jackson library dependency to build 2025-01-05 11:26:50 -08:00
4afe97334f Fix PATH setting 2025-01-05 11:26:25 -08:00
3dcd3adf03 Add basic station selection 2025-01-05 11:24:47 -08:00
47e0ad7393 Add basic property binding test 2025-01-01 20:24:14 -08:00
aa42155644 Add basic settings (de)serialization 2025-01-01 20:24:02 -08:00
fea5a35240 Add station selection window 2024-12-29 15:55:59 -08:00
9 changed files with 336 additions and 17 deletions

View File

@ -1,6 +1,6 @@
$Env:JAVA_HOME = "C:\Users\nathanm\Downloads\openjdk-23.0.1_windows-x64_bin\jdk-23.0.1" $Env:JAVA_HOME = "C:\Users\nathanm\Downloads\openjdk-23.0.1_windows-x64_bin\jdk-23.0.1"
$Env:PATH += "C:\Users\nathanm\Downloads\openjdk-23.0.1_windows-x64_bin\jdk-23.0.1\bin" $Env:PATH = "C:\Users\nathanm\Downloads\openjdk-23.0.1_windows-x64_bin\jdk-23.0.1\bin;$($Env:PATH)"
$Env:PATH_TO_FX="C:\Users\nathanm\Downloads\openjfx-23.0.1_windows-x64_bin-sdk\javafx-sdk-23.0.1\lib" $Env:PATH_TO_FX="C:\Users\nathanm\Downloads\openjfx-23.0.1_windows-x64_bin-sdk\javafx-sdk-23.0.1\lib"
javac --module-path $Env:PATH_TO_FX --add-modules javafx.controls,javafx.fxml .\name\nathanmcrae\NumbersStation.java .\name\nathanmcrae\NumbersStationController.java -d out javac --module-path "$Env:PATH_TO_FX;P:\personal_root\projects\number-station\lib" --add-modules javafx.controls,javafx.fxml,com.fasterxml.jackson.annotation,com.fasterxml.jackson.core,com.fasterxml.jackson.dataformat.xml .\name\nathanmcrae\*.java -d out
cp name/nathanmcrae/*.fxml out/name/nathanmcrae cp name/nathanmcrae/*.fxml out/name/nathanmcrae
java --module-path $Env:PATH_TO_FX --add-modules javafx.controls,javafx.fxml -cp out name.nathanmcrae.NumbersStation java --module-path "$Env:PATH_TO_FX;P:\personal_root\projects\number-station\lib" --add-modules javafx.controls,javafx.fxml,com.fasterxml.jackson.annotation,com.fasterxml.jackson.core,com.fasterxml.jackson.dataformat.xml -cp out name.nathanmcrae.NumbersStation

View File

@ -50,12 +50,12 @@
<FlowPane alignment="CENTER_LEFT" prefHeight="41.0" prefWidth="640.0"> <FlowPane alignment="CENTER_LEFT" prefHeight="41.0" prefWidth="640.0">
<children> <children>
<Label prefHeight="17.0" prefWidth="49.0" text="Station: " /> <Label prefHeight="17.0" prefWidth="49.0" text="Station: " />
<TextField editable="false" style="-fx-background-color: #EEEEEE; -fx-border-color: #AAAAAA;" text="My Station"> <TextField fx:id="stationNameField" editable="false" style="-fx-background-color: #EEEEEE; -fx-border-color: #AAAAAA;" text="My Station">
<FlowPane.margin> <FlowPane.margin>
<Insets right="10.0" /> <Insets right="10.0" />
</FlowPane.margin> </FlowPane.margin>
</TextField> </TextField>
<Button mnemonicParsing="false" text="Select Station" /> <Button mnemonicParsing="false" onAction="#handleSelectStationButtonPress" text="Select Station" />
</children> </children>
<VBox.margin> <VBox.margin>
<Insets bottom="10.0" /> <Insets bottom="10.0" />
@ -74,7 +74,7 @@
<Font size="14.0" /> <Font size="14.0" />
</font> </font>
</Label> </Label>
<Button layoutX="534.0" layoutY="13.0" mnemonicParsing="false" onAction="#handleButtonPress" onMouseClicked="#handleButtonPress" text="Station Settings" AnchorPane.rightAnchor="6.5" AnchorPane.topAnchor="13.0" /> <Button layoutX="534.0" layoutY="13.0" mnemonicParsing="false" onMouseClicked="#handleSettingsButtonPress" text="Station Settings" AnchorPane.rightAnchor="6.5" AnchorPane.topAnchor="13.0" />
</children> </children>
</AnchorPane> </AnchorPane>
</children> </children>

View File

@ -1,21 +1,32 @@
package name.nathanmcrae; package name.nathanmcrae;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader; import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable; import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyEvent; import javafx.scene.input.KeyEvent;
import javafx.scene.input.KeyCode; import javafx.scene.input.KeyCode;
import javafx.scene.Parent; import javafx.scene.Parent;
import javafx.scene.Scene; import javafx.scene.Scene;
import javafx.stage.Modality;
import javafx.stage.Stage; import javafx.stage.Stage;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import java.net.URL;
import java.util.ResourceBundle;
public class NumbersStationController implements Initializable { public class NumbersStationController implements Initializable {
private Stage settingsStage; private Stage settingsStage;
private Stage selectStationStage;
private NumbersStationSettings settings;
private StationSettings selectedStation;
private StringProperty selectedStationName = new SimpleStringProperty();
@FXML @FXML
private Label lastRetrievedLabel; private Label lastRetrievedLabel;
@ -24,7 +35,10 @@ public class NumbersStationController implements Initializable {
private TextArea messageTextArea; private TextArea messageTextArea;
@FXML @FXML
private void handleButtonPress() { private TextField stationNameField;
@FXML
private void handleSettingsButtonPress() {
System.out.println("Button pressed!"); System.out.println("Button pressed!");
lastRetrievedLabel.setText("Button pressed!"); lastRetrievedLabel.setText("Button pressed!");
@ -44,8 +58,80 @@ public class NumbersStationController implements Initializable {
} }
} }
@FXML
private void handleSelectStationButtonPress() {
if (selectStationStage == null || !selectStationStage.isShowing()) {
try {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("NumbersStationSelection.fxml"));
Parent root = fxmlLoader.load();
// Pass settings to the controller
NumbersStationSelectionController controller = fxmlLoader.getController();
controller.setSettings(settings);
selectStationStage = new Stage();
selectStationStage.initModality(Modality.APPLICATION_MODAL);
selectStationStage.setUserData("test");
selectStationStage.setTitle("Numbers Station Selection");
selectStationStage.setScene(new Scene(root));
selectStationStage.show();
selectStationStage.setOnHiding(event -> {
selectedStationName.set((String) selectStationStage.getUserData());
if (selectedStation != null) {
selectedStation = settings.getStations().stream()
.filter(station -> station.getName().equals(selectedStationName.get()))
.findFirst()
.orElse(null);
}
settings.setSelectedStationName(selectedStationName.get());
XmlMapper xmlMapper = new XmlMapper();
try {
xmlMapper.writeValue(new File("setting-test.xml"), settings);
} catch (IOException e) {
e.printStackTrace();
}
});
} catch (Exception e) {
e.printStackTrace();
}
} else {
selectStationStage.toFront();
}
}
private void loadSettings() throws IOException {
File file = new File("setting-test.xml");
XmlMapper xmlMapper = new XmlMapper();
settings = xmlMapper.readValue(file, NumbersStationSettings.class);
}
@Override @Override
public void initialize(URL location, ResourceBundle resources) { public void initialize(URL location, ResourceBundle resources) {
stationNameField.textProperty().bindBidirectional(selectedStationName);
try {
loadSettings();
} catch (IOException e) {
e.printStackTrace();
}
selectedStationName.set(settings.getSelectedStationName());
if (selectedStationName.get() == null || selectedStationName.get() == "") {
selectedStation = settings.getStations().stream().findFirst().orElse(null);
selectedStationName.set(selectedStation.getName());
}
selectedStation = settings.getStations().stream()
.filter(station -> station.getName().equals(selectedStationName.get()))
.findFirst()
.orElse(null);
if (selectedStation == null) {
// TODO: create a new station and save it?
}
messageTextArea.addEventFilter(KeyEvent.ANY, event -> { messageTextArea.addEventFilter(KeyEvent.ANY, event -> {
int cursorPosition = messageTextArea.getCaretPosition(); int cursorPosition = messageTextArea.getCaretPosition();

View File

@ -0,0 +1,22 @@
<?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 maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="437.0" xmlns="http://javafx.com/javafx/23.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="name.nathanmcrae.NumbersStationSelectionController">
<children>
<Label layoutX="14.0" layoutY="14.0" text="Numbers Stations">
<font>
<Font size="20.0" />
</font>
</Label>
<Button layoutX="358.0" layoutY="17.0" mnemonicParsing="false" text="+" AnchorPane.rightAnchor="54.5" AnchorPane.topAnchor="17.0" onAction="#handleAddButtonPress"/>
<Button layoutX="391.0" layoutY="17.0" mnemonicParsing="false" prefHeight="25.0" prefWidth="25.0" text="-" AnchorPane.rightAnchor="21.0" AnchorPane.topAnchor="17.0" onAction="#handleRemoveButtonPress"/>
<ListView fx:id="stationListView" layoutX="14.0" layoutY="57.0" prefHeight="301.0" prefWidth="409.0" AnchorPane.bottomAnchor="42.0" AnchorPane.leftAnchor="14.0" AnchorPane.rightAnchor="14.0" AnchorPane.topAnchor="57.0" />
<Button layoutX="313.0" layoutY="365.0" mnemonicParsing="false" onMousePressed="#handleSelectButtonPress" text="Select" AnchorPane.bottomAnchor="10.0" AnchorPane.rightAnchor="76.5" />
<Button layoutX="370.0" layoutY="365.0" mnemonicParsing="false" text="Cancel" AnchorPane.bottomAnchor="10.0" AnchorPane.rightAnchor="15.5" />
</children>
</AnchorPane>

View File

@ -0,0 +1,89 @@
package name.nathanmcrae;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.TextInputDialog;
import javafx.event.ActionEvent;
import javafx.event.Event;
import javafx.scene.Node;
import javafx.stage.Stage;
import java.util.Optional;
public class NumbersStationSelectionController {
@FXML
private ListView<StationSettings> stationListView;
private ObservableList<StationSettings> stationList;
public NumbersStationSelectionController() {
// Initialize the list with an empty list
stationList = FXCollections.observableArrayList();
}
@FXML
private void initialize() {
// Set custom cell factory to display station name
stationListView.setCellFactory(param -> new ListCell<StationSettings>() {
@Override
protected void updateItem(StationSettings item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null || item.getName() == null) {
setText(null);
} else {
setText(item.getName());
}
}
});
}
public void setSettings(NumbersStationSettings settings) {
// Populate the list with stations from settings
stationList.addAll(settings.getStations());
stationListView.setItems(stationList);
}
@FXML
private void handleAddButtonPress(ActionEvent event) {
// Create a TextInputDialog
TextInputDialog dialog = new TextInputDialog();
dialog.setTitle("New Station");
dialog.setHeaderText("Add a New Station");
dialog.setContentText("Please enter the station name:");
// Show the dialog and capture the result
Optional<String> result = dialog.showAndWait();
result.ifPresent(stationName -> {
// Add the new station to the list
StationSettings newStation = new StationSettings();
newStation.setName(stationName);
stationList.add(newStation);
});
}
@FXML
private void handleRemoveButtonPress(ActionEvent event) {
// Remove the selected item from the list
int selectedIndex = stationListView.getSelectionModel().getSelectedIndex();
if (selectedIndex >= 0) {
stationList.remove(selectedIndex);
}
}
@FXML
private void handleSelectButtonPress(Event e) {
Node node = (Node) e.getSource();
Stage stage = (Stage) node.getScene().getWindow();
StationSettings selectedStation = stationListView.getSelectionModel().getSelectedItem();
if (selectedStation != null) {
stage.setUserData(selectedStation.getName());
System.out.println("Selected Station: " + selectedStation.getName());
}
stage.close();
}
}

View File

@ -12,8 +12,7 @@
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?> <?import javafx.scene.text.Font?>
<AnchorPane prefHeight="700.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/23.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="name.nathanmcrae.NumbersStationSettingsController">
<AnchorPane prefHeight="700.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/23.0.1" xmlns:fx="http://javafx.com/fxml/1">
<children> <children>
<ScrollPane fitToWidth="true" hbarPolicy="NEVER" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="297.0" prefWidth="600.0" AnchorPane.bottomAnchor="40.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> <ScrollPane fitToWidth="true" hbarPolicy="NEVER" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="297.0" prefWidth="600.0" AnchorPane.bottomAnchor="40.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<content> <content>
@ -22,7 +21,7 @@
<FlowPane alignment="CENTER_LEFT" prefHeight="41.0" prefWidth="640.0"> <FlowPane alignment="CENTER_LEFT" prefHeight="41.0" prefWidth="640.0">
<children> <children>
<Label prefHeight="17.0" prefWidth="49.0" text="Station: " /> <Label prefHeight="17.0" prefWidth="49.0" text="Station: " />
<TextField editable="false" style="-fx-background-color: #EEEEEE; -fx-border-color: #AAAAAA;" text="My Station"> <TextField fx:id="stationNameField" editable="false" style="-fx-background-color: #EEEEEE; -fx-border-color: #AAAAAA;" text="My Station">
<FlowPane.margin> <FlowPane.margin>
<Insets right="10.0" /> <Insets right="10.0" />
</FlowPane.margin> </FlowPane.margin>
@ -76,7 +75,7 @@
</font> </font>
</Label> </Label>
<Label layoutX="170.0" layoutY="16.0" text="Numbers station address:" /> <Label layoutX="170.0" layoutY="16.0" text="Numbers station address:" />
<TextField layoutX="180.0" layoutY="40.0" prefHeight="25.0" prefWidth="390.0" AnchorPane.leftAnchor="188.0" AnchorPane.rightAnchor="0.0" /> <TextField fx:id="stationAddressField" layoutX="180.0" layoutY="40.0" prefHeight="25.0" prefWidth="390.0" AnchorPane.leftAnchor="188.0" AnchorPane.rightAnchor="0.0" />
</children> </children>
</AnchorPane> </AnchorPane>
<Separator prefWidth="200.0" /> <Separator prefWidth="200.0" />
@ -89,7 +88,7 @@
</ScrollPane> </ScrollPane>
<FlowPane alignment="CENTER_RIGHT" prefHeight="40.0" prefWidth="600.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0"> <FlowPane alignment="CENTER_RIGHT" prefHeight="40.0" prefWidth="600.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0">
<children> <children>
<Button mnemonicParsing="false" text="Save" textAlignment="RIGHT"> <Button mnemonicParsing="false" onMousePressed="#handleSaveButtonPress" text="Save" textAlignment="RIGHT">
<FlowPane.margin> <FlowPane.margin>
<Insets right="10.0" /> <Insets right="10.0" />
</FlowPane.margin> </FlowPane.margin>

View File

@ -0,0 +1,40 @@
package name.nathanmcrae;
import java.util.ArrayList;
public class NumbersStationSettings {
private int digitsPerGroup;
private String username;
private int refreshInterval;
private String selectedStationName;
private ArrayList<StationSettings> stations;
public ArrayList<StationSettings> getStations() {
return stations;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public int getRefreshInterval() {
return refreshInterval;
}
public void setRefreshInterval(int refreshInterval) {
this.refreshInterval = refreshInterval;
}
public String getSelectedStationName() {
return selectedStationName;
}
public void setSelectedStationName(String selectedStationName) {
this.selectedStationName = selectedStationName;
}
}

View File

@ -0,0 +1,47 @@
package name.nathanmcrae;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import java.io.File;
import java.io.IOException;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.fxml.FXML;
import javafx.scene.control.TextField;
public class NumbersStationSettingsController {
private NumbersStationSettings settings;
private StringProperty stationNameAndAddress = new SimpleStringProperty();
@FXML
private TextField stationNameField;
@FXML
private TextField stationAddressField;
public NumbersStationSettingsController() throws IOException {
System.out.println("Created settings controller");
File file = new File("setting-test.xml");
XmlMapper xmlMapper = new XmlMapper();
settings = xmlMapper.readValue(file, NumbersStationSettings.class);
settings.setRefreshInterval(settings.getRefreshInterval() + 40);
settings.getStations().add(new StationSettings());
}
@FXML
private void initialize() {
stationNameField.textProperty().bindBidirectional(stationNameAndAddress);
stationAddressField.textProperty().bindBidirectional(stationNameAndAddress);
}
@FXML
private void handleSaveButtonPress() throws IOException {
XmlMapper xmlMapper = new XmlMapper();
xmlMapper.writeValue(new File("setting-test.xml"), settings);
}
public StringProperty stationNameAndAddressProperty() {
return stationNameAndAddress;
}
}

View File

@ -0,0 +1,36 @@
package name.nathanmcrae;
public class StationSettings {
private String name;
private int digitsPerGroup;
private int messageLength;
public String getName() {
return name;
}
public void setName(String newName) {
name = newName;
}
public int getDigitsPerGroup() {
return digitsPerGroup;
}
public void setDigitsPerGroup(int newDigitsPerGroup) {
digitsPerGroup = newDigitsPerGroup;
}
public int getMessageLength() {
return messageLength;
}
public void setMessageLength(int newMessageLength) {
messageLength = newMessageLength;
}
@Override
public String toString() {
return name;
}
}