3253-omnibus save
[jalview.git] / src / jalview / gui / SplashScreen.java
index 4fb9136..782c842 100755 (executable)
@@ -29,218 +29,220 @@ import java.awt.Dimension;
 import java.awt.Font;
 import java.awt.Graphics;
 import java.awt.Image;
-import java.awt.Insets;
 import java.awt.MediaTracker;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
+import java.awt.Toolkit;
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
-import java.beans.PropertyVetoException;
+import java.net.URL;
 
 import javax.swing.JInternalFrame;
 import javax.swing.JLabel;
 import javax.swing.JLayeredPane;
 import javax.swing.JPanel;
 import javax.swing.JTextPane;
-import javax.swing.Timer;
-import javax.swing.border.EmptyBorder;
 import javax.swing.event.HyperlinkEvent;
 import javax.swing.event.HyperlinkListener;
 
 /**
- * A class that serves both as an initial 5-second splash screen (interactive
- * false) as well as for the Help menu item action (interactive true).
- * 
- * As a splash screen, the frame closes if clicked by the user.
- * 
- * Closure loop converted from a while/sleep loop to a JavaScript-compatible
- * state machine by Bob Hanson 2019.11.26.
- * 
- * TODO: get JTextPane working for read-only HTML.
+ * DOCUMENT ME!
  * 
+ * @author $author$
+ * @version $Revision$
  */
-@SuppressWarnings("serial")
 public class SplashScreen extends JPanel
         implements Runnable, HyperlinkListener
 {
-  private static final int STATE_INIT = 0;
-
-  private static final int STATE_LOOP = 1;
+  private static final int SHOW_FOR_SECS = 5;
 
-  private static final int STATE_DONE = 2;
+  private static final int FONT_SIZE = 11;
 
-  // boolean visible = true;
+  private boolean visible = true;
 
   private JPanel iconimg = new JPanel(new BorderLayout());
 
-  /**
-   * Temporary SwingJS Hack: Either a JLabel in JavaScript or a JTextPane in
-   * Java
+  /*
+   * as JTextPane in Java, JLabel in javascript
    */
-  protected Component htmlPane;
+  private Component splashText;
 
   private JInternalFrame iframe;
 
   private Image image;
 
-  private final static int fontSize = 11;
-
-  protected final static Font largeFont = new Font("Verdana", Font.BOLD,
-          fontSize + 6);
+  private boolean transientDialog = false;
 
-  int yoffset = 30;
+  private long oldTextLength = -1;
 
-  /**
-   * Creates a new SplashScreen object.
-   */
-  public SplashScreen()
-  {
-    this(false);
-  }
-
-  protected boolean isInteractive = false;
-
-  /**
-   * 
-   * @param interactive
-   *          if true - an internal dialog is opened rather than a free-floating
-   *          splash screen
+  /*
+   * allow click in the initial splash screen to dismiss it
+   * immediately (not if opened from About menu)
    */
-  public SplashScreen(boolean isInteractive)
-  {
-    this.isInteractive = isInteractive;
-    Thread t = new Thread(this, "SplashScreen");
-    t.start();
-  }
-
-  MouseAdapter closer = new MouseAdapter()
+  private MouseAdapter closer = new MouseAdapter()
   {
     @Override
     public void mousePressed(MouseEvent evt)
     {
-      try
+      if (transientDialog)
       {
-        if (!isInteractive)
+        try
         {
-          setVisible(false);
+          visible = false;
           closeSplash();
+        } catch (Exception ex)
+        {
         }
-      } catch (Exception ex)
-      {
       }
     }
   };
 
   /**
+   * Constructor that displays the splash screen
+   * 
+   * @param isTransient
+   *          if true the panel removes itself on click or after a few seconds;
+   *          if false it stays up until closed by the user
+   */
+  public SplashScreen(boolean isTransient)
+  {
+    this.transientDialog = isTransient;
+
+    if (Platform.isJS()) // BH 2019
+    {
+      splashText = new JLabel("");
+      run();
+    }
+    else
+    {
+      /**
+       * Java only
+       *
+       * @j2sIgnore
+       */
+      {
+        splashText = new JTextPane();
+        Thread t = new Thread(this);
+        t.start();
+      }
+    }
+  }
+
+  /**
    * ping the jalview version page then create and display the jalview
    * splashscreen window.
    */
-  protected void initSplashScreenWindow()
+  void initSplashScreenWindow()
   {
     addMouseListener(closer);
+
     try
     {
-      java.net.URL url = getClass().getResource("/images/Jalview_Logo.png");
-      image = java.awt.Toolkit.getDefaultToolkit().createImage(url);
-      MediaTracker mt = new MediaTracker(this);
-      mt.addImage(image, 0);
-      Image logo = (Platform.isJS() ? null
-              : java.awt.Toolkit.getDefaultToolkit().createImage(getClass()
-                      .getResource("/images/Jalview_Logo_small.png")));
-      if (logo != null)
+      URL url = getClass().getResource("/images/Jalview_Logo.png");
+      URL urllogo = getClass()
+              .getResource("/images/Jalview_Logo_small.png");
+
+      if (!Platform.isJS() && url != null)
       {
+        image = Toolkit.getDefaultToolkit().createImage(url);
+        Image logo = Toolkit.getDefaultToolkit().createImage(urllogo);
+        MediaTracker mt = new MediaTracker(this);
+        mt.addImage(image, 0);
         mt.addImage(logo, 1);
-      }
-      do
-      {
-        try
-        {
-          mt.waitForAll();
-        } catch (InterruptedException x)
+        do
         {
-        }
-        if (mt.isErrorAny())
-        {
-          System.err.println("Error when loading images!");
-        }
-      } while (!mt.checkAll());
-      if (url != null)
-      {
+          try
+          {
+            mt.waitForAll();
+          } catch (InterruptedException x)
+          {
+          }
+          if (mt.isErrorAny())
+          {
+            System.err.println("Error when loading images!");
+          }
+        } while (!mt.checkAll());
         Desktop.getInstance().setIconImage(logo);
       }
     } catch (Exception ex)
     {
     }
+
     iframe = new JInternalFrame();
     iframe.setFrameIcon(null);
-    iframe.setClosable(isInteractive);
+    iframe.setClosable(true);
     this.setLayout(new BorderLayout());
     iframe.setContentPane(this);
     iframe.setLayer(JLayeredPane.PALETTE_LAYER);
-    SplashImage splashimg = new SplashImage(image);
-    iconimg.add(splashimg, BorderLayout.CENTER);
-    add(iconimg, BorderLayout.NORTH);
+    if (Platform.isJS())
+    {
+      // ignore in JavaScript
+    }
+    else
+    /**
+     * Java only
+     * 
+     * @j2sIgnore
+     */
+    {
+      ((JTextPane) splashText).setEditable(false);
+
+      SplashImage splashimg = new SplashImage(image);
+      iconimg.add(splashimg, BorderLayout.CENTER);
+      add(iconimg, BorderLayout.NORTH);
+    }
+    add(splashText, BorderLayout.CENTER);
+    splashText.addMouseListener(closer);
     Desktop.getDesktopPane().add(iframe);
     refreshText();
   }
 
-  String oldtext;
-
-  private int mainState;
-
   /**
    * update text in author text panel reflecting current version information
    */
   protected boolean refreshText()
   {
-    Desktop desktop = Desktop.getInstance();
-    String newtext = desktop.getAboutMessage(true).toString();
+    String newtext = Desktop.getInstance().getAboutMessage();
     // System.err.println("Text found: \n"+newtext+"\nEnd of newtext.");
-    if (!newtext.equals(oldtext))
+    if (oldTextLength != newtext.length())
     {
       iframe.setVisible(false);
-      oldtext = newtext;
+      oldTextLength = newtext.length();
       if (Platform.isJS()) // BH 2019
       {
-        // BH TODO SwingJS does not implement HTML style. Could rethink this.
-
-        if (htmlPane == null)
-        {
-          htmlPane = new JLabel();
-        }
-        JLabel l = (JLabel)htmlPane;
-        l.setText(newtext);
-        Font f = htmlPane.getFont();
-        l.setFont(new Font(f.getFamily(), Font.PLAIN, f.getSize()));
-        l.setBorder(new EmptyBorder(new Insets(5, 5, 5, 5)));
-        l.setOpaque(true);
-        l.setBackground(Color.white);
-        htmlPane = l;
+        /*
+         * SwingJS doesn't have HTMLEditorKit, required for a JTextPane
+         * to display formatted html, so we use a simple alternative
+         */
+        String text = "<html><br><br><img src=\"swingjs/j2s/images/Jalview_Logo.png\"/><br>"
+                + newtext + "</html>";
+        JLabel ta = new JLabel(text);
+        ta.setOpaque(true);
+        ta.setBackground(Color.white);
+        splashText = ta;
       }
       else
       /**
        * Java only
-       * 
+       *
        * @j2sIgnore
        */
       {
-        if (htmlPane == null)
-        {
-          htmlPane = new JTextPane();
-        }
-        JTextPane pane = (JTextPane)htmlPane;
-        pane.setEditable(false);
-        pane.setContentType("text/html");
-        pane.setText(newtext);
-        pane.addHyperlinkListener(this);
-        htmlPane = pane;
+        JTextPane jtp = new JTextPane();
+        jtp.setEditable(false);
+        jtp.setContentType("text/html");
+        jtp.setText("<html>" + newtext + "</html>");
+        jtp.addHyperlinkListener(this);
+        splashText = jtp;
       }
-      htmlPane.addMouseListener(closer);
-      htmlPane.setSize(new Dimension(750, 375));
-      add(htmlPane, BorderLayout.CENTER);
-      int h = htmlPane.getHeight() + iconimg.getHeight();
-      iframe.setBounds(Math.max(0, (desktop.getWidth() - 750) / 2),
-              Math.max(0, (desktop.getHeight() - h) / 2), 750, h);
+      splashText.addMouseListener(closer);
+
+      splashText.setVisible(true);
+      splashText.setSize(new Dimension(750, 375));
+      add(splashText, BorderLayout.CENTER);
+      revalidate();
+      iframe.setBounds((Desktop.getInstance().getWidth() - 750) / 2,
+              (Desktop.getInstance().getHeight() - 375) / 2, 750,
+              splashText.getHeight() + iconimg.getHeight());
+      iframe.validate();
       iframe.setVisible(true);
       return true;
     }
@@ -253,88 +255,57 @@ public class SplashScreen extends JPanel
   @Override
   public void run()
   {
-    mainState = STATE_INIT;
-    mainLoop();
-  }
+    initSplashScreenWindow();
 
-  protected long startTime;
+    long startTime = System.currentTimeMillis() / 1000;
 
-  /**
-   * A simple state machine with just three states: init, loop, and done. Ideal
-   * for a simple while/sleep loop that works in Java and JavaScript
-   * identically.
-   * 
-   */
-  protected void mainLoop()
-  {
-    while (true)
+    while (visible)
     {
-      switch (mainState)
+      iframe.repaint();
+      try
       {
-      case STATE_INIT:
-        initSplashScreenWindow();
-        startTime = System.currentTimeMillis() / 1000;
-        mainState = STATE_LOOP;
-        continue;
-      case STATE_LOOP:
-        if (!isVisible())
-        {
-          mainState = STATE_DONE;
-          continue;
-        }
-        if (!isInteractive
-                && ((System.currentTimeMillis() / 1000) - startTime) > 5)
-        {
-          setVisible(false);
-          continue;
-        }
-        if (isVisible() && refreshText())
-        {
-          iframe.repaint();
-        }
-        if (isInteractive)
-        {
-          return;
-        }
-        Timer timer = new Timer(500, new ActionListener()
-        {
-          @Override
-          public void actionPerformed(ActionEvent e)
-          {
-            mainLoop();
-          }
+        Thread.sleep(500);
+      } catch (Exception ex)
+      {
+      }
 
-        });
-        timer.setRepeats(false);
-        timer.start();
-        return;
-      case STATE_DONE:
-        closeSplash();
-        Desktop.getInstance().startDialogQueue();
+      if (transientDialog && ((System.currentTimeMillis() / 1000)
+              - startTime) > SHOW_FOR_SECS)
+      {
+        visible = false;
+      }
+
+      if (visible && refreshText())
+      {
+        iframe.repaint();
+      }
+      if (!transientDialog)
+      {
         return;
       }
     }
 
+    closeSplash();
+    Desktop.getInstance().startDialogQueue();
   }
 
   /**
-   * Close the internal frame, either from the timer expiring or from the mouse
-   * action.
+   * DOCUMENT ME!
    */
   public void closeSplash()
   {
-    setVisible(false);
     try
     {
+
       iframe.setClosed(true);
-    } catch (PropertyVetoException e)
+    } catch (Exception ex)
     {
     }
   }
 
-  private class SplashImage extends JPanel
+  public class SplashImage extends JPanel
   {
-    private Image image;
+    Image image;
 
     public SplashImage(Image todisplay)
     {
@@ -358,7 +329,7 @@ public class SplashScreen extends JPanel
       g.setColor(Color.white);
       g.fillRect(0, 0, getWidth(), getHeight());
       g.setColor(Color.black);
-      g.setFont(largeFont);
+      g.setFont(new Font("Verdana", Font.BOLD, FONT_SIZE + 6));
 
       if (image != null)
       {
@@ -366,46 +337,6 @@ public class SplashScreen extends JPanel
                 (getHeight() - image.getHeight(this)) / 2, this);
       }
     }
-    /*
-     * int y = yoffset;
-     * 
-     * g.drawString("Jalview " + jalview.bin.Cache.getProperty("VERSION"), 50,
-     * y);
-     * 
-     * FontMetrics fm = g.getFontMetrics(); int vwidth =
-     * fm.stringWidth("Jalview " + jalview.bin.Cache.getProperty("VERSION"));
-     * g.setFont(new Font("Verdana", Font.BOLD, fontSize + 2)); g.drawString(
-     * "Last updated: " + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"),
-     * 50 + vwidth + 5, y); if (jalview.bin.Cache.getDefault("LATEST_VERSION",
-     * "Checking").equals( "Checking")) { // Displayed when code version and
-     * jnlp version do not match g.drawString("...Checking latest version...",
-     * 50, y += fontSize + 10); y += 5; g.setColor(Color.black); } else if
-     * (!jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
-     * .equals(jalview.bin.Cache.getProperty("VERSION"))) { if
-     * (jalview.bin.Cache.getProperty("VERSION").toLowerCase()
-     * .indexOf("automated build") == -1) { // Displayed when code version and
-     * jnlp version do not match and code // version is not a development build
-     * g.setColor(Color.red); } g.drawString( "!! Jalview version " +
-     * jalview.bin.Cache.getDefault("LATEST_VERSION", "..Checking..") +
-     * " is available for download from "
-     * +jalview.bin.Cache.getDefault("www.jalview.org"
-     * ,"http://www.jalview.org")+" !!", 50, y += fontSize + 10); y += 5;
-     * g.setColor(Color.black); }
-     * 
-     * g.setFont(new Font("Verdana", Font.BOLD, fontSize)); g.drawString(
-     * "Authors: Jim Procter, Andrew Waterhouse, Michele Clamp, James Cuff, Steve Searle,"
-     * , 50, y += fontSize + 4); g.drawString("David Martin & Geoff Barton.",
-     * 60, y += fontSize + 4); g.drawString(
-     * "Development managed by The Barton Group, University of Dundee.", 50, y
-     * += fontSize + 4); g.drawString("If  you use Jalview, please cite: ", 50,
-     * y += fontSize + 4); g.drawString(
-     * "Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
-     * , 50, y += fontSize + 4); g.drawString(
-     * "Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
-     * , 50, y += fontSize + 4);
-     * g.drawString("Bioinformatics doi: 10.1093/bioinformatics/btp033", 50, y
-     * += fontSize + 4); }
-     */
   }
 
   @Override
@@ -414,5 +345,4 @@ public class SplashScreen extends JPanel
     Desktop.hyperlinkUpdate(e);
 
   }
-
 }