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