6219179ef6c06f3676bcf42a362cd9ebaf01fd1b
[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       dpiScale = 1;
174     }
175     if (dimensionScale > MAX_SCALE) {
176       dimensionScale = 1;
177     }
178
179     // choose larger of dimensionScale or dpiScale (most likely dimensionScale
180     // as dpiScale often misreported)
181     int autoScale = Math.max(dpiScale, dimensionScale);
182
183     // only make an automatic change if scale is changed and other conditions
184     // (OS is linux) apply, or if setHiDPI has been specified
185     if ((autoScale > 1 && isLinux) || setHiDPI)
186     {
187       setHiDPIScale(autoScale);
188       return;
189     }
190
191     // looks like we're not doing any scaling
192     doneInit = true;
193   }
194
195   public static void setHiDPIScale(int s)
196   {
197     scale = s;
198     allowScalePropertyArg = true;
199     doneInit = true;
200   }
201
202   public static String getScalePropertyArg(int s)
203   {
204     return "-D" + scalePropertyName + "=" + String.valueOf(s);
205   }
206
207   public static String getScalePropertyArg()
208   {
209     init();
210     // HiDPI setting. Just looking at Linux to start with. Test with Windows.
211     return allowScalePropertyArg ? getScalePropertyArg(scale) : null;
212   }
213
214   public static void clear()
215   {
216     setHiDPI = false;
217     setHiDPIScale = 0;
218     dpi = 0;
219     mindimension = 0;
220     width = 0;
221     scale = 0;
222     doneInit = false;
223     allowScalePropertyArg = false;
224   }
225
226   public static void setScreenInfo(ScreenInfo si)
227   {
228     screenInfo = si;
229   }
230
231   public static ScreenInfo getScreenInfo()
232   {
233     if (screenInfo == null)
234     {
235       screenInfo = new ScreenInfo();
236     }
237     return screenInfo;
238   }
239 }