Lines 38-48
Link Here
|
38 |
*/ |
38 |
*/ |
39 |
package org.netbeans.modules.progress.ui; |
39 |
package org.netbeans.modules.progress.ui; |
40 |
|
40 |
|
|
|
41 |
import java.awt.BorderLayout; |
42 |
import java.awt.Color; |
41 |
import java.awt.Component; |
43 |
import java.awt.Component; |
42 |
import java.awt.Cursor; |
44 |
import java.awt.Cursor; |
43 |
import java.awt.Dialog; |
45 |
import java.awt.Dialog; |
|
|
46 |
import java.awt.Dimension; |
47 |
import java.awt.EventQueue; |
48 |
import java.awt.Font; |
49 |
import java.awt.Frame; |
50 |
import java.awt.Graphics; |
51 |
import java.awt.Graphics2D; |
52 |
import java.awt.GridLayout; |
53 |
import java.awt.RenderingHints; |
54 |
import java.awt.Toolkit; |
44 |
import java.awt.event.ActionEvent; |
55 |
import java.awt.event.ActionEvent; |
45 |
import java.awt.event.ActionListener; |
56 |
import java.awt.event.ActionListener; |
|
|
57 |
import java.awt.event.WindowAdapter; |
58 |
import java.awt.event.WindowEvent; |
46 |
import java.util.Map; |
59 |
import java.util.Map; |
47 |
import java.util.WeakHashMap; |
60 |
import java.util.WeakHashMap; |
48 |
import java.util.concurrent.CountDownLatch; |
61 |
import java.util.concurrent.CountDownLatch; |
Lines 51-74
Link Here
|
51 |
import java.util.concurrent.atomic.AtomicReference; |
64 |
import java.util.concurrent.atomic.AtomicReference; |
52 |
import java.util.logging.Level; |
65 |
import java.util.logging.Level; |
53 |
import java.util.logging.Logger; |
66 |
import java.util.logging.Logger; |
|
|
67 |
import javax.swing.BorderFactory; |
68 |
import javax.swing.JComponent; |
69 |
import javax.swing.JDialog; |
54 |
import javax.swing.JFrame; |
70 |
import javax.swing.JFrame; |
|
|
71 |
import javax.swing.JLabel; |
72 |
import javax.swing.JPanel; |
55 |
import javax.swing.SwingUtilities; |
73 |
import javax.swing.SwingUtilities; |
|
|
74 |
import javax.swing.WindowConstants; |
75 |
import org.netbeans.api.progress.ProgressRunnable; |
76 |
import org.netbeans.api.progress.ProgressHandle; |
77 |
import org.netbeans.api.progress.ProgressHandleFactory; |
56 |
import org.netbeans.api.progress.ProgressUtils; |
78 |
import org.netbeans.api.progress.ProgressUtils; |
57 |
import org.netbeans.modules.progress.spi.RunOffEDTProvider; |
79 |
import org.netbeans.modules.progress.spi.RunOffEDTProvider; |
|
|
80 |
import org.netbeans.modules.progress.spi.ProgressRunOffEdtProvider; |
58 |
import org.openide.DialogDescriptor; |
81 |
import org.openide.DialogDescriptor; |
59 |
import org.openide.DialogDisplayer; |
82 |
import org.openide.DialogDisplayer; |
60 |
import org.openide.NotifyDescriptor; |
83 |
import org.openide.NotifyDescriptor; |
|
|
84 |
import org.openide.util.Exceptions; |
61 |
import org.openide.util.NbBundle; |
85 |
import org.openide.util.NbBundle; |
62 |
import org.openide.util.Parameters; |
86 |
import org.openide.util.Parameters; |
63 |
import org.openide.util.RequestProcessor; |
87 |
import org.openide.util.RequestProcessor; |
|
|
88 |
import org.openide.util.Utilities; |
64 |
import org.openide.windows.WindowManager; |
89 |
import org.openide.windows.WindowManager; |
65 |
|
90 |
|
66 |
/** |
91 |
/** |
67 |
* Default RunOffEDTProvider implementation for ProgressUtils.runOffEventDispatchThread() methods |
92 |
* Default RunOffEDTProvider implementation for ProgressUtils.runOffEventDispatchThread() methods |
68 |
* @author Jan Lahoda, Tomas Holy |
93 |
* @author Jan Lahoda, Tomas Holy, Tim Boudreau |
69 |
*/ |
94 |
*/ |
70 |
@org.openide.util.lookup.ServiceProvider(service = org.netbeans.modules.progress.spi.RunOffEDTProvider.class, position = 100) |
95 |
@org.openide.util.lookup.ServiceProvider(service = org.netbeans.modules.progress.spi.RunOffEDTProvider.class, position = 100) |
71 |
public class RunOffEDTImpl implements RunOffEDTProvider { |
96 |
public class RunOffEDTImpl implements RunOffEDTProvider, ProgressRunOffEdtProvider { |
72 |
|
97 |
|
73 |
private static final RequestProcessor WORKER = new RequestProcessor(ProgressUtils.class.getName()); |
98 |
private static final RequestProcessor WORKER = new RequestProcessor(ProgressUtils.class.getName()); |
74 |
private static final Map<Class<? extends Runnable>, Integer> OPERATIONS = new WeakHashMap<Class<? extends Runnable>, Integer>(); |
99 |
private static final Map<Class<? extends Runnable>, Integer> OPERATIONS = new WeakHashMap<Class<? extends Runnable>, Integer>(); |
Lines 190-193
Link Here
|
190 |
glassPane.setCursor(original); |
215 |
glassPane.setCursor(original); |
191 |
} |
216 |
} |
192 |
} |
217 |
} |
|
|
218 |
|
219 |
@Override |
220 |
public void showProgressDialogAndRun(Runnable operation, ProgressHandle handle, boolean includeDetailLabel) { |
221 |
AbstractWindowRunner wr = new RunnableWindowRunner(operation, handle, includeDetailLabel); |
222 |
wr.start(); |
223 |
if (!EventQueue.isDispatchThread()) { |
224 |
try { |
225 |
wr.await(); |
226 |
} catch (InterruptedException ex) { |
227 |
Exceptions.printStackTrace(ex); |
228 |
} |
229 |
} |
230 |
} |
231 |
|
232 |
@Override |
233 |
public <T> T showProgressDialogAndRun(ProgressRunnable<T> toRun, String displayName, boolean includeDetailLabel) { |
234 |
AbstractWindowRunner<T> wr = new ProgressBackgroundRunner<T>(toRun, displayName, includeDetailLabel); |
235 |
wr.start(); |
236 |
if (!EventQueue.isDispatchThread()) { |
237 |
try { |
238 |
wr.await(); |
239 |
} catch (InterruptedException ex) { |
240 |
Exceptions.printStackTrace(ex); |
241 |
} |
242 |
} |
243 |
return wr.getResult(); |
244 |
} |
245 |
|
246 |
private static abstract class AbstractWindowRunner<T> extends WindowAdapter implements Runnable { |
247 |
private volatile JDialog dlg; |
248 |
private final boolean includeDetail; |
249 |
protected final ProgressHandle handle; |
250 |
private final CountDownLatch latch = new CountDownLatch(1); |
251 |
private volatile T operationResult; |
252 |
|
253 |
AbstractWindowRunner(ProgressHandle handle, boolean includeDetail) { |
254 |
this.includeDetail = includeDetail; |
255 |
this.handle = handle; |
256 |
} |
257 |
|
258 |
@Override |
259 |
public final void windowOpened(WindowEvent e) { |
260 |
dlg = (JDialog) e.getSource(); |
261 |
RequestProcessor.getDefault().post(this); |
262 |
grayOutMainWindow(); |
263 |
} |
264 |
|
265 |
@Override |
266 |
public final void windowClosed(WindowEvent e) { |
267 |
ungrayMainWindow(); |
268 |
latch.countDown(); |
269 |
} |
270 |
|
271 |
final void await() throws InterruptedException { |
272 |
latch.await(); |
273 |
} |
274 |
|
275 |
final void start() { |
276 |
if (EventQueue.isDispatchThread()) { |
277 |
createModalProgressDialog(handle, includeDetail); |
278 |
} else { |
279 |
CountDownLatch dlgLatch = new CountDownLatch(1); |
280 |
DialogCreator dc = new DialogCreator(dlgLatch); |
281 |
EventQueue.invokeLater (dc); |
282 |
try { |
283 |
dlgLatch.await(); |
284 |
} catch (InterruptedException ex) { |
285 |
throw new IllegalStateException(ex); |
286 |
} |
287 |
} |
288 |
} |
289 |
|
290 |
protected abstract T runBackground(); |
291 |
|
292 |
T getResult() { |
293 |
return operationResult; |
294 |
} |
295 |
|
296 |
@Override |
297 |
public void run() { |
298 |
if (!EventQueue.isDispatchThread()) { |
299 |
try { |
300 |
operationResult = runBackground(); |
301 |
} finally { |
302 |
EventQueue.invokeLater(this); |
303 |
} |
304 |
} else { |
305 |
dlg.setVisible(false); |
306 |
dlg.dispose(); |
307 |
} |
308 |
} |
309 |
|
310 |
private final class DialogCreator implements Runnable { |
311 |
private final CountDownLatch latch; |
312 |
DialogCreator (CountDownLatch latch) { |
313 |
this.latch = latch; |
314 |
} |
315 |
|
316 |
@Override |
317 |
public void run() { |
318 |
createModalProgressDialog(handle, includeDetail); |
319 |
latch.countDown(); |
320 |
} |
321 |
} |
322 |
|
323 |
private JDialog createModalProgressDialog(ProgressHandle handle, boolean includeDetail) { |
324 |
assert EventQueue.isDispatchThread(); |
325 |
int edgeGap = Utilities.isMac() ? 12 : 8; |
326 |
int compGap = Utilities.isMac() ? 9 : 5; |
327 |
JPanel panel = new JPanel(new GridLayout(includeDetail ? 3 : 2, 1, compGap, compGap)); |
328 |
JLabel mainLabel = ProgressHandleFactory.createMainLabelComponent(handle); |
329 |
Font f = mainLabel.getFont(); |
330 |
if (f != null) { |
331 |
mainLabel.setFont (f.deriveFont(Font.BOLD)); |
332 |
} |
333 |
panel.add(mainLabel); |
334 |
|
335 |
JComponent progressBar = ProgressHandleFactory.createProgressComponent(handle); |
336 |
progressBar.setMinimumSize(new Dimension (400, 32)); |
337 |
panel.add(progressBar); |
338 |
|
339 |
if (includeDetail) { |
340 |
JLabel details = ProgressHandleFactory.createDetailLabelComponent(handle); |
341 |
details.setMinimumSize(new Dimension(300, 16)); |
342 |
panel.add(details); |
343 |
} |
344 |
panel.setBorder (BorderFactory.createCompoundBorder( |
345 |
BorderFactory.createRaisedBevelBorder(), |
346 |
BorderFactory.createEmptyBorder(edgeGap, edgeGap, edgeGap, edgeGap))); |
347 |
panel.setMinimumSize(new Dimension(400, 100)); |
348 |
Frame mainWindow = WindowManager.getDefault().getMainWindow(); |
349 |
JDialog result = new JDialog(mainWindow, true); |
350 |
result.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); |
351 |
result.setUndecorated(true); |
352 |
result.setSize(400, 100); |
353 |
result.getContentPane().setLayout(new BorderLayout()); |
354 |
result.getContentPane().add(panel, BorderLayout.CENTER); |
355 |
result.pack(); |
356 |
int reqWidth = result.getWidth(); |
357 |
result.setSize(Math.max (reqWidth, |
358 |
mainWindow instanceof JFrame ? |
359 |
((JFrame) mainWindow).getContentPane().getWidth() / 3 : |
360 |
mainWindow.getWidth()), result.getHeight()); |
361 |
result.setLocationRelativeTo(WindowManager.getDefault().getMainWindow()); |
362 |
result.addWindowListener(this); |
363 |
result.setVisible(true); |
364 |
return result; |
365 |
} |
366 |
|
367 |
private Component oldGlassPane; |
368 |
private void grayOutMainWindow() { |
369 |
assert EventQueue.isDispatchThread(); |
370 |
Frame f = WindowManager.getDefault().getMainWindow(); |
371 |
if (f instanceof JFrame) { |
372 |
Map<?,?> hintsMap = (Map)(Toolkit.getDefaultToolkit().getDesktopProperty("awt.font.desktophints")); //NOI18N |
373 |
//Avoid translucent painting on, for example, remote X terminal |
374 |
if (hintsMap == null || !RenderingHints.VALUE_TEXT_ANTIALIAS_OFF.equals(hintsMap.get(RenderingHints.KEY_TEXT_ANTIALIASING))) { |
375 |
JFrame jf = (JFrame) f; |
376 |
TranslucentMask mask = new TranslucentMask(); |
377 |
oldGlassPane = jf.getGlassPane(); |
378 |
jf.setGlassPane(mask); |
379 |
mask.setVisible(true); |
380 |
mask.setBounds (0, 0, jf.getContentPane().getWidth(), jf.getContentPane().getHeight()); |
381 |
mask.invalidate(); |
382 |
mask.revalidate(); |
383 |
mask.repaint(); |
384 |
jf.getRootPane().paintImmediately(0, 0, jf.getRootPane().getWidth(), jf.getRootPane().getHeight()); |
385 |
} |
386 |
} |
387 |
} |
388 |
|
389 |
private void ungrayMainWindow() { |
390 |
if (oldGlassPane != null) { |
391 |
JFrame jf = (JFrame) WindowManager.getDefault().getMainWindow(); |
392 |
jf.setGlassPane(oldGlassPane); |
393 |
jf.invalidate(); |
394 |
jf.repaint(); |
395 |
} |
396 |
} |
397 |
} |
398 |
|
399 |
static final class TranslucentMask extends JComponent { //pkg private for tests |
400 |
TranslucentMask() { |
401 |
setVisible(false); //so we will trigger a property change |
402 |
} |
403 |
|
404 |
@Override |
405 |
public boolean isOpaque() { |
406 |
return false; |
407 |
} |
408 |
|
409 |
@Override |
410 |
public void paint (Graphics g) { |
411 |
Graphics2D g2d = (Graphics2D) g; |
412 |
Color translu = new Color (180, 180, 180, 148); |
413 |
g2d.setColor(translu); |
414 |
g2d.fillRect (0, 0, getWidth(), getHeight()); |
415 |
} |
416 |
} |
417 |
|
418 |
private static final class ProgressBackgroundRunner<T> extends AbstractWindowRunner<T> { |
419 |
private final ProgressRunnable<T> toRun; |
420 |
public ProgressBackgroundRunner(ProgressRunnable<T> toRun, String displayName, boolean includeDetail) { |
421 |
super (ProgressHandleFactory.createHandle(displayName), includeDetail); |
422 |
this.toRun = toRun; |
423 |
} |
424 |
|
425 |
@Override |
426 |
protected T runBackground() { |
427 |
handle.start(); |
428 |
handle.switchToIndeterminate(); |
429 |
T result; |
430 |
try { |
431 |
result = toRun.run(handle); |
432 |
} finally { |
433 |
handle.finish(); |
434 |
} |
435 |
return result; |
436 |
} |
437 |
} |
438 |
|
439 |
private static final class RunnableWindowRunner extends AbstractWindowRunner<Void> { |
440 |
private Runnable toRun; |
441 |
public RunnableWindowRunner(Runnable toRun, ProgressHandle progress, boolean includeDetail) { |
442 |
super (progress, includeDetail); |
443 |
this.toRun = toRun; |
444 |
} |
445 |
|
446 |
@Override |
447 |
protected Void runBackground() { |
448 |
toRun.run(); |
449 |
return null; |
450 |
} |
451 |
} |
452 |
|
193 |
} |
453 |
} |