diff -r f058f21b9e99 netx/net/sourceforge/jnlp/splashscreen/impls/CircleSplashScreen.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/netx/net/sourceforge/jnlp/splashscreen/impls/CircleSplashScreen.java Thu Mar 01 13:31:17 2012 +0100 @@ -0,0 +1,670 @@ +/* CircleSplashScreen.java +Copyright (C) 2012 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea 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 2, or (at your option) +any later version. + +IcedTea 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 IcedTea; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ +package net.sourceforge.jnlp.splashscreen.impls; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Point; +import java.awt.RadialGradientPaint; +import java.awt.RenderingHints; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Point2D; +import java.awt.geom.RectangularShape; +import java.awt.geom.RoundRectangle2D; +import java.awt.image.BufferedImage; +import java.util.List; + +import javax.swing.SwingUtilities; +import net.sourceforge.jnlp.splashscreen.SplashUtils.SplashReason; +import net.sourceforge.jnlp.splashscreen.SplashPanel; +import net.sourceforge.jnlp.splashscreen.parts.BasicComponentSplashScreen; +import net.sourceforge.jnlp.splashscreen.parts.InfoItem; + +public final class CircleSplashScreen extends BasicComponentSplashScreen { + + /** Position of the spinner (angle in degrees) */ + private int spinnerPos = 0; + /** How much the spinner should move in each time slice */ + private static final int spinFactor = 1; + /** Frequency (per X iterations) at which dot animation moves forward */ + private static final int dotAnimationFrequency = 18; + /** The project name to display */ + private static final String projDisplayName = "IcedTea-Web Plugin"; + /** The loading message */ + private static final String loadingMsg = "Loading"; + /** The animated applet loading message (....'s are animated) */ + private static final String animatedLoadingMsg = loadingMsg + "...."; + /** Number of dots after the loading message (to animate it) */ + private int numDotsAfterLoadingMsg; + /** Dark color of icedtea */ + private Color darkIcedTeaColor = new Color(84, 0, 0); + /** Light color of icedtea */ + private Color lightIcedTeaColor = new Color(217, 191, 55); + /** The corner width for the rectangles */ + private int rectangleArcWidth; + /** The inner rectangle */ + private RectangularShape innerRectangle; + /** The shadow of the inner rectangle */ + private RectangularShape shadowRectangle; + /** Returns the center circle */ + private Ellipse2D centerCircle; + /** Size of the shadow */ + private int shadowSize; + /** The background image (everything but the spinner) */ + private BufferedImage panelBG; + /** Image where everything is drawn off-screen */ + private Image bufferedPanelImage; + /** Graphics associated with the off-screen drawing image */ + private Graphics bufferedImageGraphics; + /** Minimum height/width for spinner */ + private static final int minSizeForSpinner = 120; + /** The minimum dimension (height of width) */ + private int minDimension; + private final CircleSplashScreen self; + + /** + * Constructor. Takes an initial size for the panel and sets up listeners for resize + * + * @param initialPluginWidth The initial width of the plugin/panel + * @param initialPluginHeight The initial height of the plugin/panel + */ + public CircleSplashScreen(final int initialPluginWidth, final int initialPluginHeight, SplashReason splashReason) { + this.self = this; + this.setSplashReason(splashReason); + // Adjust vars based on initial size + adjustForSize(initialPluginWidth, initialPluginHeight); + + // Add a new listener for resizes + addComponentListener(new ComponentListener() { + + // Nothing to do for this + @Override + public void componentShown(ComponentEvent e) { + } + + // Re-adjust variables based on size + @Override + public void componentResized(ComponentEvent e) { + adjustForSize(getWidth(), getHeight()); + } + + // Nothing to do for this + @Override + public void componentMoved(ComponentEvent e) { + } + + // Nothing to do for this + @Override + public void componentHidden(ComponentEvent e) { + } + }); + + } + + /** + * Adjusts drawing related variables based on size of the panel + * + * @param pluginWidth The width of the panel + * @param pluginHeight The height of the panel + */ + @Override + public void adjustForSize(int pluginWidth, int pluginHeight) { + + // Set the class-wide variables + this.setPluginWidth(pluginWidth); + this.setPluginHeight(pluginHeight); + + // The minimum dimension (either height or width) + minDimension = Math.min(pluginHeight, pluginWidth); + + // The arc-width -- default is 20, but set to 0 (sharp corners) if panel is too small + rectangleArcWidth = 20; + rectangleArcWidth = minDimension >= rectangleArcWidth * 2 ? rectangleArcWidth : 0; + + // Size of the simulated shadow cast + shadowSize = Math.max(minDimension / 20, 5); + + // The shadow rectangle shape + shadowRectangle = getShadowRectangle(new Point(shadowSize, shadowSize)); + + // The inner (reddish-maroon) box + innerRectangle = getInnerRect(new Point(0, 0)); + + // The circle in the center around which the spinner runs + centerCircle = getCenterCircle(); + + // Calculate how many dots after the loading message (so that we can animate that) + // Do it in a quick and dirty way.. this code is called only once per splash + + String loadingMsgCopy = new String(animatedLoadingMsg); + numDotsAfterLoadingMsg = 0; + while (loadingMsgCopy.endsWith(".")) { + + // shorten string by 1 + loadingMsgCopy = loadingMsgCopy.substring(0, loadingMsgCopy.length() - 1); + + // increment dot count + numDotsAfterLoadingMsg++; + } + + // The background panel (all the satic stuff is pre-drawn for speed) + if (getState() != SplashPanel.State.ERROR) { + panelBG = getBufferedBgImage(false); + } else { + panelBG = getBufferedBgImage(true); + } + + } + + /** + * Methods to start the animation in the splash panel. + * + * This method exits after starting a new thread to do the animation. It + * is synchronized to prevent multiple spin threads from being created. + */ + @Override + public void spin() { + + /* If already spinning, don't do it again */ + //if (spin) + // return; + spin = true; + // Create a new thread to increment spinFactor and repaint + Thread t = new Thread() { + + @Override + public void run() { + + // While spinning + while (spin) { + try { + + // Reset spinner if we have crossed 360 + if (spinnerPos > 360) { + spinnerPos = 0; + } + + // Move 1 degree per spin + spinnerPos += spinFactor; + + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + + // Force repaint + if (self.getState() == SplashPanel.State.LOADING) { + repaint(); + } + } + }); + + Thread.sleep(30); + + } catch (Exception e) { + e.printStackTrace(); + } + } + } + }; + + t.start(); // Start spinning + } + + /** + * Stops the animation + */ + @Override + public void stopSpinning() { + spin = false; + } + + /** + * Shows an error message + */ + @Override + public void showError(Throwable ex) { + if (State.ERROR.equals(getState())) { + return; + } + panelBG = getBufferedBgImage(true); + setState(SplashPanel.State.ERROR); + this.setLoadingException(ex); + stopSpinning(); + try { + Thread.sleep(30); + } catch (Exception iex) { + ex.printStackTrace(); + } + repaint(); + } + + /** + * Creates a background image with non-animated components and returns it + * + * @param errorBg Boolean indicating if the background is for an error. + * True indicates error background. + * + * @return The background image + */ + public BufferedImage getBufferedBgImage(boolean errorBg) { + + // New static image for bg and text, so we don't have to redraw + BufferedImage bi = new BufferedImage(getPluginWidth(), getPluginHeight(), BufferedImage.TYPE_INT_RGB); + + // The graphics instance for the image + Graphics2D g2d = (Graphics2D) bi.getGraphics(); + + // Text should look nice. Anti-alias it + Object defaultAntialias = g2d.getRenderingHint(RenderingHints.KEY_ANTIALIASING); + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + + // Start drawing the elements. Complex drawing is split off + // into smaller functions, rest is done here + + // == Back ground == + // First, paint a while background + g2d.setPaint(new Color(255, 255, 255)); + g2d.fillRect(0, 0, pluginWidth, pluginHeight); + + // == Shadow == + drawShadow(g2d); + + // == Inner rectangle == + // Set the rectangle color. Reddish-maroon for normal, dark gray for error + if (errorBg) { + g2d.setPaint(Color.DARK_GRAY); + } else { + g2d.setPaint(darkIcedTeaColor); + } + + // Fill the inner rectangle with the above color + g2d.fill(innerRectangle); + + // == Project logo == + drawTextAroundCenter(g2d, -0.5, 0, projDisplayName); + + // == center circle == + if (!errorBg && minDimension >= minSizeForSpinner) { + drawCenterCircle(g2d); + } + + // If there is an error, draw text as well + if (errorBg) { + drawTextAroundCenter(g2d, 2, 0, "Loading failed"); + // if (loadingException != null) + { + Font msgFont = new Font("Dialog", Font.ITALIC, 10); + Font fontBackup = g2d.getFont(); + g2d.setFont(msgFont); + String s = "click here for details"; + final int sh = g2d.getFontMetrics().getHeight(); + final int sw = g2d.getFontMetrics().stringWidth(s); + final int padding = 2; + final CircleSplashScreen self = this; + MouseListener[] oldML = this.getMouseListeners(); + for (MouseListener mouseListener : oldML) { + this.removeMouseListener(mouseListener); + } + this.addMouseListener(new MouseAdapter() { + + @Override + public void mouseClicked(MouseEvent e) { + if (e.getX() > pluginWidth - sw - 2 * padding - shadowSize && e.getY() > pluginHeight - 2 * sh - 2 * padding - shadowSize) { + raiseExceptionDialog(); + } + } + }); + g2d.drawString(s, pluginWidth - sw - 2 * padding - shadowSize, pluginHeight - sh - 2 * padding - shadowSize); + g2d.setFont(fontBackup); + } + } + Font f = (new Font("Serif", Font.PLAIN, 12)); + Font b = g2d.getFont(); + g2d.setFont(f); + g2d.setColor(Color.white); + if (getInformationContent() != null) { + List<String> s = getInformationContent().getHeader(); + for (int i = 0; i < s.size(); i++) { + String string = s.get(i); + g2d.drawString(string, 10, (i + 1) * g2d.getFontMetrics().getHeight()); + + } + InfoItem ii = getInformationContent().getBestMatchingDescriptionForSplash(); + if (ii != null) { + g2d.drawString(ii.toNiceString(), 10, getPluginHeight() - g2d.getFontMetrics().getHeight() - shadowSize); + } + g2d.setFont(b); + } + if (getVersion() != null) { + g2d.drawString(getVersion(), getPluginWidth() - g2d.getFontMetrics().stringWidth(getVersion()) - shadowSize, g2d.getFontMetrics().getHeight()); + } + g2d.setFont(b); + // Set anti-aliasing back to whatever it was + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, defaultAntialias); + + return bi; + } + + /** + * Returns the shadow shadow for the main rectangle + * + * @param topLeft The start (top-left) co-ordinates of the shadow + * @return The shadow rectangle shape + */ + private RectangularShape getShadowRectangle(Point topLeft) { + + // The height and width of the shadow + + // When computing shadow size, we want to deduct from the applet size: + // 1) The top left starting point + // 2) The thickness of the shadow (since we use stroke to blend into a white bg) + + int shadowHeight = pluginHeight - topLeft.x - shadowSize; + int shadowWidth = pluginWidth - topLeft.y - shadowSize; + + return new RoundRectangle2D.Double(topLeft.x, topLeft.y, + shadowWidth, shadowHeight, + rectangleArcWidth, rectangleArcWidth); + } + + /** + * Returns the main rectangle shape + * + * @param topLeft The start (top-left) co-ordinates of the rectangle + * @return The main rectangle shape + */ + private RectangularShape getInnerRect(Point topLeft) { + + // When computing rect size, we want to deduct from the applet size: + // 1) The top left starting point + // 2) The thickness of the shadow + + int rectHeight = pluginHeight - topLeft.x - shadowSize; + int rectWidth = pluginWidth - topLeft.y - shadowSize; + + return new RoundRectangle2D.Double(topLeft.x, topLeft.y, + rectWidth, rectHeight, + rectangleArcWidth, rectangleArcWidth); + } + + /** + * Returns the center circle around which the glowing sphere spins + * + * @return The circle shape + */ + private Ellipse2D getCenterCircle() { + + // Radius should be decided by min of height/width + int diameter = Math.min((int) innerRectangle.getHeight(), (int) innerRectangle.getWidth()); + diameter -= shadowSize * 2; // Enough padding on all sides so that the glow stays in + + // Center of the rectangle + Point innerRectCenter = new Point((int) innerRectangle.getCenterX(), (int) innerRectangle.getCenterY()); + + // Compute the top left point for the ellipse + Point topLeft = new Point(innerRectCenter.x - (int) (diameter / 2), innerRectCenter.y - (int) (diameter / 2)); + + return new Ellipse2D.Double(topLeft.x, topLeft.y, diameter, diameter); + } + + /** + * Draws the shadow for the main rectangle + * + * @param g2d The Graphics2D object in which to draw + */ + private void drawShadow(Graphics2D g2d) { + + /* Successively stroke with different colors from white + * to black, with white being the thickest stroke and black being + * the thinnest. This approach makes rendering a lot faster than + * using alpha composites. + */ + for (int width = shadowSize; width > 0; width--) { + g2d.setColor(new Color((float) width / shadowSize, (float) width / shadowSize, (float) width / shadowSize)); + g2d.setStroke(new BasicStroke(width)); + g2d.draw(shadowRectangle); + } + } + + /** + * Draws text around the center area. + * + * This is a generic function that can draw text in the center as well + * as around it vertically (based on the offset). It can also be told + * to cut off the last X characters, which makes it useful for drawing + * animated text content. + * + * @param g2d The Graphics2D object + * @param heightOffset The offset from the center line in units of font height + * @param charsToCutOff How many characters to cut off from the string + * @param msg The text to draw + */ + private void drawTextAroundCenter(Graphics2D g2d, double heightOffset, + int charsToCutOff, String msg) { + + // Font color = white + g2d.setPaint(new Color(1.0f, 1.0f, 1.0f)); + + // Calculate font size + // First, get the lower bound of height/width + int minSize = Math.min(pluginHeight, pluginWidth); + + // Now, compute font size relative to the min size. + int fontSize = Math.max(minSize / 16, 7); + + // Set the font + Font msgFont = new Font("Dialog", Font.BOLD, fontSize); + g2d.setFont(msgFont); + + // Calculate font location + FontMetrics fontMetrics; + int fontWidth; + int fontHeight; + + // Get the rendered font size + g2d.setFont(msgFont); + fontMetrics = g2d.getFontMetrics(); + fontWidth = fontMetrics.stringWidth(msg); + fontHeight = fontMetrics.getHeight(); + + // We now know the center of the rectangle, and the size of the text + // Compute were the font should be drawn + + // Horizontally + int fontXLocation = (int) (innerRectangle.getCenterX() - fontWidth / 2); // half-width right from center + + // Vertically (center + offset) + int fontYLocation = (int) ((innerRectangle.getCenterY()) + heightOffset * fontHeight); + + // Finally, make sure the string will be in bounds + if (innerRectangle.getMinX() > fontXLocation /* top left X */ || innerRectangle.getMinY() > fontYLocation /* top left Y */ || innerRectangle.getMaxX() < fontXLocation + fontWidth /* bottom right X */ || innerRectangle.getMaxY() < fontYLocation + fontHeight /* bottom right Y */) { + return; + } + + // Everything is within bounds + g2d.drawString(msg.substring(0, msg.length() - charsToCutOff), fontXLocation, fontYLocation); + } + + /** + * Draws the center circle along which a tiny sphere spins. The drawing is + * done in successive steps to give it a soft edge. + * + *@param g2d The Graphics2D instance to draw onto + */ + private void drawCenterCircle(Graphics2D g2d) { + + // Calculate the thickness of the curcle + int circleThickness = Math.min((int) Math.min(pluginHeight, pluginWidth) / 25, shadowSize); // never make it bigger than shadow + + // Keep stroking successively, the higher the stroke + // width, the lighter the color + for (int width = circleThickness; width > 0; width--) { + g2d.setColor(getCompositedColor(lightIcedTeaColor, darkIcedTeaColor, width, circleThickness)); + g2d.setStroke(new BasicStroke(width)); + g2d.draw(centerCircle); + } + } + + /** + * Function get composite color for use with iterative stroking for a soft edge + * + * This function returns a color between 2 given colors, based on the width of + * the stroke (higher width = most toward end color) + * + * @param start The start color + * @param end The end color + * @param width The width of the current stroke + * @param totalWidth Total width across which the stroking will be done + * @return The resulting composite color + */ + private Color getCompositedColor(Color start, Color end, float width, float totalWidth) { + + // Find the distance between the colors + int rColorDistance = start.getRed() - end.getRed(); + int gColorDistance = start.getGreen() - end.getGreen(); + int bColorDistance = start.getBlue() - end.getBlue(); + + // Compute the fraction by which it should be incremented + int rIncr = (int) (((float) rColorDistance * width) / totalWidth); + int gIncr = (int) (((float) gColorDistance * width) / totalWidth); + int bIncr = (int) (((float) bColorDistance * width) / totalWidth); + + return new Color(start.getRed() - rIncr, start.getGreen() - gIncr, start.getBlue() - bIncr); + } + + /** + * Draws the spinner based on spinner position + * + * @param g2d The Graphics2D object to draw on + */ + private void drawSpinner(Graphics2D g2d) { + + // Do nothing when we are not spinning + if (!spin) { + return; + } + + // Use anti-aliasing to make things look good + Object defaultAntialias = g2d.getRenderingHint(RenderingHints.KEY_ANTIALIASING); + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + + /* To show the "...." animation, we want to draw a new dot every + * X paint calls (where X is perfectly divisible by 360). + * So divide position by dotAnimationFrequency and mod by number + * of dots + 1 (the +1 because there are max + 1 states including + * the case of 0 dots) + */ + + // Figure out characters (dots) to cut + int charsToCut = numDotsAfterLoadingMsg /*total */ - (spinnerPos / dotAnimationFrequency) % (numDotsAfterLoadingMsg + 1) /* how many to cut off */; + + // Draw the text + drawTextAroundCenter(g2d, 0.5, charsToCut, animatedLoadingMsg); + + if (minDimension < minSizeForSpinner) { + return; + } + + // In the parametric form, we can compute the positions on the + // circumference using the equations: + + // x = x_center + radius*cos(t); + // y = y_center + radius*sin(t); + + // Where t is the angle from the X axis (in degrees) + float radius = (float) centerCircle.getWidth() / 2; + + int x = (int) (centerCircle.getCenterX() + radius * (Math.cos(Math.toRadians(spinnerPos)))); + int y = (int) (centerCircle.getCenterY() + radius * (Math.sin(Math.toRadians(spinnerPos)))); + + // The spinning sphere size + int sphereSize = (int) (shadowSize); + + // Draw the sphere + Point2D center = new Point2D.Float(x, y); + float[] dist = {0.0f, 1.0f}; + Color[] colors = {lightIcedTeaColor, darkIcedTeaColor}; + RadialGradientPaint p = new RadialGradientPaint(center, sphereSize, dist, colors); + g2d.setPaint(p); + g2d.fillOval(x - sphereSize, y - sphereSize, sphereSize * 2, sphereSize * 2); + + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, defaultAntialias); + } + + @Override + public void paintComponent(Graphics g) { + paint(g); + } + + @Override + public void paint(Graphics g) { + + Graphics2D g2d = (Graphics2D) g; + + // Draw the background + g2d.drawImage(panelBG, 0, 0, null); + + // Draw the spinner + drawSpinner(g2d); + } + + @Override + public void update(Graphics g) { + + // If the buffered image or graphics don't exit, create them + if (bufferedPanelImage == null || bufferedImageGraphics == null) { + bufferedPanelImage = createImage(pluginWidth, pluginHeight); + bufferedImageGraphics = bufferedPanelImage.getGraphics(); + } + + paint(bufferedImageGraphics); + g.drawImage(bufferedPanelImage, 0, 0, this); + } +} diff -r f058f21b9e99 netx/net/sourceforge/jnlp/splashscreen/impls/DummySpalshScreen.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/netx/net/sourceforge/jnlp/splashscreen/impls/DummySpalshScreen.java Thu Mar 01 13:31:17 2012 +0100 @@ -0,0 +1,347 @@ +/* DummySplashScreen.java +Copyright (C) 2012 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea 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 2, or (at your option) +any later version. + +IcedTea 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 IcedTea; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ +package net.sourceforge.jnlp.splashscreen.impls; + +import java.awt.Color; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.LinkedList; +import java.util.List; +import java.util.Random; + +import javax.swing.SwingUtilities; +import net.sourceforge.jnlp.splashscreen.SplashUtils.SplashReason; +import net.sourceforge.jnlp.splashscreen.parts.JEditorPaneBasedExceptionDialog; +import net.sourceforge.jnlp.splashscreen.SplashPanel; +import net.sourceforge.jnlp.splashscreen.parts.BasicComponentSplashScreen; +import net.sourceforge.jnlp.splashscreen.parts.InfoItem; + +public final class DummySpalshScreen extends BasicComponentSplashScreen { + + /** The loading message */ + private static final String loadingMsg = "Loading"; + List<Point> l = new LinkedList<Point>(); + private final DummySpalshScreen self; + + /** + * Constructor. Takes an initial size for the panel and sets up listeners for resize + * + * @param initialPluginWidth The initial width of the plugin/panel + * @param initialPluginHeight The initial height of the plugin/panel + */ + public DummySpalshScreen(final int initialPluginWidth, final int initialPluginHeight, SplashReason splashReason) { + this.setSplashReason(splashReason); + // Adjust vars based on initial size + adjustForSize(initialPluginWidth, initialPluginHeight); + + // Add a new listener for resizes + addComponentListener(new ComponentListener() { + + // Nothing to do for this + @Override + public void componentShown(ComponentEvent e) { + } + + // Re-adjust variables based on size + @Override + public void componentResized(ComponentEvent e) { + adjustForSize(getWidth(), getHeight()); + } + + // Nothing to do for this + @Override + public void componentMoved(ComponentEvent e) { + } + + // Nothing to do for this + @Override + public void componentHidden(ComponentEvent e) { + } + }); + + self = this; + this.addMouseListener(new MouseAdapter() { + + @Override + public void mouseClicked(MouseEvent e) { + if (getState().equals(State.ERROR)) { + raiseExceptionDialog(); + } + } + }); + } + + /** + * Adjusts drawing related variables based on size of the panel + * + * @param pluginWidth The width of the panel + * @param pluginHeight The height of the panel + */ + @Override + public void adjustForSize(int pluginWidth, int pluginHeight) { + this.setPluginWidth(pluginWidth); + this.setPluginHeight(pluginHeight); + } + + /** + * Methods to start the animation in the splash panel. + * + * This method exits after starting a new thread to do the animation. It + * is synchronized to prevent multiple spin threads from being created. + */ + @Override + public void spin() { + + /* If already spinning, don't do it again */ + if (isSpin()) { + return; + } + spin = true; + + // Create a new thread to increment spinFactor and repaint + Thread t = new Thread() { + + public void run() { + + // While spinning + while (spin) { + try { + + + + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + + Random r = new Random(); + l.add(new Point(r.nextInt(getPluginWidth()), r.nextInt(getPluginHeight()))); + // Force repaint + if (self.getState() == SplashPanel.State.LOADING) { + repaint(); + } + } + }); + + Thread.sleep(30); + + } catch (Exception e) { + e.printStackTrace(); + } + } + } + }; + + t.start(); + } + + /** + * Stops the animation + */ + @Override + public void stopSpinning() { + spin = false; + } + + /** + * Shows an error message + */ + @Override + public void showError(Throwable ex) { + if (State.ERROR.equals(getState())) { + return; + } + //panelBG = getBufferedBgImage(true); + setState(SplashPanel.State.ERROR); + setLoadingException(ex); + stopSpinning(); + try { + Thread.sleep(30); + } catch (Exception iex) { + ex.printStackTrace(); + } + repaint(); + } + + /** + * Draws text around the center area. + * + * This is a generic function that can draw text in the center as well + * as around it vertically (based on the offset). It can also be told + * to cut off the last X characters, which makes it useful for drawing + * animated text content. + * + * @param g2d The Graphics2D object + * @param heightOffset The offset from the center line in units of font height + * @param charsToCutOff How many characters to cut off from the string + * @param msg The text to draw + */ + private void drawTextAroundCenter(Graphics2D g2d, double heightOffset, + int charsToCutOff, String msg) { + + + + // Calculate font size + // First, get the lower bound of height/width + int minSize = Math.min(getPluginHeight(), getPluginWidth()); + + // Now, compute font size relative to the min size. + int fontSize = Math.max(minSize / 16, 7); + + // Set the font + Font msgFont = new Font("Dialog", Font.BOLD, fontSize); + g2d.setFont(msgFont); + + // Calculate font location + FontMetrics fontMetrics; + int fontWidth; + int fontHeight; + + g2d.setFont(msgFont); + fontMetrics = g2d.getFontMetrics(); + fontWidth = fontMetrics.stringWidth(msg); + fontHeight = fontMetrics.getHeight(); + + int fontXLocation = (int) (getPluginWidth() / 2 - fontWidth / 2); // half-width right from center + + + int fontYLocation = (int) (getPluginHeight() / 2 + heightOffset * fontHeight); + + + + // Everything is within bounds + g2d.drawString(msg.substring(0, msg.length() - charsToCutOff), fontXLocation, fontYLocation); + } + + @Override + public void paintComponent(Graphics g) { + paint(g); + } + + @Override + public void paint(Graphics g) { + + Graphics2D g2d = (Graphics2D) g; + + // Draw the background + //g2d.drawImage(panelBG, 0, 0, null); + + // Draw the spinner + g2d.setColor(Color.BLACK); + if (getState() == State.LOADING) { + for (int i = 1; i < l.size(); i++) { + g2d.drawLine( + l.get(i - 1).x, + l.get(i - 1).y, + l.get(i).x, + l.get(i).y); + + } + } + g2d.setColor(Color.GREEN); + if (getInformationContent() != null) { + Font f = new Font("Dialog", Font.PLAIN, 10); + Font b = g2d.getFont(); + g2d.setFont(f); + List<String> s = getInformationContent().getHeader(); + for (int i = 0; i < s.size(); i++) { + String string = s.get(i); + g2d.drawString(string, 10, (i + 1) * g2d.getFontMetrics().getHeight()); + + } + InfoItem ii = getInformationContent().getBestMatchingDescriptionForSplash(); + if (ii != null) { + g2d.drawString(ii.toString(), 10, getPluginHeight() - g2d.getFontMetrics().getHeight()); + } + g2d.setFont(b); + } + + if (getState() == State.ERROR) { + if (getLoadingException() != null) { + g2d.setColor(Color.pink); + Font f = new Font("Serif", Font.PLAIN, 10); + Font b = g2d.getFont(); + g2d.setFont(f); + String[] s = JEditorPaneBasedExceptionDialog.getExceptionStackTraceAsStrings(getLoadingException()); + for (int i = 0; i < s.length; i++) { + String string = s[i]; + g2d.drawString(string, 10, getPluginHeight() * 2 / 3 + (i + 1) * g2d.getFontMetrics().getHeight()); + + } + g2d.setFont(b); + } + } + g2d.setColor(Color.BLUE); + + drawTextAroundCenter(g2d, -2, 0, getSplashReason().toString()); + + if (self.getState() == State.LOADING) { + drawTextAroundCenter(g2d, 2, 0, loadingMsg); + } else { + g2d.setColor(Color.red); + drawTextAroundCenter(g2d, 2, 0, "Failed"); + } + + if (getVersion() != null) { + g2d.setColor(Color.CYAN); + g2d.drawString(getVersion(), getPluginWidth() - g2d.getFontMetrics().stringWidth(getVersion()), g2d.getFontMetrics().getHeight()); + } + + + } + + @Override + public void update(Graphics g) { + + // If the buffered image or graphics don't exit, create them +// if (bufferedPanelImage == null || bufferedImageGraphics == null) { +// bufferedPanelImage = createImage(pluginWidth, pluginHeight); +// bufferedImageGraphics = bufferedPanelImage.getGraphics(); +// } +// +// paint(bufferedImageGraphics); +// g.drawImage(bufferedPanelImage, 0, 0, this); + paint(g); + } +} diff -r f058f21b9e99 netx/net/sourceforge/jnlp/splashscreen/impls/SpalshScreenTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/netx/net/sourceforge/jnlp/splashscreen/impls/SpalshScreenTest.java Thu Mar 01 13:31:17 2012 +0100 @@ -0,0 +1,127 @@ +/* SplashScreenTest.java + Copyright (C) 2012 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea 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 2, or (at your option) +any later version. + +IcedTea 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 IcedTea; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package net.sourceforge.jnlp.splashscreen.impls; + +import java.awt.BorderLayout; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import javax.swing.JDialog; + +import net.sourceforge.jnlp.JNLPSplashScreen; +import net.sourceforge.jnlp.splashscreen.SplashPanel; +import net.sourceforge.jnlp.splashscreen.SplashUtils; +import net.sourceforge.jnlp.splashscreen.parts.InfoItem; +import net.sourceforge.jnlp.splashscreen.parts.InformationElement; + +public class SpalshScreenTest extends JDialog { + + static int width = JNLPSplashScreen.DEF_W; + static int height = JNLPSplashScreen.DEF_H; + static SplashPanel panel; + + public SpalshScreenTest() { + + setSize(width - getInsets().left - getInsets().right, height - getInsets().bottom - getInsets().top); +// Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize(); +// int x = (int) ((dimension.getWidth() - getWidth()) / 2); +// int y = (int) ((dimension.getHeight() - getHeight()) / 2); + //setLocation(x, y); + setLocationRelativeTo(null); + this.pack(); + panel = SplashUtils.getSplashScreen(width, height, SplashUtils.SplashReason.JAVAWS); + InformationElement ie = new InformationElement(); + ie.setHomepage("http://someones.org/amazing?page"); + ie.setTitle("Testing information title"); + ie.setvendor("IcedTea-Web team"); + ie.addDescription("Testing null description"); + ie.addDescription("tsting twoline des ...break\ncription of kind short", InfoItem.descriptionKindShort); + //panel.setInformationContent(ie); + //panel.setVersion("1.2-re45fdg"); + setLayout(new BorderLayout()); + getContentPane().add(panel.getPanel(), BorderLayout.CENTER); + + setVisible(true); + + addComponentListener(new ComponentListener() { + + @Override + public void componentShown(ComponentEvent e) { + } + + @Override + public void componentResized(ComponentEvent e) { + //panel.getPanel().setSize(getWidth(), getHeight()); + //panel.adjustForSize(getWidth(), getHeight()); + } + + @Override + public void componentMoved(ComponentEvent e) { + } + + @Override + public void componentHidden(ComponentEvent e) { + } + }); + } + + public static void main(String args[]) { + SpalshScreenTest app = new SpalshScreenTest(); + + app.addWindowListener( + new WindowAdapter() { + + public void windowClosing(WindowEvent e) { + System.exit(0); + } + }); + + panel.spin(); + + try { + Thread.sleep(10000); + } catch (Exception e) { + } + + panel.stopSpinning(); + Exception ex = new Exception("Hi there"); + panel.showError(ex); + + } +}