Compare commits
	
		
			3 Commits
		
	
	
		
			837b08c4cb
			...
			5a3df459f9
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 5a3df459f9 | |||
| 1ae75d4891 | |||
| 0704a4a931 | 
| @@ -0,0 +1,34 @@ | ||||
| package name.nathanmcrae.numbersstation; | ||||
|  | ||||
| import java.io.PrintWriter; | ||||
| import java.io.StringWriter; | ||||
| import java.text.SimpleDateFormat; | ||||
| import java.util.Date; | ||||
| import java.util.logging.Formatter; | ||||
| import java.util.logging.LogRecord; | ||||
|  | ||||
| public class CustomFormatter extends Formatter { | ||||
|     private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"); | ||||
|  | ||||
|     @Override | ||||
|     public String format(LogRecord record) { | ||||
|         String timestamp = dateFormat.format(new Date(record.getMillis())); | ||||
|         String logLevel = record.getLevel().getName(); | ||||
|         String className = record.getSourceClassName(); | ||||
|         String methodName = record.getSourceMethodName(); | ||||
|         String message = formatMessage(record); | ||||
|  | ||||
|         StringBuilder logMessage = new StringBuilder(); | ||||
|         logMessage.append(String.format("%s\t%s\t%s\t%s\t%s", timestamp, logLevel, className, methodName, message)); | ||||
|  | ||||
|         if (record.getThrown() != null) { | ||||
|             StringWriter sw = new StringWriter(); | ||||
|             PrintWriter pw = new PrintWriter(sw); | ||||
|             record.getThrown().printStackTrace(pw); | ||||
|             logMessage.append("\n\t").append(sw.toString()); | ||||
|         } | ||||
|  | ||||
|         logMessage.append(System.lineSeparator()); | ||||
|         return logMessage.toString(); | ||||
|     } | ||||
| } | ||||
| @@ -1,21 +1,74 @@ | ||||
| package name.nathanmcrae.numbersstation; | ||||
|  | ||||
| import java.io.IOException; | ||||
| import java.nio.file.Files; | ||||
| import java.nio.file.Path; | ||||
| import java.nio.file.Paths; | ||||
| import java.util.logging.FileHandler; | ||||
| import java.util.logging.Logger; | ||||
| import java.util.logging.Level; | ||||
| import javafx.application.Application; | ||||
| import javafx.application.Platform; | ||||
| import javafx.fxml.FXMLLoader; | ||||
| import javafx.scene.Parent; | ||||
| import javafx.scene.Scene; | ||||
| import javafx.stage.Stage; | ||||
|  | ||||
| public class Main extends Application { | ||||
|     private static final Logger logger = Logger.getLogger(Main.class.getName()); | ||||
|  | ||||
|     private static Path statePath = null; | ||||
|  | ||||
|     public Path getStatePath() { | ||||
|         if (statePath == null) { | ||||
|             String stateHome = System.getenv("XDG_STATE_HOME"); | ||||
|             if (stateHome == null || stateHome.isEmpty() || !Paths.get(stateHome).isAbsolute()) { | ||||
|                 String userHome = System.getProperty("user.home"); | ||||
|                 statePath = Paths.get(userHome, ".local", "state", "numbers-station"); | ||||
|             } else { | ||||
|                 statePath = Paths.get(stateHome, "numbers-station"); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return statePath; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void start(Stage primaryStage) throws Exception { | ||||
|         setupLogger(); | ||||
|         Parent root = FXMLLoader.load(getClass().getResource("MainView.fxml")); | ||||
|         primaryStage.setTitle("Numbers Station"); | ||||
|         primaryStage.setScene(new Scene(root)); | ||||
|         primaryStage.show(); | ||||
|         logger.info("Application started"); | ||||
|     } | ||||
|  | ||||
|     private void setupLogger() { | ||||
|         try { | ||||
|             Path logFile = getStatePath().resolve("main.log"); | ||||
|  | ||||
|             if (!Files.exists(logFile.getParent())) { | ||||
|                 Files.createDirectories(logFile.getParent()); | ||||
|             } | ||||
|  | ||||
|             FileHandler fileHandler = new FileHandler(logFile.toString(), true); | ||||
|             fileHandler.setFormatter(new CustomFormatter()); | ||||
|             logger.addHandler(fileHandler); | ||||
|         } catch (IOException e) { | ||||
|             System.out.println("Failed to set up logger: " + e.getMessage()); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public static void main(String[] args) { | ||||
|         Thread.setDefaultUncaughtExceptionHandler((thread, throwable) -> { | ||||
|             logger.log(Level.SEVERE, "Unhandled exception caught", throwable); | ||||
|         }); | ||||
|  | ||||
|         Platform.setImplicitExit(false); | ||||
|         Thread.currentThread().setUncaughtExceptionHandler((thread, throwable) -> { | ||||
|             logger.log(Level.SEVERE, "Unhandled exception in JavaFX application thread", throwable); | ||||
|         }); | ||||
|  | ||||
|         launch(args); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -10,6 +10,8 @@ import java.net.URL; | ||||
| import java.nio.file.Files; | ||||
| import java.nio.file.Path; | ||||
| import java.nio.file.Paths; | ||||
| import java.util.logging.Level; | ||||
| import java.util.logging.Logger; | ||||
| import java.util.Random; | ||||
| import java.util.ResourceBundle; | ||||
| import javafx.beans.property.SimpleStringProperty; | ||||
| @@ -29,6 +31,8 @@ import javafx.stage.Modality; | ||||
| import javafx.stage.Stage; | ||||
|  | ||||
| public class MainController implements Initializable { | ||||
|     private static final Logger logger = Logger.getLogger(Main.class.getName()); | ||||
|  | ||||
|     private Stage settingsStage; | ||||
|     private Stage selectStationStage; | ||||
|     private MainSettings settings; | ||||
| @@ -75,7 +79,7 @@ public class MainController implements Initializable { | ||||
|                     updateStationSettings(selectedStation); | ||||
|                 }); | ||||
|             } catch (Exception e) { | ||||
|                 e.printStackTrace(); | ||||
|                 logger.log(Level.SEVERE, "Exception while opening settings", e); | ||||
|             } | ||||
|         } else { | ||||
|             settingsStage.toFront(); | ||||
| @@ -83,7 +87,7 @@ public class MainController implements Initializable { | ||||
|     } | ||||
|  | ||||
|     @FXML | ||||
|     private void handleSelectStationButtonPress() { | ||||
|     private void handleSelectStationButtonPress() throws Exception { | ||||
|         if (selectStationStage == null || !selectStationStage.isShowing()) { | ||||
|             try { | ||||
|                 FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("StationSelectionView.fxml")); | ||||
| @@ -107,7 +111,7 @@ public class MainController implements Initializable { | ||||
|                     updateStationSettings(newSelectedStation); | ||||
|                 }); | ||||
|             } catch (Exception e) { | ||||
|                 e.printStackTrace(); | ||||
|                 logger.log(Level.SEVERE, "Exception while selecting station", e); | ||||
|             } | ||||
|         } else { | ||||
|             selectStationStage.toFront(); | ||||
| @@ -118,12 +122,10 @@ public class MainController implements Initializable { | ||||
|         XmlMapper xmlMapper = new XmlMapper(); | ||||
|         xmlMapper.registerModule(new JavaTimeModule()); | ||||
|         String userHome = System.getProperty("user.home"); | ||||
|         // TODO: XDG | ||||
|         Path directoryPath = Paths.get(userHome, ".numbers-station"); | ||||
|         Path filePath = directoryPath.resolve("settings.xml"); | ||||
|         try { | ||||
|  | ||||
|             // Create the directory if it doesn't exist | ||||
|         Path filePath = MainSettings.getSettingsFilePath(); | ||||
|         Path directoryPath = filePath.getParent(); | ||||
|         try { | ||||
|             if (!Files.exists(directoryPath)) { | ||||
|                 Files.createDirectories(directoryPath); | ||||
|             } | ||||
| @@ -141,9 +143,8 @@ public class MainController implements Initializable { | ||||
|                 } | ||||
|             } | ||||
|         } catch (IOException e) { | ||||
|             // Print the contents of filePath | ||||
|             logger.log(Level.SEVERE, "Failed to load settings from " + filePath.toString(), e); | ||||
|             System.out.println("File contents: " + Files.readString(filePath)); | ||||
|             e.printStackTrace(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -218,6 +219,8 @@ public class MainController implements Initializable { | ||||
|     } | ||||
|  | ||||
|     private void updateStationSettings(StationSettings newStationSettings) { | ||||
|         logger.info("Updating station settings: " + newStationSettings.getName()); | ||||
|  | ||||
|         if (newStationSettings == null) { | ||||
|             return; | ||||
|         } | ||||
|   | ||||
| @@ -11,8 +11,11 @@ import java.nio.file.Files; | ||||
| import java.nio.file.Path; | ||||
| import java.nio.file.Paths; | ||||
| import java.util.ArrayList; | ||||
| import java.util.logging.Logger; | ||||
|  | ||||
| public class MainSettings { | ||||
|     private static final Logger logger = Logger.getLogger(Main.class.getName()); | ||||
|  | ||||
|     private int digitsPerGroup; | ||||
|     private String username; | ||||
|     private int refreshInterval; | ||||
| @@ -25,6 +28,21 @@ public class MainSettings { | ||||
|         stations.add(new StationSettings("Station 1")); | ||||
|     } | ||||
|  | ||||
|     public static Path getSettingsFilePath() { | ||||
|         String configHome = System.getenv("XDG_CONFIG_HOME"); | ||||
|         Path directoryPath; | ||||
|         Path filePath; | ||||
|  | ||||
|         if (configHome != null && !configHome.isEmpty() && Paths.get(configHome).isAbsolute()) { | ||||
|             directoryPath = Paths.get(configHome, "numbers-station"); | ||||
|         } else { | ||||
|             String userHome = System.getProperty("user.home"); | ||||
|             directoryPath = Paths.get(userHome, ".config", "numbers-station"); | ||||
|         } | ||||
|  | ||||
|         return directoryPath.resolve("main-settings.xml"); | ||||
|     } | ||||
|  | ||||
|     public ArrayList<StationSettings> getStations() { | ||||
|         return stations; | ||||
|     } | ||||
| @@ -58,16 +76,15 @@ public class MainSettings { | ||||
|         xmlMapper.registerModule(new JavaTimeModule()); | ||||
|         xmlMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); | ||||
|         try { | ||||
|             String userHome = System.getProperty("user.home"); | ||||
|             Path directoryPath = Paths.get(userHome, ".numbers-station"); | ||||
|             Path filePath = directoryPath.resolve("settings.xml"); | ||||
|             Path filePath = getSettingsFilePath(); | ||||
|             Path directoryPath = filePath.getParent(); | ||||
|  | ||||
|             // Create the directory if it doesn't exist | ||||
|             if (!Files.exists(directoryPath)) { | ||||
|                 Files.createDirectories(directoryPath); | ||||
|             } | ||||
|  | ||||
|             xmlMapper.writeValue(new File(filePath.toString()), this); | ||||
|             logger.info("Settings saved to " + filePath.toString()); | ||||
|         } catch (IOException e) { | ||||
|             e.printStackTrace(); | ||||
|         } | ||||
|   | ||||
| @@ -63,6 +63,13 @@ public class StationSelectionController { | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     @FXML | ||||
|     private void handleCancelButtonPress(Event event) { | ||||
|         Node node = (Node) event.getSource(); | ||||
|         Stage stage = (Stage) node.getScene().getWindow(); | ||||
|         stage.close(); | ||||
|     } | ||||
|  | ||||
|     @FXML | ||||
|     private void handleRemoveButtonPress(ActionEvent event) { | ||||
|         int selectedIndex = stationListView.getSelectionModel().getSelectedIndex(); | ||||
|   | ||||
| @@ -13,10 +13,10 @@ | ||||
|             <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"/> | ||||
|       <Button layoutX="358.0" layoutY="17.0" mnemonicParsing="false" onAction="#handleAddButtonPress" text="+" AnchorPane.rightAnchor="54.5" AnchorPane.topAnchor="17.0" /> | ||||
|       <Button layoutX="391.0" layoutY="17.0" mnemonicParsing="false" onAction="#handleRemoveButtonPress" prefHeight="25.0" prefWidth="25.0" text="-" AnchorPane.rightAnchor="21.0" AnchorPane.topAnchor="17.0" /> | ||||
|       <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" /> | ||||
|       <Button layoutX="370.0" layoutY="365.0" mnemonicParsing="false" onMousePressed="#handleCancelButtonPress" text="Cancel" AnchorPane.bottomAnchor="10.0" AnchorPane.rightAnchor="15.5" /> | ||||
|    </children> | ||||
| </AnchorPane> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user