Mega Code Archive

 
Categories / Java / J2ME
 

Animated Timer

/*--------------------------------------------------  * AnimatedTimer - Main midlet.  * Shows canvas with an animated timer. Includes  * configuration options to start/stop the timer  * and to adjust the sleep interval of the thread  *  * Example from the book:     Core J2ME Technology  * Copyright John W. Muchow   http://www.CoreJ2ME.com  * You may use/modify for any non-commercial purpose   *-------------------------------------------------*/ import java.util.Stack; import javax.microedition.lcdui.Alert; import javax.microedition.lcdui.Canvas; import javax.microedition.lcdui.Command; import javax.microedition.lcdui.CommandListener; import javax.microedition.lcdui.Display; import javax.microedition.lcdui.Displayable; import javax.microedition.lcdui.Form; import javax.microedition.lcdui.Gauge; import javax.microedition.lcdui.Graphics; import javax.microedition.lcdui.Image; import javax.microedition.lcdui.List; import javax.microedition.midlet.MIDlet; public class AnimatedTimer extends MIDlet {   private Display display; // The display   protected TimerCanvas cvTimer; // Canvas to display timer   protected OptionsList lsOptions; // List to change timer options   protected SleepForm fmSleep; // Form with gauge to set timer sleep   protected DisplayManager displayMgr; // Class to help manage screens   public AnimatedTimer() {     display = Display.getDisplay(this);     cvTimer = new TimerCanvas(this);     lsOptions = new OptionsList("Timer options", List.IMPLICIT, this);     fmSleep = new SleepForm("Adjust sleep", this);     // Create a display manager object     displayMgr = new DisplayManager(display, cvTimer);   }   protected void startApp() {     // Start with the canvas     display.setCurrent(cvTimer);   }   protected void pauseApp() {   }   protected void destroyApp(boolean unconditional) {   }   public void exitMIDlet() {     destroyApp(true);     notifyDestroyed();   } } /*--------------------------------------------------  * Use a stack to push and pop displayable objects  *  * public void pushDisplayable(Displayable)  * public void popDisplayable()  * public void home()    *  * Example from the book:     Core J2ME Technology  * Copyright John W. Muchow   http://www.CoreJ2ME.com  * You may use/modify for any non-commercial purpose   *-------------------------------------------------*/ class DisplayManager extends Stack {   private Display display; // Reference to Display object   private Displayable mainDisplayable; // Main displayable for MIDlet   private Alert alStackError; // Alert for error conditions   /*--------------------------------------------------    * Display manager constructor    *-------------------------------------------------*/   public DisplayManager(Display display, Displayable mainDisplayable) {     // Only one display object per midlet, this is it     this.display = display;     this.mainDisplayable = mainDisplayable;     // Create an alert displayed when an error occurs     alStackError = new Alert("Displayable Stack Error");     alStackError.setTimeout(Alert.FOREVER); // Modal   }   /*--------------------------------------------------    * Push the current displayable onto stack and set    * the passed in displayable as active    *-------------------------------------------------*/   public void pushDisplayable(Displayable newDisplayable) {     push(display.getCurrent());     display.setCurrent(newDisplayable);   }   /*--------------------------------------------------    * Return to the main displayable object of MIDlet    *-------------------------------------------------*/   public void home() {     while (elementCount > 1)       pop();     display.setCurrent(mainDisplayable);   }   /*--------------------------------------------------    * Pop displayable from stack and set as active    *-------------------------------------------------*/   public void popDisplayable() {     // If the stack is not empty, pop next displayable     if (empty() == false)       display.setCurrent((Displayable) pop());     else       // On error show an alert       // Once acknowledged, set 'mainDisplayable' as active       display.setCurrent(alStackError, mainDisplayable);   } } /*--------------------------------------------------  * Class TimerCanvas  *  * Animate a sequence of images to simulate   * a moving timer  *  * Example from the book:     Core J2ME Technology  * Copyright John W. Muchow   http://www.CoreJ2ME.com  * You may use/modify for any non-commercial purpose   *-------------------------------------------------*/ class TimerCanvas extends Canvas implements Runnable, CommandListener {   private AnimatedTimer midlet; // Main midlet   private Command cmExit; // Exit midlet   private Command cmOptions; // Display options list   private Image im = null; // Sequence of images   private int imageCount = 4; // Four images in the sequence   private int imageWidth; // Width of one image in the sequence   private int imageHeight; // Height of one image in the sequence   private int imageIndex; // Current image in the sequence   private int translate_x; // Translated x and y   private int translate_y;   private int viewport_x; // Location of the viewport   private int viewport_y;   private boolean active = false; // Timer active?   private boolean requestedToStop = false; // Did user request to stop timer   private int sleepTime = 400; // Current sleep time (milliseconds)   public TimerCanvas(AnimatedTimer midlet) {     // Call canvas constructor     super();     // Save reference to MIDlet so we can     // access the display manager class     this.midlet = midlet;     // Create commands & listen for events     cmExit = new Command("Exit", Command.EXIT, 1);     cmOptions = new Command("Config", Command.SCREEN, 2);     addCommand(cmExit);     addCommand(cmOptions);     setCommandListener(this);   }   /*--------------------------------------------------    * Application manager is about to display canvas    *-------------------------------------------------*/   protected void showNotify() {     if (im == null) {       try {         // Read the png from a file and get width and         // height of one image in the sequence         im = Image.createImage("/timer.png");         imageHeight = im.getHeight();         imageWidth = im.getWidth() / imageCount;         // Get the coordinates for x/y of viewport         // Viewport is centered on the display         viewport_x = (getWidth() / 2) - (imageWidth / 2);         viewport_y = (getHeight() / 2) - (imageHeight / 2);         // Set first translated coordinate to match viewport         translate_x = viewport_x;         translate_y = viewport_y;       } catch (Exception e) {         System.err.println("Unable to read png file.");       }       // Begin with the first image in the sequence       imageIndex = 0;     }     // If the user has not requested to stop the timer...     if (!requestedToStop)       active = true;     new Thread(this).start();   }   /*--------------------------------------------------    * Application manager is no longer displaying canvas    *-------------------------------------------------*/   protected void hideNotify() {     active = false;   }   /*--------------------------------------------------    * Draw next timer in sequence    *-------------------------------------------------*/   protected void paint(Graphics g) {     if (im != null) {       // Due to a bug in MIDP 1.0.3 we need to       // force a clear of the display       g.setColor(255, 255, 255); // White pen       g.fillRect(0, 0, getWidth(), getHeight());       g.setColor(0, 0, 0); // Black pen       // Viewport at center of display       g.setClip(viewport_x, viewport_y, imageWidth, imageHeight);       // Draw image at translated coordinates       g.drawImage(im, translate_x, translate_y, Graphics.TOP           | Graphics.LEFT);     }   }   /*--------------------------------------------------    * Loop forever, translating image coordinates    *-------------------------------------------------*/   public void run() {     try {       while (active) {         Thread.sleep(sleepTime);         repaint();         // Reached the last image in sequence         if (imageIndex == imageCount - 1) {           // Reset translated coordinates           translate_x = viewport_x;           translate_y = viewport_y;         } else {           // Translate coordinate system to the left           translate_x -= imageWidth;         }         // Which image in the sequence is next         imageIndex = (imageIndex + 1) % imageCount;       }     } catch (InterruptedException e) {     }   }   /*--------------------------------------------------    * Called from the "Config" options menu    *-------------------------------------------------*/   public void startTimer() {     requestedToStop = false;     active = true;     repaint();   }   /*--------------------------------------------------    * Called from the "Config" options menu    *-------------------------------------------------*/   public void stopTimer() {     requestedToStop = true;     active = false;     repaint();   }   /*--------------------------------------------------    * Called from form/gauge to adjust sleep    *-------------------------------------------------*/   public void setSleep(int sleepTime) {     this.sleepTime = sleepTime;   }   /*--------------------------------------------------    * Called from form/gauge to adjust sleep    *-------------------------------------------------*/   public int getSleep() {     return sleepTime;   }   /*--------------------------------------------------    * Command event handling    *-------------------------------------------------*/   public void commandAction(Command c, Displayable s) {     if (c == cmOptions) {       // Push current displayable and show the options list       midlet.displayMgr.pushDisplayable(midlet.lsOptions);     } else if (c == cmExit) {       midlet.exitMIDlet();     }   } } /*--------------------------------------------------  * Class SleepForm  *  * Form with gauge to adjust sleep interval of timer  *  * Example from the book:     Core J2ME Technology  * Copyright John W. Muchow   http://www.CoreJ2ME.com  * You may use/modify for any non-commercial purpose   *-------------------------------------------------*/ class SleepForm extends Form implements CommandListener {   private AnimatedTimer midlet; // Main midlet   private Command cmBack, // Back to options list       cmHome, // Go to main displayable (canvas)       cmSave; // Save new sleep time   private Gauge gaSleep; // Gauge to adjust sleep   public SleepForm(String title, AnimatedTimer midlet) {     // Call the form constructor     super(title);     // Save reference to MIDlet so we can     // access the display manager class     this.midlet = midlet;     // Commands     cmSave = new Command("Save", Command.SCREEN, 1);     cmBack = new Command("Back", Command.BACK, 2);     cmHome = new Command("Home", Command.SCREEN, 2);     // Gauge to adjust the length of timer sleep     gaSleep = new Gauge("Timer Sleep", true, 100, 1000);     // Set to current sleep. Gauge holds values 0 to 100,     // divide the current sleep (milliseconds) by 10     gaSleep.setValue(midlet.cvTimer.getSleep() / 10);     // Add to form and listen for events     append(gaSleep);     addCommand(cmSave);     addCommand(cmBack);     addCommand(cmHome);     setCommandListener(this);   }   /*--------------------------------------------------    * Command event handling    *-------------------------------------------------*/   public void commandAction(Command c, Displayable s) {     if (c == cmSave) {       // Gauge returns a value between 0 and 100       // We want milliseconds, so multiply by 10       midlet.cvTimer.setSleep(gaSleep.getValue() * 10);       // Return to main midlet       midlet.displayMgr.home();     } else if (c == cmBack) {       // Pop the last displayable off the stack       midlet.displayMgr.popDisplayable();     } else if (c == cmHome) {       // Return to main midlet       midlet.displayMgr.home();     }   } } /*--------------------------------------------------  * Class OptionsList  *  * List to provide options for configuring of timer  *  * Example from the book:     Core J2ME Technology  * Copyright John W. Muchow   http://www.CoreJ2ME.com  * You may use/modify for any non-commercial purpose   *-------------------------------------------------*/ class OptionsList extends List implements CommandListener {   private AnimatedTimer midlet; // Main midlet   private Command cmBack;   public OptionsList(String title, int listType, AnimatedTimer midlet) {     // Call list constructor     super(title, listType);     // Save reference to MIDlet so we can     // access the display manager class     this.midlet = midlet;     // Create the list entries     append("Sleep interval", null);     append("Start", null);     append("Stop", null);     // Create command and listen for events     cmBack = new Command("Back", Command.BACK, 1);     addCommand(cmBack);     setCommandListener(this);   }   /*--------------------------------------------------    * Command event handling    *-------------------------------------------------*/   public void commandAction(Command c, Displayable s) {     // Event generated by the implicit list     if (c == List.SELECT_COMMAND) {       switch (getSelectedIndex()) {       case 0:         // Push current displayable and show the form         // to adjust the timer sleep         midlet.displayMgr.pushDisplayable(midlet.fmSleep);         break;       case 1:         // Start timer and return to previous displayable         midlet.cvTimer.startTimer();         midlet.displayMgr.popDisplayable();         break;       case 2:         // Stop timer and return to previous displayable         midlet.cvTimer.stopTimer();         midlet.displayMgr.popDisplayable();         break;       }     } else if (c == cmBack) {       // Return to previous displayable       midlet.displayMgr.popDisplayable();     }   } }