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

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

fix #8575 - NPE

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