]> git.argeo.org Git - lgpl/argeo-commons.git/blob - swt/org.argeo.cms.swt/src/org/argeo/cms/swt/dialogs/LightweightDialog.java
Start improving single-user login
[lgpl/argeo-commons.git] / swt / org.argeo.cms.swt / src / org / argeo / cms / swt / dialogs / LightweightDialog.java
1 package org.argeo.cms.swt.dialogs;
2
3 import org.argeo.api.cms.CmsLog;
4 import org.argeo.cms.ux.widgets.CmsDialog;
5 import org.argeo.eclipse.ui.EclipseUiException;
6 import org.eclipse.swt.SWT;
7 import org.eclipse.swt.events.FocusEvent;
8 import org.eclipse.swt.events.FocusListener;
9 import org.eclipse.swt.events.ShellAdapter;
10 import org.eclipse.swt.events.ShellEvent;
11 import org.eclipse.swt.graphics.Point;
12 import org.eclipse.swt.graphics.Rectangle;
13 import org.eclipse.swt.layout.GridData;
14 import org.eclipse.swt.layout.GridLayout;
15 import org.eclipse.swt.widgets.Composite;
16 import org.eclipse.swt.widgets.Control;
17 import org.eclipse.swt.widgets.Display;
18 import org.eclipse.swt.widgets.Shell;
19
20 /** Generic lightweight dialog, not based on JFace. */
21 public class LightweightDialog {
22 private final static CmsLog log = CmsLog.getLog(LightweightDialog.class);
23
24 private Shell parentShell;
25 private Shell backgroundShell;
26 private Shell foregoundShell;
27
28 private Display display;
29
30 private Integer returnCode = null;
31 private boolean block = true;
32
33 private String title;
34
35 /** Tries to find a display */
36 static Display findDisplay() {
37 try {
38 Display display = Display.getCurrent();
39 if (display != null)
40 return display;
41 else
42 return Display.getDefault();
43 } catch (Exception e) {
44 return Display.getCurrent();
45 }
46 }
47
48 public LightweightDialog(Shell parentShell) {
49 this.parentShell = parentShell;
50 }
51
52 public int open() {
53 display = findDisplay();
54 if (foregoundShell != null)
55 throw new EclipseUiException("There is already a shell");
56 backgroundShell = new Shell(parentShell, SWT.ON_TOP);
57 backgroundShell.setFullScreen(true);
58 // if (parentShell != null) {
59 // backgroundShell.setBounds(parentShell.getBounds());
60 // } else
61 // backgroundShell.setMaximized(true);
62 backgroundShell.setAlpha(128);
63 backgroundShell.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
64 foregoundShell = new Shell(backgroundShell, SWT.NO_TRIM | SWT.ON_TOP);
65 if (title != null)
66 setTitle(title);
67 foregoundShell.setLayout(new GridLayout());
68 foregoundShell.setSize(getInitialSize());
69 createDialogArea(foregoundShell);
70 // shell.pack();
71 // shell.layout();
72
73 Rectangle shellBounds = parentShell != null ? parentShell.getBounds() : display.getBounds();// RAP
74 Point dialogSize = foregoundShell.getSize();
75 int x = shellBounds.x + (shellBounds.width - dialogSize.x) / 2;
76 int y = shellBounds.y + (shellBounds.height - dialogSize.y) / 2;
77 foregoundShell.setLocation(x, y);
78
79 foregoundShell.addShellListener(new ShellAdapter() {
80 private static final long serialVersionUID = -2701270481953688763L;
81
82 @Override
83 public void shellDeactivated(ShellEvent e) {
84 if (hasChildShells())
85 return;
86 if (returnCode == null)// not yet closed
87 closeShell(CmsDialog.CANCEL);
88 }
89
90 @Override
91 public void shellClosed(ShellEvent e) {
92 notifyClose();
93 }
94
95 });
96
97 backgroundShell.open();
98 foregoundShell.open();
99 // after the foreground shell has been opened
100 backgroundShell.addFocusListener(new FocusListener() {
101 private static final long serialVersionUID = 3137408447474661070L;
102
103 @Override
104 public void focusLost(FocusEvent event) {
105 }
106
107 @Override
108 public void focusGained(FocusEvent event) {
109 if (hasChildShells())
110 return;
111 if (returnCode == null)// not yet closed
112 closeShell(CmsDialog.CANCEL);
113 }
114 });
115 backgroundShell.addDisposeListener((event) -> onClose());
116
117 if (block) {
118 block();
119 }
120 if (returnCode == null)
121 returnCode = CmsDialog.OK;
122 return returnCode;
123 }
124
125 public void block() {
126 try {
127 runEventLoop(foregoundShell);
128 } catch (ThreadDeath t) {
129 returnCode = CmsDialog.CANCEL;
130 if (log.isTraceEnabled())
131 log.error("Thread death, canceling dialog", t);
132 } catch (Throwable t) {
133 returnCode = CmsDialog.CANCEL;
134 log.error("Cannot open blocking lightweight dialog", t);
135 }
136 }
137
138 private boolean hasChildShells() {
139 if (foregoundShell == null)
140 return false;
141 return foregoundShell.getShells().length != 0;
142 }
143
144 protected void onClose() {
145
146 }
147
148 // public synchronized int openAndWait() {
149 // open();
150 // while (returnCode == null)
151 // try {
152 // wait(100);
153 // } catch (InterruptedException e) {
154 // // silent
155 // }
156 // return returnCode;
157 // }
158
159 private synchronized void notifyClose() {
160 if (returnCode == null)
161 returnCode = CmsDialog.CANCEL;
162 notifyAll();
163 }
164
165 protected void closeShell(int returnCode) {
166 this.returnCode = returnCode;
167 if (CmsDialog.CANCEL == returnCode)
168 onCancel();
169 if (foregoundShell != null && !foregoundShell.isDisposed()) {
170 foregoundShell.close();
171 foregoundShell.dispose();
172 foregoundShell = null;
173 }
174
175 if (backgroundShell != null && !backgroundShell.isDisposed()) {
176 backgroundShell.close();
177 backgroundShell.dispose();
178 }
179 }
180
181 protected Point getInitialSize() {
182 return new Point(600, 400);
183 }
184
185 protected Control createDialogArea(Composite parent) {
186 Composite dialogarea = new Composite(parent, SWT.NONE);
187 dialogarea.setLayout(new GridLayout());
188 dialogarea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
189 return dialogarea;
190 }
191
192 protected Shell getBackgroundShell() {
193 return backgroundShell;
194 }
195
196 protected Shell getForegoundShell() {
197 return foregoundShell;
198 }
199
200 public void setBlockOnOpen(boolean shouldBlock) {
201 block = shouldBlock;
202 }
203
204 public void pack() {
205 foregoundShell.pack();
206 }
207
208 private void runEventLoop(Shell loopShell) {
209 Display display;
210 if (foregoundShell == null) {
211 display = Display.getCurrent();
212 } else {
213 display = loopShell.getDisplay();
214 }
215
216 while (loopShell != null && !loopShell.isDisposed()) {
217 try {
218 if (!display.readAndDispatch()) {
219 display.sleep();
220 }
221 } catch (UnsupportedOperationException e) {
222 throw e;
223 } catch (Throwable e) {
224 handleException(e);
225 }
226 }
227 if (!display.isDisposed())
228 display.update();
229 }
230
231 protected void handleException(Throwable t) {
232 if (t instanceof ThreadDeath) {
233 // Don't catch ThreadDeath as this is a normal occurrence when
234 // the thread dies
235 throw (ThreadDeath) t;
236 }
237 // Try to keep running.
238 t.printStackTrace();
239 }
240
241 /** @return false, if the dialog should not be closed. */
242 protected boolean onCancel() {
243 return true;
244 }
245
246 public void setTitle(String title) {
247 this.title = title;
248 if (title != null && getForegoundShell() != null)
249 getForegoundShell().setText(title);
250 }
251
252 public Integer getReturnCode() {
253 return returnCode;
254 }
255
256 Display getDisplay() {
257 return display;
258 }
259
260 }