]> git.argeo.org Git - lgpl/argeo-commons.git/blob - swt/org.argeo.cms.swt/src/org/argeo/cms/swt/widgets/ContextOverlay.java
Add account-related RFC 2307bis LDAP objects and attributes
[lgpl/argeo-commons.git] / swt / org.argeo.cms.swt / src / org / argeo / cms / swt / widgets / ContextOverlay.java
1 package org.argeo.cms.swt.widgets;
2
3 import org.argeo.cms.swt.CmsSwtUtils;
4 import org.eclipse.swt.SWT;
5 import org.eclipse.swt.events.ShellAdapter;
6 import org.eclipse.swt.events.ShellEvent;
7 import org.eclipse.swt.graphics.Point;
8 import org.eclipse.swt.widgets.Composite;
9 import org.eclipse.swt.widgets.Control;
10 import org.eclipse.swt.widgets.Shell;
11
12 /**
13 * Manages a lightweight shell which is related to a {@link Control}, typically
14 * in order to reproduce a dropdown semantic, but with more flexibility.
15 */
16 public class ContextOverlay extends ScrolledPage {
17 private static final long serialVersionUID = 6702077429573324009L;
18
19 // private Shell shell;
20 private Control control;
21
22 private int maxHeight = 400;
23
24 public ContextOverlay(Control control, int style) {
25 super(createShell(control, style), SWT.NONE);
26 Shell shell = getShell();
27 setLayoutData(CmsSwtUtils.fillAll());
28 // TODO make autohide configurable?
29 //shell.addShellListener(new AutoHideShellListener());
30 this.control = control;
31 control.addDisposeListener((e) -> {
32 dispose();
33 shell.dispose();
34 });
35 }
36
37 private static Composite createShell(Control control, int style) {
38 if (control == null)
39 throw new IllegalArgumentException("Control cannot be null");
40 if (control.isDisposed())
41 throw new IllegalArgumentException("Control is disposed");
42 Shell shell = new Shell(control.getShell(), SWT.NO_TRIM);
43 shell.setLayout(CmsSwtUtils.noSpaceGridLayout());
44 Composite placeholder = new Composite(shell, SWT.BORDER);
45 placeholder.setLayoutData(CmsSwtUtils.fillAll());
46 placeholder.setLayout(CmsSwtUtils.noSpaceGridLayout());
47 return placeholder;
48 }
49
50 public void show() {
51 Point relativeControlLocation = control.getLocation();
52 Point controlLocation = control.toDisplay(relativeControlLocation.x, relativeControlLocation.y);
53
54 int controlWidth = control.getBounds().width;
55
56 Shell shell = getShell();
57
58 layout(true, true);
59 shell.pack();
60 shell.layout(true, true);
61 int targetShellWidth = shell.getSize().x < controlWidth ? controlWidth : shell.getSize().x;
62 if (shell.getSize().y > maxHeight) {
63 shell.setSize(targetShellWidth, maxHeight);
64 } else {
65 shell.setSize(targetShellWidth, shell.getSize().y);
66 }
67
68 int shellHeight = shell.getSize().y;
69 int controlHeight = control.getBounds().height;
70 Point shellLocation = new Point(controlLocation.x, controlLocation.y + controlHeight);
71 int displayHeight = shell.getDisplay().getBounds().height;
72 if (shellLocation.y + shellHeight > displayHeight) {// bottom of page
73 shellLocation = new Point(controlLocation.x, controlLocation.y - shellHeight);
74 }
75 shell.setLocation(shellLocation);
76
77 if (getChildren().length != 0)
78 shell.open();
79 if (!control.isDisposed())
80 control.setFocus();
81 }
82
83 public void hide() {
84 getShell().setVisible(false);
85 onHide();
86 }
87
88 public boolean isShellVisible() {
89 if (isDisposed())
90 return false;
91 return getShell().isVisible();
92 }
93
94 /** to be overridden */
95 protected void onHide() {
96 // does nothing by default.
97 }
98
99 private class AutoHideShellListener extends ShellAdapter {
100 private static final long serialVersionUID = 7743287433907938099L;
101
102 @Override
103 public void shellDeactivated(ShellEvent e) {
104 try {
105 Thread.sleep(1000);
106 } catch (InterruptedException e1) {
107 // silent
108 }
109 if (!control.isDisposed() && !control.isFocusControl())
110 hide();
111 }
112 }
113 }