source: josm/trunk/src/org/openstreetmap/josm/gui/progress/swing/PleaseWaitProgressMonitor.java@ 14302

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

see #16781 - fix more typos using https://github.com/vlajos/misspell-fixer

  • Property svn:eol-style set to native
File size: 13.0 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.progress.swing;
3
4import java.awt.Component;
5import java.awt.GraphicsEnvironment;
6import java.awt.event.ActionListener;
7import java.awt.event.WindowAdapter;
8import java.awt.event.WindowEvent;
9import java.awt.event.WindowListener;
10
11import javax.swing.SwingUtilities;
12
13import org.openstreetmap.josm.gui.MainApplication;
14import org.openstreetmap.josm.gui.MapFrame;
15import org.openstreetmap.josm.gui.MapStatus.BackgroundProgressMonitor;
16import org.openstreetmap.josm.gui.PleaseWaitDialog;
17import org.openstreetmap.josm.gui.progress.AbstractProgressMonitor;
18import org.openstreetmap.josm.gui.progress.CancelHandler;
19import org.openstreetmap.josm.gui.progress.ProgressException;
20import org.openstreetmap.josm.gui.progress.ProgressTaskId;
21import org.openstreetmap.josm.gui.util.GuiHelper;
22import org.openstreetmap.josm.tools.bugreport.BugReport;
23
24/**
25 * A progress monitor used in {@link org.openstreetmap.josm.gui.PleaseWaitRunnable}.
26 * <p>
27 * Progress is displayed in a dialog window ({@link PleaseWaitDialog}).
28 * @since 12675 (moved from {@code gui.progress} package}
29 */
30public class PleaseWaitProgressMonitor extends AbstractProgressMonitor {
31
32 /**
33 * Implemented by both foreground dialog and background progress dialog (in status bar)
34 */
35 public interface ProgressMonitorDialog {
36 /**
37 * Sets the visibility of this dialog
38 * @param visible The visibility, <code>true</code> to show it, <code>false</code> to hide it
39 */
40 void setVisible(boolean visible);
41
42 /**
43 * Updates the progress value to the specified progress.
44 * @param progress The progress as integer. Between 0 and {@link PleaseWaitProgressMonitor#PROGRESS_BAR_MAX}
45 */
46 void updateProgress(int progress);
47
48 /**
49 * Sets the description of what is done
50 * @param text The description of the task
51 */
52 void setCustomText(String text);
53
54 /**
55 * Sets the current action that is done
56 * @param text The current action
57 */
58 void setCurrentAction(String text);
59
60 /**
61 * Display that the current progress cannot be determined
62 * @param newValue whether the progress cannot be determined
63 */
64 void setIndeterminate(boolean newValue);
65
66 /**
67 * Append a message to the progress log
68 * <p>
69 * TODO Not implemented properly in background monitor, log message will get lost if progress runs in background
70 * @param message The message
71 */
72 void appendLogMessage(String message);
73 }
74
75 /**
76 * The maximum value the progress bar that displays the current progress should have.
77 */
78 public static final int PROGRESS_BAR_MAX = 10_000;
79
80 /**
81 * The progress monitor being currently displayed.
82 */
83 static PleaseWaitProgressMonitor currentProgressMonitor;
84
85 private final Component dialogParent;
86
87 private int currentProgressValue;
88 private String customText;
89 private String title;
90 private boolean indeterminate;
91
92 private boolean isInBackground;
93 private PleaseWaitDialog dialog;
94 private String windowTitle;
95 protected ProgressTaskId taskId;
96
97 private boolean cancelable;
98
99 /**
100 * Returns the progress monitor being currently displayed.
101 * @return the progress monitor being currently displayed
102 * @since 12638
103 */
104 public static PleaseWaitProgressMonitor getCurrent() {
105 return currentProgressMonitor;
106 }
107
108 private void doInEDT(Runnable runnable) {
109 // This must be invoke later even if current thread is EDT because inside there is dialog.setVisible
110 // which freeze current code flow until modal dialog is closed
111 SwingUtilities.invokeLater(() -> {
112 try {
113 runnable.run();
114 } catch (RuntimeException e) { // NOPMD
115 throw BugReport.intercept(e).put("monitor", this);
116 }
117 });
118 }
119
120 private void setDialogVisible(boolean visible) {
121 if (dialog.isVisible() != visible) {
122 dialog.setVisible(visible);
123 }
124 }
125
126 private ProgressMonitorDialog getDialog() {
127
128 BackgroundProgressMonitor backgroundMonitor = null;
129 MapFrame map = MainApplication.getMap();
130 if (map != null) {
131 backgroundMonitor = map.statusLine.progressMonitor;
132 }
133
134 if (backgroundMonitor != null) {
135 backgroundMonitor.setVisible(isInBackground);
136 }
137 if (dialog != null) {
138 setDialogVisible(!isInBackground || backgroundMonitor == null);
139 }
140
141 if (isInBackground && backgroundMonitor != null) {
142 backgroundMonitor.setVisible(true);
143 if (dialog != null) {
144 setDialogVisible(false);
145 }
146 return backgroundMonitor;
147 } else if (backgroundMonitor != null) {
148 backgroundMonitor.setVisible(false);
149 if (dialog != null) {
150 setDialogVisible(true);
151 }
152 return dialog;
153 } else if (dialog != null) {
154 setDialogVisible(true);
155 return dialog;
156 } else
157 return null;
158 }
159
160 /**
161 * Constructs a new {@code PleaseWaitProgressMonitor}.
162 */
163 public PleaseWaitProgressMonitor() {
164 this("");
165 }
166
167 /**
168 * Constructs a new {@code PleaseWaitProgressMonitor}.
169 * @param windowTitle window title
170 */
171 public PleaseWaitProgressMonitor(String windowTitle) {
172 this(MainApplication.getMainFrame());
173 this.windowTitle = windowTitle;
174 }
175
176 /**
177 * Constructs a new {@code PleaseWaitProgressMonitor}.
178 * @param dialogParent component to get parent frame from
179 */
180 public PleaseWaitProgressMonitor(Component dialogParent) {
181 super(new CancelHandler());
182 if (GraphicsEnvironment.isHeadless()) {
183 this.dialogParent = dialogParent;
184 } else {
185 this.dialogParent = GuiHelper.getFrameForComponent(dialogParent);
186 }
187 this.cancelable = true;
188 }
189
190 /**
191 * Constructs a new {@code PleaseWaitProgressMonitor}.
192 * @param dialogParent component to get parent frame from
193 * @param windowTitle window title
194 */
195 public PleaseWaitProgressMonitor(Component dialogParent, String windowTitle) {
196 this(GuiHelper.getFrameForComponent(dialogParent));
197 this.windowTitle = windowTitle;
198 }
199
200 private final ActionListener cancelListener = e -> cancel();
201
202 private final ActionListener inBackgroundListener = e -> {
203 isInBackground = true;
204 ProgressMonitorDialog dlg = getDialog();
205 if (dlg != null) {
206 reset();
207 dlg.setVisible(true);
208 }
209 };
210
211 private final WindowListener windowListener = new WindowAdapter() {
212 @Override public void windowClosing(WindowEvent e) {
213 cancel();
214 }
215 };
216
217 /**
218 * See if this task is canceleable
219 * @return <code>true</code> if it can be canceled
220 */
221 public final boolean isCancelable() {
222 return cancelable;
223 }
224
225 /**
226 * Sets this task to be cancelable
227 * @param cancelable Whether it can be canceled
228 */
229 public final void setCancelable(boolean cancelable) {
230 this.cancelable = cancelable;
231 }
232
233 @Override
234 public void doBeginTask() {
235 doInEDT(() -> {
236 currentProgressMonitor = this;
237 if (GraphicsEnvironment.isHeadless()) {
238 return;
239 }
240 if (dialogParent != null && dialog == null) {
241 dialog = new PleaseWaitDialog(dialogParent);
242 } else {
243 throw new ProgressException("PleaseWaitDialog parent must be set");
244 }
245
246 if (windowTitle != null) {
247 dialog.setTitle(windowTitle);
248 }
249 dialog.setCancelEnabled(cancelable);
250 dialog.setCancelCallback(cancelListener);
251 dialog.setInBackgroundCallback(inBackgroundListener);
252 dialog.setCustomText("");
253 dialog.addWindowListener(windowListener);
254 dialog.setMaximumProgress(PROGRESS_BAR_MAX);
255 dialog.setVisible(true);
256 });
257 }
258
259 @Override
260 public void doFinishTask() {
261 // do nothing
262 }
263
264 @Override
265 protected void updateProgress(double progressValue) {
266 final int newValue = (int) (progressValue * PROGRESS_BAR_MAX);
267 if (newValue != currentProgressValue) {
268 currentProgressValue = newValue;
269 doInEDT(() -> {
270 ProgressMonitorDialog dlg = getDialog();
271 if (dlg != null) {
272 dlg.updateProgress(currentProgressValue);
273 }
274 });
275 }
276 }
277
278 @Override
279 protected void doSetCustomText(final String title) {
280 checkState(State.IN_TASK, State.IN_SUBTASK);
281 this.customText = title;
282 doInEDT(() -> {
283 ProgressMonitorDialog dlg = getDialog();
284 if (dlg != null) {
285 dlg.setCustomText(title);
286 }
287 });
288 }
289
290 @Override
291 protected void doSetTitle(final String title) {
292 checkState(State.IN_TASK, State.IN_SUBTASK);
293 this.title = title;
294 doInEDT(() -> {
295 ProgressMonitorDialog dlg = getDialog();
296 if (dlg != null) {
297 dlg.setCurrentAction(title);
298 }
299 });
300 }
301
302 @Override
303 protected void doSetIntermediate(final boolean value) {
304 this.indeterminate = value;
305 doInEDT(() -> {
306 // Enable only if progress is at the beginning. Doing intermediate progress in the middle
307 // will hide already reached progress
308 ProgressMonitorDialog dlg = getDialog();
309 if (dlg != null) {
310 dlg.setIndeterminate(value && currentProgressValue == 0);
311 }
312 });
313 }
314
315 @Override
316 public void appendLogMessage(final String message) {
317 doInEDT(() -> {
318 ProgressMonitorDialog dlg = getDialog();
319 if (dlg != null) {
320 dlg.appendLogMessage(message);
321 }
322 });
323 }
324
325 /**
326 * Update the dialog values
327 */
328 public void reset() {
329 if (dialog != null) {
330 dialog.setTitle(title);
331 dialog.setCustomText(customText);
332 dialog.updateProgress(currentProgressValue);
333 dialog.setIndeterminate(indeterminate && currentProgressValue == 0);
334 }
335 BackgroundProgressMonitor backgroundMonitor = null;
336 MapFrame map = MainApplication.getMap();
337 if (map != null) {
338 backgroundMonitor = map.statusLine.progressMonitor;
339 }
340 if (backgroundMonitor != null) {
341 backgroundMonitor.setCurrentAction(title);
342 backgroundMonitor.setCustomText(customText);
343 backgroundMonitor.updateProgress(currentProgressValue);
344 backgroundMonitor.setIndeterminate(indeterminate && currentProgressValue == 0);
345 }
346 }
347
348 /**
349 * Close the progress dialog window.
350 */
351 public void close() {
352 doInEDT(() -> {
353 if (dialog != null) {
354 dialog.setVisible(false);
355 dialog.setCancelCallback(null);
356 dialog.setInBackgroundCallback(null);
357 dialog.removeWindowListener(windowListener);
358 dialog.dispose();
359 dialog = null;
360 currentProgressMonitor = null;
361 MapFrame map = MainApplication.getMap();
362 if (map != null) {
363 map.statusLine.progressMonitor.setVisible(false);
364 }
365 }
366 });
367 }
368
369 /**
370 * Show the progress dialog in foreground
371 */
372 public void showForegroundDialog() {
373 isInBackground = false;
374 doInEDT(() -> {
375 if (dialog != null) {
376 dialog.setInBackgroundPossible(taskId != null && MainApplication.isDisplayingMapView());
377 reset();
378 getDialog();
379 }
380 });
381 }
382
383 @Override
384 public void setProgressTaskId(ProgressTaskId taskId) {
385 this.taskId = taskId;
386 doInEDT(() -> {
387 if (dialog != null) {
388 dialog.setInBackgroundPossible(taskId != null && MainApplication.isDisplayingMapView());
389 }
390 });
391 }
392
393 @Override
394 public ProgressTaskId getProgressTaskId() {
395 return taskId;
396 }
397
398 @Override
399 public Component getWindowParent() {
400 Component parent = dialog;
401 if (isInBackground || parent == null)
402 return MainApplication.getMainFrame();
403 else
404 return parent;
405 }
406
407 @Override
408 public String toString() {
409 return "PleaseWaitProgressMonitor [currentProgressValue=" + currentProgressValue + ", customText=" + customText
410 + ", title=" + title + ", indeterminate=" + indeterminate + ", isInBackground=" + isInBackground
411 + ", windowTitle=" + windowTitle + ", taskId=" + taskId + ", cancelable=" + cancelable + ", state="
412 + state + "]";
413 }
414}
Note: See TracBrowser for help on using the repository browser.