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