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

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

see #11795 - fix HeadlessException with Jenkins

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