]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms.swt/src/org/argeo/cms/swt/dialogs/LightweightDialog.java
Start integrating GCR and JCR (not yet working)
[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.apache.commons.logging.Log;
4 import org.apache.commons.logging.LogFactory;
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 Log log = LogFactory.getLog(LightweightDialog.class);
23
24 // must be the same value as org.eclipse.jface.window.Window#OK
25 public final static int OK = 0;
26 // must be the same value as org.eclipse.jface.window.Window#CANCEL
27 public final static int CANCEL = 1;
28
29 private Shell parentShell;
30 private Shell backgroundShell;
31 private Shell foregoundShell;
32
33 private Integer returnCode = null;
34 private boolean block = true;
35
36 private String title;
37
38 /** Tries to find a display */
39 private static Display getDisplay() {
40 try {
41 Display display = Display.getCurrent();
42 if (display != null)
43 return display;
44 else
45 return Display.getDefault();
46 } catch (Exception e) {
47 return Display.getCurrent();
48 }
49 }
50
51 public LightweightDialog(Shell parentShell) {
52 this.parentShell = parentShell;
53 }
54
55 public int open() {
56 if (foregoundShell != null)
57 throw new EclipseUiException("There is already a shell");
58 backgroundShell = new Shell(parentShell, SWT.ON_TOP);
59 backgroundShell.setFullScreen(true);
60 // if (parentShell != null) {
61 // backgroundShell.setBounds(parentShell.getBounds());
62 // } else
63 // backgroundShell.setMaximized(true);
64 backgroundShell.setAlpha(128);
65 backgroundShell.setBackground(getDisplay().getSystemColor(SWT.COLOR_BLACK));
66 foregoundShell = new Shell(backgroundShell, SWT.NO_TRIM | SWT.ON_TOP);
67 if (title != null)
68 setTitle(title);
69 foregoundShell.setLayout(new GridLayout());
70 foregoundShell.setSize(getInitialSize());
71 createDialogArea(foregoundShell);
72 // shell.pack();
73 // shell.layout();
74
75 Rectangle shellBounds = parentShell != null ? parentShell.getBounds() : Display.getCurrent().getBounds();// RAP
76 Point dialogSize = foregoundShell.getSize();
77 int x = shellBounds.x + (shellBounds.width - dialogSize.x) / 2;
78 int y = shellBounds.y + (shellBounds.height - dialogSize.y) / 2;
79 foregoundShell.setLocation(x, y);
80
81 foregoundShell.addShellListener(new ShellAdapter() {
82 private static final long serialVersionUID = -2701270481953688763L;
83
84 @Override
85 public void shellDeactivated(ShellEvent e) {
86 if (hasChildShells())
87 return;
88 if (returnCode == null)// not yet closed
89 closeShell(CANCEL);
90 }
91
92 @Override
93 public void shellClosed(ShellEvent e) {
94 notifyClose();
95 }
96
97 });
98
99 backgroundShell.open();
100 foregoundShell.open();
101 // after the foreground shell has been opened
102 backgroundShell.addFocusListener(new FocusListener() {
103 private static final long serialVersionUID = 3137408447474661070L;
104
105 @Override
106 public void focusLost(FocusEvent event) {
107 }
108
109 @Override
110 public void focusGained(FocusEvent event) {
111 if (hasChildShells())
112 return;
113 if (returnCode == null)// not yet closed
114 closeShell(CANCEL);
115 }
116 });
117
118 if (block) {
119 block();
120 }
121 if (returnCode == null)
122 returnCode = OK;
123 return returnCode;
124 }
125
126 public void block() {
127 try {
128 runEventLoop(foregoundShell);
129 } catch (ThreadDeath t) {
130 returnCode = CANCEL;
131 if (log.isTraceEnabled())
132 log.error("Thread death, canceling dialog", t);
133 } catch (Throwable t) {
134 returnCode = CANCEL;
135 log.error("Cannot open blocking lightweight dialog", t);
136 }
137 }
138
139 private boolean hasChildShells() {
140 if (foregoundShell == null)
141 return false;
142 return foregoundShell.getShells().length != 0;
143 }
144
145 // public synchronized int openAndWait() {
146 // open();
147 // while (returnCode == null)
148 // try {
149 // wait(100);
150 // } catch (InterruptedException e) {
151 // // silent
152 // }
153 // return returnCode;
154 // }
155
156 private synchronized void notifyClose() {
157 if (returnCode == null)
158 returnCode = CANCEL;
159 notifyAll();
160 }
161
162 protected void closeShell(int returnCode) {
163 this.returnCode = returnCode;
164 if (CANCEL == returnCode)
165 onCancel();
166 if (foregoundShell != null && !foregoundShell.isDisposed()) {
167 foregoundShell.close();
168 foregoundShell.dispose();
169 foregoundShell = null;
170 }
171
172 if (backgroundShell != null && !backgroundShell.isDisposed()) {
173 backgroundShell.close();
174 backgroundShell.dispose();
175 }
176 }
177
178 protected Point getInitialSize() {
179 // if (exception != null)
180 // return new Point(800, 600);
181 // else
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 }