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