]> git.argeo.org Git - lgpl/argeo-commons.git/blob - LightweightDialog.java
a923b0134c6c0173eef2eb0dd5bb7ea4555a915f
[lgpl/argeo-commons.git] / LightweightDialog.java
1 /*
2 * Copyright (C) 2007-2012 Argeo GmbH
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package org.argeo.eclipse.ui.dialogs;
17
18 import org.apache.commons.logging.Log;
19 import org.apache.commons.logging.LogFactory;
20 import org.argeo.eclipse.ui.EclipseUiException;
21 import org.eclipse.swt.SWT;
22 import org.eclipse.swt.events.FocusEvent;
23 import org.eclipse.swt.events.FocusListener;
24 import org.eclipse.swt.events.ShellAdapter;
25 import org.eclipse.swt.events.ShellEvent;
26 import org.eclipse.swt.graphics.Point;
27 import org.eclipse.swt.graphics.Rectangle;
28 import org.eclipse.swt.layout.GridData;
29 import org.eclipse.swt.layout.GridLayout;
30 import org.eclipse.swt.widgets.Composite;
31 import org.eclipse.swt.widgets.Control;
32 import org.eclipse.swt.widgets.Display;
33 import org.eclipse.swt.widgets.Shell;
34
35 /** Generic lightweight dialog, not based on JFace. */
36 public class LightweightDialog {
37 private final static Log log = LogFactory.getLog(LightweightDialog.class);
38
39 // must be the same value as org.eclipse.jface.window.Window#OK
40 public final static int OK = 0;
41 // must be the same value as org.eclipse.jface.window.Window#CANCEL
42 public final static int CANCEL = 1;
43
44 private Shell parentShell;
45 private Shell backgroundShell;
46 private Shell foregoundShell;
47
48 private Integer returnCode = null;
49 private boolean block = true;
50
51 private String title;
52
53 /** Tries to find a display */
54 private static Display getDisplay() {
55 try {
56 Display display = Display.getCurrent();
57 if (display != null)
58 return display;
59 else
60 return Display.getDefault();
61 } catch (Exception e) {
62 return Display.getCurrent();
63 }
64 }
65
66 public LightweightDialog(Shell parentShell) {
67 this.parentShell = parentShell;
68 }
69
70 public int open() {
71 if (foregoundShell != null)
72 throw new EclipseUiException("There is already a shell");
73 backgroundShell = new Shell(parentShell, SWT.DIALOG_TRIM | SWT.ON_TOP);
74 backgroundShell.setFullScreen(true);
75 // backgroundShell.setMaximized(true);
76 backgroundShell.setAlpha(128);
77 backgroundShell.setBackground(getDisplay().getSystemColor(SWT.COLOR_BLACK));
78 foregoundShell = new Shell(backgroundShell, SWT.NO_TRIM | SWT.ON_TOP);
79 if (title != null)
80 setTitle(title);
81 foregoundShell.setLayout(new GridLayout());
82 foregoundShell.setSize(getInitialSize());
83 createDialogArea(foregoundShell);
84 // shell.pack();
85 // shell.layout();
86
87 Rectangle shellBounds = Display.getCurrent().getBounds();// RAP
88 Point dialogSize = foregoundShell.getSize();
89 int x = shellBounds.x + (shellBounds.width - dialogSize.x) / 2;
90 int y = shellBounds.y + (shellBounds.height - dialogSize.y) / 2;
91 foregoundShell.setLocation(x, y);
92
93 foregoundShell.addShellListener(new ShellAdapter() {
94 private static final long serialVersionUID = -2701270481953688763L;
95
96 @Override
97 public void shellDeactivated(ShellEvent e) {
98 if (returnCode == null)// not yet closed
99 closeShell(CANCEL);
100 }
101
102 @Override
103 public void shellClosed(ShellEvent e) {
104 notifyClose();
105 }
106
107 });
108
109 backgroundShell.open();
110 foregoundShell.open();
111 // after the foreground shell has been opened
112 backgroundShell.addFocusListener(new FocusListener() {
113 private static final long serialVersionUID = 3137408447474661070L;
114
115 @Override
116 public void focusLost(FocusEvent event) {
117 }
118
119 @Override
120 public void focusGained(FocusEvent event) {
121 if (returnCode == null)// not yet closed
122 closeShell(CANCEL);
123 }
124 });
125
126 if (block) {
127 try {
128 runEventLoop(foregoundShell);
129 } catch (Throwable t) {
130 log.error("Cannot open blocking lightweight dialog", t);
131 }
132 }
133 if (returnCode == null)
134 returnCode = OK;
135 return returnCode;
136 }
137
138 // public synchronized int openAndWait() {
139 // open();
140 // while (returnCode == null)
141 // try {
142 // wait(100);
143 // } catch (InterruptedException e) {
144 // // silent
145 // }
146 // return returnCode;
147 // }
148
149 private synchronized void notifyClose() {
150 if (returnCode == null)
151 returnCode = CANCEL;
152 notifyAll();
153 }
154
155 protected void closeShell(int returnCode) {
156 this.returnCode = returnCode;
157 if (CANCEL == returnCode)
158 onCancel();
159 if (foregoundShell != null && !foregoundShell.isDisposed()) {
160 foregoundShell.close();
161 foregoundShell.dispose();
162 foregoundShell = null;
163 }
164
165 if (backgroundShell != null && !backgroundShell.isDisposed()) {
166 backgroundShell.close();
167 backgroundShell.dispose();
168 }
169 }
170
171 protected Point getInitialSize() {
172 // if (exception != null)
173 // return new Point(800, 600);
174 // else
175 return new Point(600, 400);
176 }
177
178 protected Control createDialogArea(Composite parent) {
179 Composite dialogarea = new Composite(parent, SWT.NONE);
180 dialogarea.setLayout(new GridLayout());
181 dialogarea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
182 return dialogarea;
183 }
184
185 protected Shell getBackgroundShell() {
186 return backgroundShell;
187 }
188
189 protected Shell getForegoundShell() {
190 return foregoundShell;
191 }
192
193 public void setBlockOnOpen(boolean shouldBlock) {
194 block = shouldBlock;
195 }
196
197 public void pack() {
198 foregoundShell.pack();
199 }
200
201 private void runEventLoop(Shell loopShell) {
202 Display display;
203 if (foregoundShell == null) {
204 display = Display.getCurrent();
205 } else {
206 display = loopShell.getDisplay();
207 }
208
209 while (loopShell != null && !loopShell.isDisposed()) {
210 try {
211 if (!display.readAndDispatch()) {
212 display.sleep();
213 }
214 } catch (Throwable e) {
215 handleException(e);
216 }
217 }
218 if (!display.isDisposed())
219 display.update();
220 }
221
222 protected void handleException(Throwable t) {
223 if (t instanceof ThreadDeath) {
224 // Don't catch ThreadDeath as this is a normal occurrence when
225 // the thread dies
226 throw (ThreadDeath) t;
227 }
228 // Try to keep running.
229 t.printStackTrace();
230 }
231
232 /** @return false, if the dialog should not be closed. */
233 protected boolean onCancel() {
234 return true;
235 }
236
237 public void setTitle(String title) {
238 this.title = title;
239 if (title != null && getForegoundShell() != null)
240 getForegoundShell().setText(title);
241 }
242
243 }