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

Last change on this file since 12541 was 11801, checked in by Don-vip, 7 years ago

see #14595 - catch UnsupportedOperationException

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