From: Niki Roo Date: Mon, 4 May 2020 12:34:02 +0000 (+0200) Subject: new: waiting dialog X-Git-Url: https://git.nikiroo.be/?a=commitdiff_plain;h=982c5a80524fc76a51e39ec9376ef6a243f30c70;p=fanfix-swing.git new: waiting dialog --- diff --git a/ui/WaitingDialog.java b/ui/WaitingDialog.java new file mode 100644 index 00000000..2c02c092 --- /dev/null +++ b/ui/WaitingDialog.java @@ -0,0 +1,170 @@ +package be.nikiroo.utils.ui; + +import java.awt.Window; + +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.SwingWorker; +import javax.swing.border.EmptyBorder; + +import be.nikiroo.utils.Progress; +import be.nikiroo.utils.Progress.ProgressListener; + +/** + * A small waiting dialog that will show only if more than X milliseconds passed + * before we dismiss it. + * + * @author niki + */ +public class WaitingDialog extends JDialog { + private static final long serialVersionUID = 1L; + + private boolean waitScreen; + private Object waitLock = new Object(); + + private Progress pg; + private ProgressListener pgl; + + /** + * Create a new {@link WaitingDialog}. + * + * @param parent + * the parent/owner of this {@link WaitingDialog} + * @param delayMs + * the delay after which to show the dialog if it is still not + * dismiss (see {@link WaitingDialog#done()}) + */ + public WaitingDialog(Window parent, long delayMs) { + this(parent, delayMs, null, null); + } + + /** + * Create a new {@link WaitingDialog}. + * + * @param parent + * the parent/owner of this {@link WaitingDialog} + * @param delayMs + * the delay after which to show the dialog if it is still not + * dismiss (see {@link WaitingDialog#done()}) + * @param pg + * the {@link Progress} to listen on -- when it is + * {@link Progress#done()}, this {@link WaitingDialog} will + * automatically be dismissed as if {@link WaitingDialog#done()} + * was called + */ + public WaitingDialog(Window parent, long delayMs, Progress pg) { + this(parent, delayMs, pg, null); + } + + /** + * Create a new {@link WaitingDialog}. + * + * @param parent + * the parent/owner of this {@link WaitingDialog} + * @param delayMs + * the delay after which to show the dialog if it is still not + * dismiss (see {@link WaitingDialog#done()}) + * @param waitingText + * a waiting text to display (note: you may want to subclass it + * for nicer UI) + */ + public WaitingDialog(Window parent, long delayMs, String waitingText) { + this(parent, delayMs, null, waitingText); + } + + /** + * Create a new {@link WaitingDialog}. + * + * @param parent + * the parent/owner of this {@link WaitingDialog} + * @param delayMs + * the delay after which to show the dialog if it is still not + * dismiss (see {@link WaitingDialog#done()}) + * @param pg + * the {@link Progress} to listen on -- when it is + * {@link Progress#done()}, this {@link WaitingDialog} will + * automatically be dismissed as if {@link WaitingDialog#done()} + * was called + * @param waitingText + * a waiting text to display (note: you may want to subclass it + * for nicer UI) + */ + public WaitingDialog(Window parent, long delayMs, Progress pg, + String waitingText) { + super(parent); + + this.pg = pg; + + if (waitingText != null) { + JLabel waitingTextLabel = new JLabel(waitingText); + this.add(waitingTextLabel); + waitingTextLabel.setBorder(new EmptyBorder(10, 10, 10, 10)); + this.pack(); + } + + if (pg != null) { + pgl = new ProgressListener() { + @Override + public void progress(Progress progress, String name) { + if (WaitingDialog.this.pg.isDone()) { + // Must be done out of this thread (cannot remove a pgl + // from a running pgl) + new SwingWorker() { + @Override + protected Void doInBackground() throws Exception { + return null; + } + + @Override + public void done() { + WaitingDialog.this.done(); + } + }.execute(); + } + } + }; + + pg.addProgressListener(pgl); + + if (pg.isDone()) { + done(); + return; + } + } + + final long delay = delayMs; + new Thread(new Runnable() { + @Override + public void run() { + try { + Thread.sleep(delay); + } catch (InterruptedException e) { + } + + synchronized (waitLock) { + if (!waitScreen) { + waitScreen = true; + setVisible(true); + } + } + } + }).start(); + } + + /** + * Notify this {@link WaitingDialog} that the job is done, and dismiss it if + * it was already showing on screen (or never show it if it was not). + */ + public void done() { + synchronized (waitLock) { + if (waitScreen) { + setVisible(false); + } + waitScreen = true; + } + + if (pg != null) { + pg.removeProgressListener(pgl); + } + } +}