001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026:
027: package com.sun.midp.lcdui;
028:
029: import javax.microedition.lcdui.*;
030: import com.sun.midp.events.EventQueue;
031:
032: import com.sun.midp.log.Logging;
033: import com.sun.midp.log.LogChannels;
034:
035: /**
036: * Display a preempting alert and wait for the user to acknowledge it.
037: */
038: public class SystemAlert extends Alert implements CommandListener,
039: Runnable {
040:
041: /** Preempt token for displaying errors. */
042: private Object preemptToken;
043:
044: /** The display event handler for displaying errors. */
045: private DisplayEventHandler displayEventHandler;
046:
047: /** Explicit command lstener for this alert, null if not set. */
048: private CommandListener explicitListener;
049:
050: /** Synchronization lock for setting explicit command listener. */
051: private final Object listenerLock = new Object();
052:
053: /** Flag to identify if the alert is being displayed currently. */
054: private boolean shown = false;
055:
056: /**
057: * Construct an <code>SystemAlert</code>.
058: *
059: * @param displayEventHandler The display event handler for error display
060: * @param title The title of the <tt>Alert</tt>
061: * @param text The text of the <tt>Alert</tt>
062: * @param image An <tt>Image</tt> to display on the <tt>Alert</tt>
063: * @param type The <tt>Alert</tt> type
064: */
065: public SystemAlert(DisplayEventHandler displayEventHandler,
066: String title, String text, Image image, AlertType type) {
067:
068: super (title, text, image, type);
069:
070: setTimeout(Alert.FOREVER);
071:
072: super .setCommandListener(this );
073:
074: this .displayEventHandler = displayEventHandler;
075:
076: }
077:
078: /** Waits for the user to acknowledge the alert. */
079: public synchronized void waitForUser() {
080: if (!shown) {
081: return;
082: }
083:
084: if (EventQueue.isDispatchThread()) {
085: // Developer programming error
086: throw new RuntimeException(
087: "Blocking call performed in the event thread");
088: }
089:
090: try {
091: wait();
092: } catch (Throwable t) {
093: if (Logging.REPORT_LEVEL <= Logging.WARNING) {
094: Logging.report(Logging.WARNING, LogChannels.LC_CORE,
095: "Throwable while SystemAlert.waitForUser");
096: }
097: }
098: }
099:
100: /** Dismiss the alert */
101: public synchronized void dismiss() {
102: if (shown) {
103: notify(); // wait up waitForUser() thread
104: displayEventHandler.donePreempting(preemptToken);
105: preemptToken = null;
106: shown = false;
107: }
108: }
109:
110: /**
111: * Respond to a command issued on this alert.
112: *
113: * @param c command activated by the user
114: * @param s the Displayable the command was on.
115: */
116: public void commandAction(Command c, Displayable s) {
117: synchronized (listenerLock) {
118: if (null != explicitListener) {
119: explicitListener.commandAction(c, s);
120: } else {
121: dismiss();
122: }
123: }
124:
125: }
126:
127: /**
128: * Assigns explicit command listener to this alert. If an non-null
129: * explcit listener its commandAction() method is called to process
130: * a command, otherwise default dismiss() action is used.
131: *
132: * @param cl expilict command listener, null to remove any explicit
133: * listener
134: */
135: public void setCommandListener(CommandListener cl) {
136: synchronized (listenerLock) {
137: explicitListener = cl;
138: }
139: }
140:
141: /**
142: * Displays this alert. Since alert displaying may be blocking, it is
143: * not allowed in the event dispatching thread. Nothing is done when
144: * the method is called from the dispatching thread, to produce a
145: * system alert from ituse runInNewThread(). Nothing is done if the
146: * alert is being displayed currently.
147: */
148: public synchronized void run() {
149: shown = true;
150:
151: if (preemptToken != null) {
152: return;
153: }
154:
155: try {
156: preemptToken = displayEventHandler.preemptDisplay(this ,
157: true);
158: } catch (Throwable e) {
159: if (Logging.REPORT_LEVEL <= Logging.WARNING) {
160: Logging.report(Logging.WARNING, LogChannels.LC_CORE,
161: "Throwable while preempting Display");
162: }
163: }
164: }
165:
166: /**
167: * Launches a new thread and displays this alert from it. Use this method
168: * to avoid blocking a thread that produces the alert. Makes nothing if
169: * the alert is being displayed currently.
170: */
171: public synchronized void runInNewThread() {
172: shown = true;
173: new Thread(this).start();
174: }
175: }
|