package org.jcon.ui;

import java.awt.Dialog;
import java.awt.Frame;
import java.awt.Window;
/**
 * Blinks a window title, which can be used to indicate the
 * user should wait. This is an alternative to a cursor
 * hourglass. A use example is:
 * <p><pre>
 *      In your fields:
 * private WindowTitleBlinker blinker = new WindowTitleBlinker();
 *
 *      In your constructor:
 * blinker.setWindow((Window)menuFrame.getFrame());
 * blinker.setStartDelay(1000); // 1 second
 *
 *      In an actionPerformed() method:
 * blinker.start();
 * fireMessageEvent(new Message(command));
 * blinker.stop();
 * </pre>
 * @author Jack Harich
 */
public class WindowTitleBlinker implements Runnable {

//---------- Private Fields ------------------------------
// Properties
private Window  window;
private String  blinkText  = " - Working";
private int     startDelay = 2000; // Milliseconds
private int     blinkRate  = 500;
private boolean working;

//---------- Runnable Implementation ---------------------
public void run() {
    // Start delay
    try {
        Thread.currentThread().sleep(startDelay);
    } catch(InterruptedException ex) {
        print(".run() - Start delay interrupted"); // Should not happen
        return;
    }
    // Blink until not working
    String title = getWindowTitle();
    boolean on = false;
    String suffix;

    while (working) {
        try {
            Thread.currentThread().sleep(blinkRate);
            on = ! on;
            suffix = (on ? blinkText : "");
            setWindowTitle(title + suffix);

        } catch(InterruptedException ex) {
            print(".run() - Working interrupted"); // Should not happen
            working = false;
        }
    }
    // Done - Restore original window title
    setWindowTitle(title);
}
//---------- Properties ----------------------------------
//----- window
/**
 * Sets the window whose title will be blinked. It may be
 * any Window decendant, such as a Frame or Dialog, or
 * even a JFrame or JDialog.
 * <p>
 * After the blinker is stopped you may prefer to call
 * setWindow(null).
 */
public void setWindow(Window window) {
    this.window = window;
}
public Window getWindow() {
    return window;
}
//----- blinkText
/**
 * Sets the text that will be "blinked" by showing and
 * hiding it as the suffix to the window title. The default
 * is " - Working".
 */
public void setBlinkText(String blinkText) {
    this.blinkText = blinkText;
}
public String getBlinkText() {
    return blinkText;
}
//----- startDelay
/**
 * Sets the number of milliseconds that must pass before
 * the blinker starts blinking. The default is 2000, which
 * is 2 seconds.
 */
public void setStartDelay(int startDelay) {
    this.startDelay = startDelay;
}
public int getStartDelay() {
    return startDelay;
}
//----- blinkRate
/**
 * Sets the number of milliseconds between blinks. The
 * default is 500, which is 1/2 second. This is about right.
 */
public void setBlinkRate(int blinkRate) {
    this.blinkRate = blinkRate;
}
public int getBlinkRate() {
    return blinkRate;
}
//----- working
/**
 * Returns true if started and false if stopped.
 * The initial state is false.
 */
public boolean isWorking() {
    return working;
}
//---------- Public Methods ------------------------------
/**
 * Starts the blinker. The client must have first supplied
 * a window with setWindow(). The other properties have
 * acceptable defaults, but should also be set first if
 * different behavior is desired.
 */
public void start() {
    if (window == null) throw new IllegalStateException(
        "The window is null. Please set it before starting.");
    working = true;
    Thread workerThread = new Thread(this);
    workerThread.setPriority(Thread.MAX_PRIORITY);
    workerThread.start();
}
/**
 * Stops the blinker. This must be called or the blinker
 * will blink forever once started.
 */
public void stop() {
    working = false;
}
//---------- Private Methods -----------------------------
private void setWindowTitle(String newTitle) {
    if (window instanceof Frame) {
        ((Frame)window).setTitle(newTitle);
    } else {
        ((Dialog)window).setTitle(newTitle);
    }
}
private String getWindowTitle() {
    if (window instanceof Frame) {
        return ((Frame)window).getTitle();
    } else {
        return ((Dialog)window).getTitle();
    }
}
//--- Std
private static void print(String text) {
    System.out.println("WindowTitleBlinker" + text);
}

} // End class
