]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/dialogs/LightweightDialog.java
Introduce ranking key.
[lgpl/argeo-commons.git] / org.argeo.eclipse.ui / src / org / argeo / eclipse / ui / dialogs / LightweightDialog.java
1 package org.argeo.eclipse.ui.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 try {
120 runEventLoop(foregoundShell);
121 } catch (ThreadDeath t) {
122 returnCode = CANCEL;
123 if (log.isTraceEnabled())
124 log.error("Thread death, canceling dialog", t);
125 } catch (Throwable t) {
126 returnCode = CANCEL;
127 log.error("Cannot open blocking lightweight dialog", t);
128 }
129 }
130 if (returnCode == null)
131 returnCode = OK;
132 return returnCode;
133 }
134
135 private boolean hasChildShells() {
136 if (foregoundShell == null)
137 return false;
138 return foregoundShell.getShells().length != 0;
139 }
140
141 // public synchronized int openAndWait() {
142 // open();
143 // while (returnCode == null)
144 // try {
145 // wait(100);
146 // } catch (InterruptedException e) {
147 // // silent
148 // }
149 // return returnCode;
150 // }
151
152 private synchronized void notifyClose() {
153 if (returnCode == null)
154 returnCode = CANCEL;
155 notifyAll();
156 }
157
158 protected void closeShell(int returnCode) {
159 this.returnCode = returnCode;
160 if (CANCEL == returnCode)
161 onCancel();
162 if (foregoundShell != null && !foregoundShell.isDisposed()) {
163 foregoundShell.close();
164 foregoundShell.dispose();
165 foregoundShell = null;
166 }
167
168 if (backgroundShell != null && !backgroundShell.isDisposed()) {
169 backgroundShell.close();
170 backgroundShell.dispose();
171 }
172 }
173
174 protected Point getInitialSize() {
175 // if (exception != null)
176 // return new Point(800, 600);
177 // else
178 return new Point(600, 400);
179 }
180
181 protected Control createDialogArea(Composite parent) {
182 Composite dialogarea = new Composite(parent, SWT.NONE);
183 dialogarea.setLayout(new GridLayout());
184 dialogarea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
185 return dialogarea;
186 }
187
188 protected Shell getBackgroundShell() {
189 return backgroundShell;
190 }
191
192 protected Shell getForegoundShell() {
193 return foregoundShell;
194 }
195
196 public void setBlockOnOpen(boolean shouldBlock) {
197 block = shouldBlock;
198 }
199
200 public void pack() {
201 foregoundShell.pack();
202 }
203
204 private void runEventLoop(Shell loopShell) {
205 Display display;
206 if (foregoundShell == null) {
207 display = Display.getCurrent();
208 } else {
209 display = loopShell.getDisplay();
210 }
211
212 while (loopShell != null && !loopShell.isDisposed()) {
213 try {
214 if (!display.readAndDispatch()) {
215 display.sleep();
216 }
217 } catch (Throwable e) {
218 handleException(e);
219 }
220 }
221 if (!display.isDisposed())
222 display.update();
223 }
224
225 protected void handleException(Throwable t) {
226 if (t instanceof ThreadDeath) {
227 // Don't catch ThreadDeath as this is a normal occurrence when
228 // the thread dies
229 throw (ThreadDeath) t;
230 }
231 // Try to keep running.
232 t.printStackTrace();
233 }
234
235 /** @return false, if the dialog should not be closed. */
236 protected boolean onCancel() {
237 return true;
238 }
239
240 public void setTitle(String title) {
241 this.title = title;
242 if (title != null && getForegoundShell() != null)
243 getForegoundShell().setText(title);
244 }
245
246 public Integer getReturnCode() {
247 return returnCode;
248 }
249
250 }