1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package davmail.ui.tray;
20
21 import davmail.BundleMessage;
22 import davmail.Settings;
23 import davmail.exchange.NetworkDownException;
24 import org.apache.log4j.Level;
25 import org.apache.log4j.Logger;
26
27 import javax.imageio.ImageIO;
28 import java.awt.*;
29 import java.awt.color.ColorSpace;
30 import java.awt.image.BufferedImage;
31 import java.awt.image.ColorConvertOp;
32 import java.io.IOException;
33 import java.net.URL;
34
35
36
37
38
39 public final class DavGatewayTray {
40 private static final Logger LOGGER = Logger.getLogger("davmail");
41 private static final long ICON_SWITCH_MINIMUM_DELAY = 250;
42 private static long lastIconSwitch;
43
44 private DavGatewayTray() {
45 }
46
47 static DavGatewayTrayInterface davGatewayTray;
48
49
50
51
52
53
54 public static java.util.List<Image> getFrameIcons() {
55 java.util.List<Image> icons = null;
56 if (davGatewayTray != null) {
57 icons = davGatewayTray.getFrameIcons();
58 }
59 return icons;
60 }
61
62
63
64
65 public static void switchIcon() {
66 if (davGatewayTray != null && !Settings.getBooleanProperty("davmail.disableTrayActivitySwitch")) {
67 if (System.currentTimeMillis() - lastIconSwitch > ICON_SWITCH_MINIMUM_DELAY) {
68 davGatewayTray.switchIcon();
69 lastIconSwitch = System.currentTimeMillis();
70 }
71 }
72 }
73
74
75
76
77 public static void resetIcon() {
78 if (davGatewayTray != null && isActive()) {
79 davGatewayTray.resetIcon();
80 }
81 }
82
83
84
85
86
87
88 public static boolean isActive() {
89 return davGatewayTray == null || davGatewayTray.isActive();
90 }
91
92
93
94
95
96
97
98 private static void displayMessage(BundleMessage message, Level level) {
99 LOGGER.log(level, message.formatLog());
100 if (davGatewayTray != null && !Settings.getBooleanProperty("davmail.disableGuiNotifications")) {
101 davGatewayTray.displayMessage(message.format(), level);
102 }
103 }
104
105
106
107
108
109
110
111
112 private static void displayMessage(BundleMessage message, Exception e, Level level) {
113 if (e instanceof NetworkDownException) {
114 LOGGER.log(level, BundleMessage.getExceptionLogMessage(message, e));
115 } else {
116 LOGGER.log(level, BundleMessage.getExceptionLogMessage(message, e), e);
117 }
118 if (davGatewayTray != null && !Settings.getBooleanProperty("davmail.disableGuiNotifications")
119 && (!(e instanceof NetworkDownException))) {
120 davGatewayTray.displayMessage(BundleMessage.getExceptionMessage(message, e), level);
121 }
122 if (davGatewayTray != null && e instanceof NetworkDownException) {
123 davGatewayTray.inactiveIcon();
124 }
125 }
126
127
128
129
130
131
132 public static void debug(BundleMessage message) {
133 displayMessage(message, Level.DEBUG);
134 }
135
136
137
138
139
140
141 public static void info(BundleMessage message) {
142 displayMessage(message, Level.INFO);
143 }
144
145
146
147
148
149
150 public static void warn(BundleMessage message) {
151 displayMessage(message, Level.WARN);
152 }
153
154
155
156
157
158
159 public static void warn(Exception e) {
160 displayMessage(null, e, Level.WARN);
161 }
162
163
164
165
166
167
168 public static void error(BundleMessage message) {
169 displayMessage(message, Level.ERROR);
170 }
171
172
173
174
175
176
177
178 public static void log(Exception e) {
179
180 if (e instanceof NetworkDownException) {
181 warn(e);
182 } else {
183 error(e);
184 }
185 }
186
187
188
189
190
191
192 public static void error(Exception e) {
193 displayMessage(null, e, Level.ERROR);
194 }
195
196
197
198
199
200
201
202 public static void debug(BundleMessage message, Exception e) {
203 displayMessage(message, e, Level.DEBUG);
204 }
205
206
207
208
209
210
211
212 public static void warn(BundleMessage message, Exception e) {
213 displayMessage(message, e, Level.WARN);
214 }
215
216
217
218
219
220
221
222 public static void error(BundleMessage message, Exception e) {
223 displayMessage(message, e, Level.ERROR);
224 }
225
226
227
228
229 public static void init() {
230 String currentDesktop = System.getenv("XDG_CURRENT_DESKTOP");
231 String javaVersion = System.getProperty("java.version");
232 String arch = System.getProperty("sun.arch.data.model");
233 LOGGER.debug("OS Name: " + System.getProperty("os.name") +
234 " Java version: " + javaVersion + ((arch != null) ? ' ' + arch : "") +
235 " System tray " + (SystemTray.isSupported() ? "" : "not ") + "supported " +
236 ((currentDesktop == null) ? "" : "Current Desktop: " + currentDesktop)
237 );
238
239 if (Settings.isLinux()) {
240
241 System.setProperty("awt.useSystemAAFontSettings", "on");
242 System.setProperty("swing.aatext", "true");
243 }
244
245 if (!Settings.getBooleanProperty("davmail.server")) {
246
247 if (Settings.getBooleanProperty("davmail.enableTray", !Settings.isLinux())) {
248 if ("Unity".equals(currentDesktop)) {
249 LOGGER.info("Detected Unity desktop, please follow instructions at " +
250 "https://davmail.sourceforge.net/linuxsetup.html to restore normal systray " +
251 "or run DavMail in server mode");
252 } else if (currentDesktop != null && currentDesktop.contains("GNOME")) {
253 LOGGER.info("Detected Gnome desktop, please follow instructions at " +
254 "https://davmail.sourceforge.net/linuxsetup.html or " +
255 "https://extensions.gnome.org/extension/1503/tray-icons/ " +
256 "to restore normal systray or run DavMail in server mode");
257 }
258
259 boolean isSWTAvailable = Settings.isSWTAvailable();
260 if (isSWTAvailable) {
261 try {
262
263 davGatewayTray = new SwtGatewayTray();
264 davGatewayTray.init();
265 } catch (Throwable e) {
266 DavGatewayTray.info(new BundleMessage("LOG_SWT_NOT_AVAILABLE"));
267 davGatewayTray = null;
268 }
269 }
270
271 if (davGatewayTray == null ) {
272 try {
273 if (SystemTray.isSupported()) {
274 if (isOSX()) {
275 davGatewayTray = new OSXAwtGatewayTray();
276 } else {
277 davGatewayTray = new AwtGatewayTray();
278 }
279 davGatewayTray.init();
280 }
281 } catch (NoClassDefFoundError e) {
282 DavGatewayTray.info(new BundleMessage("LOG_SYSTEM_TRAY_NOT_AVAILABLE"));
283 }
284 }
285 }
286
287 if (davGatewayTray == null) {
288 if (isOSX()) {
289
290 davGatewayTray = new OSXFrameGatewayTray();
291 } else {
292 davGatewayTray = new FrameGatewayTray();
293 }
294 davGatewayTray.init();
295 }
296 }
297 }
298
299
300
301
302
303
304 public static boolean isOSX() {
305 return System.getProperty("os.name").toLowerCase().startsWith("mac os x");
306 }
307
308
309
310
311
312
313 public static boolean isWindows() {
314 return System.getProperty("os.name").toLowerCase().startsWith("windows");
315 }
316
317
318
319
320
321
322 public static boolean isLinux() {
323 return System.getProperty("os.name").toLowerCase().startsWith("linux");
324 }
325
326
327
328
329
330
331
332 public static BufferedImage loadImage(String fileName) {
333 BufferedImage result = null;
334 try {
335 ClassLoader classloader = DavGatewayTray.class.getClassLoader();
336 URL imageUrl = classloader.getResource(fileName);
337 if (imageUrl == null) {
338 throw new IOException("Missing resource: " + fileName);
339 }
340 result = ImageIO.read(imageUrl);
341 } catch (IOException e) {
342 DavGatewayTray.warn(new BundleMessage("LOG_UNABLE_TO_LOAD_IMAGE"), e);
343 }
344 return result;
345 }
346
347 public static BufferedImage convertGrayscale(BufferedImage colorImage) {
348 BufferedImage grayImage = new BufferedImage(colorImage.getWidth(), colorImage.getHeight(), BufferedImage.TYPE_INT_ARGB);
349
350 ColorConvertOp op = new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null);
351 op.filter(colorImage, grayImage);
352
353 return grayImage;
354 }
355
356 public static BufferedImage scaleImage(BufferedImage sourceImage, int targetSize) {
357 Image scaledImage = sourceImage.getScaledInstance(targetSize, targetSize, Image.SCALE_AREA_AVERAGING);
358
359 BufferedImage targetImage = new BufferedImage(targetSize, targetSize, BufferedImage.TYPE_INT_ARGB);
360 targetImage.getGraphics().drawImage(scaledImage, 0, 0, null);
361 return targetImage;
362 }
363
364 public static BufferedImage adjustTrayIcon(BufferedImage image) {
365 if (Settings.getBooleanProperty("davmail.trayGrayscale", false)) {
366 image = convertGrayscale(image);
367 }
368 Color backgroundColor = null;
369 String backgroundColorString = Settings.getProperty("davmail.trayBackgroundColor");
370
371 String xdgCurrentDesktop = System.getenv("XDG_CURRENT_DESKTOP");
372
373 boolean isKDE = "KDE".equals(xdgCurrentDesktop);
374 boolean isXFCE = "XFCE".equals(xdgCurrentDesktop);
375 boolean isUnity = "Unity".equals(xdgCurrentDesktop);
376 boolean isCinnamon = "X-Cinnamon".equals(xdgCurrentDesktop);
377 boolean isGnome = xdgCurrentDesktop != null && xdgCurrentDesktop.contains("GNOME");
378
379 if (backgroundColorString == null || backgroundColorString.isEmpty()) {
380
381 if (isKDE) {
382 backgroundColorString = "#DDF6E8";
383 }
384 if (isUnity) {
385 backgroundColorString = "#4D4B45";
386 }
387 if (isXFCE) {
388 backgroundColorString = "#E8E8E7";
389 }
390 if (isCinnamon) {
391 backgroundColorString = "#2E2E2E";
392 }
393 if (isGnome) {
394 backgroundColorString = "#000000";
395 }
396 }
397
398 int imageType = BufferedImage.TYPE_INT_ARGB;
399 if (backgroundColorString != null && backgroundColorString.length() == 7
400 && backgroundColorString.startsWith("#")) {
401 int red = Integer.parseInt(backgroundColorString.substring(1, 3), 16);
402 int green = Integer.parseInt(backgroundColorString.substring(3, 5), 16);
403 int blue = Integer.parseInt(backgroundColorString.substring(5, 7), 16);
404 backgroundColor = new Color(red, green, blue);
405 imageType = BufferedImage.TYPE_INT_RGB;
406 }
407
408 if (backgroundColor != null || isKDE || isUnity || isXFCE || isGnome) {
409 int width = image.getWidth();
410 int height = image.getHeight();
411 int x = 0;
412 int y = 0;
413 if (isKDE || isXFCE) {
414 width = 22;
415 height = 22;
416 x = 3;
417 y = 3;
418 } else if (isUnity) {
419 width = 22;
420 height = 24;
421 x = 4;
422 y = 4;
423 } else if (isCinnamon || isGnome) {
424 width = 24;
425 height = 24;
426 x = 4;
427 y = 4;
428 }
429 BufferedImage bufferedImage = new BufferedImage(width, height, imageType);
430 Graphics2D graphics = bufferedImage.createGraphics();
431 graphics.setColor(backgroundColor);
432 graphics.fillRect(0, 0, width, height);
433 graphics.drawImage(image, x, y, null);
434 graphics.dispose();
435 return bufferedImage;
436 } else {
437 return image;
438 }
439 }
440
441
442
443
444
445 public static void dispose() {
446 if (davGatewayTray != null) {
447 davGatewayTray.dispose();
448 }
449 }
450
451 }