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

Last change on this file since 16913 was 16913, checked in by simon04, 4 years ago

fix #19698 - Refactoring: make private fields final

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