001package jmri.util; 002 003import java.awt.GraphicsConfiguration; 004import java.awt.GraphicsEnvironment; 005import java.awt.geom.AffineTransform; 006import java.io.*; 007import java.util.ArrayList; 008import java.util.List; 009import java.util.Properties; 010 011import jmri.InstanceManager; 012import jmri.ShutDownManager; 013 014/** 015 * Allow the user to configure properties that needs to be setup very early 016 * when JMRI starts, for example before Swing starts up. 017 * 018 * @author Daniel Bergqvist Copyright (C) 2021 019 */ 020public class EarlyInitializationPreferences { 021 022 private static final String FILENAME = jmri.util.FileUtil 023 .getExternalFilename("settings:JMRI_InitPreferences.properties"); 024 025 private static final EarlyInitializationPreferences INSTANCE = 026 new EarlyInitializationPreferences(); 027 028 private final Properties preferences = new Properties(); 029 030 // The preferences might have been changed after startup, but we want to 031 // keep a list of the preferences used at startup for the JMRI Context. 032 private final List<String> startupPrefs = new ArrayList<>(); 033 034 035 private EarlyInitializationPreferences() { 036 // Private constructor to protect singleton pattern. 037 } 038 039 public static EarlyInitializationPreferences getInstance() { 040 return INSTANCE; 041 } 042 043 public String getPreference(String pref) { 044 return preferences.getProperty(pref); 045 } 046 047 public void setPreference(String pref, String value) { 048 preferences.setProperty(pref, value); 049 store(); 050 } 051 052 public boolean getGUIForce100percentScaling() { 053 String value = getPreference("sun.java2d.uiScale"); 054 if (value == null) return false; 055 try { 056 return Integer.parseInt(value) == 1; 057 } catch (NumberFormatException e) { 058 return false; 059 } 060 } 061 062 public void setGUIForce100percentScaling(boolean value) { 063 setPreference("sun.java2d.uiScale", value ? "1" : "0"); 064 } 065 066 /** 067 * Load the preferences at startup and set them. 068 */ 069 public void loadAndSetPreferences() { 070 load(); 071 for (String pref : preferences.stringPropertyNames()) { 072 System.setProperty(pref, preferences.getProperty(pref)); 073 startupPrefs.add(pref + ": " + preferences.getProperty(pref)); 074 } 075 } 076 077 /** 078 * Return the preferences set at startup. 079 * @return the preferences 080 */ 081 public List<String> getStartupPreferences() { 082 return startupPrefs; 083 } 084 085 private boolean store() { 086 try (OutputStream output = new FileOutputStream(FILENAME)) { 087 preferences.store(output, null); 088 return true; 089 } catch (FileNotFoundException e){ 090 System.err.println("Could not store to " + FILENAME 091 + ", Normal if JMRI has not been started before."); 092 } catch (IOException ex) { 093 ex.printStackTrace(System.err); 094 } 095 return false; 096 } 097 098 private void load() { 099 try (InputStream input = new FileInputStream(FILENAME)) { 100 preferences.load(input); 101 } catch (IOException ex) { 102 setupNewPreferences(); 103 } 104 } 105 106 private void setupNewPreferences() { 107 boolean restartIsNeeded = false; 108 109 if (SystemType.isWindows()) { 110 int uiScale = 1; 111 112 if (!GraphicsEnvironment.isHeadless()) { 113 try { 114 // We must restart JMRI since we read the scale. Java 115 // will not listen to sun.java2d.uiScale unless we set 116 // it _before_ awt and Swing is started. 117 restartIsNeeded = true; 118 119 GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration(); 120 AffineTransform transform = gc.getDefaultTransform(); 121 122 double scaleX = transform.getScaleX(); 123 double scaleY = transform.getScaleY(); 124 System.err.format("ScaleX: %1.2f%n", scaleX); 125 System.err.format("ScaleY: %1.2f%n", scaleY); 126 127 // Don't set uiScale to 1 if Windows has a scaling above 125% 128 if ((scaleX >= 1.3) || (scaleY >= 1.3)) uiScale = 0; 129 } catch (NullPointerException e) { 130 e.printStackTrace(System.err); 131 } 132 } 133 134 preferences.setProperty("sun.java2d.uiScale", Integer.toString(uiScale)); 135 } 136 137 if (store() && restartIsNeeded) { 138 InstanceManager.getDefault(ShutDownManager.class).restart(); 139 } 140 } 141 142// private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(EarlyInitializationPreferences.class); 143}