Lines 44-274
Link Here
|
44 |
package org.netbeans.modules.cnd.utils.ui; |
44 |
package org.netbeans.modules.cnd.utils.ui; |
45 |
|
45 |
|
46 |
import java.awt.Dialog; |
46 |
import java.awt.Dialog; |
47 |
import java.awt.Dimension; |
|
|
48 |
import java.awt.Frame; |
47 |
import java.awt.Frame; |
49 |
import java.awt.Rectangle; |
|
|
50 |
import java.awt.Toolkit; |
51 |
import java.awt.Window; |
48 |
import java.awt.Window; |
52 |
import java.awt.event.WindowAdapter; |
49 |
import java.util.concurrent.ExecutionException; |
53 |
import java.awt.event.WindowEvent; |
50 |
import java.util.concurrent.Future; |
54 |
import java.util.concurrent.atomic.AtomicBoolean; |
51 |
import java.util.concurrent.atomic.AtomicBoolean; |
55 |
import javax.swing.JDialog; |
|
|
56 |
import javax.swing.JPanel; |
57 |
import javax.swing.SwingUtilities; |
52 |
import javax.swing.SwingUtilities; |
|
|
53 |
import org.netbeans.api.progress.ProgressHandle; |
54 |
import org.netbeans.api.progress.ProgressRunnable; |
55 |
import org.netbeans.api.progress.ProgressUtils; |
58 |
import org.netbeans.modules.cnd.utils.CndUtils; |
56 |
import org.netbeans.modules.cnd.utils.CndUtils; |
59 |
import org.netbeans.modules.cnd.utils.NamedRunnable; |
57 |
import org.netbeans.modules.cnd.utils.NamedRunnable; |
60 |
import org.openide.util.Cancellable; |
58 |
import org.openide.util.Cancellable; |
|
|
59 |
import org.openide.util.Exceptions; |
61 |
import org.openide.util.RequestProcessor; |
60 |
import org.openide.util.RequestProcessor; |
62 |
import org.openide.util.RequestProcessor.Task; |
|
|
63 |
|
61 |
|
64 |
/** |
62 |
/** |
|
|
63 |
* Utility class for displaying a modal Dialog (effectively blocking (but not |
64 |
* freezing) UI) while running a task in background. |
65 |
* |
66 |
* Current implementation uses org.netbeans.api.progress.ProgressUtils. |
67 |
* |
68 |
* @Deprecated - Use org.netbeans.api.progress.ProgressUtils. |
65 |
* |
69 |
* |
66 |
* @author Vladimir Voskresensky |
70 |
* @author Vladimir Voskresensky |
67 |
*/ |
71 |
*/ |
68 |
public class ModalMessageDlg extends javax.swing.JPanel { |
72 |
@Deprecated |
69 |
private static final RequestProcessor RP = new RequestProcessor(ModalMessageDlg.class.getName(), 4); |
73 |
public final class ModalMessageDlg { |
70 |
|
74 |
|
71 |
/** |
75 |
public interface LongWorker { |
72 |
* allows to display modal dialog with title and message for the period of |
76 |
|
73 |
* long task run |
77 |
void doWork(); |
74 |
* @param parent parent frame or dialog |
78 |
|
75 |
* @param workTask non EDT task to run |
79 |
void doPostRunInEDT(); |
76 |
* @param postEDTTask EDT task to run after closing modal dialog (can be null) |
|
|
77 |
* @param title title of dialog |
78 |
* @param message message in dialog |
79 |
* @return |
80 |
*/ |
81 |
public static void runLongTask(Dialog parent, |
82 |
final Runnable workTask, final Runnable postEDTTask, final Cancellable canceller, |
83 |
String title, String message) { |
84 |
runLongTaskImpl(parent, workTask, postEDTTask, title, message, canceller); |
85 |
} |
80 |
} |
86 |
|
81 |
|
87 |
public static void runLongTask(Frame parent, |
82 |
private ModalMessageDlg() { |
88 |
final Runnable workTask, final Runnable postEDTTask, final Cancellable canceller, |
|
|
89 |
String title, String message) { |
90 |
runLongTaskImpl(parent, workTask, postEDTTask, title, message, canceller); |
91 |
} |
83 |
} |
92 |
|
84 |
|
93 |
/** |
85 |
/** |
|
|
86 |
* Show a modal progress dialog that blocks the main window, while running |
87 |
* the passed runnable on a background thread. |
94 |
* |
88 |
* |
95 |
* @param parent |
89 |
* <p> This method is thread-safe, and will block until the operation has |
96 |
* @param title |
90 |
* completed, regardless of what thread calls this method. </p> |
97 |
* @param message |
91 |
* |
98 |
* @param workTask if workTask is Cancellable => dialog will have Cancel button |
92 |
* @param parent <b>Not used</b> |
99 |
* if not => no Cancel button is shown |
93 |
* @param workTask a Runnable to start in non-EDT thread. Unlike |
|
|
94 |
* {@link ProgressUtils}'s operation this argument is never tested for the |
95 |
* {@link Cancellable} interface. Use <b>canceller</b> for the task |
96 |
* interruption facility. |
97 |
* @param postEDTTask a task to run in the EDT after the <b>workTask</b> is |
98 |
* processed. <code>null</code> is allowed. <b>NB:</b> The postEDTTask is |
99 |
* called either if this method is invoked from tests or if <b>workTask</b> |
100 |
* was <b>not cancelled</b> by pressing the cancel button. |
101 |
* @param canceller if not <code>null</code> a cancel button is displayed |
102 |
* while <b>workTask</b> is running. <br/> Note that once the cancel button |
103 |
* is pressed, no <b>postEDTTask</b> will be called. |
104 |
* @param title title of a dialog. If <b>message</b> is not null, |
105 |
* <b>title</b> is <b>not used</b>. |
106 |
* @param message message to display. Could be <code>null</code>. In this |
107 |
* case <b>title</b> is used. |
108 |
* |
100 |
*/ |
109 |
*/ |
101 |
public static void runLongTask(Window parent, String title, String message, |
110 |
public static void runLongTask(Dialog parent, final Runnable workTask, |
|
|
111 |
final Runnable postEDTTask, final Cancellable canceller, |
112 |
String title, String message) { |
113 |
run(workTask, postEDTTask, canceller, title, message); |
114 |
} |
115 |
|
116 |
/** |
117 |
* Show a modal progress dialog that blocks the main window, while running |
118 |
* the passed runnable on a background thread. |
119 |
* |
120 |
* @see #runLongTask(Dialog, Runnable, Runnable, Cancellable, String, |
121 |
* String) |
122 |
*/ |
123 |
public static void runLongTask(final Frame parent, final Runnable workTask, |
124 |
final Runnable postEDTTask, final Cancellable canceller, |
125 |
String title, String message) { |
126 |
run(workTask, postEDTTask, canceller, title, message); |
127 |
} |
128 |
|
129 |
/** |
130 |
* Show a modal progress dialog that blocks the main window, while running |
131 |
* the passed runnable on a background thread. |
132 |
* |
133 |
* <p> This is almost the same as runLongTask(Dialog, Runnable, Runnable, |
134 |
* Cancellable, String, String), but has one significant difference! </p> |
135 |
* |
136 |
* <p>Not only it uses a {@link LongWorker} instead of two |
137 |
* {@link Runnable}s, but also the {@link LongWorker#doPostRunInEDT()} is |
138 |
* invoked disregarding the cancellation status.</p> |
139 |
* |
140 |
* @see #runLongTask(Dialog, Runnable, Runnable, Cancellable, String, |
141 |
* String) |
142 |
*/ |
143 |
public static void runLongTask(final Window parent, final String title, final String message, |
102 |
final LongWorker workTask, final Cancellable canceller) { |
144 |
final LongWorker workTask, final Cancellable canceller) { |
103 |
|
145 |
|
104 |
final JDialog dialog = createDialog(parent, title); |
146 |
run(new Runnable() { |
105 |
|
|
|
106 |
final Runnable finalizer = new Runnable() { |
107 |
@Override |
147 |
@Override |
108 |
public void run() { |
148 |
public void run() { |
109 |
// hide dialog and run action if successfully connected |
149 |
workTask.doWork(); |
110 |
dialog.setVisible(false); |
150 |
} |
111 |
dialog.dispose(); |
151 |
}, null, canceller, title, message); |
|
|
152 |
|
153 |
SwingUtilities.invokeLater(new Runnable() { |
154 |
@Override |
155 |
public void run() { |
112 |
workTask.doPostRunInEDT(); |
156 |
workTask.doPostRunInEDT(); |
113 |
} |
157 |
} |
114 |
}; |
158 |
}); |
|
|
159 |
} |
115 |
|
160 |
|
116 |
JPanel panel; |
161 |
private static void run(final Runnable workTask, final Runnable postEDTTask, |
117 |
if (canceller == null) { |
162 |
final Cancellable canceller, final String title, String message) { |
118 |
panel = new ModalMessageDlgPane(message); |
163 |
|
|
|
164 |
if (invokedFromTests()) { |
165 |
// The code below is just to preserve the behaviour as it was |
166 |
// before switchig to the ProgressUtils... |
167 |
Future<?> task = RequestProcessor.getDefault().submit(new NamedRunnable(title) { |
168 |
@Override |
169 |
protected void runImpl() { |
170 |
workTask.run(); |
171 |
} |
172 |
}); |
173 |
try { |
174 |
task.get(); |
175 |
} catch (InterruptedException ex) { |
176 |
Exceptions.printStackTrace(ex); |
177 |
} catch (ExecutionException ex) { |
178 |
Exceptions.printStackTrace(ex); |
179 |
} |
180 |
if (postEDTTask != null) { |
181 |
SwingUtilities.invokeLater(postEDTTask); |
182 |
} |
119 |
} else { |
183 |
} else { |
120 |
Cancellable wrapper = new Cancellable() { |
184 |
final MyRP r; |
121 |
/** is invoked from a separate cancellation thread */ |
|
|
122 |
@Override |
123 |
public boolean cancel() { |
124 |
if (canceller.cancel()) { |
125 |
// remember for return value |
126 |
return true; |
127 |
} else { |
128 |
return false; |
129 |
} |
130 |
} |
131 |
}; |
132 |
panel = new ModalMessageDlgCancellablePane(message, wrapper); |
133 |
} |
134 |
addPanel(parent, dialog, panel); |
135 |
|
185 |
|
136 |
RP.post(new NamedRunnable(title) { |
186 |
if (canceller != null) { |
137 |
@Override |
187 |
r = new MyCRP(workTask, canceller, message); |
138 |
public void runImpl() { |
188 |
} else { |
139 |
try { |
189 |
r = new MyRP(workTask, message); |
140 |
workTask.doWork(); |
|
|
141 |
} finally { |
142 |
SwingUtilities.invokeLater(finalizer); |
143 |
} |
144 |
} |
190 |
} |
145 |
}); |
191 |
|
146 |
if (!CndUtils.isStandalone()) { // this means we run in tests |
192 |
ProgressUtils.showProgressDialogAndRun(r, title, true); |
147 |
dialog.setVisible(true); |
193 |
|
|
|
194 |
if (postEDTTask != null && !r.wasCancelled()) { |
195 |
SwingUtilities.invokeLater(workTask); |
196 |
} |
148 |
} |
197 |
} |
149 |
} |
198 |
} |
150 |
|
199 |
|
151 |
private static boolean runLongTaskImpl(Window parent, final Runnable workTask, final Runnable postEDTTask, |
200 |
private static boolean invokedFromTests() { |
152 |
final String title, String message, final Cancellable canceller) { |
201 |
return CndUtils.isStandalone(); |
153 |
|
|
|
154 |
final JDialog dialog = createDialog(parent, title); |
155 |
final AtomicBoolean cancelled = new AtomicBoolean(false); |
156 |
|
157 |
final Runnable finalizer = new Runnable() { |
158 |
@Override |
159 |
public void run() { |
160 |
// hide dialog and run action if successfully connected |
161 |
dialog.setVisible(false); |
162 |
dialog.dispose(); |
163 |
if (postEDTTask != null && ! cancelled.get()) { |
164 |
postEDTTask.run(); |
165 |
} |
166 |
} |
167 |
}; |
168 |
|
169 |
JPanel panel; |
170 |
if (canceller == null) { |
171 |
panel = new ModalMessageDlgPane(message); |
172 |
} else { |
173 |
Cancellable wrapper = new Cancellable() { |
174 |
/** is invoked from a separate cancellation thread */ |
175 |
@Override |
176 |
public boolean cancel() { |
177 |
if (canceller.cancel()) { |
178 |
cancelled.set(true); |
179 |
SwingUtilities.invokeLater(finalizer); |
180 |
return true; |
181 |
} else { |
182 |
return false; |
183 |
} |
184 |
} |
185 |
}; |
186 |
panel = new ModalMessageDlgCancellablePane(message, wrapper); |
187 |
} |
188 |
addPanel(parent, dialog, panel); |
189 |
|
190 |
final WindowAdapterImpl windowAdapterImpl = new WindowAdapterImpl(dialog, title, workTask, finalizer); |
191 |
|
192 |
if (CndUtils.isStandalone()) { // this means we run in tests |
193 |
Task task = windowAdapterImpl.submitJob(); |
194 |
task.waitFinished(); |
195 |
} else { |
196 |
dialog.addWindowListener(windowAdapterImpl); |
197 |
dialog.setVisible(true); |
198 |
} |
199 |
|
200 |
return !cancelled.get(); |
201 |
} |
202 |
} |
202 |
|
203 |
|
203 |
private static JDialog createDialog(Window parent, String title) { |
204 |
private static class MyRP implements ProgressRunnable<Void> { |
204 |
JDialog dialog; |
|
|
205 |
if (parent == null) { |
206 |
dialog = new JDialog(); |
207 |
} else if (parent instanceof Frame) { |
208 |
dialog = new JDialog((Frame)parent); |
209 |
} else { |
210 |
assert (parent instanceof Dialog); |
211 |
dialog = new JDialog((Dialog)parent); |
212 |
} |
213 |
dialog.setTitle(title); |
214 |
dialog.setModal(true); |
215 |
return dialog; |
216 |
} |
217 |
|
205 |
|
218 |
private static void addPanel(Window parent, JDialog dialog, JPanel panel){ |
206 |
private final Runnable task; |
219 |
dialog.getContentPane().add(panel); |
207 |
private final String message; |
220 |
dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE); //make sure the dialog is not closed during the project open |
|
|
221 |
dialog.pack(); |
222 |
|
208 |
|
223 |
Rectangle bounds = (parent == null) ? |
209 |
public MyRP(final Runnable task, final String message) { |
224 |
new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()) : parent.getBounds(); |
210 |
this.task = task; |
225 |
|
211 |
this.message = message; |
226 |
int middleX = bounds.x + bounds.width / 2; |
|
|
227 |
int middleY = bounds.y + bounds.height / 2; |
228 |
|
229 |
Dimension size = dialog.getPreferredSize(); |
230 |
|
231 |
dialog.setBounds(middleX - size.width / 2, middleY - size.height / 2, size.width, size.height); |
232 |
} |
233 |
|
234 |
public interface LongWorker { |
235 |
void doWork(); |
236 |
void doPostRunInEDT(); |
237 |
} |
238 |
|
239 |
private static class WindowAdapterImpl extends WindowAdapter { |
240 |
|
241 |
private final String title; |
242 |
private final Runnable workTask; |
243 |
private final Runnable finalizer; |
244 |
private final JDialog dialog; |
245 |
|
246 |
public WindowAdapterImpl(JDialog dialog, String title, Runnable workTask, Runnable finalizer) { |
247 |
this.title = title; |
248 |
this.workTask = workTask; |
249 |
this.finalizer = finalizer; |
250 |
this.dialog = dialog; |
251 |
} |
212 |
} |
252 |
|
213 |
|
253 |
@Override |
214 |
@Override |
254 |
public void windowOpened(WindowEvent e) { |
215 |
public Void run(final ProgressHandle handle) { |
255 |
dialog.removeWindowListener(this); |
216 |
if (message != null) { |
256 |
submitJob(); |
217 |
handle.setDisplayName(message); |
|
|
218 |
} |
219 |
task.run(); |
220 |
return null; |
257 |
} |
221 |
} |
258 |
|
222 |
|
259 |
private Task submitJob() { |
223 |
public boolean wasCancelled() { |
260 |
Task task = RP.post(new NamedRunnable(title) { |
224 |
return false; |
|
|
225 |
} |
226 |
} |
261 |
|
227 |
|
262 |
@Override |
228 |
private static class MyCRP extends MyRP implements Cancellable { |
263 |
public void runImpl() { |
229 |
|
264 |
try { |
230 |
private final Cancellable canceller; |
265 |
workTask.run(); |
231 |
private final AtomicBoolean wasCancelled = new AtomicBoolean(false); |
266 |
} finally { |
232 |
|
267 |
SwingUtilities.invokeLater(finalizer); |
233 |
public MyCRP(final Runnable task, final Cancellable canceller, final String message) { |
268 |
} |
234 |
super(task, message); |
269 |
} |
235 |
this.canceller = canceller; |
270 |
}); |
236 |
} |
271 |
return task; |
237 |
|
|
|
238 |
@Override |
239 |
public boolean cancel() { |
240 |
wasCancelled.set(true); |
241 |
return canceller.cancel(); |
242 |
} |
243 |
|
244 |
@Override |
245 |
public boolean wasCancelled() { |
246 |
return wasCancelled.get(); |
272 |
} |
247 |
} |
273 |
} |
248 |
} |
274 |
} |
249 |
} |