source: josm/trunk/src/org/openstreetmap/josm/gui/PleaseWaitRunnable.java@ 7597

Last change on this file since 7597 was 7597, checked in by Don-vip, 10 years ago

fix #10588 - DownloadGpsTask ignores the ProgressMonitor argument given in its constructor

  • Property svn:eol-style set to native
File size: 7.5 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui;
3
4import java.awt.Component;
5import java.awt.EventQueue;
6import java.io.IOException;
7
8import javax.swing.SwingUtilities;
9
10import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor;
11import org.openstreetmap.josm.gui.progress.ProgressMonitor;
12import org.openstreetmap.josm.gui.progress.ProgressMonitor.CancelListener;
13import org.openstreetmap.josm.gui.progress.ProgressTaskId;
14import org.openstreetmap.josm.io.OsmTransferException;
15import org.openstreetmap.josm.tools.BugReportExceptionHandler;
16import org.openstreetmap.josm.tools.CheckParameterUtil;
17import org.xml.sax.SAXException;
18
19/**
20 * Instanced of this thread will display a "Please Wait" message in middle of JOSM
21 * to indicate a progress being executed.
22 *
23 * @author Imi
24 */
25public abstract class PleaseWaitRunnable implements Runnable, CancelListener {
26 private boolean canceled = false;
27 private boolean ignoreException;
28 private final String title;
29
30 protected final ProgressMonitor progressMonitor;
31
32 /**
33 * Create the runnable object with a given message for the user.
34 * @param title message for the user
35 */
36 public PleaseWaitRunnable(String title) {
37 this(title, false);
38 }
39
40 /**
41 * Create the runnable object with a given message for the user.
42 *
43 * @param title message for the user
44 * @param ignoreException If true, exception will be propagated to calling code. If false then
45 * exception will be thrown directly in EDT. When this runnable is executed using executor framework
46 * then use false unless you read result of task (because exception will get lost if you don't)
47 */
48 public PleaseWaitRunnable(String title, boolean ignoreException) {
49 this(title, new PleaseWaitProgressMonitor(title), ignoreException);
50 }
51
52 /**
53 * Create the runnable object with a given message for the user
54 *
55 * @param parent the parent component for the please wait dialog. Must not be null.
56 * @param title message for the user
57 * @param ignoreException If true, exception will be propagated to calling code. If false then
58 * exception will be thrown directly in EDT. When this runnable is executed using executor framework
59 * then use false unless you read result of task (because exception will get lost if you don't)
60 * @throws IllegalArgumentException thrown if parent is null
61 */
62 public PleaseWaitRunnable(Component parent, String title, boolean ignoreException) throws IllegalArgumentException{
63 CheckParameterUtil.ensureParameterNotNull(parent, "parent");
64 this.title = title;
65 this.progressMonitor = new PleaseWaitProgressMonitor(parent, title);
66 this.ignoreException = ignoreException;
67 }
68
69 /**
70 * Create the runnable object with a given message for the user
71 *
72 * @param title message for the user
73 * @param progressMonitor progress monitor
74 * @param ignoreException If true, exception will be propagated to calling code. If false then
75 * exception will be thrown directly in EDT. When this runnable is executed using executor framework
76 * then use false unless you read result of task (because exception will get lost if you don't)
77 * @throws IllegalArgumentException thrown if parent is null
78 */
79 public PleaseWaitRunnable(String title, ProgressMonitor progressMonitor, boolean ignoreException) {
80 this.title = title;
81 this.progressMonitor = progressMonitor == null?new PleaseWaitProgressMonitor(title):progressMonitor;
82 this.ignoreException = ignoreException;
83 }
84
85 private void doRealRun() {
86 try {
87 ProgressTaskId oldTaskId = null;
88 try {
89 progressMonitor.addCancelListener(this);
90 progressMonitor.beginTask(title);
91 oldTaskId = progressMonitor.getProgressTaskId();
92 progressMonitor.setProgressTaskId(canRunInBackground());
93 try {
94 realRun();
95 } finally {
96 if (EventQueue.isDispatchThread()) {
97 finish();
98 } else {
99 EventQueue.invokeAndWait(new Runnable() {
100 @Override
101 public void run() {
102 finish();
103 }
104 });
105 }
106 }
107 } finally {
108 progressMonitor.finishTask();
109 progressMonitor.removeCancelListener(this);
110 progressMonitor.setProgressTaskId(oldTaskId);
111 if (progressMonitor instanceof PleaseWaitProgressMonitor) {
112 ((PleaseWaitProgressMonitor)progressMonitor).close();
113 }
114 if (EventQueue.isDispatchThread()) {
115 afterFinish();
116 } else {
117 EventQueue.invokeAndWait(new Runnable() {
118 @Override
119 public void run() {
120 afterFinish();
121 }
122 });
123 }
124 }
125 } catch (final Exception e) {
126 if (!ignoreException) {
127 // Exception has to thrown in EDT to be shown to user
128 SwingUtilities.invokeLater(new Runnable() {
129 @Override
130 public void run() {
131 if (e instanceof RuntimeException) {
132 BugReportExceptionHandler.handleException(e);
133 } else {
134 ExceptionDialogUtil.explainException(e);
135 }
136 }
137 });
138 }
139 }
140 }
141
142 /**
143 * Can be overriden if something needs to run after progress monitor is closed.
144 */
145 protected void afterFinish() {
146
147 }
148
149 @Override
150 public final void run() {
151 if (canceled)
152 return; // since realRun isn't executed, do not call to finish
153
154 if (EventQueue.isDispatchThread()) {
155 new Thread(new Runnable() {
156 @Override
157 public void run() {
158 doRealRun();
159 }
160 }).start();
161 } else {
162 doRealRun();
163 }
164 }
165
166 @Override
167 public void operationCanceled() {
168 cancel();
169 }
170
171 /**
172 * User pressed cancel button.
173 */
174 protected abstract void cancel();
175
176 /**
177 * Called in the worker thread to do the actual work. When any of the
178 * exception is thrown, a message box will be displayed and closeDialog
179 * is called. finish() is called in any case.
180 */
181 protected abstract void realRun() throws SAXException, IOException, OsmTransferException;
182
183 /**
184 * Finish up the data work. Is guaranteed to be called if realRun is called.
185 * Finish is called in the gui thread just after the dialog disappeared.
186 */
187 protected abstract void finish();
188
189 /**
190 * Relies the progress monitor.
191 * @return the progress monitor
192 */
193 public ProgressMonitor getProgressMonitor() {
194 return progressMonitor;
195 }
196
197 /**
198 * Task can run in background if returned value != null. Note that it's tasks responsibility
199 * to ensure proper synchronization, PleaseWaitRunnable doesn't with it.
200 * @return If returned value is != null then task can run in background. TaskId could be used in future for "Always run in background" checkbox
201 */
202 public ProgressTaskId canRunInBackground() {
203 return null;
204 }
205}
Note: See TracBrowser for help on using the repository browser.