eplaceInputStream: fix more-than-one replaces
[fanfix.git] / src / be / nikiroo / utils / ui / WaitingDialog.java
1 package be.nikiroo.utils.ui;
2
3 import java.awt.Window;
4
5 import javax.swing.JDialog;
6 import javax.swing.JLabel;
7 import javax.swing.SwingWorker;
8 import javax.swing.border.EmptyBorder;
9
10 import be.nikiroo.utils.Progress;
11 import be.nikiroo.utils.Progress.ProgressListener;
12
13 /**
14 * A small waiting dialog that will show only if more than X milliseconds passed
15 * before we dismiss it.
16 *
17 * @author niki
18 */
19 public class WaitingDialog extends JDialog {
20 private static final long serialVersionUID = 1L;
21
22 private boolean waitScreen;
23 private Object waitLock = new Object();
24
25 private Progress pg;
26 private ProgressListener pgl;
27
28 /**
29 * Create a new {@link WaitingDialog}.
30 *
31 * @param parent
32 * the parent/owner of this {@link WaitingDialog}
33 * @param delayMs
34 * the delay after which to show the dialog if it is still not
35 * dismiss (see {@link WaitingDialog#dismiss()})
36 */
37 public WaitingDialog(Window parent, long delayMs) {
38 this(parent, delayMs, null, null);
39 }
40
41 /**
42 * Create a new {@link WaitingDialog}.
43 *
44 * @param parent
45 * the parent/owner of this {@link WaitingDialog}
46 * @param delayMs
47 * the delay after which to show the dialog if it is still not
48 * dismiss (see {@link WaitingDialog#dismiss()})
49 * @param pg
50 * the {@link Progress} to listen on -- when it is
51 * {@link Progress#done()}, this {@link WaitingDialog} will
52 * automatically be dismissed as if
53 * {@link WaitingDialog#dismiss()} was called
54 */
55 public WaitingDialog(Window parent, long delayMs, Progress pg) {
56 this(parent, delayMs, pg, null);
57 }
58
59 /**
60 * Create a new {@link WaitingDialog}.
61 *
62 * @param parent
63 * the parent/owner of this {@link WaitingDialog}
64 * @param delayMs
65 * the delay after which to show the dialog if it is still not
66 * dismiss (see {@link WaitingDialog#dismiss()})
67 * @param waitingText
68 * a waiting text to display (note: you may want to subclass it
69 * for nicer UI)
70 */
71 public WaitingDialog(Window parent, long delayMs, String waitingText) {
72 this(parent, delayMs, null, waitingText);
73 }
74
75 /**
76 * Create a new {@link WaitingDialog}.
77 *
78 * @param parent
79 * the parent/owner of this {@link WaitingDialog}
80 * @param delayMs
81 * the delay after which to show the dialog if it is still not
82 * dismiss (see {@link WaitingDialog#dismiss()})
83 * @param pg
84 * the {@link Progress} to listen on -- when it is
85 * {@link Progress#done()}, this {@link WaitingDialog} will
86 * automatically be dismissed as if
87 * {@link WaitingDialog#dismiss()} was called
88 * @param waitingText
89 * a waiting text to display (note: you may want to subclass it
90 * for nicer UI)
91 */
92 public WaitingDialog(Window parent, long delayMs, Progress pg,
93 String waitingText) {
94 super(parent);
95
96 this.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
97
98 this.pg = pg;
99
100 if (waitingText != null) {
101 JLabel waitingTextLabel = new JLabel(waitingText);
102 this.add(waitingTextLabel);
103 waitingTextLabel.setBorder(new EmptyBorder(10, 10, 10, 10));
104 this.pack();
105 }
106
107 if (pg != null) {
108 pgl = new ProgressListener() {
109 @Override
110 public void progress(Progress progress, String name) {
111 if (WaitingDialog.this.pg.isDone()) {
112 // Must be done out of this thread (cannot remove a pgl
113 // from a running pgl)
114 new SwingWorker<Void, Void>() {
115 @Override
116 protected Void doInBackground() throws Exception {
117 return null;
118 }
119
120 @Override
121 public void done() {
122 dismiss();
123 }
124 }.execute();
125 }
126 }
127 };
128
129 pg.addProgressListener(pgl);
130
131 if (pg.isDone()) {
132 dismiss();
133 return;
134 }
135 }
136
137 final long delay = delayMs;
138 new Thread(new Runnable() {
139 @Override
140 public void run() {
141 try {
142 Thread.sleep(delay);
143 } catch (InterruptedException e) {
144 }
145
146 synchronized (waitLock) {
147 if (!waitScreen) {
148 waitScreen = true;
149 setVisible(true);
150 }
151 }
152 }
153 }).start();
154 }
155
156 /**
157 * Notify this {@link WaitingDialog} that the job is done, and dismiss it if
158 * it was already showing on screen (or never show it if it was not).
159 * <p>
160 * Will also dispose the {@link WaitingDialog}.
161 */
162 public void dismiss() {
163 synchronized (waitLock) {
164 if (waitScreen) {
165 setVisible(false);
166 }
167 waitScreen = true;
168 }
169
170 if (pg != null) {
171 pg.removeProgressListener(pgl);
172 }
173
174 dispose();
175 }
176 }