//$Header: /cvsroot-fuse/mec-as2/39/mendelson/util/Splash.java,v 1.1 2012/04/18 14:10:41 heller Exp $ package de.mendelson.util; import javax.swing.*; import java.awt.*; import java.awt.image.*; import java.awt.geom.*; import java.awt.font.*; import java.util.*; import java.io.*; import java.text.*; import java.util.List; import javax.imageio.ImageIO; /* * Copyright (C) mendelson-e-commerce GmbH Berlin Germany * * This software is subject to the license agreement set forth in the license. * Please read and agree to all terms before using this software. * Other product and brand names are trademarks of their respective owners. */ /** * Splash window to been shown while one of the mendelson products load * @author S.Heller * @version $Revision: 1.1 $ */ public class Splash extends JWindow implements SwingConstants { /**Image to display*/ private BufferedImage image = null; /**PrintStream to pass to out components to let them write stuff into*/ private SplashPrintStream out = null; /**Indicates if this splash should have a progress bar, this is done *if this is != null */ private Progress progress = null; /**List of display string to display static in the Splash*/ private List<DisplayString> displayStringList = new ArrayList<DisplayString>(); /**Indicates if textual output should be antialiased in the splash*/ private boolean textAntialiasing = true; /**Creates a new splash with the given width and length * @param imageResource ResourcePath to the image */ public Splash(String imageResource) { this.image = this.loadImage(imageResource); this.getContentPane().setLayout(new BorderLayout()); int width = this.image.getWidth(this); int height = this.image.getHeight(this); Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); this.setBounds((screenSize.width - width) / 2, (screenSize.height - height) / 2, width, height); } /**Adds a static display string to the splash, this is always painted *using the passed parameters *@param font Font to use to display the text in the splash *@param x X position of the output *@param y y position of the output *@param text Text to display *@param color Color to use for the text display *@param transform Allows to transform the font in any kind. Please *remember that there is always a translation on the font, depending *on the position! This parameter may be null. */ public void addDisplayString(Font font, int x, int y, String text, Color color, AffineTransform transform) { DisplayString displayString = new DisplayString(font, x, y, text, color, transform); this.displayStringList.add(displayString); } /**Defines where to write the output to, with which properties *@param font Font to use *@param x X Position of the output *@param y Y Position of the output *@param fontColor Font color to use */ public PrintStream createPrintStream(Font font, int x, int y, Color fontColor) { StringBuffer buffer = new StringBuffer(); StringBufferOutputStream outStream = new StringBufferOutputStream(this, buffer); this.out = new SplashPrintStream(outStream, buffer, font, x, y, fontColor); return (this.out); } /**Passes a progress container to this splash. By passing a progress this is *shown! *@param x XPos of the bar *@param y yPos of the bar *@param height Bars height *@param width Bars width *@param border set this to null to not draw a border *@param foreground foreground color of the bar *@param background set this to null to have a transparent background *@param showPercent indicates to show the progress in procent */ public Splash.Progress createProgress( int x, int y, int height, int width, Color foreground, Color background, Color border, boolean showPercent) { this.progress = new Progress(x, y, height, width, foreground, background, border, showPercent); return (this.progress); } /**Enables or disables the antialiasing of text output on the Splash*/ public void setTextAntiAliasing(boolean textAntialiasing) { this.textAntialiasing = textAntialiasing; } /**Draw/update this component*/ public void paint(Graphics g) { if (this.image == null) { return; } //draw into the memory image off-screen BufferedImage memoryImage = new BufferedImage( this.image.getWidth(this), this.image.getHeight(this), BufferedImage.TYPE_INT_ARGB); Graphics2D imageGraphics = (Graphics2D) memoryImage.getGraphics(); imageGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); imageGraphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); if (this.textAntialiasing) { imageGraphics.setRenderingHint( RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); } else { imageGraphics.setRenderingHint( RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); //copy the image into memory, off-screen } imageGraphics.drawImage(this.image, 0, 0, this); FontRenderContext renderContext = imageGraphics.getFontRenderContext(); //display static strings in Splash for (int i = 0; i < this.displayStringList.size(); i++) { DisplayString displayString = (DisplayString) this.displayStringList.get(i); TextLayout layout = new TextLayout(displayString.getText(), displayString.getFont(), renderContext); AffineTransform transformPosition = new AffineTransform(); transformPosition.setToTranslation( displayString.getX(), displayString.getY()); //only concat a transform if the display string has one if (displayString.getTransform() != null) { transformPosition.concatenate(displayString.getTransform()); } Shape shape = layout.getOutline(transformPosition); imageGraphics.setColor(displayString.getColor()); imageGraphics.fill(shape); } //draw printstream output if (this.out != null) { imageGraphics.setFont(this.out.getFont()); imageGraphics.setColor(this.out.getFontColor()); imageGraphics.drawString(this.out.getText(), this.out.getX(), this.out.getY()); } //draw progress bar if (this.progress != null) { if (this.progress.getBorder() != null) { imageGraphics.setColor(this.progress.getBorder()); imageGraphics.drawRect(this.progress.getX() - 1, this.progress.getY() - 1, this.progress.getWidth() + 1, this.progress.getHeight() + 1); } if (this.progress.getBackground() != null) { if (this.progress.getUseGradientPaint()) { //draw background of the progress bar with 3d effects GradientPaint paint = new GradientPaint( this.progress.getX(), this.progress.getY() - this.progress.getHeight(), this.progress.getBackground().darker(), this.progress.getX(), this.progress.getY() + this.progress.getHeight() / 2, this.progress.getBackground()); imageGraphics.setPaint(paint); } else { imageGraphics.setPaint(progress.getBackground()); } imageGraphics.fillRect(this.progress.getX(), this.progress.getY(), this.progress.getWidth(), this.progress.getHeight() / 2); if (this.progress.getUseGradientPaint()) { //draw background of the progress bar with 3d effects GradientPaint paint = new GradientPaint( this.progress.getX(), this.progress.getY() + this.progress.getHeight() / 2, this.progress.getBackground(), this.progress.getX(), this.progress.getY() + 2 * this.progress.getHeight(), this.progress.getBackground().brighter()); imageGraphics.setPaint(paint); } else { imageGraphics.setPaint(progress.getBackground()); } imageGraphics.fillRect(this.progress.getX(), this.progress.getY() + this.progress.getHeight() / 2, this.progress.getWidth(), this.progress.getHeight() / 2); } if (this.progress.getUseGradientPaint()) { //draw bar itself, with 3D effect GradientPaint paint = new GradientPaint( this.progress.getX(), this.progress.getY(), this.progress.getForeground(), this.progress.getX(), this.progress.getY() + this.progress.getHeight(), Color.white); imageGraphics.setPaint(paint); } else { imageGraphics.setPaint(progress.getForeground()); } imageGraphics.fillRect(this.progress.getX(), this.progress.getY(), this.progress.getProgress(), this.progress.getHeight() / 2); if (this.progress.getUseGradientPaint()) { //draw bar itself, with 3D effect GradientPaint paint = new GradientPaint( this.progress.getX(), this.progress.getY(), Color.white, this.progress.getX(), this.progress.getY() + this.progress.getHeight(), this.progress.getForeground()); imageGraphics.setPaint(paint); } else { imageGraphics.setPaint(progress.getForeground()); } imageGraphics.fillRect(this.progress.getX(), this.progress.getY() + this.progress.getHeight() / 2, this.progress.getProgress(), this.progress.getHeight() / 2); if (this.progress.showPercent()) { TextLayout layout = new TextLayout(this.progress.getPercent(), new Font("Dialog", Font.PLAIN, (int) (this.progress.getHeight() / 2)), renderContext); AffineTransform transformPosition = new AffineTransform(); transformPosition.setToTranslation( this.progress.getX() + this.progress.getWidth() / 2, (int) (this.progress.getY() + this.progress.getHeight() - this.progress.getHeight() * 0.25)); Shape shape = layout.getOutline(transformPosition); imageGraphics.setColor(progress.getForeground()); imageGraphics.fill(shape); imageGraphics.clip(new Rectangle(this.progress.getX(), this.progress.getY(), this.progress.getProgress(), this.progress.getHeight())); imageGraphics.setColor(progress.getBackground()); imageGraphics.fill(shape); } } //bring the image to the screen g.setPaintMode(); g.drawImage(memoryImage, 0, 0, memoryImage.getWidth(this), memoryImage.getHeight(this), this); } /**Loads the image and tracks it * @param resource image resource to load the image */ private BufferedImage loadImage(String resource) { BufferedImage bufferedImage = null; try { //get an input stream from the resource InputStream inStream = Splash.class.getResourceAsStream(resource); bufferedImage = ImageIO.read(inStream); inStream.close(); } catch (Exception e) { System.err.println("Fatal: Unable to load splash image resource " + resource + "."); System.exit(-1); } return (bufferedImage); } @Override public void setVisible(boolean flag) { super.setVisible(flag); if (flag) { this.toFront(); } } /**removes the splash window */ public void destroy() { this.setVisible(false); } /**PrintStream that will stores also information about position of the output *and refreshed the passed component whenever a \n occurs */ public static class SplashPrintStream extends PrintStream { /**Font to use for the text printstream output in splash*/ private Font font = new Font("Dialog", Font.PLAIN, 10); /**Font color to use in splash*/ private Color fontColor = Color.black; /**Position to use to write output to*/ private int outputX = 0; private int outputY = 0; private StringBuffer buffer = new StringBuffer(); /** *@param @param outStream stream to write entries to a string buffer *@param font Font to use *@param x X Position of the output *@param y Y Position of the output *@param fontColor Font color to use */ public SplashPrintStream(StringBufferOutputStream outStream, StringBuffer buffer, Font font, int x, int y, Color fontColor) { super(outStream); this.buffer = buffer; this.font = font; this.outputX = x; this.outputY = y; this.fontColor = fontColor; } public Font getFont() { return (this.font); } public int getX() { return (this.outputX); } public int getY() { return (this.outputY); } public Color getFontColor() { return (this.fontColor); } public String getText() { return (this.buffer.toString()); } } /**Output Stream that writes it output to a stringbuffer, the buffer is only *refreshed if a \n occurs **/ public static class StringBufferOutputStream extends OutputStream { private StringBuffer buffer = null; private Component component = null; /**TempBuffer is necessary because an update of the component could be *forced outside this class, the LAST valid value is always in the passed *buffer pointer. Whenever a \n accurs, the pass buffer will get a *valid value and store it until the next \n appears */ private StringBuffer tempBuffer = new StringBuffer(); /**@param component Component to update on an end of a line *@param buffer Buffer to write output to */ public StringBufferOutputStream(Component component, StringBuffer buffer) { this.buffer = buffer; this.component = component; } public void write(int i) throws IOException { char addChar = this.int2char(i); if (addChar == '\n') { this.buffer.delete(0, this.buffer.length()); this.buffer.append(tempBuffer.toString()); if (this.component.getGraphics() != null) { this.component.update(this.component.getGraphics()); } tempBuffer.delete(0, this.buffer.length()); } else { this.tempBuffer.append(addChar); } } /**Map bytes to characters, bytes are always signed in java!*/ private final char int2char(int i) { return (char) ((i < 0) ? i + 0x100 : i); } } /**Class that stores progress information*/ public class Progress { /**Position and size of the progress bar*/ private int x = 0; private int y = 0; private int height = 0; private int width = 0; /**Progress bar border*/ private Color background = Color.white; /**Progress bar color itself*/ private Color foreground = Color.blue; /**Border color for the progress bar*/ private Color border = Color.darkGray; /**Progress state*/ private int maxProgress = 0; private int actualProgress = 0; private boolean showPercent = false; /**Format to format the percent output*/ private DecimalFormat format = new DecimalFormat("0.0"); /**Indicates if the bar should be rendered with a 3D effect*/ private boolean useGradientPaint = true; /**Initialize the progress bar *@param x XPos of the bar *@param y yPos of the bar *@param height Bars height *@param width Bars width *@param background color, set this to null to have a transparent background *@param foreground bar color *@param border progress bar border color set this to null to not have a border *@param showPercent indicates to show the progress in procent */ public Progress(int x, int y, int height, int width, Color foreground, Color background, Color border, boolean showPercent) { this.x = x; this.y = y; this.height = height; this.width = width; this.foreground = foreground; this.background = background; this.border = border; this.showPercent = showPercent; } /**Number of steps untill 100%*/ public void setMax(int max) { this.maxProgress = max; } public int getX() { return (this.x); } public int getY() { return (this.y); } public int getWidth() { return (this.width); } public int getHeight() { return (this.height); } /**indicates if the progress bar should be painted using a 3D effect*/ public void setUseGradientPaint(boolean useGradientPaint) { this.useGradientPaint = useGradientPaint; } /**indicates if the progress bar should be painted using a 3D effect*/ public boolean getUseGradientPaint() { return (this.useGradientPaint); } /**Increates the progress */ public void inc() { this.actualProgress++; //force a graphic refresh update(getGraphics()); } /**gets the progress in pixel, depends on the width! */ public int getProgress() { return ((int) (((float) this.width / (float) maxProgress) * (float) this.actualProgress)); } /**Background color*/ public Color getBackground() { return (this.background); } /**Foreground color*/ public Color getForeground() { return (this.foreground); } /**Border color*/ public Color getBorder() { return (this.border); } public boolean showPercent() { return (this.showPercent); } /**Returns the percent string to show*/ public String getPercent() { return (format.format(this.getPercentValue()) + '%'); } /**Returns the computed progress percent*/ public float getPercentValue() { float percent = 0.0f; if (this.maxProgress > 0) { percent = (float) this.actualProgress * 100f / (float) this.maxProgress; } return (percent); } } /**Class that stores output strings to display in the splash screen. This *text will appear on each update of the component! */ public static class DisplayString { /**Font to use for the output*/ private Font font = null; /**Position where to output the string*/ private int x = 0; private int y = 0; private String text = null; private Color color = null; private AffineTransform transform = null; /**@param font Font to use to display the text in the splash *@param x X position of the output *@param y y position of the output *@param text Text to display *@param color Color to use for the text display *@param transform Allows to transform the font in any kind. Please *remember that there is always a translation on the font, depending *on the position! This parameter may be null. */ public DisplayString(Font font, int x, int y, String text, Color color, AffineTransform transform) { this.font = font; this.x = x; this.y = y; this.text = text; this.color = color; this.transform = transform; } public int getX() { return (this.x); } public int getY() { return (this.y); } public Font getFont() { return (this.font); } public String getText() { return (this.text); } public Color getColor() { return (this.color); } public AffineTransform getTransform() { return (this.transform); } } }