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

Last change on this file since 1750 was 1733, checked in by stoecker, 15 years ago

fixed #2821, #2775 - agpifojpicture position wrong, preferences callable twice

  • Property svn:eol-style set to native
File size: 6.5 KB
Line 
1// License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.gui;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.EventQueue;
7import java.awt.event.ActionEvent;
8import java.awt.event.ActionListener;
9import java.awt.event.WindowAdapter;
10import java.awt.event.WindowEvent;
11import java.awt.event.WindowListener;
12import java.io.FileNotFoundException;
13import java.io.IOException;
14import java.lang.reflect.InvocationTargetException;
15
16import javax.swing.JOptionPane;
17import javax.swing.SwingUtilities;
18
19import org.openstreetmap.josm.Main;
20import org.openstreetmap.josm.io.OsmTransferException;
21import org.xml.sax.SAXException;
22
23/**
24 * Instanced of this thread will display a "Please Wait" message in middle of JOSM
25 * to indicate a progress being executed.
26 *
27 * @author Imi
28 */
29public abstract class PleaseWaitRunnable implements Runnable {
30 public boolean silent = false;
31 public String errorMessage;
32
33 private boolean closeDialogCalled = false;
34 private boolean cancelled = false;
35 private boolean ignoreException;
36
37 private final String title;
38
39 private ActionListener cancelListener = new ActionListener(){
40 public void actionPerformed(ActionEvent e) {
41 if (!cancelled) {
42 cancelled = true;
43 cancel();
44 }
45 }
46 };
47
48 private WindowListener windowListener = new WindowAdapter(){
49 @Override public void windowClosing(WindowEvent e) {
50 if (!closeDialogCalled) {
51 if (!cancelled) {
52 cancelled = true;
53 cancel();
54 }
55 closeDialog();
56 }
57 }
58 };
59
60 /**
61 * Create the runnable object with a given message for the user.
62 */
63 public PleaseWaitRunnable(String title) {
64 this(title, false);
65 }
66
67 /**
68 * Create the runnable object with a given message for the user.
69 * @param title Message for user
70 * @param ignoreException If true, exception will be propaged to calling code. If false then
71 * exception will be thrown directly in EDT. When this runnable is executed using executor framework
72 * then use false unless you read result of task (because exception will get lost if you don't)
73 */
74 public PleaseWaitRunnable(String title, boolean ignoreException) {
75 this.title = title;
76 this.ignoreException = ignoreException;
77 }
78
79 private void prepareDialog() {
80 // reset dialog state
81 errorMessage = null;
82 closeDialogCalled = false;
83
84 Main.pleaseWaitDlg.setTitle(title);
85 Main.pleaseWaitDlg.cancel.setEnabled(true);
86 Main.pleaseWaitDlg.setCustomText("");
87 Main.pleaseWaitDlg.cancel.addActionListener(cancelListener);
88 Main.pleaseWaitDlg.addWindowListener(windowListener);
89 Main.pleaseWaitDlg.setVisible(true);
90 }
91
92 private void doRealRun() {
93 try {
94 try {
95 realRun();
96 } catch (SAXException x) {
97 x.printStackTrace();
98 errorMessage = tr("Error while parsing")+": "+x.getMessage();
99 } catch (FileNotFoundException x) {
100 x.printStackTrace();
101 errorMessage = tr("File not found")+": "+x.getMessage();
102 } catch (IOException x) {
103 x.printStackTrace();
104 errorMessage = x.getMessage();
105 } catch(OsmTransferException x) {
106 x.printStackTrace();
107 if (x.getCause() != null) {
108 errorMessage = x.getCause().getMessage();
109 } else {
110 errorMessage = x.getMessage();
111 }
112 } finally {
113 closeDialog();
114 }
115 } catch (final Throwable e) {
116 if (!ignoreException) {
117 // Exception has to thrown in EDT to be shown to user
118 SwingUtilities.invokeLater(new Runnable() {
119 public void run() {
120 throw new RuntimeException(e);
121 }
122 });
123 }
124 }
125 }
126
127 public final void run() {
128 if (cancelled)
129 return; // since realRun isn't executed, do not call to finish
130
131 if (EventQueue.isDispatchThread()) {
132 new Thread(new Runnable() {
133 public void run() {
134 doRealRun();
135 }
136 }).start();
137 prepareDialog();
138 } else {
139 EventQueue.invokeLater(new Runnable() {
140 public void run() {
141 prepareDialog();
142 }
143 });
144 doRealRun();
145 }
146 }
147
148 /**
149 * User pressed cancel button.
150 */
151 protected abstract void cancel();
152
153 /**
154 * Called in the worker thread to do the actual work. When any of the
155 * exception is thrown, a message box will be displayed and closeDialog
156 * is called. finish() is called in any case.
157 */
158 protected abstract void realRun() throws SAXException, IOException, OsmTransferException;
159
160 /**
161 * Finish up the data work. Is guaranteed to be called if realRun is called.
162 * Finish is called in the gui thread just after the dialog disappeared.
163 */
164 protected abstract void finish();
165
166 /**
167 * Close the dialog. Usually called from worker thread.
168 */
169 public void closeDialog() {
170 if (closeDialogCalled)
171 return;
172 closeDialogCalled = true;
173 try {
174 Runnable runnable = new Runnable(){
175 public void run() {
176 try {
177 finish();
178 } finally {
179 Main.pleaseWaitDlg.setVisible(false);
180 Main.pleaseWaitDlg.dispose();
181 Main.pleaseWaitDlg.removeWindowListener(windowListener);
182 Main.pleaseWaitDlg.cancel.removeActionListener(cancelListener);
183 }
184 if (errorMessage != null && !silent) {
185 JOptionPane.showMessageDialog(Main.parent, errorMessage);
186 }
187 }
188 };
189
190 // make sure, this is called in the dispatcher thread ASAP
191 if (EventQueue.isDispatchThread()) {
192 runnable.run();
193 } else {
194 EventQueue.invokeAndWait(runnable);
195 }
196
197 } catch (InterruptedException e) {
198 } catch (InvocationTargetException e) {
199 throw new RuntimeException(e);
200 }
201 }
202}
Note: See TracBrowser for help on using the repository browser.