/*
GeoGebra - Dynamic Mathematics for Everyone
http://www.geogebra.org
This file is part of GeoGebra.
This program 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.
*/
package org.geogebra.desktop;
/*
* Copyright (c) 1999-2003 Werner Randelshofer
* Staldenmattweg 2, Immensee, CH-6405, Switzerland
* All rights reserved.
*
* This material is provided "as is", with absolutely no warranty expressed
* or implied. Any use is at your own risk.
*
* Permission to use or copy this software is hereby granted without fee,
* provided this copyright notice is retained on all copies.
*/
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Window;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
/**
* Splash Window to show an image during startup of an application.
* <p>
*
* Usage:
*
* <pre>
* // open the splash window
* Frame splashOwner = SplashWindow.splash(anImage);
*
* // start the application
* // ...
*
* // dispose the splash window by disposing the frame that owns the window.
* splashOwner.dispose();
* </pre>
*
* <p>
* To use the splash window as an about dialog write this:
*
* <pre>
* new SplashWindow(this,
* getToolkit()
* .createImage(getClass().getResource(GeoGebra.SPLASH_STRING)))
* .show();
* </pre>
*
* The splash window disposes itself when the user clicks on it.
*
* @author Werner Randelshofer, Staldenmattweg 2, Immensee, CH-6405,
* Switzerland.
* @version 1.3 2003-06-01 Revised.
*/
public class SplashWindow extends Window {
/**
*
*/
private static final long serialVersionUID = 1L;
private Image splashImage;
/**
* This attribute indicates whether the method paint(Graphics) has been
* called at least once since the construction of this window.<br>
* This attribute is used to notify method splash(Image) that the window has
* been drawn at least once by the AWT event dispatcher thread.<br>
* This attribute acts like a latch. Once set to true, it will never be
* changed back to false again.
*
* @see #paint
* @see #splash
*/
private boolean paintCalled = false;
/**
* Constructs a splash window and centers it on the screen. The user can
* click on the window to dispose it.
*
* @param owner
* The frame owning the splash window.
* @param splashImage
* The splashImage to be displayed.
* @param canDispose
* If a mouse click should dispose the window
*/
public SplashWindow(Frame owner, Image splashImage, boolean canDispose) {
super(owner);
this.splashImage = splashImage;
// Load the image
MediaTracker mt = new MediaTracker(this);
mt.addImage(splashImage, 0);
try {
mt.waitForID(0);
} catch (InterruptedException ie) {
}
// Center the window on the screen.
int imgWidth = splashImage.getWidth(this);
int imgHeight = splashImage.getHeight(this);
setSize(imgWidth, imgHeight);
setLocationRelativeTo(null);
if (canDispose) {
// Users shall be able to close the splash window by
// clicking on its display area. This mouse listener
// listens for mouse clicks and disposes the splash window.
MouseAdapter disposeOnClick = new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent evt) {
// Note: To avoid that method splash hangs, we
// must set paintCalled to true and call notifyAll.
// This is necessary because the mouse click may
// occur before the contents of the window
// has been painted.
synchronized (SplashWindow.this) {
paintCalled = true;
notifyAll();
}
setVisible(false);
}
};
addMouseListener(disposeOnClick);
}
}
/**
* Updates the display area of the window.
*/
@Override
public void update(Graphics g) {
// Note: Since the paint method is going to draw an
// image that covers the complete area of the component we
// do not fill the component with its background color
// here. This avoids flickering.
g.setColor(getForeground());
paint(g);
}
/**
* Paints the image on the window.
*/
@Override
public void paint(Graphics g) {
g.drawImage(splashImage, 0, 0, this);
// Markus Hohenwarter (14. 4. 2006): add border to splashImage
g.setColor(Color.darkGray);
g.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
// Notify method splash that the window
// has been painted.
// Note: To improve performance we do not enter
// the synchronized block unless we have to.
if (!paintCalled) {
paintCalled = true;
synchronized (this) {
notifyAll();
}
}
}
/**
* Constructs and displays a SplashWindow.
* <p>
* This method is useful for startup splashs. Dispose the return frame to
* get rid of the splash window.
* <p>
*
* @param splashImage
* The image to be displayed.
* @return Returns the frame that owns the SplashWindow.
*/
public static Frame splash(Image splashImage) {
Frame f = new Frame();
SplashWindow w = new SplashWindow(f, splashImage, false);
// Show the window.
w.toFront();
w.setVisible(true);
// Note: To make sure the user gets a chance to see the
// splash window we wait until its paint method has been
// called at least by the AWT event dispatcher thread.
if (!EventQueue.isDispatchThread()) {
synchronized (w) {
while (!w.paintCalled) {
try {
w.wait();
} catch (InterruptedException e) {
}
}
}
}
return f;
}
}