/* * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) * Copyright (C) $$Year-Rel$$ The Jalview Authors * * This file is part of Jalview. * * Jalview is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation, either version 3 * of the License, or (at your option) any later version. * * Jalview is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Jalview. If not, see . * The Jalview Authors are detailed in the 'AUTHORS' file. */ package jalview.gui; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics; import java.awt.Image; import java.awt.MediaTracker; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import javax.swing.JInternalFrame; import javax.swing.JLabel; import javax.swing.JLayeredPane; import javax.swing.JPanel; import javax.swing.JTextPane; import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkListener; import jalview.util.ChannelProperties; import jalview.util.Platform; /** * DOCUMENT ME! * * @author $author$ * @version $Revision$ */ @SuppressWarnings("serial") public class SplashScreen extends JPanel implements HyperlinkListener, StateMachine { private static final int STATE_INIT = 0; private static final int STATE_LOOP = 1; private static final int STATE_DONE = 2; private static final int SHOW_FOR_SECS = 5; private static final int FONT_SIZE = (Platform.isJS() ? 14 : 11); private boolean visible = true; private JPanel iconimg = new JPanel(new BorderLayout()); // could change fg, bg, font later to use ChannelProperties (these are not // actually being used!) private static Color bg = Color.WHITE; private static Color fg = Color.BLACK; /* * as JTextPane in Java, JLabel in javascript */ private Component splashText; private JInternalFrame iframe; private Image image; private boolean transientDialog = false; private long oldTextLength = -1; /* * allow click in the initial splash screen to dismiss it * immediately (not if opened from About menu) */ private MouseAdapter closer = new MouseAdapter() { @Override public void mousePressed(MouseEvent evt) { if (transientDialog) { try { closeSplash(); } catch (Exception ex) { } } } }; /** * Constructor that displays the splash screen * * @param isStartup * if true the panel removes itself on click or after a few seconds; * if false it stays up until closed by the user (from Help..About menu) */ public SplashScreen(boolean isStartup) { this.transientDialog = isStartup; // we must get the image in JavaScript BEFORE starting the helper, // as it will take a 1 ms clock tick to obtain width and height information. image = ChannelProperties.getImage("banner"); logo = ChannelProperties.getImage("logo.48"); font = new Font("SansSerif", Font.PLAIN, FONT_SIZE); helper = new StateHelper(this); helper.next(STATE_INIT); } protected void initSplashScreenWindow() { addMouseListener(closer); waitForImages(); setLayout(new BorderLayout()); iframe = new JInternalFrame(); iframe.setFrameIcon(null); iframe.setClosable(true); iframe.setContentPane(this); iframe.setLayer(JLayeredPane.PALETTE_LAYER); SplashImage splashimg = new SplashImage(image); imgPanel.add(splashimg, BorderLayout.CENTER); add(imgPanel, BorderLayout.NORTH); Desktop.getDesktopPane().add(iframe); refreshText(); } /** * Both Java and JavaScript have to wait for images, but this method will * accomplish nothing for JavaScript. We have already taken care of image * loading with our state loop in JavaScript. * */ private void waitForImages() { if (Platform.isJS()) return; MediaTracker mt = new MediaTracker(this); mt.addImage(image, 0); mt.addImage(logo, 1); do { try { mt.waitForAll(); } catch (InterruptedException x) { } if (mt.isErrorAny()) { System.err.println("Error when loading images!"); break; } } while (!mt.checkAll()); if (logo != null) { Desktop.getInstance().setIconImage(logo); } this.setBackground(bg); this.setForeground(fg); this.setFont(font); } /** * update text in author text panel reflecting current version information */ protected boolean refreshText() { String newtext = Desktop.getInstance().getAboutMessage(); // System.err.println("Text found: \n"+newtext+"\nEnd of newtext."); if (oldTextLength == newtext.length()) { return false; } iframe.setVisible(false); oldTextLength = newtext.length(); if (Platform.isJS()) // BH 2019 { /* * SwingJS doesn't have HTMLEditorKit, required for a JTextPane * to display formatted html, so we use a simple alternative */ String text = "
" + newtext + "
"; JLabel ta = new JLabel(text); ta.setOpaque(true); ta.setBackground(Color.white); splashText = ta; } else /** * Java only * * @j2sIgnore */ { JTextPane jtp = new JTextPane(); jtp.setEditable(false); jtp.setBackground(bg); jtp.setForeground(fg); jtp.setFont(font); jtp.setContentType("text/html"); jtp.setText("" + newtext + ""); jtp.addHyperlinkListener(this); splashText = jtp; } splashText.addMouseListener(closer); splashText.setVisible(true); splashText.setSize(new Dimension(750, 375 + logoSize + (Platform.isJS() ? 40 : 0))); splashText.setBackground(bg); splashText.setForeground(fg); splashText.setFont(font); add(splashText, BorderLayout.CENTER); revalidate(); int width = Math.max(splashText.getWidth(), iconimg.getWidth()); int height = splashText.getHeight() + iconimg.getHeight(); iframe.setBounds((iframe.getParent().getWidth() - width) / 2, (iframe.getParent().getHeight() - height) / 2, 750, width,height); iframe.validate(); iframe.setVisible(true); return true; } protected void closeSplash() { try { iframe.setClosed(true); } catch (Exception ex) { } } /** * 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. * */ @Override public boolean stateLoop() { while (true) { switch (helper.getState()) { case STATE_INIT: initSplashScreenWindow(); helper.setState(STATE_LOOP); continue; case STATE_LOOP: if (!isVisible()) { helper.setState(STATE_DONE); continue; } if (refreshText()) { iframe.repaint(); } if (isStartup) helper.delayedState(SHOW_FOR_SECS * 1000, STATE_DONE); return true; default: case STATE_DONE: setVisible(false); closeSplash(); Desktop.getInstance().startDialogQueue(); return true; } } } private class SplashImage extends JPanel { Image image; public SplashImage(Image todisplay) { image = todisplay; if (image != null) { setPreferredSize(new Dimension(image.getWidth(this) + 8, image.getHeight(this))); } } @Override public Dimension getPreferredSize() { return new Dimension(image.getWidth(this) + 8, image.getHeight(this)); } @Override public void paintComponent(Graphics g) { g.setColor(bg); g.fillRect(0, 0, getWidth(), getHeight()); g.setColor(fg); g.setFont(new Font(font.getFontName(), Font.BOLD, FONT_SIZE + 6)); if (image != null) { g.drawImage(image, (getWidth() - image.getWidth(this)) / 2, (getHeight() - image.getHeight(this)) / 2, this); } } } @Override public void hyperlinkUpdate(HyperlinkEvent e) { Desktop.hyperlinkUpdate(e); } }