/* From http://java.sun.com/docs/books/tutorial/index.html */
/*
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* -Redistribution of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* -Redistribution in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
* ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
* OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
* AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
* AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
* DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
* REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
* INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
* OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed, licensed or intended
* for use in the design, construction, operation or maintenance of any
* nuclear facility.
*/
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.net.URL;
import java.util.Vector;
import javax.swing.AbstractButton;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
public class IconDemoApplet extends JApplet implements ActionListener {
Vector pictures;
JButton previousButton;
JButton nextButton;
JLabel photographLabel;
JLabel captionLabel;
JLabel numberLabel;
int current = 0;
int widthOfWidest = 0;
int heightOfTallest = 0;
String imagedir = null;
public void init() {
//Parse the applet parameters
pictures = parseParameters();
//If the applet tag doesn't provide an "IMAGE0" parameter,
//display an error message.
if (pictures.size() == 0) {
captionLabel = new JLabel("No images listed in applet tag.");
captionLabel.setHorizontalAlignment(JLabel.CENTER);
getContentPane().add(captionLabel);
return;
}
//NOW CREATE THE GUI COMPONENTS
//A label to identify XX of XX.
numberLabel = new JLabel("Picture " + (current + 1) + " of "
+ pictures.size());
numberLabel.setHorizontalAlignment(JLabel.LEFT);
numberLabel.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 5));
//A label for the caption.
final Photo first = (Photo) pictures.firstElement();
captionLabel = new JLabel(first.caption);
captionLabel.setHorizontalAlignment(JLabel.CENTER);
captionLabel.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0));
//A label for displaying the photographs.
photographLabel = new JLabel("Loading first image...");
photographLabel.setHorizontalAlignment(JLabel.CENTER);
photographLabel.setVerticalAlignment(JLabel.CENTER);
photographLabel.setVerticalTextPosition(JLabel.CENTER);
photographLabel.setHorizontalTextPosition(JLabel.CENTER);
photographLabel.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createLoweredBevelBorder(), BorderFactory
.createEmptyBorder(5, 5, 5, 5)));
photographLabel.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createEmptyBorder(0, 0, 10, 0), photographLabel
.getBorder()));
//Set the preferred size for the picture,
//with room for the borders.
Insets i = photographLabel.getInsets();
photographLabel.setPreferredSize(new Dimension(widthOfWidest + i.left
+ i.right, heightOfTallest + i.bottom + i.top));
//Create the next and previous buttons.
ImageIcon nextIcon = new ImageIcon(getURL(imagedir + "right.gif"));
ImageIcon dimmedNextIcon = new ImageIcon(getURL(imagedir
+ "dimmedRight.gif"));
ImageIcon previousIcon = new ImageIcon(getURL(imagedir + "left.gif"));
ImageIcon dimmedPreviousIcon = new ImageIcon(getURL(imagedir
+ "dimmedLeft.gif"));
previousButton = new JButton("Previous Picture", previousIcon);
previousButton.setDisabledIcon(dimmedPreviousIcon);
previousButton.setVerticalTextPosition(AbstractButton.CENTER);
previousButton.setHorizontalTextPosition(AbstractButton.RIGHT);
previousButton.setMnemonic(KeyEvent.VK_P);
previousButton.setActionCommand("previous");
previousButton.addActionListener(this);
previousButton.setEnabled(false);
nextButton = new JButton("Next Picture", nextIcon);
nextButton.setDisabledIcon(dimmedNextIcon);
nextButton.setVerticalTextPosition(AbstractButton.CENTER);
nextButton.setHorizontalTextPosition(AbstractButton.LEFT);
nextButton.setMnemonic(KeyEvent.VK_N);
nextButton.setActionCommand("next");
nextButton.addActionListener(this);
//Lay out the GUI.
GridBagLayout layout = new GridBagLayout();
GridBagConstraints c = new GridBagConstraints();
Container contentPane = getContentPane();
contentPane.setLayout(layout);
c.gridwidth = GridBagConstraints.REMAINDER;
c.fill = GridBagConstraints.HORIZONTAL;
layout.setConstraints(numberLabel, c);
contentPane.add(numberLabel);
layout.setConstraints(captionLabel, c);
contentPane.add(captionLabel);
c.gridwidth = GridBagConstraints.REMAINDER;
c.fill = GridBagConstraints.BOTH;
layout.setConstraints(photographLabel, c);
contentPane.add(photographLabel);
c.gridwidth = GridBagConstraints.RELATIVE;
c.fill = GridBagConstraints.HORIZONTAL;
layout.setConstraints(previousButton, c);
contentPane.add(previousButton);
c.gridwidth = GridBagConstraints.REMAINDER;
layout.setConstraints(nextButton, c);
contentPane.add(nextButton);
//Start loading the image for the first photograph now.
//The loadImage method uses a SwingWorker
//to load the image in a separate thread.
loadImage(imagedir + first.filename, current);
}
//User clicked either the next or the previous button.
public void actionPerformed(ActionEvent e) {
//Show loading message.
photographLabel.setIcon(null);
photographLabel.setText("Loading image...");
//Compute index of photograph to view.
if (e.getActionCommand().equals("next")) {
current += 1;
if (!previousButton.isEnabled())
previousButton.setEnabled(true);
if (current == pictures.size() - 1)
nextButton.setEnabled(false);
} else {
current -= 1;
if (!nextButton.isEnabled())
nextButton.setEnabled(true);
if (current == 0)
previousButton.setEnabled(false);
}
//Get the photo object.
Photo pic = (Photo) pictures.elementAt(current);
//Update the caption and number labels.
captionLabel.setText(pic.caption);
numberLabel.setText("Picture " + (current + 1) + " of "
+ pictures.size());
//Update the photograph.
ImageIcon icon = pic.getIcon();
if (icon == null) { //haven't viewed this photo before
loadImage(imagedir + pic.filename, current);
} else {
updatePhotograph(current, pic);
}
}
//Must be invoked from the event-dispatching thread.
private void updatePhotograph(int index, Photo pic) {
ImageIcon icon = pic.getIcon();
photographLabel.setToolTipText(pic.filename + ": "
+ icon.getIconWidth() + " X " + icon.getIconHeight());
photographLabel.setIcon(icon);
photographLabel.setText("");
}
//Load an image in a separate thread.
private void loadImage(final String imagePath, final int index) {
final SwingWorker worker = new SwingWorker() {
ImageIcon icon = null;
public Object construct() {
icon = new ImageIcon(getURL(imagePath));
return icon; //return value not used by this program
}
//Runs on the event-dispatching thread.
public void finished() {
Photo pic = (Photo) pictures.elementAt(index);
pic.setIcon(icon);
if (index == current)
updatePhotograph(index, pic);
}
};
worker.start();
}
protected URL getURL(String filename) {
URL codeBase = this.getCodeBase();
URL url = null;
try {
url = new URL(codeBase, filename);
} catch (java.net.MalformedURLException e) {
System.out.println("Couldn't create image: "
+ "badly specified URL");
return null;
}
return url;
}
protected Vector parseParameters() {
Vector pix = new Vector(10); //start with 10, grows if necessary
int i = 0; //parameters index must start at 0
String paramName = "IMAGE" + i;
String paramValue;
while ((paramValue = getParameter(paramName)) != null) {
Photo pic = new Photo(paramValue, getCaption(i), getWidth(i),
getHeight(i));
pix.addElement(pic);
i++;
paramName = "IMAGE" + i;
}
//Get the name of the directory that contains the image files.
imagedir = getParameter("IMAGEDIR");
if (imagedir != null)
imagedir = imagedir + "/";
return pix;
}
protected String getCaption(int i) {
return getParameter("CAPTION" + i);
}
protected int getWidth(int i) {
int width = 0;
String widthString = getParameter("WIDTH" + i);
if (widthString != null) {
try {
width = Integer.parseInt(widthString);
} catch (NumberFormatException e) {
width = 0;
}
} else {
width = 0;
}
if (width > widthOfWidest)
widthOfWidest = width;
return width;
}
protected int getHeight(int i) {
int height = 0;
String heightString = getParameter("HEIGHT" + i);
if (heightString != null) {
try {
height = Integer.parseInt(heightString);
} catch (NumberFormatException e) {
height = 0;
}
} else {
height = 0;
}
if (height > heightOfTallest)
heightOfTallest = height;
return height;
}
public String[][] getParameterInfo() {
String[][] info = {
{ "IMAGEDIR", "string", "directory containing image files" },
{ "IMAGEN", "string", "filename" },
{ "CAPTIONN", "string", "caption" },
{ "WIDTHN", "integer", "width of image" },
{ "HEIGHTN", "integer", "height of image" }, };
return info;
}
}
class Photo {
public String filename;
public String caption;
public int width;
public int height;
public ImageIcon icon;
public Photo(String filename, String caption, int w, int h) {
this.filename = filename;
if (caption == null)
this.caption = filename;
else
this.caption = caption;
width = w;
height = h;
icon = null;
}
public void setIcon(ImageIcon i) {
icon = i;
}
public ImageIcon getIcon() {
return icon;
}
}
/**
* This is the 3rd version of SwingWorker (also known as SwingWorker 3), an
* abstract class that you subclass to perform GUI-related work in a dedicated
* thread. For instructions on and examples of using this class, see:
*
* http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html
*
* Note that the API changed slightly in the 3rd version: You must now invoke
* start() on the SwingWorker after creating it.
*/
abstract class SwingWorker {
private Object value; // see getValue(), setValue()
/**
* Class to maintain reference to current worker thread under separate
* synchronization control.
*/
private static class ThreadVar {
private Thread thread;
ThreadVar(Thread t) {
thread = t;
}
synchronized Thread get() {
return thread;
}
synchronized void clear() {
thread = null;
}
}
private ThreadVar threadVar;
/**
* Get the value produced by the worker thread, or null if it hasn't been
* constructed yet.
*/
protected synchronized Object getValue() {
return value;
}
/**
* Set the value produced by worker thread
*/
private synchronized void setValue(Object x) {
value = x;
}
/**
* Compute the value to be returned by the <code>get</code> method.
*/
public abstract Object construct();
/**
* Called on the event dispatching thread (not on the worker thread) after
* the <code>construct</code> method has returned.
*/
public void finished() {
}
/**
* A new method that interrupts the worker thread. Call this method to force
* the worker to stop what it's doing.
*/
public void interrupt() {
Thread t = threadVar.get();
if (t != null) {
t.interrupt();
}
threadVar.clear();
}
/**
* Return the value created by the <code>construct</code> method. Returns
* null if either the constructing thread or the current thread was
* interrupted before a value was produced.
*
* @return the value created by the <code>construct</code> method
*/
public Object get() {
while (true) {
Thread t = threadVar.get();
if (t == null) {
return getValue();
}
try {
t.join();
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // propagate
return null;
}
}
}
/**
* Start a thread that will call the <code>construct</code> method and
* then exit.
*/
public SwingWorker() {
final Runnable doFinished = new Runnable() {
public void run() {
finished();
}
};
Runnable doConstruct = new Runnable() {
public void run() {
try {
setValue(construct());
} finally {
threadVar.clear();
}
SwingUtilities.invokeLater(doFinished);
}
};
Thread t = new Thread(doConstruct);
threadVar = new ThreadVar(t);
}
/**
* Start the worker thread.
*/
public void start() {
Thread t = threadVar.get();
if (t != null) {
t.start();
}
}
}
|