38b758702dae3861a271e7274f5ffb47546d9817
[jalview.git] / HiDPISetting.java
1 package jalview.bin;
2
3 import java.awt.HeadlessException;
4
5 public class HiDPISetting
6 {
7   private static final int hidpiThreshold = 160;
8
9   private static final int hidpiMultiThreshold = 240;
10
11   private static final int bigScreenThreshold = 1400;
12
13   public static final String scalePropertyName = "sun.java2d.uiScale";
14
15   private static final boolean isLinux;
16
17   // private static final boolean isAMac;
18
19   // private static final boolean isWindows;
20
21   public static final String setHiDPIPropertyName = "setHiDPI";
22
23   public static final String setHiDPIScalePropertyName = "setHiDPIScale";
24
25   private static boolean setHiDPI = false;
26
27   private static int setHiDPIScale = 0;
28
29   public static int dpi = 0;
30
31   public static int mindimension = 0;
32
33   public static int width = 0;
34
35   public static int scale = 0;
36
37   public final static int MAX_SCALE = 8;
38
39   private static boolean doneInit = false;
40
41   private static boolean allowScalePropertyArg = false;
42
43   private static ScreenInfo screenInfo = new ScreenInfo();
44
45   static
46   {
47     String system = System.getProperty("os.name") == null ? null
48             : System.getProperty("os.name").toLowerCase();
49     if (system != null)
50     {
51       isLinux = system.indexOf("linux") > -1;
52       // isAMac = system.indexOf("mac") > -1;
53       // isWindows = system.indexOf("windows") > -1;
54     }
55     else
56     {
57       isLinux = false;
58       // isAMac = isWindows = false;
59     }
60   }
61
62   private static void init()
63   {
64     if (doneInit)
65     {
66       return;
67     }
68
69     // get and use command line property values first
70     String setHiDPIProperty = System.getProperty(setHiDPIPropertyName);
71     boolean setHiDPIPropertyBool = Boolean.parseBoolean(setHiDPIProperty);
72
73     // allow -DsetHiDPI=false to turn off HiDPI scaling
74     if (setHiDPIProperty != null && !setHiDPIPropertyBool)
75     {
76       clear();
77       doneInit = true;
78       return;
79     }
80
81     setHiDPI = setHiDPIProperty != null && setHiDPIPropertyBool;
82
83     String setHiDPIScaleProperty = System
84             .getProperty(setHiDPIScalePropertyName);
85     if (setHiDPIScaleProperty != null)
86     {
87       try
88       {
89         setHiDPIScale = Integer.parseInt(setHiDPIScaleProperty);
90         // if setHiDPIScale property is validly set and setHiDPI property wasn't
91         // attempted to be set we assume setHiDPIScale to be true
92         if (setHiDPIProperty == null)
93         {
94           setHiDPI = true;
95         }
96       } catch (NumberFormatException e)
97       {
98         System.err.println(setHiDPIScalePropertyName + " property give ("
99                 + setHiDPIScaleProperty + ") but not parseable as integer");
100       }
101     }
102     if (setHiDPI && setHiDPIScale > 0)
103     {
104       setHiDPIScale(setHiDPIScale);
105       return;
106     }
107
108     // check to see if the scale property has already been set by something else
109     // (e.g. the OS)
110     String existingProperty = System.getProperty(scalePropertyName);
111     if (existingProperty != null)
112     {
113       try
114       {
115         int existingPropertyVal = Integer.parseInt(existingProperty);
116         System.out.println("Existing " + scalePropertyName + " is "
117                 + existingPropertyVal);
118         if (existingPropertyVal > 1)
119         {
120           setHiDPIScale(existingPropertyVal);
121           return;
122         }
123       } catch (NumberFormatException e)
124       {
125         System.out.println("Could not convert property " + scalePropertyName
126                 + " vale '" + existingProperty + "' to number");
127       }
128     }
129
130     // Try and auto guess a good scale based on reported DPI (not trustworthy)
131     // and screen resolution (more trustworthy)
132
133     // get screen dpi
134     screenInfo = getScreenInfo();
135     try
136     {
137       dpi = screenInfo.getScreenResolution();
138     } catch (HeadlessException e)
139     {
140       System.err.println("Cannot get screen resolution: " + e.getMessage());
141     }
142
143     // try and get screen size height and width
144     try
145     {
146       int height = screenInfo.getScreenHeight();
147       int width = screenInfo.getScreenWidth();
148       // using mindimension in case of portrait screens
149       mindimension = Math.min(height, width);
150     } catch (HeadlessException e)
151     {
152       System.err.println(
153               "Cannot get screen size height and width:" + e.getMessage());
154     }
155
156     // attempt at a formula for scaling based on screen dpi and mindimension.
157     // scale will be an integer >=1. This formula is based on some testing and
158     // guesswork!
159
160     // scale based on reported dpi. if dpi>hidpiThreshold then scale=2+multiples
161     // of hidpiMultiThreshold (else scale=1)
162     // (e.g. dpi of 110 scales 1. dpi of 120 scales 2. dpi of 360 scales 3)
163     int dpiScale = (dpi - hidpiThreshold > 0)
164             ? 2 + ((dpi - hidpiThreshold) / hidpiMultiThreshold)
165             : 1;
166
167     int dimensionScale = 1 + (mindimension / bigScreenThreshold);
168
169     // reject outrageous values -- dpiScale in particular could be mistaken
170     if (dpiScale > MAX_SCALE) {
171       dpiScale = 1;
172     }
173     if (dimensionScale > MAX_SCALE) {
174       dimensionScale = 1;
175     }
176
177     // choose larger of dimensionScale or dpiScale (most likely dimensionScale
178     // as dpiScale often misreported)
179     int autoScale = Math.max(dpiScale, dimensionScale);
180
181     // only make an automatic change if scale is changed and other conditions
182     // (OS is linux) apply, or if setHiDPI has been specified
183     if ((autoScale > 1 && isLinux) || setHiDPI)
184     {
185       setHiDPIScale(autoScale);
186       return;
187     }
188
189     // looks like we're not doing any scaling
190     doneInit = true;
191   }
192
193   public static void setHiDPIScale(int s)
194   {
195     scale = s;
196     allowScalePropertyArg = true;
197     doneInit = true;
198   }
199
200   public static String getScalePropertyArg(int s)
201   {
202     return "-D" + scalePropertyName + "=" + String.valueOf(s);
203   }
204
205   public static String getScalePropertyArg()
206   {
207     init();
208     // HiDPI setting. Just looking at Linux to start with. Test with Windows.
209     return allowScalePropertyArg ? getScalePropertyArg(scale) : null;
210   }
211
212   public static void clear()
213   {
214     setHiDPI = false;
215     setHiDPIScale = 0;
216     dpi = 0;
217     mindimension = 0;
218     width = 0;
219     scale = 0;
220     doneInit = false;
221     allowScalePropertyArg = false;
222   }
223
224   public static void setScreenInfo(ScreenInfo si)
225   {
226     screenInfo = si;
227   }
228
229   public static ScreenInfo getScreenInfo()
230   {
231     if (screenInfo == null)
232     {
233       screenInfo = new ScreenInfo();
234     }
235     return screenInfo;
236   }
237 }