97707befb5bd42e753df3426764c6d019b6bd0db
[jalview.git] / src / jalview / gui / SplashScreen.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.gui;
22
23 import jalview.util.Platform;
24
25 import java.awt.BorderLayout;
26 import java.awt.Color;
27 import java.awt.Component;
28 import java.awt.Dimension;
29 import java.awt.Font;
30 import java.awt.Graphics;
31 import java.awt.Image;
32 import java.awt.Insets;
33 import java.awt.MediaTracker;
34 import java.awt.event.ActionEvent;
35 import java.awt.event.ActionListener;
36 import java.awt.event.MouseAdapter;
37 import java.awt.event.MouseEvent;
38
39 import javax.swing.JInternalFrame;
40 import javax.swing.JLabel;
41 import javax.swing.JLayeredPane;
42 import javax.swing.JPanel;
43 import javax.swing.JTextPane;
44 import javax.swing.Timer;
45 import javax.swing.border.EmptyBorder;
46 import javax.swing.event.HyperlinkEvent;
47 import javax.swing.event.HyperlinkListener;
48
49 /**
50  * DOCUMENT ME!
51  * 
52  * @author $author$
53  * @version $Revision$
54  */
55 public class SplashScreen extends JPanel
56         implements Runnable, HyperlinkListener
57 {
58   private static final int STATE_INIT = 0;
59
60   private static final int STATE_LOOP = 1;
61
62   private static final int STATE_DONE = 2;
63
64   boolean visible = true;
65
66   JPanel iconimg = new JPanel(new BorderLayout());
67
68   /**
69    * either text area in javascript or in java text pane
70    */
71   Component htmlPane;
72
73   JInternalFrame iframe;
74
75   Image image;
76
77   int fontSize = 11;
78
79   int yoffset = 30;
80
81   /**
82    * Creates a new SplashScreen object.
83    */
84   public SplashScreen()
85   {
86     this(false);
87   }
88
89   protected boolean interactiveDialog = false;
90
91   /**
92    * 
93    * @param interactive
94    *          if true - an internal dialog is opened rather than a free-floating
95    *          splash screen
96    */
97   public SplashScreen(boolean interactive)
98   {
99     this.interactiveDialog = interactive;
100     // show a splashscreen that will disapper
101     if (Platform.isJS()) // BH 2019
102     {
103       htmlPane = new JLabel("");
104       run();
105     }
106     else
107     {
108       /**
109        * Java only
110        * 
111        * @j2sIgnore
112        */
113       {
114         htmlPane = new JTextPane();
115         Thread t = new Thread(this, "SplashScreen");
116         t.start();
117       }
118     }
119
120   }
121
122   MouseAdapter closer = new MouseAdapter()
123   {
124     @Override
125     public void mousePressed(MouseEvent evt)
126     {
127       try
128       {
129         if (!interactiveDialog)
130         {
131           visible = false;
132           closeSplash();
133         }
134       } catch (Exception ex)
135       {
136       }
137     }
138   };
139
140   /**
141    * ping the jalview version page then create and display the jalview
142    * splashscreen window.
143    */
144   protected void initSplashScreenWindow()
145   {
146     addMouseListener(closer);
147     try
148     {
149       java.net.URL url = getClass().getResource("/images/Jalview_Logo.png");
150       image = java.awt.Toolkit.getDefaultToolkit().createImage(url);
151       MediaTracker mt = new MediaTracker(this);
152       mt.addImage(image, 0);
153       Image logo = (Platform.isJS() ? null
154               : java.awt.Toolkit.getDefaultToolkit().createImage(getClass()
155                       .getResource("/images/Jalview_Logo_small.png")));
156       if (logo != null)
157       {
158         mt.addImage(logo, 1);
159       }
160       do
161       {
162         try
163         {
164           mt.waitForAll();
165         } catch (InterruptedException x)
166         {
167         }
168         if (mt.isErrorAny())
169         {
170           System.err.println("Error when loading images!");
171         }
172       } while (!mt.checkAll());
173       if (url != null)
174       {
175         Desktop.getInstance().setIconImage(logo);
176       }
177     } catch (Exception ex)
178     {
179     }
180     iframe = new JInternalFrame();
181     iframe.setFrameIcon(null);
182     iframe.setClosable(interactiveDialog);
183     this.setLayout(new BorderLayout());
184     iframe.setContentPane(this);
185     iframe.setLayer(JLayeredPane.PALETTE_LAYER);
186     if (htmlPane instanceof JTextPane) 
187     {
188       ((JTextPane) htmlPane).setEditable(false);
189     }
190     SplashImage splashimg = new SplashImage(image);
191     iconimg.add(splashimg, BorderLayout.CENTER);
192     add(iconimg, BorderLayout.NORTH);
193     add(htmlPane, BorderLayout.CENTER);
194     htmlPane.addMouseListener(closer);
195     Desktop.getDesktopPane().add(iframe);
196     refreshText();
197   }
198
199   long oldtext = -1;
200
201   private int mainState;
202
203   /**
204    * update text in author text panel reflecting current version information
205    */
206   protected boolean refreshText()
207   {
208     Desktop desktop = Desktop.getInstance();
209     String newtext = desktop.getAboutMessage(true).toString();
210     // System.err.println("Text found: \n"+newtext+"\nEnd of newtext.");
211     if (oldtext != newtext.length())
212     {
213       iframe.setVisible(false);
214       oldtext = newtext.length();
215       System.out.println(newtext);
216       if (Platform.isJS()) // BH 2019
217       {
218         // BH TODO SwingJS does not implement HTML style. Could rethink this.
219
220         htmlPane = new JLabel(newtext);
221         ((JLabel) htmlPane)
222                 .setBorder(new EmptyBorder(new Insets(5, 5, 5, 5)));
223         ((JLabel) htmlPane).setOpaque(true);
224         ((JLabel) htmlPane).setBackground(Color.white);
225       }
226       else
227       /**
228        * Java only
229        * 
230        * @j2sIgnore
231        */
232       {
233         htmlPane = new JTextPane();
234         ((JTextPane) htmlPane).setEditable(false);
235         ((JTextPane) htmlPane).setContentType("text/html");
236         ((JTextPane) htmlPane).setText(newtext);
237         ((JTextPane) htmlPane).addHyperlinkListener(this);
238       }
239       htmlPane.addMouseListener(closer);
240
241       htmlPane.setVisible(true);
242       htmlPane.setSize(new Dimension(750, 375));
243       add(htmlPane, BorderLayout.CENTER);
244       revalidate();
245       iframe.setBounds((desktop.getWidth() - 750) / 2,
246               (desktop.getHeight() - 375) / 2, 750,
247               htmlPane.getHeight() + iconimg.getHeight());
248       iframe.validate();
249       iframe.setVisible(true);
250       return true;
251     }
252     return false;
253   }
254
255   /**
256    * Create splash screen, display it and clear it off again.
257    */
258   @Override
259   public void run()
260   {
261     mainState = STATE_INIT;
262     mainLoop();
263   }
264
265   protected long startTime;
266
267   protected void mainLoop()
268   {
269     while (true)
270     {
271       if (!visible)
272       {
273         mainState = STATE_DONE;
274       }
275       switch (mainState)
276       {
277       case STATE_INIT:
278         initSplashScreenWindow();
279         startTime = System.currentTimeMillis() / 1000;
280         mainState = STATE_LOOP;
281         continue;
282       case STATE_LOOP:
283         if (!interactiveDialog
284                 && ((System.currentTimeMillis() / 1000) - startTime) > 5)
285         {
286           visible = false;
287           continue;
288         }
289         if (visible && refreshText())
290         {
291           iframe.repaint();
292         }
293         if (interactiveDialog)
294         {
295           return;
296         }
297         Timer timer = new Timer(500, new ActionListener()
298         {
299           @Override
300           public void actionPerformed(ActionEvent e)
301           {
302             mainLoop();
303           }
304
305         });
306         timer.start();
307         return;
308       case STATE_DONE:
309         closeSplash();
310         Desktop.getInstance().startDialogQueue();
311         return;
312       }
313     }
314
315   }
316
317   /**
318    * Close the internal frame, either from the timer expiring or from the mouse
319    * action.
320    */
321   public void closeSplash()
322   {
323     try
324     {
325
326       iframe.setClosed(true);
327     } catch (Exception ex)
328     {
329     }
330   }
331
332   public class SplashImage extends JPanel
333   {
334     Image image;
335
336     public SplashImage(Image todisplay)
337     {
338       image = todisplay;
339       if (image != null)
340       {
341         setPreferredSize(new Dimension(image.getWidth(this) + 8,
342                 image.getHeight(this)));
343       }
344     }
345
346     @Override
347     public Dimension getPreferredSize()
348     {
349       return new Dimension(image.getWidth(this) + 8, image.getHeight(this));
350     }
351
352     @Override
353     public void paintComponent(Graphics g)
354     {
355       g.setColor(Color.white);
356       g.fillRect(0, 0, getWidth(), getHeight());
357       g.setColor(Color.black);
358       g.setFont(new Font("Verdana", Font.BOLD, fontSize + 6));
359
360       if (image != null)
361       {
362         g.drawImage(image, (getWidth() - image.getWidth(this)) / 2,
363                 (getHeight() - image.getHeight(this)) / 2, this);
364       }
365     }
366     /*
367      * int y = yoffset;
368      * 
369      * g.drawString("Jalview " + jalview.bin.Cache.getProperty("VERSION"), 50,
370      * y);
371      * 
372      * FontMetrics fm = g.getFontMetrics(); int vwidth =
373      * fm.stringWidth("Jalview " + jalview.bin.Cache.getProperty("VERSION"));
374      * g.setFont(new Font("Verdana", Font.BOLD, fontSize + 2)); g.drawString(
375      * "Last updated: " + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"),
376      * 50 + vwidth + 5, y); if (jalview.bin.Cache.getDefault("LATEST_VERSION",
377      * "Checking").equals( "Checking")) { // Displayed when code version and
378      * jnlp version do not match g.drawString("...Checking latest version...",
379      * 50, y += fontSize + 10); y += 5; g.setColor(Color.black); } else if
380      * (!jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
381      * .equals(jalview.bin.Cache.getProperty("VERSION"))) { if
382      * (jalview.bin.Cache.getProperty("VERSION").toLowerCase()
383      * .indexOf("automated build") == -1) { // Displayed when code version and
384      * jnlp version do not match and code // version is not a development build
385      * g.setColor(Color.red); } g.drawString( "!! Jalview version " +
386      * jalview.bin.Cache.getDefault("LATEST_VERSION", "..Checking..") +
387      * " is available for download from "
388      * +jalview.bin.Cache.getDefault("www.jalview.org"
389      * ,"http://www.jalview.org")+" !!", 50, y += fontSize + 10); y += 5;
390      * g.setColor(Color.black); }
391      * 
392      * g.setFont(new Font("Verdana", Font.BOLD, fontSize)); g.drawString(
393      * "Authors: Jim Procter, Andrew Waterhouse, Michele Clamp, James Cuff, Steve Searle,"
394      * , 50, y += fontSize + 4); g.drawString("David Martin & Geoff Barton.",
395      * 60, y += fontSize + 4); g.drawString(
396      * "Development managed by The Barton Group, University of Dundee.", 50, y
397      * += fontSize + 4); g.drawString("If  you use Jalview, please cite: ", 50,
398      * y += fontSize + 4); g.drawString(
399      * "Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
400      * , 50, y += fontSize + 4); g.drawString(
401      * "Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
402      * , 50, y += fontSize + 4);
403      * g.drawString("Bioinformatics doi: 10.1093/bioinformatics/btp033", 50, y
404      * += fontSize + 4); }
405      */
406   }
407
408   @Override
409   public void hyperlinkUpdate(HyperlinkEvent e)
410   {
411     Desktop.hyperlinkUpdate(e);
412
413   }
414 }