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

Revision 4907, 6.7 KB checked in by jttt, 3 months ago (diff)

access gui in edt

  • Property svn:eol-style set to native
Line 
1// License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.gui;
3
4import java.awt.Component;
5import java.awt.EventQueue;
6import java.io.IOException;
7
8import javax.swing.SwingUtilities;
9
10import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor;
11import org.openstreetmap.josm.gui.progress.ProgressMonitor;
12import org.openstreetmap.josm.gui.progress.ProgressMonitor.CancelListener;
13import org.openstreetmap.josm.gui.progress.ProgressTaskId;
14import org.openstreetmap.josm.io.OsmTransferException;
15import org.openstreetmap.josm.tools.BugReportExceptionHandler;
16import org.openstreetmap.josm.tools.CheckParameterUtil;
17import org.xml.sax.SAXException;
18
19/**
20 * Instanced of this thread will display a "Please Wait" message in middle of JOSM
21 * to indicate a progress being executed.
22 *
23 * @author Imi
24 */
25public abstract class PleaseWaitRunnable implements Runnable, CancelListener {
26    private boolean canceled = false;
27    private boolean ignoreException;
28    private final String title;
29
30    protected final ProgressMonitor progressMonitor;
31
32    /**
33     * Create the runnable object with a given message for the user.
34     */
35    public PleaseWaitRunnable(String title) {
36        this(title, false);
37    }
38    /**
39     * Create the runnable object with a given message for the user.
40     *
41     * @param title message for the user
42     * @param ignoreException If true, exception will be propagated to calling code. If false then
43     * exception will be thrown directly in EDT. When this runnable is executed using executor framework
44     * then use false unless you read result of task (because exception will get lost if you don't)
45     */
46    public PleaseWaitRunnable(String title, boolean ignoreException) {
47        this(title, new PleaseWaitProgressMonitor(title), ignoreException);
48    }
49
50    /**
51     * Create the runnable object with a given message for the user
52     *
53     * @param parent the parent component for the please wait dialog. Must not be null.
54     * @param title message for the user
55     * @param ignoreException If true, exception will be propagated to calling code. If false then
56     * exception will be thrown directly in EDT. When this runnable is executed using executor framework
57     * then use false unless you read result of task (because exception will get lost if you don't)
58     * @throws IllegalArgumentException thrown if parent is null
59     */
60    public PleaseWaitRunnable(Component parent, String title, boolean ignoreException) throws IllegalArgumentException{
61        CheckParameterUtil.ensureParameterNotNull(parent, "parent");
62        this.title = title;
63        this.progressMonitor = new PleaseWaitProgressMonitor(parent, title);
64        this.ignoreException = ignoreException;
65    }
66
67    public PleaseWaitRunnable(String title, ProgressMonitor progressMonitor, boolean ignoreException) {
68        this.title = title;
69        this.progressMonitor = progressMonitor == null?new PleaseWaitProgressMonitor(title):progressMonitor;
70        this.ignoreException = ignoreException;
71    }
72
73    private void doRealRun() {
74        try {
75            ProgressTaskId oldTaskId = null;
76            try {
77                progressMonitor.addCancelListener(this);
78                progressMonitor.beginTask(title);
79                oldTaskId = progressMonitor.getProgressTaskId();
80                progressMonitor.setProgressTaskId(canRunInBackground());
81                try {
82                    realRun();
83                } finally {
84                    if (EventQueue.isDispatchThread()) {
85                        finish();
86                    } else {
87                        EventQueue.invokeAndWait(new Runnable() {
88                            public void run() {
89                                finish();
90                            }
91                        });
92                    }
93                }
94            } finally {
95                progressMonitor.finishTask();
96                progressMonitor.removeCancelListener(this);
97                progressMonitor.setProgressTaskId(oldTaskId);
98                if (progressMonitor instanceof PleaseWaitProgressMonitor) {
99                    ((PleaseWaitProgressMonitor)progressMonitor).close();
100                }
101                if (EventQueue.isDispatchThread()) {
102                    afterFinish();
103                } else {
104                    EventQueue.invokeAndWait(new Runnable() {
105                        public void run() {
106                            afterFinish();
107                        }
108                    });
109                }
110            }
111        } catch (final Exception e) {
112            if (!ignoreException) {
113                // Exception has to thrown in EDT to be shown to user
114                SwingUtilities.invokeLater(new Runnable() {
115                    public void run() {
116                        if (e instanceof RuntimeException) {
117                            BugReportExceptionHandler.handleException(e);
118                        } else {
119                            ExceptionDialogUtil.explainException(e);
120                        }
121                    }
122                });
123            }
124        }
125    }
126
127    /**
128     * Can be overriden if something needs to run after progress monitor is closed.
129     */
130    protected void afterFinish() {
131
132    }
133
134    public final void run() {
135        if (canceled)
136            return; // since realRun isn't executed, do not call to finish
137
138        if (EventQueue.isDispatchThread()) {
139            new Thread(new Runnable() {
140                public void run() {
141                    doRealRun();
142                }
143            }).start();
144        } else {
145            doRealRun();
146        }
147    }
148
149    public void operationCanceled() {
150        cancel();
151    }
152
153    /**
154     * User pressed cancel button.
155     */
156    protected abstract void cancel();
157
158    /**
159     * Called in the worker thread to do the actual work. When any of the
160     * exception is thrown, a message box will be displayed and closeDialog
161     * is called. finish() is called in any case.
162     */
163    protected abstract void realRun() throws SAXException, IOException, OsmTransferException;
164
165    /**
166     * Finish up the data work. Is guaranteed to be called if realRun is called.
167     * Finish is called in the gui thread just after the dialog disappeared.
168     */
169    protected abstract void finish();
170
171    public ProgressMonitor getProgressMonitor() {
172        return progressMonitor;
173    }
174
175    /**
176     * Task can run in background if returned value <> null. Note that it's tasks responsibility
177     * to ensure proper synchronization, PleaseWaitRunnable doesn't with it.
178     * @return If returned value is <> null then task can run in background. TaskId could be used in future for "Always run in background" checkbox
179     */
180    public ProgressTaskId canRunInBackground() {
181        return null;
182    }
183}
Note: See TracBrowser for help on using the repository browser.