001: /*
002: * The contents of this file are subject to the terms of the Common Development
003: * and Distribution License (the License). You may not use this file except in
004: * compliance with the License.
005: *
006: * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
007: * or http://www.netbeans.org/cddl.txt.
008: *
009: * When distributing Covered Code, include this CDDL Header Notice in each file
010: * and include the License file at http://www.netbeans.org/cddl.txt.
011: * If applicable, add the following below the CDDL Header, with the fields
012: * enclosed by brackets [] replaced by your own identifying information:
013: * "Portions Copyrighted [year] [name of copyright owner]"
014: *
015: * The Original Software is NetBeans. The Initial Developer of the Original
016: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
017: * Microsystems, Inc. All Rights Reserved.
018: */
019:
020: package org.netbeans.modules.compapp.projects.wizard;
021:
022: import java.awt.Component;
023: import java.beans.PropertyChangeEvent;
024: import java.beans.PropertyChangeListener;
025: import java.lang.reflect.InvocationTargetException;
026: import javax.swing.SwingUtilities;
027: import org.netbeans.api.progress.ProgressHandle;
028:
029: /**
030: * An adapter for ProgressHandle objects. A ProgressController is a management
031: * object that is used to start/stop the task, and to report its progress.
032: *
033: * @see org.netbeans.modules.compapp.projects.wizard.ProgressDialogFactory
034: * @see org.netbeans.api.progress.ProgressHandle
035: *
036: * @author Tientien Li
037: */
038: public class ProgressController {
039:
040: ProgressController(ProgressHandle handle, Component uiComponent) {
041: if (handle == null) {
042: throw new NullPointerException("handle");
043: }
044: if (uiComponent == null) {
045: throw new NullPointerException("uiComponent");
046: }
047: progress = handle;
048: target = uiComponent;
049: }
050:
051: /**
052: * Stop the task. Calling this method causes the associated presentation
053: * component to be made not visible.
054: */
055: public void finish() {
056: avoidEventDispatchThreadExecution();
057:
058: synchronized (this ) {
059: progress.finish();
060: finished = true;
061: }
062:
063: Thread job = new Thread(new Runnable() {
064: public void run() {
065: try {
066: SwingUtilities.invokeAndWait(new Runnable() {
067: public void run() {
068: target
069: .firePropertyChange(
070: ProgressDialogFactory.FINISH_OPTION,
071: 0, 1);
072: }
073: });
074: Thread.sleep(PAUSE);
075: } catch (InterruptedException ex) {
076: ;
077: } catch (InvocationTargetException ex) {
078: ;
079: }
080: }
081: });
082:
083: job.start();
084: try {
085: job.join();
086: } catch (InterruptedException ex) {
087: ;
088: }
089: showUIComponent(false);
090: }
091:
092: /**
093: * Indicate the cancelation of the task. Calling this method causes the
094: * associated presentation component to be made not visible.
095: */
096: public void cancel() {
097: avoidEventDispatchThreadExecution();
098:
099: synchronized (this ) {
100: progress.finish();
101: finished = true;
102: canceled = true;
103: }
104:
105: Thread job = new Thread(new Runnable() {
106: public void run() {
107: try {
108: SwingUtilities.invokeAndWait(new Runnable() {
109: public void run() {
110: target
111: .firePropertyChange(
112: ProgressDialogFactory.CANCEL_OPTION,
113: 0, 1);
114: }
115: });
116: Thread.sleep(PAUSE);
117: } catch (InterruptedException ex) {
118: ;
119: } catch (InvocationTargetException ex) {
120: ;
121: }
122: }
123: });
124:
125: job.start();
126: try {
127: job.join();
128: } catch (InterruptedException ex) {
129: ;
130: }
131: showUIComponent(false);
132: }
133:
134: /**
135: * Indicates if {@link #cancel} has been called on this object.
136: */
137: public synchronized boolean isCanceled() {
138: return canceled;
139: }
140:
141: /**
142: * Indicates if {@link #finish} has been called on this object.
143: */
144: public synchronized boolean isFinished() {
145: return finished;
146: }
147:
148: /**
149: * Indicate progress made in the task.
150: *
151: * @param workunit Cumulative number of workunits completed so far
152: */
153: public void progress(int workunit) {
154: progress.progress(workunit);
155: }
156:
157: /**
158: * Disables the ability to cancel progress tracking. Use this to indicate
159: * to the controller object that all further progress workunits are
160: * irrevocable.
161: */
162: public void lockout() {
163: avoidEventDispatchThreadExecution();
164:
165: Thread job = new Thread(new Runnable() {
166: public void run() {
167: try {
168: SwingUtilities.invokeAndWait(new Runnable() {
169: public void run() {
170: target
171: .firePropertyChange(
172: ProgressDialogFactory.CANCEL_LOCKOUT_OPTION,
173: 0, 1);
174: }
175: });
176: } catch (InterruptedException ex) {
177: ;
178: } catch (InvocationTargetException ex) {
179: ;
180: }
181: }
182: });
183:
184: job.start();
185: try {
186: job.join();
187: } catch (InterruptedException ex) {
188: ;
189: }
190: }
191:
192: /**
193: * Indicate progress made in the task.
194: *
195: * @param message Status of the task
196: * @param workunit Cumulative number of workunits completed so far
197: */
198: public void progress(String message, int workunit) {
199: avoidEventDispatchThreadExecution();
200: progress.progress(message, workunit);
201: updateProgressMessage(message);
202: }
203:
204: /**
205: * Indicate progress made in the task. This method does not cause the
206: * visual progress indicator to advance.
207: *
208: * @param message Status of the task
209: */
210: public void progress(String message) {
211: avoidEventDispatchThreadExecution();
212: progress.progress(message);
213: updateProgressMessage(message);
214: }
215:
216: /**
217: * Start the progress indication for an indeterminate task. Calling this
218: * method causes the associated presentation component to be made visible.
219: *
220: * @throws IllegalStateException if the progress this controller is
221: * tracking has already been started, finished, or canceled.
222: */
223: public synchronized void start() {
224: avoidEventDispatchThreadExecution();
225: if (used) {
226: throw new IllegalStateException("Task already started");
227: }
228: showUIComponent(true);
229: progress.start();
230: used = true;
231: }
232:
233: /**
234: * Start the progress indication for a task with a known number of steps.
235: * Calling this method causes the associated presentation component to be
236: * made visible.
237: *
238: * @throws IllegalStateException if the progress this controller is
239: * tracking has already been started, finished, or canceled.
240: */
241: public synchronized void start(int workunits) {
242: avoidEventDispatchThreadExecution();
243: if (used) {
244: throw new IllegalStateException("Task already started");
245: }
246: showUIComponent(true);
247: used = true;
248: progress.start(workunits);
249: }
250:
251: /**
252: * Discard the tracker. Its associated presentation component is made
253: * not visible.
254: *
255: * @throws IllegalStateException if the progress this controller is
256: * tracking has not yet been finished or canceled.
257: */
258: public synchronized void dispose() {
259: avoidEventDispatchThreadExecution();
260: if (!finished) {
261: throw new IllegalStateException(
262: "Task not yet finished/canceled");
263: }
264: showUIComponent(false);
265: }
266:
267: synchronized void setCanceled() {
268: finished = true;
269: canceled = true;
270: }
271:
272: private void showUIComponent(final boolean show) {
273: try {
274: SwingUtilities.invokeAndWait(new Runnable() {
275: public void run() {
276: target.setVisible(show);
277: }
278: });
279: } catch (InterruptedException ex) {
280: ;
281: } catch (InvocationTargetException ex) {
282: ;
283: }
284: }
285:
286: private void updateProgressMessage(String message) {
287: final PropertyChangeListener[] listeners = target
288: .getPropertyChangeListeners();
289:
290: final PropertyChangeEvent evt = new PropertyChangeEvent(this ,
291: ProgressDialogFactory.UPDATE_OPTION, "", message);
292:
293: SwingUtilities.invokeLater(new Runnable() {
294: public void run() {
295: for (int i = 0; i < listeners.length; ++i) {
296: listeners[i].propertyChange(evt);
297: }
298: }
299: });
300: }
301:
302: private void avoidEventDispatchThreadExecution()
303: throws RuntimeException {
304: if (SwingUtilities.isEventDispatchThread()) {
305: throw new RuntimeException(
306: "AWT Event Dispatch Thread used!");
307: }
308: }
309:
310: private static final long PAUSE = 1000L;
311: private final ProgressHandle progress;
312: private final Component target;
313: private boolean used;
314: private boolean canceled;
315: private boolean finished;
316: }
|