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
RevLine 
[1811]1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.progress;
3
[2687]4import java.awt.Component;
[1811]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;
[4758]15import javax.swing.SwingUtilities;
[1811]16
17import org.openstreetmap.josm.Main;
[4718]18import org.openstreetmap.josm.gui.MapFrame;
19import org.openstreetmap.josm.gui.MapStatus.BackgroundProgressMonitor;
[1811]20import org.openstreetmap.josm.gui.PleaseWaitDialog;
21
22public class PleaseWaitProgressMonitor extends AbstractProgressMonitor {
23
[4739]24 /**
25 * Implemented by both foreground dialog and background progress dialog (in status bar)
26 */
[4718]27 public interface ProgressMonitorDialog {
28 void setVisible(boolean visible);
29 void updateProgress(int progress);
30 void setCustomText(String text);
[4739]31 void setCurrentAction(String text);
[4718]32 void setIndeterminate(boolean newValue);
[4739]33 void appendLogMessage(String message); //TODO Not implemented properly in background monitor, log message will get lost if progress runs in background
[4718]34 }
35
[5534]36 public static final int PROGRESS_BAR_MAX = 10000;
[1811]37 private final Window dialogParent;
[4739]38
[1863]39 private int currentProgressValue = 0;
[4739]40 private String customText;
41 private String title;
42 private boolean indeterminate;
[1811]43
[4718]44 private boolean isInBackground;
[1811]45 private PleaseWaitDialog dialog;
[2025]46 private String windowTitle;
[4718]47 protected ProgressTaskId taskId;
48
[4684]49 private boolean cancelable;
[1811]50
[4758]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
[4754]57 private void setDialogVisible(boolean visible) {
58 if (dialog.isVisible() != visible) {
59 dialog.setVisible(visible);
60 }
61 }
62
[4718]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) {
[4754]75 setDialogVisible(!isInBackground || backgroundMonitor == null);
[4718]76 }
77
78 if (isInBackground && backgroundMonitor != null) {
79 backgroundMonitor.setVisible(true);
80 if (dialog != null) {
[4754]81 setDialogVisible(false);
[4718]82 }
83 return backgroundMonitor;
84 } else if (backgroundMonitor != null) {
85 backgroundMonitor.setVisible(false);
86 if (dialog != null) {
[4754]87 setDialogVisible(true);
[4718]88 }
89 return dialog;
90 } else if (dialog != null) {
[4754]91 setDialogVisible(true);
[4718]92 return dialog;
93 } else
94 return null;
95 }
96
[2057]97 public PleaseWaitProgressMonitor() {
98 this("");
99 }
100
[2025]101 public PleaseWaitProgressMonitor(String windowTitle) {
[2687]102 this(Main.parent);
[2025]103 this.windowTitle = windowTitle;
[1811]104 }
105
[2687]106 public PleaseWaitProgressMonitor(Component dialogParent) {
[1811]107 super(new CancelHandler());
[2687]108 this.dialogParent = JOptionPane.getFrameForComponent(dialogParent);
[4684]109 this.cancelable = true;
[1811]110 }
111
[2687]112 public PleaseWaitProgressMonitor(Component dialogParent, String windowTitle) {
113 this(JOptionPane.getFrameForComponent(dialogParent));
114 this.windowTitle = windowTitle;
115 }
116
[1811]117 private ActionListener cancelListener = new ActionListener(){
118 public void actionPerformed(ActionEvent e) {
119 cancel();
120 }
121 };
122
[4718]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) {
[4739]129 reset();
[4718]130 dialog.setVisible(true);
131 }
132 }
133 };
134
[1811]135 private WindowListener windowListener = new WindowAdapter(){
136 @Override public void windowClosing(WindowEvent e) {
137 cancel();
138 }
139 };
140
[4684]141 public final boolean isCancelable() {
142 return cancelable;
143 }
144
145 public final void setCancelable(boolean cancelable) {
146 this.cancelable = cancelable;
147 }
148
[1865]149 @Override
[1811]150 public void doBeginTask() {
151 doInEDT(new Runnable() {
152 public void run() {
[4718]153 Main.currentProgressMonitor = PleaseWaitProgressMonitor.this;
[2319]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);
[1865]158 } else
[1811]159 throw new ProgressException("PleaseWaitDialog parent must be either Frame or Dialog");
160
[2025]161 if (windowTitle != null) {
162 dialog.setTitle(windowTitle);
163 }
[4684]164 dialog.setCancelEnabled(cancelable);
[2319]165 dialog.setCancelCallback(cancelListener);
[4718]166 dialog.setInBackgroundCallback(inBackgroundListener);
[1811]167 dialog.setCustomText("");
168 dialog.addWindowListener(windowListener);
169 dialog.progress.setMaximum(PROGRESS_BAR_MAX);
170 dialog.setVisible(true);
171 }
172 });
173 }
174
[1865]175 @Override
[1811]176 public void doFinishTask() {
[2319]177 // do nothing
[1811]178 }
179
[1865]180 @Override
[1863]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() {
[4718]187 ProgressMonitorDialog dialog = getDialog();
188 if (dialog != null) {
189 dialog.updateProgress(currentProgressValue);
190 }
[1863]191 }
192 });
193 }
[1811]194 }
195
196 @Override
197 protected void doSetCustomText(final String title) {
198 checkState(State.IN_TASK, State.IN_SUBTASK);
[4739]199 this.customText = title;
[1811]200 doInEDT(new Runnable() {
201 public void run() {
[4718]202 ProgressMonitorDialog dialog = getDialog();
203 if (dialog != null) {
204 dialog.setCustomText(title);
205 }
[1811]206 }
207 });
208 }
209
210 @Override
211 protected void doSetTitle(final String title) {
212 checkState(State.IN_TASK, State.IN_SUBTASK);
[4739]213 this.title = title;
[1811]214 doInEDT(new Runnable() {
215 public void run() {
[4718]216 ProgressMonitorDialog dialog = getDialog();
217 if (dialog != null) {
[4739]218 dialog.setCurrentAction(title);
[4718]219 }
[1811]220 }
221 });
222 }
223
224 @Override
225 protected void doSetIntermediate(final boolean value) {
[4739]226 this.indeterminate = value;
[1811]227 doInEDT(new Runnable() {
228 public void run() {
[4718]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) {
[4739]233 dialog.setIndeterminate(value && currentProgressValue == 0);
[1811]234 }
235 }
236 });
237 }
238
239 @Override
[2319]240 public void appendLogMessage(final String message) {
241 doInEDT(new Runnable() {
242 public void run() {
[4718]243 ProgressMonitorDialog dialog = getDialog();
244 if (dialog != null) {
245 dialog.appendLogMessage(message);
246 }
[2319]247 }
248 });
249 }
250
[4739]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
[2319]272 public void close() {
[4718]273 doInEDT(new Runnable() {
274 @Override
275 public void run() {
[4761]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 }
[4718]288 }
289 }
290 });
[2319]291 }
[4718]292
293 public void showForegroundDialog() {
294 isInBackground = false;
295 doInEDT(new Runnable() {
296 @Override
297 public void run() {
[4756]298 if (dialog != null) {
299 dialog.setInBackgroundPossible(PleaseWaitProgressMonitor.this.taskId != null && Main.isDisplayingMapView());
300 reset();
301 getDialog();
302 }
[4718]303 }
304 });
305
[3752]306 }
[4718]307
308 @Override
309 public void setProgressTaskId(ProgressTaskId taskId) {
310 this.taskId = taskId;
311 doInEDT(new Runnable() {
312 @Override
313 public void run() {
[5826]314 if (dialog != null) {
315 dialog.setInBackgroundPossible(PleaseWaitProgressMonitor.this.taskId != null && Main.isDisplayingMapView());
316 }
[4718]317 }
318 });
319 }
320
321 @Override
322 public ProgressTaskId getProgressTaskId() {
323 return taskId;
324 }
325
[4762]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 }
[1811]335}
Note: See TracBrowser for help on using the repository browser.