KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jface > dialogs > TrayDialog


1 /*******************************************************************************
2  * Copyright (c) 2005, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jface.dialogs;
12
13 import org.eclipse.jface.resource.JFaceResources;
14 import org.eclipse.jface.window.IShellProvider;
15 import org.eclipse.swt.SWT;
16 import org.eclipse.swt.events.DisposeEvent;
17 import org.eclipse.swt.events.DisposeListener;
18 import org.eclipse.swt.events.SelectionAdapter;
19 import org.eclipse.swt.events.SelectionEvent;
20 import org.eclipse.swt.graphics.Cursor;
21 import org.eclipse.swt.graphics.Image;
22 import org.eclipse.swt.graphics.Rectangle;
23 import org.eclipse.swt.layout.GridData;
24 import org.eclipse.swt.layout.GridLayout;
25 import org.eclipse.swt.widgets.Composite;
26 import org.eclipse.swt.widgets.Control;
27 import org.eclipse.swt.widgets.Event;
28 import org.eclipse.swt.widgets.Label;
29 import org.eclipse.swt.widgets.Layout;
30 import org.eclipse.swt.widgets.Link;
31 import org.eclipse.swt.widgets.Listener;
32 import org.eclipse.swt.widgets.Sash;
33 import org.eclipse.swt.widgets.Shell;
34 import org.eclipse.swt.widgets.ToolBar;
35 import org.eclipse.swt.widgets.ToolItem;
36
37 /**
38  * A <code>TrayDialog</code> is a specialized <code>Dialog</code> that can contain
39  * a tray on its side. The tray's content is provided as a <code>DialogTray</code>.
40  * <p>
41  * It is recommended to subclass this class instead of <code>Dialog</code> in all
42  * cases except where the dialog should never show a tray. For example, dialogs
43  * which are very short, simple, and quick to dismiss (e.g. a message dialog with
44  * an OK button) should subclass <code>Dialog</code>.
45  * </p>
46  * <p>
47  * Note: Trays are not supported on dialogs that use a custom layout on the <code>
48  * Shell</code> by overriding <code>Window#getLayout()</code>.
49  * </p>
50  *
51  * @see org.eclipse.jface.dialogs.DialogTray
52  * @see org.eclipse.jface.window.Window#getLayout()
53  * @since 3.2
54  */

55 public abstract class TrayDialog extends Dialog {
56
57     private static boolean dialogHelpAvailable;
58
59     /*
60      * The dialog's tray (null if none).
61      */

62     private DialogTray tray;
63
64     /*
65      * The tray's control.
66      */

67     private Control trayControl;
68     
69     /*
70      * The separator to the left of the sash.
71      */

72     private Label leftSeparator;
73     
74     /*
75      * The separator to the right of the sash.
76      */

77     private Label rightSeparator;
78     
79     /*
80      * The sash that allows the user to resize the tray.
81      */

82     private Sash sash;
83     
84     /*
85      * Whether or not help is available for this dialog.
86      */

87     private boolean helpAvailable = isDialogHelpAvailable();
88
89     /**
90      * Creates a tray dialog instance. Note that the window will have no visual
91      * representation (no widgets) until it is told to open.
92      *
93      * @param shell the parent shell, or <code>null</code> to create a top-level shell
94      */

95     protected TrayDialog(Shell shell) {
96         super(shell);
97     }
98     
99     /**
100      * Creates a tray dialog with the given parent.
101      *
102      * @param parentShell the object that returns the current parent shell
103      */

104     protected TrayDialog(IShellProvider parentShell) {
105         super(parentShell);
106     }
107
108     /**
109      * Closes this dialog's tray, disposing its widgets.
110      *
111      * @throws IllegalStateException if the tray was not open
112      */

113     public void closeTray() throws IllegalStateException JavaDoc {
114         if (getTray() == null) {
115             throw new IllegalStateException JavaDoc("Tray was not open"); //$NON-NLS-1$
116
}
117         int trayWidth = trayControl.getSize().x + leftSeparator.getSize().x + sash.getSize().x + rightSeparator.getSize().x;
118         trayControl.dispose();
119         trayControl = null;
120         tray = null;
121         leftSeparator.dispose();
122         leftSeparator = null;
123         rightSeparator.dispose();
124         rightSeparator = null;
125         sash.dispose();
126         sash = null;
127         Shell shell = getShell();
128         Rectangle bounds = shell.getBounds();
129         shell.setBounds(bounds.x + ((getDefaultOrientation() == SWT.RIGHT_TO_LEFT) ? trayWidth : 0), bounds.y, bounds.width - trayWidth, bounds.height);
130     }
131     
132     /* (non-Javadoc)
133      * @see org.eclipse.jface.dialogs.Dialog#close()
134      */

135     public boolean close() {
136         /*
137          * Close the tray to ensure that those dialogs that remember their
138          * size do not store the tray size.
139          */

140         if (getTray() != null) {
141             closeTray();
142         }
143         return super.close();
144     }
145     
146     /* (non-Javadoc)
147      * @see org.eclipse.jface.dialogs.Dialog#createButtonBar(org.eclipse.swt.widgets.Composite)
148      */

149     protected Control createButtonBar(Composite parent) {
150         Composite composite = new Composite(parent, SWT.NONE);
151         GridLayout layout = new GridLayout();
152         layout.marginWidth = 0;
153         layout.marginHeight = 0;
154         layout.horizontalSpacing = 0;
155         composite.setLayout(layout);
156         composite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
157         composite.setFont(parent.getFont());
158
159         // create help control if needed
160
if (isHelpAvailable()) {
161             Control helpControl = createHelpControl(composite);
162             ((GridData) helpControl.getLayoutData()).horizontalIndent = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
163         }
164         Control buttonSection = super.createButtonBar(composite);
165         ((GridData) buttonSection.getLayoutData()).grabExcessHorizontalSpace = true;
166         return composite;
167     }
168
169     /**
170      * Creates a new help control that provides access to context help.
171      * <p>
172      * The <code>TrayDialog</code> implementation of this method creates
173      * the control, registers it for selection events including selection,
174      * Note that the parent's layout is assumed to be a <code>GridLayout</code>
175      * and the number of columns in this layout is incremented. Subclasses may
176      * override.
177      * </p>
178      *
179      * @param parent the parent composite
180      * @return the help control
181      */

182     protected Control createHelpControl(Composite parent) {
183         Image helpImage = JFaceResources.getImage(DLG_IMG_HELP);
184         if (helpImage != null) {
185             return createHelpImageButton(parent, helpImage);
186         }
187         return createHelpLink(parent);
188     }
189     
190     /*
191      * Creates a button with a help image. This is only used if there
192      * is an image available.
193      */

194     private ToolBar createHelpImageButton(Composite parent, Image image) {
195         ToolBar toolBar = new ToolBar(parent, SWT.FLAT | SWT.NO_FOCUS);
196         ((GridLayout) parent.getLayout()).numColumns++;
197         toolBar.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_CENTER));
198         final Cursor cursor = new Cursor(parent.getDisplay(), SWT.CURSOR_HAND);
199         toolBar.setCursor(cursor);
200         toolBar.addDisposeListener(new DisposeListener() {
201             public void widgetDisposed(DisposeEvent e) {
202                 cursor.dispose();
203             }
204         });
205         ToolItem item = new ToolItem(toolBar, SWT.NONE);
206         item.setImage(image);
207         item.setToolTipText(JFaceResources.getString("helpToolTip")); //$NON-NLS-1$
208
item.addSelectionListener(new SelectionAdapter() {
209             public void widgetSelected(SelectionEvent e) {
210                 helpPressed();
211             }
212         });
213         return toolBar;
214     }
215
216     /*
217      * Creates a help link. This is used when there is no help image
218      * available.
219      */

220     private Link createHelpLink(Composite parent) {
221         Link link = new Link(parent, SWT.WRAP | SWT.NO_FOCUS);
222         ((GridLayout) parent.getLayout()).numColumns++;
223         link.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_CENTER));
224         link.setText("<a>"+IDialogConstants.HELP_LABEL+"</a>"); //$NON-NLS-1$ //$NON-NLS-2$
225
link.setToolTipText(IDialogConstants.HELP_LABEL);
226         link.addSelectionListener(new SelectionAdapter() {
227             public void widgetSelected(SelectionEvent e) {
228                 helpPressed();
229             }
230         });
231         return link;
232     }
233     
234     /*
235      * Returns whether or not the given layout can support the addition of a tray.
236      */

237     private boolean isCompatibleLayout(Layout layout) {
238         if (layout != null && layout instanceof GridLayout) {
239             GridLayout grid = (GridLayout)layout;
240             return !grid.makeColumnsEqualWidth && (grid.horizontalSpacing == 0) &&
241                     (grid.marginWidth == 0) && (grid.marginHeight == 0) &&
242                     (grid.horizontalSpacing == 0) && (grid.numColumns == 5);
243         }
244         return false;
245     }
246
247     /**
248      * Returns whether or not context help is available for this dialog. This
249      * can affect whether or not the dialog will display additional help
250      * mechanisms such as a help control in the button bar.
251      *
252      * @return whether or not context help is available for this dialog
253      */

254     public boolean isHelpAvailable() {
255         return helpAvailable;
256     }
257     
258     /**
259      * The tray dialog's default layout is a modified version of the default
260      * <code>Window</code> layout that can accomodate a tray, however it still
261      * conforms to the description of the <code>Window</code> default layout.
262      * <p>
263      * Note: Trays may not be supported with all custom layouts on the dialog's
264      * Shell. To avoid problems, use a single outer <code>Composite</code> for
265      * your dialog area, and set your custom layout on that <code>Composite</code>.
266      * </p>
267      *
268      * @see org.eclipse.jface.window.Window#getLayout()
269      * @return a newly created layout or <code>null</code> for no layout
270      */

271     protected Layout getLayout() {
272         GridLayout layout = (GridLayout)super.getLayout();
273         layout.numColumns = 5;
274         layout.horizontalSpacing = 0;
275         return layout;
276     }
277     
278     /**
279      * Returns the tray currently shown in the dialog, or <code>null</code>
280      * if there is no tray.
281      *
282      * @return the dialog's current tray, or <code>null</code> if there is none
283      */

284     public DialogTray getTray() {
285         return tray;
286     }
287     
288     /*
289      * Called when the help control is invoked. This emulates the keyboard
290      * context help behavior (e.g. F1 on Windows). It traverses the widget
291      * tree upward until it finds a widget that has a help listener on it,
292      * then invokes a help event on that widget.
293      */

294     private void helpPressed() {
295         if (getShell() != null) {
296             Control c = getShell().getDisplay().getFocusControl();
297             while (c != null) {
298                 if (c.isListening(SWT.Help)) {
299                     c.notifyListeners(SWT.Help, new Event());
300                     break;
301                 }
302                 c = c.getParent();
303             }
304         }
305     }
306     
307     /**
308      * Constructs the tray's widgets and displays the tray in this dialog. The
309      * dialog's size will be adjusted to accomodate the tray.
310      *
311      * @param tray the tray to show in this dialog
312      * @throws IllegalStateException if the dialog already has a tray open
313      * @throws UnsupportedOperationException if the dialog does not support trays,
314      * for example if it uses a custom layout.
315      */

316     public void openTray(DialogTray tray) throws IllegalStateException JavaDoc, UnsupportedOperationException JavaDoc {
317         if (tray == null) {
318             throw new NullPointerException JavaDoc("Tray was null"); //$NON-NLS-1$
319
}
320         if (getTray() != null) {
321             throw new IllegalStateException JavaDoc("Tray was already open"); //$NON-NLS-1$
322
}
323         if (!isCompatibleLayout(getShell().getLayout())) {
324             throw new UnsupportedOperationException JavaDoc("Trays not supported with custom layouts"); //$NON-NLS-1$
325
}
326         final Shell shell = getShell();
327         leftSeparator = new Label(shell, SWT.SEPARATOR | SWT.VERTICAL);
328         leftSeparator.setLayoutData(new GridData(GridData.FILL_VERTICAL));
329         sash = new Sash(shell, SWT.VERTICAL);
330         sash.setLayoutData(new GridData(GridData.FILL_VERTICAL));
331         rightSeparator = new Label(shell, SWT.SEPARATOR | SWT.VERTICAL);
332         rightSeparator.setLayoutData(new GridData(GridData.FILL_VERTICAL));
333         trayControl = tray.createContents(shell);
334         Rectangle clientArea = shell.getClientArea();
335         final GridData data = new GridData(GridData.FILL_VERTICAL);
336         data.widthHint = trayControl.computeSize(SWT.DEFAULT, clientArea.height).x;
337         trayControl.setLayoutData(data);
338         int trayWidth = leftSeparator.computeSize(SWT.DEFAULT, clientArea.height).x + sash.computeSize(SWT.DEFAULT, clientArea.height).x + rightSeparator.computeSize(SWT.DEFAULT, clientArea.height).x + data.widthHint;
339         Rectangle bounds = shell.getBounds();
340         shell.setBounds(bounds.x - ((getDefaultOrientation() == SWT.RIGHT_TO_LEFT) ? trayWidth : 0), bounds.y, bounds.width + trayWidth, bounds.height);
341         sash.addListener(SWT.Selection, new Listener() {
342             public void handleEvent(Event event) {
343                 if (event.detail != SWT.DRAG) {
344                     Rectangle clientArea = shell.getClientArea();
345                     int newWidth = clientArea.width - event.x - (sash.getSize().x + rightSeparator.getSize().x);
346                     if (newWidth != data.widthHint) {
347                         data.widthHint = newWidth;
348                         shell.layout();
349                     }
350                 }
351             }
352         });
353         this.tray = tray;
354     }
355     
356     /**
357      * Sets whether or not context help is available for this dialog. This
358      * can affect whether or not the dialog will display additional help
359      * mechanisms such as a help control in the button bar.
360      *
361      * @param helpAvailable whether or not context help is available for the dialog
362      */

363     public void setHelpAvailable(boolean helpAvailable) {
364         this.helpAvailable = helpAvailable;
365     }
366     
367     /**
368      * Tests if dialogs that have help control should show it
369      * all the time or only when explicitly requested for
370      * each dialog instance.
371      *
372      * @return <code>true</code> if dialogs that support help
373      * control should show it by default, <code>false</code> otherwise.
374      * @since 3.2
375      */

376     public static boolean isDialogHelpAvailable() {
377         return dialogHelpAvailable;
378     }
379     
380     /**
381      * Sets whether JFace dialogs that support help control should
382      * show the control by default. If set to <code>false</code>,
383      * help control can still be shown on a per-dialog basis.
384      *
385      * @param helpAvailable <code>true</code> to show the help
386      * control, <code>false</code> otherwise.
387      * @since 3.2
388      */

389     public static void setDialogHelpAvailable(boolean helpAvailable) {
390         dialogHelpAvailable = helpAvailable;
391     }
392 }
393
Popular Tags