/* * The contents of this file are subject to the terms of the Common Development * and Distribution License (the License). You may not use this file except in * compliance with the License. * * You can obtain a copy of the License at http://www.netbeans.org/cddl.html * or http://www.netbeans.org/cddl.txt. * * The Original Software is NetBeans. The Initial Developer of the Original * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun * Microsystems, Inc. All Rights Reserved. */ /* * WaitScreen.java * * Created on August 11, 2005, 1:33 PM * */ package org.netbeans.microedition.lcdui; import javax.microedition.lcdui.Alert; import javax.microedition.lcdui.Command; import javax.microedition.lcdui.CommandListener; import javax.microedition.lcdui.Display; import javax.microedition.lcdui.Displayable; import org.netbeans.microedition.util.CancellableTask; /** * This component suits as a wait screen, which let the user to execute a blocking * background task (e.g. a network communication) and waits for it until finished. * <p/> * The background task is being started immediately prior the component is being * shown on the screen. * <p/> * When the background task is finished, this component calls commandAction method * on assigned CommandListener object. In the case of success, the commandAction method * is called with SUCCESS_COMMAND as parameter, in the case of failure, the commandAction * method is called with FAILURE_COMMAND as parameter. * <p/> * The functionality from previous version, where the component automatically swiches * to another <code>Displayable</code> objects is still available, but has beeen * deprecated. * <p/> * The deprecated behavior is the following - in the case of success (i.e. the * task finished successfully), it switches to displayable(s) supplied by * <code>setNextDisplayable()</code> methods, in the case of failure, it switched to displaybles(s) * supplied by <code>setFailureDisplayable()</code> methods. In the case there is not * set failure displayable, <code>WaitScreen</code> even in the * case of failure switches to displayables specified by the <code>setNextDisplayable()</code> * method. In the case there is even no next displayable specified, after the * task is finished, <code>WaitScreen</code> switches back to the screen it was * previously visible on the display. * * @author breh */ public class WaitScreen extends AbstractInfoScreen { private CancellableTask task = null; private Thread backgroundExecutor = null; private Displayable failureDisplayble; private Alert failureAlert; /** * Command fired when the background task was finished succesfully */ public static final Command SUCCESS_COMMAND = new Command("Success",Command.OK,0); /** * Command fired when the background task failed (threw exception) */ public static final Command FAILURE_COMMAND = new Command("Failure",Command.OK,0); /** * Creates a new instance of WaitScreen for given <code>Display</code> object. * @param display A non-null display object. * @throws IllegalArgumentException when the supplied argument is null */ public WaitScreen(Display display) throws IllegalArgumentException { super(display); } /** * Sets the displayable to be used to switch to in the case of the background * task failure. * @param failureDisplayble displayable, or null if the component should switch to <code>nextDisplayable</code> * even in the case of failure. * * @deprecated - use FAILURE_COMMAND in CommandListener.commandAction() to handle failure event */ public void setFailureDisplayable(Displayable failureDisplayble) { this.failureDisplayble = failureDisplayble; } /** * Requests that the specified Alert is going to be shown in the case of * failure, and failureDisplayable be made current after the Alert is dismissed. * <p/> * The failureDisplayable parameter cannot be Alert and in the case * failureAlert is not null, it also cannot be null. * @param failureAlert alert to be shown, or null if the component should always switch to nextDisplayable * @param failureDisplayble a displayable to be shown after the alert is being dismissed. This displayable * cannot be null if the <code>failureAlert</code> is not null and it also cannot be * Alert. * @throws java.lang.IllegalArgumentException If the failureAlert is not null and failureDisplay is null at the same time, or * if the failureDisplayable is instance of <code>Alert</code> * * @deprecated - use FAILURE_COMMAND in CommandListener.commandAction() to handle failure event */ public void setFailureDisplayable(Alert failureAlert, Displayable failureDisplayble) throws IllegalArgumentException { if ((failureAlert != null) && (failureDisplayble == null)) throw new IllegalArgumentException("A failureDisplayable parameter cannot be null if the failureAlert parameter is not null."); if (failureDisplayble instanceof Alert) throw new IllegalArgumentException("failureDisplayable paremter cannot be Alert."); this.failureAlert = failureAlert; this.failureDisplayble = failureDisplayble; } /** * Sets the task to be run on the background. * @param task task to be executed */ public void setTask(CancellableTask task) { this.task = task; } /** * Gets the background task. * @return task being executed in background while this component is being shown * on the screen */ public CancellableTask getTask() { return task; } /** * starts the supplied task */ protected void showNotify() { super.showNotify(); // and start the task if (task != null) { if (backgroundExecutor == null) { backgroundExecutor = new Thread(new BackgroundExecutor(task)); backgroundExecutor.start(); } } else { // switch to next displayable immediatelly - no task was assigned // do it when the task is repainted - on some devices there are // some race-conditions getDisplay().callSerially(new Runnable() { public void run() { doAction(); } }); } } // private stuff // private stuff private void doAction() { CommandListener cl = getCommandListener(); if (cl != null) { if ((task != null) && task.hasFailed()) { cl.commandAction(FAILURE_COMMAND,this); } else { // task didn't failed - success !!! cl.commandAction(SUCCESS_COMMAND,this); } } else { // old behavior - now deprecated if ((task != null) && task.hasFailed() && (failureDisplayble != null)) { switchToDisplayable(getDisplay(), failureAlert, failureDisplayble); } else { switchToNextDisplayable(); } } } /** * BackgroundExecutor task */ private class BackgroundExecutor implements Runnable { private CancellableTask task; public BackgroundExecutor(CancellableTask task) throws IllegalArgumentException { if (task == null) throw new IllegalArgumentException("Task parameter cannot be null"); this.task = task; } public void run() { try { task.run(); } finally { getDisplay().callSerially(new Runnable() { public void run() { WaitScreen.this.backgroundExecutor = null; doAction(); } }); } } } }