001: /*BEGIN_COPYRIGHT_BLOCK
002: *
003: * Copyright (c) 2001-2007, JavaPLT group at Rice University (javaplt@rice.edu)
004: * All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions are met:
008: * * Redistributions of source code must retain the above copyright
009: * notice, this list of conditions and the following disclaimer.
010: * * Redistributions in binary form must reproduce the above copyright
011: * notice, this list of conditions and the following disclaimer in the
012: * documentation and/or other materials provided with the distribution.
013: * * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
014: * names of its contributors may be used to endorse or promote products
015: * derived from this software without specific prior written permission.
016: *
017: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
018: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
019: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
020: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
021: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
022: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
023: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
024: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
025: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
026: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
027: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
028: *
029: * This software is Open Source Initiative approved Open Source Software.
030: * Open Source Initative Approved is a trademark of the Open Source Initiative.
031: *
032: * This file is part of DrJava. Download the current version of this project
033: * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
034: *
035: * END_COPYRIGHT_BLOCK*/
036:
037: package edu.rice.cs.util.swing;
038:
039: import javax.swing.ProgressMonitor;
040:
041: /**
042: * This is the base class to the component that launches the AsyncTask. It
043: * manages the multi-threading and ensures that the correct methods of the task
044: * are performed on the correct thread.
045: *
046: * @author jlugo
047: */
048: public abstract class AsyncTaskLauncher {
049:
050: /**
051: * Returns whether the launcher should call
052: * <code>setParentContainerEnabled</code> both to disable and to re-enable
053: * the parent. This gives the concrete implementation of the launcher more
054: * control in case dissabling and re-enabling the view could cause
055: * inconsistent behavior.
056: * <p>
057: * In some cases this should always be true, for instance, when for each call
058: * to lock the UI, you must call the unlock method an equal number of times to
059: * actually unlock the frame. If this were dissabling a normal swing
060: * component, where there is only on and off, you wouldn't want to re-enable
061: * the component if it was dissabled to begin with.
062: *
063: * @return whether the launcher should call
064: * <code>setParentContainerEnabled</code>
065: */
066: protected abstract boolean shouldSetEnabled();
067:
068: /**
069: * Sets the enabled state of the parent component. If the parent component is
070: * set to dissabled, this means that the user is unable to invoke any
071: * operations via mouse clicks or key strokes. <i><b>Note:</b> this method
072: * is called strictly on the event-handling thread.</i>
073: *
074: * @param enabled
075: * Whether the parent container should be enabled
076: */
077: protected abstract void setParentContainerEnabled(boolean enabled);
078:
079: /**
080: * Creates a progress monitor that can be used to provide feedback to the user
081: * during the asynchronous task. This progress monitor will also be used to
082: * allow the user to request the task to be canceled.
083: * <p>
084: * <i><b>Note:</b> this method is called strictly on the event-handling
085: * thread.</i>
086: *
087: * @return The progress monitor used to provide feedback.
088: */
089: protected abstract IAsyncProgress createProgressMonitor(
090: String description, int min, int max);
091:
092: /**
093: * Executes the AsyncTask in its own thread after performing any needed steps
094: * to prepare the UI for its execution.
095: *
096: * @param <R>
097: * The type of result to pass from <code>runAsync</code> to
098: * <code>complete</code>
099: * @param task
100: * The task to execute on its own worker thread
101: * @param showProgress
102: * Whether the progress monitor should be displayed to the user. If
103: * it's value is false, the user will not be able to make any
104: * cancelation requests to the task.
105: * @param lockUI
106: * Whether the user should be able to interact with the rest of the
107: * UI while the task is in progress
108: */
109: public <P, R> void executeTask(final AsyncTask<P, R> task,
110: final P param, final boolean showProgress,
111: final boolean lockUI) {
112: Runnable uiInit = new Runnable() {
113: public void run() {
114: final boolean shouldUnlockUI = shouldSetEnabled()
115: && lockUI;
116: final IAsyncProgress monitor = createProgressMonitor(
117: task.getDiscriptionMessage(), task
118: .getMinProgress(), task
119: .getMaxProgress());
120: if (shouldSetEnabled() && lockUI)
121: setParentContainerEnabled(false);
122:
123: Thread taskThread = new Thread(new Runnable() {
124: public void run() {
125: R result = null;
126: Exception caughtException = null;
127: try {
128: result = task.runAsync(param, monitor);
129: } catch (Exception e) {
130: caughtException = e;
131: }
132:
133: final AsyncCompletionArgs<R> args = new AsyncCompletionArgs<R>(
134: result, caughtException, monitor
135: .isCanceled());
136:
137: Runnable cleanup = new Runnable() {
138: public void run() {
139: task.complete(args);
140:
141: if (shouldUnlockUI)
142: setParentContainerEnabled(true);
143: }
144: };
145:
146: Utilities.invokeLater(cleanup);
147: }
148: }, "Task Thread - " + task.getName());
149:
150: taskThread.start();
151: }
152: };
153:
154: Utilities.invokeLater(uiInit);
155: }
156: }
|