package dasherJava.core.settings; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; public class SettingsFileReader { public static Settings readSettingsFile(String fileName) throws IOException { try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(fileName), StandardCharsets.UTF_8))) { Map settingsLines = new HashMap<>(); String line; while ((line=reader.readLine())!=null) { //read and store all lines String[] parts = line.split("=", 2); if (parts.length!=2) { System.out.println("SettingsFileReader: Ignoring invalid input line \""+line +"\". Lines must be of the form \"key=value\""); continue; } if (settingsLines.containsKey(parts[0])) System.out.println("SettingsFileReader: Duplicate definition of the \""+parts[0] +"\" setting, overwriting the previous value"); settingsLines.put(parts[0], parts[1]); } int frameRate = Settings.DEFAULT_SETTINGS.getFrameRate(); String antialiasing = Settings.DEFAULT_SETTINGS.getAntialiasing(); String textAntialiasing = Settings.DEFAULT_SETTINGS.getTextAntialiasing(); int windowX = Settings.DEFAULT_SETTINGS.getWindowX(); int windowY = Settings.DEFAULT_SETTINGS.getWindowY(); int windowWidth = Settings.DEFAULT_SETTINGS.getWindowWidth(); int windowHeight = Settings.DEFAULT_SETTINGS.getWindowHeight(); int spaceBehindNodes = Settings.DEFAULT_SETTINGS.getSpaceBehindNodes(); String windowAlwaysOnTop = Settings.DEFAULT_SETTINGS.getWindowAlwaysOnTop(); String windowUnfocusable = Settings.DEFAULT_SETTINGS.getWindowUnfocusable(); boolean rememberWindowPosition = Settings.DEFAULT_SETTINGS.getRememberWindowPosition(); boolean rememberWindowSize = Settings.DEFAULT_SETTINGS.getRememberWindowSize(); boolean showStatusBar = Settings.DEFAULT_SETTINGS.getShowStatusBar(); String confirmExit = Settings.DEFAULT_SETTINGS.getConfirmExit(); List alphabetHistory = Settings.DEFAULT_SETTINGS.getAlphabetHistory(); int maxAlphabetHistoryLength = Settings.DEFAULT_SETTINGS.getMaxAlphabetHistoryLength(); String colorPaletteNameOverride = Settings.DEFAULT_SETTINGS.getColorPaletteNameOverride(); String orientationOverride = Settings.DEFAULT_SETTINGS.getOrientationOverride(); int ppmMaxOrder = Settings.DEFAULT_SETTINGS.getPPMMaxOrder(); int ppmAlpha = Settings.DEFAULT_SETTINGS.getPPMAlpha(); int ppmBeta = Settings.DEFAULT_SETTINGS.getPPMBeta(); int ppmUniform = Settings.DEFAULT_SETTINGS.getPPMUniform(); String textOutputTarget = Settings.DEFAULT_SETTINGS.getTextOutputTarget(); String inputProvider = Settings.DEFAULT_SETTINGS.getInputProvider(); boolean startStopOnLeftClick = Settings.DEFAULT_SETTINGS.getStartStopOnLeftClick(); float movementSpeed = Settings.DEFAULT_SETTINGS.getMovementSpeed(); boolean onlineLearning = Settings.DEFAULT_SETTINGS.getOnlineLearning(); int onlineLearningDelay = Settings.DEFAULT_SETTINGS.getOnlineLearningDelay(); int maxNumberOfNodes = Settings.DEFAULT_SETTINGS.getMaxNumberOfNodes(); int maxNumberOfOldRootNodes = Settings.DEFAULT_SETTINGS.getMaxNumberOfOldRootNodes(); float minGainForNodeTrade = Settings.DEFAULT_SETTINGS.getMinGainForNodeTrade(); float minNodeSizeForExpansion = Settings.DEFAULT_SETTINGS.getMinNodeSizeForExpansion(); float maxNodeSizeForCollapse = Settings.DEFAULT_SETTINGS.getMaxNodeSizeForCollapse(); float minNodeSizeForRendering = Settings.DEFAULT_SETTINGS.getMinNodeSizeForRendering(); float minGroupSizeForRendering = Settings.DEFAULT_SETTINGS.getMinGroupSizeForRendering(); float dropRootNodeMarginTop = Settings.DEFAULT_SETTINGS.getDropRootNodeMarginTop(); float dropRootNodeMarginBottom = Settings.DEFAULT_SETTINGS.getDropRootNodeMarginBottom(); float dropRootNodeMarginSize = Settings.DEFAULT_SETTINGS.getDropRootNodeMarginSize(); float zoomOutMarginTop = Settings.DEFAULT_SETTINGS.getZoomOutMarginTop(); float zoomOutMarginBottom = Settings.DEFAULT_SETTINGS.getZoomOutMarginBottom(); float zoomOutMarginSize = Settings.DEFAULT_SETTINGS.getZoomOutMarginSize(); int normalFontSize = Settings.DEFAULT_SETTINGS.getNormalFontSize(); int mediumFontSize = Settings.DEFAULT_SETTINGS.getMediumFontSize(); int highlightFontSize = Settings.DEFAULT_SETTINGS.getHighlightFontSize(); float mediumFontSizeMarginBefore = Settings.DEFAULT_SETTINGS.getMediumFontSizeMarginBefore(); float mediumFontSizeMarginAfter = Settings.DEFAULT_SETTINGS.getMediumFontSizeMarginAfter(); float nodeOutlineThickness = Settings.DEFAULT_SETTINGS.getNodeOutlineThickness(); float inputLineThickness = Settings.DEFAULT_SETTINGS.getInputLineThickness(); float crosshairThickness = Settings.DEFAULT_SETTINGS.getCrosshairThickness(); float crosshairWidth = Settings.DEFAULT_SETTINGS.getCrosshairWidth(); String startStopHandler = Settings.DEFAULT_SETTINGS.getStartStopHandler(); float circleSize = Settings.DEFAULT_SETTINGS.getCircleSize(); float circleOutlineThickness = Settings.DEFAULT_SETTINGS.getCircleOutlineThickness(); float circleOutlineThicknessHold = Settings.DEFAULT_SETTINGS.getCircleOutlineThicknessHold(); int circleHoldStartTime = Settings.DEFAULT_SETTINGS.getCircleHoldStartTime(); int circleHoldStopTime = Settings.DEFAULT_SETTINGS.getCircleHoldStopTime(); float firstBoxSize = Settings.DEFAULT_SETTINGS.getFirstBoxSize(); float firstBoxLeftInset = Settings.DEFAULT_SETTINGS.getFirstBoxLeftInset(); float firstBoxRightInset = Settings.DEFAULT_SETTINGS.getFirstBoxRightInset(); float firstBoxOutlineThickness = Settings.DEFAULT_SETTINGS.getFirstBoxOutlineThickness(); float firstBoxOutlineThicknessHold = Settings.DEFAULT_SETTINGS.getFirstBoxOutlineThicknessHold(); int firstBoxHoldTime = Settings.DEFAULT_SETTINGS.getFirstBoxHoldTime(); int firstBoxResetTime = Settings.DEFAULT_SETTINGS.getFirstBoxResetTime(); float secondBoxSize = Settings.DEFAULT_SETTINGS.getSecondBoxSize(); float secondBoxLeftInset = Settings.DEFAULT_SETTINGS.getSecondBoxLeftInset(); float secondBoxRightInset = Settings.DEFAULT_SETTINGS.getSecondBoxRightInset(); float secondBoxOutlineThickness = Settings.DEFAULT_SETTINGS.getSecondBoxOutlineThickness(); float secondBoxOutlineThicknessHold = Settings.DEFAULT_SETTINGS.getSecondBoxOutlineThicknessHold(); int secondBoxHoldTime = Settings.DEFAULT_SETTINGS.getSecondBoxHoldTime(); int socketOutputPort = Settings.DEFAULT_SETTINGS.getSocketOutputPort(); String joystickInputName = Settings.DEFAULT_SETTINGS.getJoystickInputName(); String joystickInputComponentNameX = Settings.DEFAULT_SETTINGS.getJoystickInputComponentNameX(); float joystickInputSensitivityX = Settings.DEFAULT_SETTINGS.getJoystickInputSensitivityX(); float joystickInputOffsetX = Settings.DEFAULT_SETTINGS.getJoystickInputOffsetX(); String joystickInputComponentNameY = Settings.DEFAULT_SETTINGS.getJoystickInputComponentNameY(); float joystickInputSensitivityY = Settings.DEFAULT_SETTINGS.getJoystickInputSensitivityY(); float joystickInputOffsetY = Settings.DEFAULT_SETTINGS.getJoystickInputOffsetY(); String joystickInputComponentNameStartStop = Settings.DEFAULT_SETTINGS.getJoystickInputComponentNameStartStop(); int socketInputPort = Settings.DEFAULT_SETTINGS.getSocketInputPort(); String socketInputLabelX = Settings.DEFAULT_SETTINGS.getSocketInputLabelX(); float socketInputMinX = Settings.DEFAULT_SETTINGS.getSocketInputMinX(); float socketInputMaxX = Settings.DEFAULT_SETTINGS.getSocketInputMaxX(); String socketInputLabelY = Settings.DEFAULT_SETTINGS.getSocketInputLabelY(); float socketInputMinY = Settings.DEFAULT_SETTINGS.getSocketInputMinY(); float socketInputMaxY = Settings.DEFAULT_SETTINGS.getSocketInputMaxY(); String socketInputLabelStartStop = Settings.DEFAULT_SETTINGS.getSocketInputLabelStartStop(); for (Entry entry : settingsLines.entrySet()) { //process stored lines switch (entry.getKey()) { case "frameRate": try { frameRate=Integer.parseInt(entry.getValue(), 10); } catch (NumberFormatException ex) { System.out.println("SettingsFileReader: Invalid \"frameRate\" setting, using default (\"" +Settings.DEFAULT_SETTINGS.getFrameRate()+"\"): NumberFormatException: "+ex.getMessage()); } break; case "antialiasing": antialiasing=entry.getValue(); break; case "textAntialiasing": textAntialiasing=entry.getValue(); break; case "windowX": try { windowX=Integer.parseInt(entry.getValue(), 10); } catch (NumberFormatException ex) { System.out.println("SettingsFileReader: Invalid \"windowX\" setting, using default (\"" +Settings.DEFAULT_SETTINGS.getWindowX()+"\"): NumberFormatException: "+ex.getMessage()); } break; case "windowY": try { windowY=Integer.parseInt(entry.getValue(), 10); } catch (NumberFormatException ex) { System.out.println("SettingsFileReader: Invalid \"windowY\" setting, using default (\"" +Settings.DEFAULT_SETTINGS.getWindowY()+"\"): NumberFormatException: "+ex.getMessage()); } break; case "windowWidth": try { windowWidth=Integer.parseInt(entry.getValue(), 10); } catch (NumberFormatException ex) { System.out.println("SettingsFileReader: Invalid \"windowWidth\" setting, using default (\"" +Settings.DEFAULT_SETTINGS.getWindowWidth()+"\"): NumberFormatException: "+ex.getMessage()); } break; case "windowHeight": try { windowHeight=Integer.parseInt(entry.getValue(), 10); } catch (NumberFormatException ex) { System.out.println("SettingsFileReader: Invalid \"windowHeight\" setting, using default (\"" +Settings.DEFAULT_SETTINGS.getWindowHeight()+"\"): NumberFormatException: "+ex.getMessage()); } break; case "spaceBehindNodes": try { spaceBehindNodes=Integer.parseInt(entry.getValue(), 10); } catch (NumberFormatException ex) { System.out.println("SettingsFileReader: Invalid \"spaceBehindNodes\" setting, using default (\"" +Settings.DEFAULT_SETTINGS.getSpaceBehindNodes()+"\"): NumberFormatException: "+ex.getMessage()); } break; case "windowAlwaysOnTop": windowAlwaysOnTop=entry.getValue(); break; case "windowUnfocusable": windowUnfocusable=entry.getValue(); break; case "rememberWindowPosition": rememberWindowPosition=!entry.getValue().equalsIgnoreCase("false"); //default value is true break; case "rememberWindowSize": rememberWindowSize=!entry.getValue().equalsIgnoreCase("false"); //default value is true break; case "showStatusBar": showStatusBar=!entry.getValue().equalsIgnoreCase("false"); //default value is true break; case "confirmExit": confirmExit=entry.getValue(); break; case "alphabetHistory": //RegEx with negative lookbehind: Only match semicolons that are not escaped with a backslash alphabetHistory=new ArrayList<>(Arrays.asList(entry.getValue().split("(?