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