View Javadoc

1   /*
2    * Copyright (c) 2014 Maxim Yunusov
3    *    Licensed under the Apache License, Version 2.0 (the "License");
4    *    you may not use this file except in compliance with the License.
5    *    You may obtain a copy of the License at
6    *
7    *        http://www.apache.org/licenses/LICENSE-2.0
8    *
9    *    Unless required by applicable law or agreed to in writing, software
10   *    distributed under the License is distributed on an "AS IS" BASIS,
11   *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   *    See the License for the specific language governing permissions and
13   *    limitations under the License.
14   */
15  
16  package org.maxur.perfmodel.backend.service.impl;
17  
18  import org.jvnet.hk2.annotations.Service;
19  import org.maxur.perfmodel.backend.service.Application;
20  import org.slf4j.Logger;
21  import org.slf4j.LoggerFactory;
22  
23  import javax.inject.Named;
24  import javax.swing.*;
25  import java.awt.*;
26  import java.io.IOException;
27  import java.net.URI;
28  import java.net.URL;
29  
30  import static java.awt.Desktop.Action.BROWSE;
31  import static java.awt.Desktop.getDesktop;
32  import static java.awt.Desktop.isDesktopSupported;
33  import static java.awt.SystemTray.getSystemTray;
34  import static java.lang.String.format;
35  import static javax.swing.JOptionPane.showMessageDialog;
36  import static javax.swing.SwingUtilities.invokeLater;
37  import static org.maxur.perfmodel.backend.utils.OsUtils.isWindows;
38  
39  /**
40   * This class represents Performance Model Calculator Application
41   * It's GUI Implementation with Tray Icon
42   *
43   * @author Maxim
44   * @version 1.0
45   * @since <pre>24.10.2014</pre>
46   * <p>
47   * see http://docs.oracle.com/javase/tutorial/displayCode.html?code=http://docs.oracle.com/javase/tutorial/uiswing/examples/misc/TrayIconDemoProject/src/misc/TrayIconDemo.java
48   */
49  @Service
50  public class TrayIconApplication extends Application {
51  
52      private static final Logger LOGGER = LoggerFactory.getLogger(TrayIconApplication.class);
53  
54      public static final String IMG_FAVICON_PATH = "/img/favicon.png";
55  
56      private TrayIcon trayIcon;
57  
58      @SuppressWarnings("unused")
59      @Named("webapp.url")
60      private URI webappUri;
61  
62      public TrayIconApplication() {
63      }
64  
65      @Override
66      public boolean isApplicable() {
67          //Check the SystemTray support
68          return SystemTray.isSupported();
69      }
70  
71      @Override
72      protected void onInit() {
73          try {
74              final String className = isWindows() ?
75                      "com.sun.java.swing.plaf.windows.WindowsLookAndFeel" :
76                      "javax.swing.plaf.metal.MetalLookAndFeel";
77              UIManager.setLookAndFeel(className);
78          } catch (UnsupportedLookAndFeelException | IllegalAccessException
79                  | InstantiationException | ClassNotFoundException ex
80                  ) {
81              LOGGER.error("Tray application is not created", ex);
82          }
83          UIManager.put("swing.boldMetal", Boolean.FALSE);
84      }
85  
86      @Override
87      protected void onStart() {
88          invokeLater(this::run);
89      }
90  
91      private void run() {
92          trayIcon = new TrayIcon(createImage(IMG_FAVICON_PATH, "tray icon"));
93          trayIcon.setToolTip("Performance Model Calculator");
94          trayIcon.setImageAutoSize(true);
95          trayIcon.setPopupMenu(createPopupMenu());
96          trayIcon.addActionListener(e -> openBrowser());
97          try {
98              getSystemTray().add(trayIcon);
99          } catch (AWTException e) {
100             final String msg = "TrayIcon could not be added.";
101             LOGGER.error(msg);
102             throw new IllegalStateException(msg, e);
103         }
104     }
105 
106     private PopupMenu createPopupMenu() {
107         final PopupMenu popup = new PopupMenu();
108 
109         final MenuItem aboutItem = new MenuItem("About");
110         final MenuItem startClientItem = new MenuItem("Start Client");
111         final MenuItem manageServiceItem = new MenuItem("Stop Service");
112         final MenuItem exitItem = new MenuItem("Exit");
113 
114         startClientItem.addActionListener(e -> openBrowser());
115 
116         manageServiceItem.addActionListener(e -> {
117             if (webServer().isStarted()) {
118                 webServer().stop();
119             } else {
120                 webServer().restart();
121             }
122             final String label = webServer().isStarted() ? "Stop Service" : "Start Service";
123             manageServiceItem.setLabel(label);
124             final String message = webServer().isStarted() ? "Web Service was started" : "Web Service was stopped";
125             trayIcon.displayMessage("Performance Model Calculator",
126                     message,
127                     TrayIcon.MessageType.INFO);
128             startClientItem.setEnabled(webServer().isStarted());
129         });
130 
131         aboutItem.addActionListener(e ->
132                         showMessageDialog(null, "Performance Model Calculator. Version: " + version())
133         );
134 
135         exitItem.addActionListener(e -> stop());
136 
137         popup.add(aboutItem);
138         popup.add(startClientItem);
139         popup.add(manageServiceItem);
140         popup.addSeparator();
141         popup.add(exitItem);
142 
143         return popup;
144     }
145 
146     @Override
147     protected void onStop() {
148         getSystemTray().remove(trayIcon);
149     }
150 
151     private static Image createImage(final String path, final String description) {
152         final URL imageURL = TrayIconApplication.class.getResource(path);
153         if (imageURL == null) {
154             final String msg = format("Resource '%s' is not found", IMG_FAVICON_PATH);
155             LOGGER.error(msg);
156             throw new IllegalStateException(msg);
157         }
158         return (new ImageIcon(imageURL, description)).getImage();
159     }
160 
161     private void openBrowser() {
162         if (!isDesktopSupported()) {
163             LOGGER.error("Cannot open browser. Desktop is not supported");
164             return;
165         }
166         final Desktop desktop = getDesktop();
167         if (!desktop.isSupported(BROWSE)) {
168             LOGGER.error("Cannot open browser. Desktop is not supported browse action");
169             return;
170         }
171         try {
172             desktop.browse(webappUri);
173         } catch (IOException e) {
174             LOGGER.error("Cannot open browser", e);
175         }
176     }
177 
178 }
179 
180