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