1 package org
.argeo
.cms
.swt
.dialogs
;
3 import org
.argeo
.api
.cms
.CmsLog
;
4 import org
.argeo
.cms
.ux
.widgets
.CmsDialog
;
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
;
20 /** Generic lightweight dialog, not based on JFace. */
21 public class LightweightDialog
{
22 private final static CmsLog log
= CmsLog
.getLog(LightweightDialog
.class);
24 private Shell parentShell
;
25 private Shell backgroundShell
;
26 private Shell foregoundShell
;
28 private Display display
;
30 private Integer returnCode
= null;
31 private boolean block
= true;
35 /** Tries to find a display */
36 static Display
findDisplay() {
38 Display display
= Display
.getCurrent();
42 return Display
.getDefault();
43 } catch (Exception e
) {
44 return Display
.getCurrent();
48 public LightweightDialog(Shell parentShell
) {
49 this.parentShell
= parentShell
;
53 display
= findDisplay();
54 if (foregoundShell
!= null)
55 throw new EclipseUiException("There is already a shell");
56 backgroundShell
= new Shell(parentShell
, SWT
.ON_TOP
);
57 backgroundShell
.setFullScreen(true);
58 // if (parentShell != null) {
59 // backgroundShell.setBounds(parentShell.getBounds());
61 // backgroundShell.setMaximized(true);
62 backgroundShell
.setAlpha(128);
63 backgroundShell
.setBackground(display
.getSystemColor(SWT
.COLOR_BLACK
));
64 foregoundShell
= new Shell(backgroundShell
, SWT
.NO_TRIM
| SWT
.ON_TOP
);
67 foregoundShell
.setLayout(new GridLayout());
68 foregoundShell
.setSize(getInitialSize());
69 createDialogArea(foregoundShell
);
73 Rectangle shellBounds
= parentShell
!= null ? parentShell
.getBounds() : display
.getBounds();// RAP
74 Point dialogSize
= foregoundShell
.getSize();
75 int x
= shellBounds
.x
+ (shellBounds
.width
- dialogSize
.x
) / 2;
76 int y
= shellBounds
.y
+ (shellBounds
.height
- dialogSize
.y
) / 2;
77 foregoundShell
.setLocation(x
, y
);
79 foregoundShell
.addShellListener(new ShellAdapter() {
80 private static final long serialVersionUID
= -2701270481953688763L;
83 public void shellDeactivated(ShellEvent e
) {
86 if (returnCode
== null)// not yet closed
87 closeShell(CmsDialog
.CANCEL
);
91 public void shellClosed(ShellEvent e
) {
97 backgroundShell
.open();
98 foregoundShell
.open();
99 // after the foreground shell has been opened
100 backgroundShell
.addFocusListener(new FocusListener() {
101 private static final long serialVersionUID
= 3137408447474661070L;
104 public void focusLost(FocusEvent event
) {
108 public void focusGained(FocusEvent event
) {
109 if (hasChildShells())
111 if (returnCode
== null)// not yet closed
112 closeShell(CmsDialog
.CANCEL
);
115 backgroundShell
.addDisposeListener((event
) -> onClose());
120 if (returnCode
== null)
121 returnCode
= CmsDialog
.OK
;
125 public void block() {
127 runEventLoop(foregoundShell
);
128 } catch (ThreadDeath t
) {
129 returnCode
= CmsDialog
.CANCEL
;
130 if (log
.isTraceEnabled())
131 log
.error("Thread death, canceling dialog", t
);
132 } catch (Throwable t
) {
133 returnCode
= CmsDialog
.CANCEL
;
134 log
.error("Cannot open blocking lightweight dialog", t
);
138 private boolean hasChildShells() {
139 if (foregoundShell
== null)
141 return foregoundShell
.getShells().length
!= 0;
144 protected void onClose() {
148 // public synchronized int openAndWait() {
150 // while (returnCode == null)
153 // } catch (InterruptedException e) {
156 // return returnCode;
159 private synchronized void notifyClose() {
160 if (returnCode
== null)
161 returnCode
= CmsDialog
.CANCEL
;
165 protected void closeShell(int returnCode
) {
166 this.returnCode
= returnCode
;
167 if (CmsDialog
.CANCEL
== returnCode
)
169 if (foregoundShell
!= null && !foregoundShell
.isDisposed()) {
170 foregoundShell
.close();
171 foregoundShell
.dispose();
172 foregoundShell
= null;
175 if (backgroundShell
!= null && !backgroundShell
.isDisposed()) {
176 backgroundShell
.close();
177 backgroundShell
.dispose();
181 protected Point
getInitialSize() {
182 return new Point(600, 400);
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));
192 protected Shell
getBackgroundShell() {
193 return backgroundShell
;
196 protected Shell
getForegoundShell() {
197 return foregoundShell
;
200 public void setBlockOnOpen(boolean shouldBlock
) {
205 foregoundShell
.pack();
208 private void runEventLoop(Shell loopShell
) {
210 if (foregoundShell
== null) {
211 display
= Display
.getCurrent();
213 display
= loopShell
.getDisplay();
216 while (loopShell
!= null && !loopShell
.isDisposed()) {
218 if (!display
.readAndDispatch()) {
221 } catch (UnsupportedOperationException e
) {
223 } catch (Throwable e
) {
227 if (!display
.isDisposed())
231 protected void handleException(Throwable t
) {
232 if (t
instanceof ThreadDeath
) {
233 // Don't catch ThreadDeath as this is a normal occurrence when
235 throw (ThreadDeath
) t
;
237 // Try to keep running.
241 /** @return false, if the dialog should not be closed. */
242 protected boolean onCancel() {
246 public void setTitle(String title
) {
248 if (title
!= null && getForegoundShell() != null)
249 getForegoundShell().setText(title
);
252 public Integer
getReturnCode() {
256 Display
getDisplay() {