JAL-3609 JAL-3775 Refactoring a bit of jalview.bin.HiDPISetting so screen display...
[jalview.git] / src / jalview / bin / 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   private static boolean doneInit = false;
38
39   private static boolean allowScalePropertyArg = false;
40
41   private static ScreenInfo screenInfo = new ScreenInfo();
42
43   static
44   {
45     String system = System.getProperty("os.name") == null ? null
46             : System.getProperty("os.name").toLowerCase();
47     if (system != null)
48     {
49       isLinux = system.indexOf("linux") > -1;
50       // isAMac = system.indexOf("mac") > -1;
51       // isWindows = system.indexOf("windows") > -1;
52     }
53     else
54     {
55       isLinux = false;
56       // isAMac = isWindows = false;
57     }
58   }
59
60   private static void init()
61   {
62     if (doneInit)
63     {
64       return;
65     }
66
67     // get and use command line property values first
68     String setHiDPIProperty = System.getProperty(setHiDPIPropertyName);
69     setHiDPI = setHiDPIProperty != null
70             && setHiDPIProperty.equalsIgnoreCase("true");
71
72     String setHiDPIScaleProperty = System
73             .getProperty(setHiDPIScalePropertyName);
74     if (setHiDPIScaleProperty != null)
75     {
76       try
77       {
78         setHiDPIScale = Integer.parseInt(setHiDPIScaleProperty);
79       } catch (NumberFormatException e)
80       {
81         System.err.println(setHiDPIScalePropertyName + " property give ("
82                 + setHiDPIScaleProperty + ") but not parseable as integer");
83       }
84     }
85     if (setHiDPI && setHiDPIScale > 0)
86     {
87       setHiDPIScale(setHiDPIScale);
88       return;
89     }
90
91     // check to see if the scale property has already been set by something else
92     // (e.g. the OS)
93     String existingProperty = System.getProperty(scalePropertyName);
94     if (existingProperty != null)
95     {
96       try
97       {
98         int existingPropertyVal = Integer.parseInt(existingProperty);
99         System.out.println("Existing " + scalePropertyName + " is "
100                 + existingPropertyVal);
101         if (existingPropertyVal > 1)
102         {
103           setHiDPIScale(existingPropertyVal);
104           return;
105         }
106       } catch (NumberFormatException e)
107       {
108         System.out.println("Could not convert property " + scalePropertyName
109                 + " vale '" + existingProperty + "' to number");
110       }
111     }
112
113     // Try and auto guess a good scale based on reported DPI (not trustworthy)
114     // and screen resolution (more trustworthy)
115
116     // get screen dpi
117     screenInfo = getScreenInfo();
118     try
119     {
120       dpi = screenInfo.getScreenResolution();
121     } catch (HeadlessException e)
122     {
123       System.err.println("Cannot get screen resolution: " + e.getMessage());
124     }
125
126     // try and get screen size height and width
127     try
128     {
129       int height = screenInfo.getScreenHeight();
130       int width = screenInfo.getScreenWidth();
131       // using mindimension in case of portrait screens
132       mindimension = Math.min(height, width);
133     } catch (HeadlessException e)
134     {
135       System.err.println(
136               "Cannot get screen size height and width:" + e.getMessage());
137     }
138
139     // attempt at a formula for scaling based on screen dpi and mindimension.
140     // scale will be an integer >=1. This formula is based on some testing and
141     // guesswork!
142
143     // scale based on reported dpi. if dpi>hidpiThreshold then scale=2+multiples
144     // of hidpiMultiThreshold (else scale=1)
145     // (e.g. dpi of 110 scales 1. dpi of 120 scales 2. dpi of 360 scales 3)
146     int dpiScale = (dpi - hidpiThreshold > 0)
147             ? 2 + ((dpi - hidpiThreshold) / hidpiMultiThreshold)
148             : 1;
149
150     int dimensionScale = 1 + (mindimension / bigScreenThreshold);
151
152     // choose larger of dimensionScale or dpiScale (most likely dimensionScale
153     // as dpiScale often misreported)
154     int autoScale = Math.max(dpiScale, dimensionScale);
155
156     // only make an automatic change if scale is changed and other conditions
157     // (OS is linux) apply, or if setHiDPI has been specified
158     if ((autoScale > 1 && isLinux) || setHiDPI)
159     {
160       setHiDPIScale(autoScale);
161       return;
162     }
163
164     // looks like we're not doing any scaling
165     doneInit = true;
166   }
167
168   public static void setHiDPIScale(int s)
169   {
170     scale = s;
171     allowScalePropertyArg = true;
172     doneInit = true;
173   }
174
175   public static String getScalePropertyArg(int s)
176   {
177     return "-D" + scalePropertyName + "=" + String.valueOf(s);
178   }
179
180   public static String getScalePropertyArg()
181   {
182     init();
183     // HiDPI setting. Just looking at Linux to start with. Test with Windows.
184     return allowScalePropertyArg ? getScalePropertyArg(scale) : null;
185   }
186
187   public static void clear()
188   {
189     setHiDPI = false;
190     setHiDPIScale = 0;
191     dpi = 0;
192     mindimension = 0;
193     width = 0;
194     scale = 0;
195     doneInit = false;
196     allowScalePropertyArg = false;
197   }
198
199   public static void setScreenInfo(ScreenInfo si)
200   {
201     screenInfo = si;
202   }
203
204   public static ScreenInfo getScreenInfo()
205   {
206     if (screenInfo == null)
207     {
208       screenInfo = new ScreenInfo();
209     }
210     return screenInfo;
211   }
212 }