/*
* @(#)PhotoAlbum.java 1.4 03/05/21
*
* Copyright (c) 2000-2003 Sun Microsystems, Inc. All rights reserved.
* PROPRIETARY/CONFIDENTIAL
* Use is subject to license terms
*/
package example.photoalbum;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import java.util.Vector;
import java.io.IOException;
import java.io.DataInputStream;
import javax.microedition.io.HttpConnection;
import javax.microedition.io.ContentConnection;
import javax.microedition.io.Connector;
import javax.microedition.rms.*;
import example.About;
/**
* The PhotoAlbum MIDlet provides the commands and screens
* that implement a simple photograph and animation album.
* The images and animations to be displayed are configured
* in the descriptor file with attributes.
* <p>
* Options are provided to to vary the speed of display
* and the frame style.
*
*/
public class PhotoAlbum
extends MIDlet
implements CommandListener, ItemStateListener, Runnable
{
/** The Command object for the About command */
private Command aboutCommand;
/** The Command object for the Exit command */
private Command exitCommand;
/** The Command object for the Ok command */
private Command okCommand;
/** The Command object for the Options command */
private Command optionsCommand;
/** The Command object for the Back command */
private Command backCommand;
/** The Command object for the Cancel command */
private Command cancelCommand;
/** The Form object for the Progress form */
private Form progressForm;
/** The Gauge object for the Progress gauge */
private Gauge progressGauge;
/** The Form object for the Options command */
private Form optionsForm;
/** Set of choices for the border styles */
private ChoiceGroup borderChoice;
/** Set of choices for the speeds */
private ChoiceGroup speedChoice;
/** The current display for this MIDlet */
private Display display;
/** The PhotoFrame that displays images */
private PhotoFrame frame;
/** The Alert for messages */
private Alert alert;
/** Contains Strings with the image names */
private Vector imageNames;
/** List of Image titles for user to select */
private List imageList;
/** Name of current image, may be null */
private String imageName;
/** Current thread loading images, may be null */
private Thread thread;
/** Name of persistent storage */
private final String optionsName = "PhotoAlbum";
/** Persistent storage for options */
private RecordStore optionsStore;
private boolean firstTime = true;
/**
* Construct a new PhotoAlbum MIDlet and initialize the base options
* and main PhotoFrame to be used when the MIDlet is started.
*/
public PhotoAlbum() {
display = Display.getDisplay(this);
exitCommand = new Command("Exit", Command.EXIT, 1);
optionsCommand = new Command("Options", Command.SCREEN, 1);
okCommand = new Command("Ok", Command.OK, 3);
backCommand = new Command("Back", Command.BACK, 3);
cancelCommand = new Command("Cancel", Command.CANCEL, 1);
aboutCommand = new Command("About", Command.HELP, 30);
frame = new PhotoFrame();
frame.setStyle(2);
frame.setSpeed(2);
frame.addCommand(optionsCommand);
frame.addCommand(backCommand);
frame.setCommandListener(this);
alert = new Alert("Warning");
setupImageList();
firstTime = true;
}
/**
* Start up the Hello MIDlet by setting the PhotoFrame
* and loading the initial images.
*/
protected void startApp() {
if(firstTime) {
if (imageList.size() > 0) {
display.setCurrent(imageList);
openOptions();
restoreOptions();
} else {
alert.setString("No images configured.");
display.setCurrent(alert, imageList);
}
firstTime = false;
}
openOptions();
restoreOptions();
}
/**
* Pause is used to release the memory used by Image.
* When restarted the images will be re-created.
* Save the options for the next restart.
*/
protected void pauseApp() {
saveOptions();
}
/**
* Destroy must cleanup everything not handled by the garbage collector.
* In this case there is nothing to cleanup.
* Save the options for the next restart.
* @param unconditional true if this MIDlet should always cleanup
*/
protected void destroyApp(boolean unconditional) {
saveOptions();
frame.reset(); // Discard images cached in the frame.
saveOptions();
closeOptions();
}
/**
* Respond to commands. Commands are added to each screen as
* they are created. Each screen uses the PhotoAlbum MIDlet as the
* CommandListener. All commands are handled here:
* <UL>
* <LI>Select on Image List - display the progress form and start the thread
* to read in the images.
* <LI>Options - display the options form.
* <LI>Ok on the Options form - returns to the PhotoFrame.
* <LI>Back - display the Image List, deactivating the PhotoFrame.
* <LI>Cancel - display the image List and stop the thread loading images.
* <LI>Exit - images are released and notification is given that the MIDlet
* has exited.
* </UL>
* @param c the command that triggered this callback
* @param s the screen that contained the command
*/
public void commandAction(Command c, Displayable s) {
if (c == exitCommand) {
// Cleanup and notify that the MIDlet has exited
destroyApp(false);
notifyDestroyed();
} else if (c == optionsCommand) {
// Display the options form
display.setCurrent(genOptions());
} else if (c == okCommand && s == optionsForm) {
// Return to the PhotoFrame, the option values have already
// been saved by the item state listener
display.setCurrent(frame);
} else if (c == List.SELECT_COMMAND) {
// Display the progress screen and
// start the thread to read the images
int i = imageList.getSelectedIndex();
imageName = (String)imageNames.elementAt(i);
display.setCurrent(genProgress(imageList.getString(i)));
thread = new Thread(this);
thread.start();
} else if (c == backCommand) {
// Display the list of images.
display.setCurrent(imageList);
} else if (c == cancelCommand) {
// Signal thread to stop and put an alert.
thread = null;
alert.setString("Loading images cancelled.");
display.setCurrent(alert, imageList);
} else if (c == aboutCommand) {
About.showAbout(display);
}
}
/**
* Listener for changes to options.
* The new values are set in the PhotoFrame.
* @param item - the item whose value has changed.
*/
public void itemStateChanged(Item item) {
if (item == borderChoice) {
frame.setStyle(borderChoice.getSelectedIndex());
} else if (item == speedChoice) {
frame.setSpeed(speedChoice.getSelectedIndex());
}
}
/**
* Generate the options form with speed and style choices.
* Speed choices are stop, slow, medium, and fast.
* Style choices for borders are none, plain, fancy.
* @return the generated options Screen
*/
private Screen genOptions() {
if (optionsForm == null) {
optionsForm = new Form("Options");
optionsForm.addCommand(okCommand);
optionsForm.setCommandListener(this);
optionsForm.setItemStateListener(this);
speedChoice = new ChoiceGroup("Speed", Choice.EXCLUSIVE);
speedChoice.append("Stop", null);
speedChoice.append("Slow", null);
speedCh