JAL-3690 List.copyOf() workaround
[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.MediaTracker;
33 import java.awt.Toolkit;
34 import java.awt.event.MouseAdapter;
35 import java.awt.event.MouseEvent;
36 import java.net.URL;
37
38 import javax.swing.JInternalFrame;
39 import javax.swing.JLabel;
40 import javax.swing.JLayeredPane;
41 import javax.swing.JPanel;
42 import javax.swing.JTextPane;
43 import javax.swing.event.HyperlinkEvent;
44 import javax.swing.event.HyperlinkListener;
45
46 /**
47  * DOCUMENT ME!
48  * 
49  * @author $author$
50  * @version $Revision$
51  */
52 public class SplashScreen extends JPanel
53         implements Runnable, HyperlinkListener
54 {
55   private static final int SHOW_FOR_SECS = 5;
56
57   private static final int FONT_SIZE = 11;
58
59   private boolean visible = true;
60
61   private JPanel iconimg = new JPanel(new BorderLayout());
62
63   /*
64    * as JTextPane in Java, JLabel in javascript
65    */
66   private Component splashText;
67
68   private JInternalFrame iframe;
69
70   private Image image;
71
72   private boolean transientDialog = false;
73
74   private long oldTextLength = -1;
75
76   /*
77    * allow click in the initial splash screen to dismiss it
78    * immediately (not if opened from About menu)
79    */
80   private MouseAdapter closer = new MouseAdapter()
81   {
82     @Override
83     public void mousePressed(MouseEvent evt)
84     {
85       if (transientDialog)
86       {
87         try
88         {
89           visible = false;
90           closeSplash();
91         } catch (Exception ex)
92         {
93         }
94       }
95     }
96   };
97
98   /**
99    * Constructor that displays the splash screen
100    * 
101    * @param isTransient
102    *          if true the panel removes itself on click or after a few seconds;
103    *          if false it stays up until closed by the user
104    */
105   public SplashScreen(boolean isTransient)
106   {
107     this.transientDialog = isTransient;
108
109     if (Platform.isJS()) // BH 2019
110     {
111       splashText = new JLabel("");
112       run();
113     }
114     else
115     {
116       /**
117        * Java only
118        *
119        * @j2sIgnore
120        */
121       {
122         splashText = new JTextPane();
123         Thread t = new Thread(this);
124         t.start();
125       }
126     }
127   }
128
129   /**
130    * ping the jalview version page then create and display the jalview
131    * splashscreen window.
132    */
133   void initSplashScreenWindow()
134   {
135     addMouseListener(closer);
136
137     try
138     {
139       URL url = getClass().getResource("/images/Jalview_Logo.png");
140       URL urllogo = getClass()
141               .getResource("/images/Jalview_Logo_small.png");
142
143       if (!Platform.isJS() && url != null)
144       {
145         image = Toolkit.getDefaultToolkit().createImage(url);
146         Image logo = Toolkit.getDefaultToolkit().createImage(urllogo);
147         MediaTracker mt = new MediaTracker(this);
148         mt.addImage(image, 0);
149         mt.addImage(logo, 1);
150         do
151         {
152           try
153           {
154             mt.waitForAll();
155           } catch (InterruptedException x)
156           {
157           }
158           if (mt.isErrorAny())
159           {
160             System.err.println("Error when loading images!");
161           }
162         } while (!mt.checkAll());
163         Desktop.instance.setIconImage(logo);
164       }
165     } catch (Exception ex)
166     {
167     }
168
169     iframe = new JInternalFrame();
170     iframe.setFrameIcon(null);
171     iframe.setClosable(true);
172     this.setLayout(new BorderLayout());
173     iframe.setContentPane(this);
174     iframe.setLayer(JLayeredPane.PALETTE_LAYER);
175     if (Platform.isJS())
176     {
177       // ignore in JavaScript
178     }
179     else
180     /**
181      * Java only
182      * 
183      * @j2sIgnore
184      */
185     {
186       ((JTextPane) splashText).setEditable(false);
187
188       SplashImage splashimg = new SplashImage(image);
189       iconimg.add(splashimg, BorderLayout.CENTER);
190       add(iconimg, BorderLayout.NORTH);
191     }
192     add(splashText, BorderLayout.CENTER);
193     splashText.addMouseListener(closer);
194     Desktop.desktop.add(iframe);
195     refreshText();
196   }
197
198   /**
199    * update text in author text panel reflecting current version information
200    */
201   protected boolean refreshText()
202   {
203     String newtext = Desktop.instance.getAboutMessage();
204     // System.err.println("Text found: \n"+newtext+"\nEnd of newtext.");
205     if (oldTextLength != newtext.length())
206     {
207       iframe.setVisible(false);
208       oldTextLength = newtext.length();
209       if (Platform.isJS()) // BH 2019
210       {
211         /*
212          * SwingJS doesn't have HTMLEditorKit, required for a JTextPane
213          * to display formatted html, so we use a simple alternative
214          */
215         String text = "<html><br><br><img src=\"swingjs/j2s/images/Jalview_Logo.png\"/><br>"
216                 + newtext + "</html>";
217         JLabel ta = new JLabel(text);
218         ta.setOpaque(true);
219         ta.setBackground(Color.white);
220         splashText = ta;
221       }
222       else
223       /**
224        * Java only
225        *
226        * @j2sIgnore
227        */
228       {
229         JTextPane jtp = new JTextPane();
230         jtp.setEditable(false);
231         jtp.setContentType("text/html");
232         jtp.setText("<html>" + newtext + "</html>");
233         jtp.addHyperlinkListener(this);
234         splashText = jtp;
235       }
236       splashText.addMouseListener(closer);
237
238       splashText.setVisible(true);
239       splashText.setSize(new Dimension(750, 375));
240       add(splashText, BorderLayout.CENTER);
241       revalidate();
242       iframe.setBounds((Desktop.instance.getWidth() - 750) / 2,
243               (Desktop.instance.getHeight() - 375) / 2, 750,
244               splashText.getHeight() + iconimg.getHeight());
245       iframe.validate();
246       iframe.setVisible(true);
247       return true;
248     }
249     return false;
250   }
251
252   /**
253    * Create splash screen, display it and clear it off again.
254    */
255   @Override
256   public void run()
257   {
258     initSplashScreenWindow();
259
260     long startTime = System.currentTimeMillis() / 1000;
261
262     while (visible)
263     {
264       iframe.repaint();
265       try
266       {
267         Thread.sleep(500);
268       } catch (Exception ex)
269       {
270       }
271
272       if (transientDialog
273               && ((System.currentTimeMillis() / 1000) - startTime) > SHOW_FOR_SECS)
274       {
275         visible = false;
276       }
277
278       if (visible && refreshText())
279       {
280         iframe.repaint();
281       }
282       if (!transientDialog)
283       {
284         return;
285       }
286     }
287
288     closeSplash();
289     Desktop.instance.startDialogQueue();
290   }
291
292   /**
293    * DOCUMENT ME!
294    */
295   public void closeSplash()
296   {
297     try
298     {
299
300       iframe.setClosed(true);
301     } catch (Exception ex)
302     {
303     }
304   }
305
306   public class SplashImage extends JPanel
307   {
308     Image image;
309
310     public SplashImage(Image todisplay)
311     {
312       image = todisplay;
313       if (image != null)
314       {
315         setPreferredSize(new Dimension(image.getWidth(this) + 8,
316                 image.getHeight(this)));
317       }
318     }
319
320     @Override
321     public Dimension getPreferredSize()
322     {
323       return new Dimension(image.getWidth(this) + 8, image.getHeight(this));
324     }
325
326     @Override
327     public void paintComponent(Graphics g)
328     {
329       g.setColor(Color.white);
330       g.fillRect(0, 0, getWidth(), getHeight());
331       g.setColor(Color.black);
332       g.setFont(new Font("Verdana", Font.BOLD, FONT_SIZE + 6));
333
334       if (image != null)
335       {
336         g.drawImage(image, (getWidth() - image.getWidth(this)) / 2,
337                 (getHeight() - image.getHeight(this)) / 2, this);
338       }
339     }
340   }
341
342   @Override
343   public void hyperlinkUpdate(HyperlinkEvent e)
344   {
345     Desktop.hyperlinkUpdate(e);
346
347   }
348 }