]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/SWTDPIUtil.java
43d19efb2571cd987d380de84f9b8d0b824b795e
[simantics/platform.git] / bundles / org.simantics.utils.ui / src / org / simantics / utils / ui / SWTDPIUtil.java
1 package org.simantics.utils.ui;
2
3 import java.awt.geom.Point2D;
4 import java.awt.geom.Rectangle2D;
5
6 import org.eclipse.swt.graphics.Point;
7 import org.eclipse.swt.graphics.Rectangle;
8 import org.eclipse.swt.internal.DPIUtil;
9
10 /**
11  * This class is needed to support {@link SWTAWTComponent} and HiDPI screens
12  * with different display zoom settings.
13  * 
14  * <p>
15  * See {@link DPIUtil} for explanations on what downscaling and upscaling are in
16  * this context. If user has zoom > 100% in use in the system display settings,
17  * SWT's API coordinates will be "downscaled" from actual internal HiDPI
18  * coordinates (pixels).
19  * 
20  * <p>
21  * This class contains methods to work around problems with e.g. opening context
22  * menu's in the correct location when using {@link SWTAWTComponent}. AWT always
23  * returns HiDPI pixel coordinates which need to be converted to SWT API
24  * coordinates before giving them to any SWT APIs.
25  *
26  * @author Tuukka Lehtonen
27  * @since 1.36.0
28  */
29 @SuppressWarnings("restriction")
30 public class SWTDPIUtil {
31
32         private static boolean initialized = false;
33         private static int swtZoom;
34         private static boolean hasSwtScale;
35
36         private static float fromSwtInternalScalingFactorF;
37         private static double fromSwtInternalScalingFactorD;
38         private static float toSwtInternalScalingFactorF;
39         private static double toSwtInternalScalingFactorD;
40
41         private static void initialize() {
42                 if (initialized)
43                         return;
44
45                 swtZoom = DPIUtil.autoScaleUp(100);
46                 hasSwtScale = swtZoom != 100;
47
48                 fromSwtInternalScalingFactorD         = 100.0 / (double) swtZoom;
49                 toSwtInternalScalingFactorD           = (double) swtZoom / 100.0;
50                 fromSwtInternalScalingFactorF         = (float) fromSwtInternalScalingFactorD;
51                 toSwtInternalScalingFactorF           = (float) toSwtInternalScalingFactorD;
52
53 //              System.out.format("SWTDPIUtil:%n\tswt zoom = %d%n\tfrom swt internal scaling factor = %f%n\tto swt internal scaling factor = %f%n",
54 //                              swtZoom,
55 //                              fromSwtInternalScalingFactorD,
56 //                              toSwtInternalScalingFactorD,
57 //                              );
58
59                 initialized = true;
60         }
61
62         // Internals
63
64         private static Rectangle scale(float s, Rectangle r, Rectangle target) {
65                 if (s == 1.0f) {
66                         if (r == target)
67                                 return r;
68                         if (target == null) {
69                                 return new Rectangle(r.x, r.y, r.width, r.height);
70                         } else {
71                                 target.x = r.x;
72                                 target.y = r.y;
73                                 target.width = r.width;
74                                 target.height = r.height;
75                                 return target;
76                         }
77                 }
78                 if (target == null) {
79                         return new Rectangle(
80                                         Math.round(r.x*s),
81                                         Math.round(r.y*s),
82                                         Math.round(r.width*s),
83                                         Math.round(r.height*s));
84                 } else {
85                         target.x = Math.round(r.x*s);
86                         target.y = Math.round(r.y*s);
87                         target.width = Math.round(r.width*s);
88                         target.height = Math.round(r.height*s);
89                         return target;
90                 }
91         }
92
93         private static Rectangle2D scale(double s, Rectangle2D r, Rectangle2D target) {
94                 if (s == 1.0) {
95                         if (r == target)
96                                 return r;
97                         if (target == null)
98                                 return (Rectangle2D) r.clone();
99                         target.setFrame(r);
100                         return target;
101                 }
102                 if (target == null)
103                         target = (Rectangle2D) r.clone();
104                 target.setFrame(r.getX()*s, r.getY()*s, r.getWidth()*s, r.getHeight()*s);
105                 return target;
106         }
107
108         private static double downscaleSwt0(double x) {
109                 return hasSwtScale ? x * fromSwtInternalScalingFactorD : x;
110         }
111
112         private static int downscaleToIntegerSwt0(double x) {
113                 return (int)(hasSwtScale ? Math.round((double) x * fromSwtInternalScalingFactorD) : x);
114         }
115
116         private static int downscaleSwt0(int x) {
117                 return hasSwtScale ? (int) Math.round((double) x * fromSwtInternalScalingFactorD) : x;
118         }
119
120         private static double upscaleSwt0(double x) {
121                 return hasSwtScale ? x * toSwtInternalScalingFactorD : x;
122         }
123
124         private static int upscaleToIntegerSwt0(double x) {
125                 return (int)(hasSwtScale ? Math.round((double) x * toSwtInternalScalingFactorD) : x);
126         }
127
128         private static int upscaleSwt0(int x) {
129                 return hasSwtScale ? (int) Math.round((double) x * toSwtInternalScalingFactorD) : x;
130         }
131
132         // SWT API Coordinates <-> pixels
133
134         // Downscaling
135
136         public static double downscaleSwt(double x) {
137                 initialize();
138                 return downscaleSwt0(x);
139         }
140
141         public static int downscaleSwt(int x) {
142                 initialize();
143                 return downscaleSwt0(x);
144         }
145
146         public static Point2D downscaleSwt(double x, double y) {
147                 initialize();
148                 if (!hasSwtScale)
149                         return new Point2D.Double(x, y);
150                 double s = fromSwtInternalScalingFactorD;
151                 return new Point2D.Double(x * s, y * s);
152         }
153
154         public static Point downscaleSwt(int x, int y) {
155                 initialize();
156                 return new Point(downscaleSwt0(x), downscaleSwt0(y));
157         }
158
159         public static Point2D downscaleSwt(Point2D p) {
160                 return downscaleSwt(p.getX(), p.getY());
161         }
162
163         public static Point downscaleSwtToInteger(Point2D p) {
164                 initialize();
165                 return new Point(downscaleToIntegerSwt0(p.getX()), downscaleToIntegerSwt0(p.getY()));
166         }
167
168         public static Rectangle2D downscaleSwt(Rectangle2D r, Rectangle2D target) {
169                 initialize();
170                 return scale(fromSwtInternalScalingFactorD, r, target);
171         }
172
173         public static Rectangle2D downscaleSwt(Rectangle2D r) {
174                 return downscaleSwt(r, null);
175         }
176
177         public static Rectangle downscaleSwt(Rectangle r, Rectangle target) {
178                 initialize();
179                 return scale(fromSwtInternalScalingFactorF, r, target);
180         }
181
182         public static Rectangle downscaleSwt(Rectangle r) {
183                 return downscaleSwt(r, null);
184         }
185
186         public static Rectangle downscaleSwtToInteger(Rectangle2D r) {
187                 initialize();
188                 return new Rectangle( 
189                                 downscaleToIntegerSwt0(r.getMinX()),
190                                 downscaleToIntegerSwt0(r.getMinY()),
191                                 downscaleToIntegerSwt0(r.getWidth()),
192                                 downscaleToIntegerSwt0(r.getHeight()));
193         }
194
195         // Upscaling
196
197         public static double upscaleSwt(double x) {
198                 initialize();
199                 return upscaleSwt0(x);
200         }
201
202         public static int upscaleSwt(int x) {
203                 initialize();
204                 return upscaleSwt0(x);
205         }
206
207         public static Point2D upscaleSwt(double x, double y) {
208                 initialize();
209                 if (!hasSwtScale)
210                         return new Point2D.Double(x, y);
211                 double s = toSwtInternalScalingFactorD;
212                 return new Point2D.Double(x * s, y * s);
213         }
214
215         public static Point upscaleSwt(int x, int y) {
216                 initialize();
217                 return new Point(upscaleSwt0(x), upscaleSwt0(y));
218         }
219
220         public static Point2D upscaleSwt(Point2D p) {
221                 return upscaleSwt(p.getX(), p.getY());
222         }
223
224         public static Point upscaleSwtToInteger(Point2D p) {
225                 initialize();
226                 return new Point(upscaleToIntegerSwt0(p.getX()), upscaleToIntegerSwt0(p.getY()));
227         }
228
229         public static Point upscaleSwt(Point p) {
230                 return upscaleSwt(p.x, p.y);
231         }
232
233         public static Rectangle2D upscaleSwt(Rectangle2D r, Rectangle2D target) {
234                 initialize();
235                 return scale(toSwtInternalScalingFactorD, r, target);
236         }
237
238         public static Rectangle upscaleSwt(Rectangle r, Rectangle target) {
239                 initialize();
240                 return scale(toSwtInternalScalingFactorF, r, target);
241         }
242
243         public static Rectangle2D upscaleSwt(Rectangle2D r) {
244                 return upscaleSwt(r, null);
245         }
246
247         public static Rectangle upscaleSwt(Rectangle r) {
248                 return upscaleSwt(r, null);
249         }
250
251         public static Rectangle upscaleSwtToInteger(Rectangle2D r) {
252                 return new Rectangle( 
253                                 upscaleToIntegerSwt0(r.getMinX()),
254                                 upscaleToIntegerSwt0(r.getMinY()),
255                                 upscaleToIntegerSwt0(r.getWidth()),
256                                 upscaleToIntegerSwt0(r.getHeight()));
257         }
258
259 }