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);
+
+    }
+}