KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*******************************************************************************
2  * Copyright (c) 2000, 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 java.util.Arrays JavaDoc;
14 import java.util.HashMap JavaDoc;
15
16 import org.eclipse.core.runtime.IProgressMonitor;
17 import org.eclipse.core.runtime.IStatus;
18 import org.eclipse.core.runtime.Status;
19 import org.eclipse.jface.resource.JFaceResources;
20 import org.eclipse.jface.util.Policy;
21 import org.eclipse.jface.window.IShellProvider;
22 import org.eclipse.jface.window.SameShellProvider;
23 import org.eclipse.jface.window.Window;
24 import org.eclipse.swt.SWT;
25 import org.eclipse.swt.events.SelectionAdapter;
26 import org.eclipse.swt.events.SelectionEvent;
27 import org.eclipse.swt.graphics.Font;
28 import org.eclipse.swt.graphics.FontData;
29 import org.eclipse.swt.graphics.FontMetrics;
30 import org.eclipse.swt.graphics.GC;
31 import org.eclipse.swt.graphics.Image;
32 import org.eclipse.swt.graphics.Point;
33 import org.eclipse.swt.layout.FormData;
34 import org.eclipse.swt.layout.GridData;
35 import org.eclipse.swt.layout.GridLayout;
36 import org.eclipse.swt.widgets.Button;
37 import org.eclipse.swt.widgets.Composite;
38 import org.eclipse.swt.widgets.Control;
39 import org.eclipse.swt.widgets.Display;
40 import org.eclipse.swt.widgets.Shell;
41
42 /**
43  * A dialog is a specialized window used for narrow-focused communication with
44  * the user.
45  * <p>
46  * Dialogs are usually modal. Consequently, it is generally bad practice to open
47  * a dialog without a parent. A modal dialog without a parent is not prevented
48  * from disappearing behind the application's other windows, making it very
49  * confusing for the user.
50  * </p>
51  * <p>
52  * If there is more than one modal dialog is open the second one should be
53  * parented off of the shell of the first one otherwise it is possible that the
54  * OS will give focus to the first dialog potentially blocking the UI.
55  * </p>
56  */

57 public abstract class Dialog extends Window {
58     /**
59      * Image registry key for error image (value
60      * <code>"dialog_error_image"</code>).
61      *
62      * @deprecated use
63      * org.eclipse.swt.widgets.Display.getSystemImage(SWT.ICON_ERROR)
64      */

65     public static final String JavaDoc DLG_IMG_ERROR = "dialog_error_image"; //$NON-NLS-1$
66

67     /**
68      * Image registry key for info image (value <code>"dialog_info_image"</code>).
69      *
70      * @deprecated use
71      * org.eclipse.swt.widgets.Display.getSystemImage(SWT.ICON_INFORMATION)
72      */

73     public static final String JavaDoc DLG_IMG_INFO = "dialog_info_imageg"; //$NON-NLS-1$
74

75     /**
76      * Image registry key for question image (value
77      * <code>"dialog_question_image"</code>).
78      *
79      * @deprecated org.eclipse.swt.widgets.Display.getSystemImage(SWT.ICON_QUESTION)
80      */

81     public static final String JavaDoc DLG_IMG_QUESTION = "dialog_question_image"; //$NON-NLS-1$
82

83     /**
84      * Image registry key for warning image (value
85      * <code>"dialog_warning_image"</code>).
86      *
87      * @deprecated use
88      * org.eclipse.swt.widgets.Display.getSystemImage(SWT.ICON_WARNING)
89      */

90     public static final String JavaDoc DLG_IMG_WARNING = "dialog_warning_image"; //$NON-NLS-1$
91

92     /**
93      * Image registry key for info message image (value
94      * <code>"dialog_messasge_info_image"</code>).
95      *
96      * @since 2.0
97      */

98     public static final String JavaDoc DLG_IMG_MESSAGE_INFO = "dialog_messasge_info_image"; //$NON-NLS-1$
99

100     /**
101      * Image registry key for info message image (value
102      * <code>"dialog_messasge_warning_image"</code>).
103      *
104      * @since 2.0
105      */

106     public static final String JavaDoc DLG_IMG_MESSAGE_WARNING = "dialog_messasge_warning_image"; //$NON-NLS-1$
107

108     /**
109      * Image registry key for info message image (value
110      * <code>"dialog_message_error_image"</code>).
111      *
112      * @since 2.0
113      */

114     public static final String JavaDoc DLG_IMG_MESSAGE_ERROR = "dialog_message_error_image"; //$NON-NLS-1$
115

116     /**
117      * Image registry key for help image (value
118      * <code>"dialog_help_image"</code>).
119      *
120      * @since 3.2
121      */

122     public static final String JavaDoc DLG_IMG_HELP = "dialog_help_image"; //$NON-NLS-1$
123

124     /**
125      * The ellipsis is the string that is used to represent shortened text.
126      *
127      * @since 3.0
128      */

129     public static final String JavaDoc ELLIPSIS = "..."; //$NON-NLS-1$
130

131     /**
132      * The dialog settings key name for stored dialog x location.
133      *
134      * @since 3.2
135      */

136     private static final String JavaDoc DIALOG_ORIGIN_X = "DIALOG_X_ORIGIN"; //$NON-NLS-1$
137

138     /**
139      * The dialog settings key name for stored dialog y location.
140      *
141      * @since 3.2
142      */

143     private static final String JavaDoc DIALOG_ORIGIN_Y = "DIALOG_Y_ORIGIN"; //$NON-NLS-1$
144

145     /**
146      * The dialog settings key name for stored dialog width.
147      *
148      * @since 3.2
149      */

150     private static final String JavaDoc DIALOG_WIDTH = "DIALOG_WIDTH"; //$NON-NLS-1$
151

152     /**
153      * The dialog settings key name for stored dialog height.
154      *
155      * @since 3.2
156      */

157     private static final String JavaDoc DIALOG_HEIGHT = "DIALOG_HEIGHT"; //$NON-NLS-1$
158

159     /**
160      * The dialog settings key name for the font used when the dialog
161      * height and width was stored.
162      *
163      *@since 3.2
164      */

165     private static final String JavaDoc DIALOG_FONT_DATA = "DIALOG_FONT_NAME"; //$NON-NLS-1$
166

167     /**
168      * A value that can be used for stored dialog width or height that
169      * indicates that the default bounds should be used.
170      *
171      * @since 3.2
172      */

173     public static final int DIALOG_DEFAULT_BOUNDS = -1;
174
175     /**
176      * Constants that can be used for specifying the strategy for persisting
177      * dialog bounds. These constants represent bit masks that can be used
178      * together.
179      *
180      *@since 3.2
181      */

182     
183     /**
184      * Persist the last location of the dialog.
185      * @since 3.2
186      */

187     public static final int DIALOG_PERSISTLOCATION = 0x0001;
188     /**
189      * Persist the last known size of the dialog.
190      * @since 3.2
191      */

192     public static final int DIALOG_PERSISTSIZE = 0x0002;
193     
194     /**
195      * The dialog area; <code>null</code> until dialog is layed out.
196      */

197     protected Control dialogArea;
198
199     /**
200      * The button bar; <code>null</code> until dialog is layed out.
201      */

202     public Control buttonBar;
203     
204     /**
205      * Collection of buttons created by the <code>createButton</code> method.
206      */

207     private HashMap JavaDoc buttons = new HashMap JavaDoc();
208
209     /**
210      * Font metrics to use for determining pixel sizes.
211      */

212     private FontMetrics fontMetrics;
213     
214     /**
215      * Number of horizontal dialog units per character, value <code>4</code>.
216      */

217     private static final int HORIZONTAL_DIALOG_UNIT_PER_CHAR = 4;
218
219     /**
220      * Number of vertical dialog units per character, value <code>8</code>.
221      */

222     private static final int VERTICAL_DIALOG_UNITS_PER_CHAR = 8;
223
224     /**
225      * Returns the number of pixels corresponding to the height of the given
226      * number of characters.
227      * <p>
228      * The required <code>FontMetrics</code> parameter may be created in the
229      * following way: <code>
230      * GC gc = new GC(control);
231      * gc.setFont(control.getFont());
232      * fontMetrics = gc.getFontMetrics();
233      * gc.dispose();
234      * </code>
235      * </p>
236      *
237      * @param fontMetrics
238      * used in performing the conversion
239      * @param chars
240      * the number of characters
241      * @return the number of pixels
242      * @since 2.0
243      */

244     public static int convertHeightInCharsToPixels(FontMetrics fontMetrics,
245             int chars) {
246         return fontMetrics.getHeight() * chars;
247     }
248
249     /**
250      * Returns the number of pixels corresponding to the given number of
251      * horizontal dialog units.
252      * <p>
253      * The required <code>FontMetrics</code> parameter may be created in the
254      * following way: <code>
255      * GC gc = new GC(control);
256      * gc.setFont(control.getFont());
257      * fontMetrics = gc.getFontMetrics();
258      * gc.dispose();
259      * </code>
260      * </p>
261      *
262      * @param fontMetrics
263      * used in performing the conversion
264      * @param dlus
265      * the number of horizontal dialog units
266      * @return the number of pixels
267      * @since 2.0
268      */

269     public static int convertHorizontalDLUsToPixels(FontMetrics fontMetrics,
270             int dlus) {
271         // round to the nearest pixel
272
return (fontMetrics.getAverageCharWidth() * dlus + HORIZONTAL_DIALOG_UNIT_PER_CHAR / 2)
273                 / HORIZONTAL_DIALOG_UNIT_PER_CHAR;
274     }
275
276     /**
277      * Returns the number of pixels corresponding to the given number of
278      * vertical dialog units.
279      * <p>
280      * The required <code>FontMetrics</code> parameter may be created in the
281      * following way: <code>
282      * GC gc = new GC(control);
283      * gc.setFont(control.getFont());
284      * fontMetrics = gc.getFontMetrics();
285      * gc.dispose();
286      * </code>
287      * </p>
288      *
289      * @param fontMetrics
290      * used in performing the conversion
291      * @param dlus
292      * the number of vertical dialog units
293      * @return the number of pixels
294      * @since 2.0
295      */

296     public static int convertVerticalDLUsToPixels(FontMetrics fontMetrics,
297             int dlus) {
298         // round to the nearest pixel
299
return (fontMetrics.getHeight() * dlus + VERTICAL_DIALOG_UNITS_PER_CHAR / 2)
300                 / VERTICAL_DIALOG_UNITS_PER_CHAR;
301     }
302
303     /**
304      * Returns the number of pixels corresponding to the width of the given
305      * number of characters.
306      * <p>
307      * The required <code>FontMetrics</code> parameter may be created in the
308      * following way: <code>
309      * GC gc = new GC(control);
310      * gc.setFont(control.getFont());
311      * fontMetrics = gc.getFontMetrics();
312      * gc.dispose();
313      * </code>
314      * </p>
315      *
316      * @param fontMetrics
317      * used in performing the conversion
318      * @param chars
319      * the number of characters
320      * @return the number of pixels
321      * @since 2.0
322      */

323     public static int convertWidthInCharsToPixels(FontMetrics fontMetrics,
324             int chars) {
325         return fontMetrics.getAverageCharWidth() * chars;
326     }
327
328     /**
329      * Shortens the given text <code>textValue</code> so that its width in
330      * pixels does not exceed the width of the given control. Overrides
331      * characters in the center of the original string with an ellipsis ("...")
332      * if necessary. If a <code>null</code> value is given, <code>null</code>
333      * is returned.
334      *
335      * @param textValue
336      * the original string or <code>null</code>
337      * @param control
338      * the control the string will be displayed on
339      * @return the string to display, or <code>null</code> if null was passed
340      * in
341      *
342      * @since 3.0
343      */

344     public static String JavaDoc shortenText(String JavaDoc textValue, Control control) {
345         if (textValue == null) {
346             return null;
347         }
348         GC gc = new GC(control);
349         int maxWidth = control.getBounds().width - 5;
350         if (gc.textExtent(textValue).x < maxWidth) {
351             gc.dispose();
352             return textValue;
353         }
354         int length = textValue.length();
355         int pivot = length / 2;
356         int start = pivot;
357         int end = pivot + 1;
358         while (start >= 0 && end < length) {
359             String JavaDoc s1 = textValue.substring(0, start);
360             String JavaDoc s2 = textValue.substring(end, length);
361             String JavaDoc s = s1 + ELLIPSIS + s2;
362             int l = gc.textExtent(s).x;
363             if (l < maxWidth) {
364                 gc.dispose();
365                 return s;
366             }
367             start--;
368             end++;
369         }
370         gc.dispose();
371         return textValue;
372     }
373
374     /**
375      * Create a default instance of the blocked handler which does not do
376      * anything.
377      */

378     public static IDialogBlockedHandler blockedHandler = new IDialogBlockedHandler() {
379         /*
380          * (non-Javadoc)
381          *
382          * @see org.eclipse.jface.dialogs.IDialogBlockedHandler#clearBlocked()
383          */

384         public void clearBlocked() {
385             // No default behaviour
386
}
387
388         /*
389          * (non-Javadoc)
390          *
391          * @see org.eclipse.jface.dialogs.IDialogBlockedHandler#showBlocked(org.eclipse.core.runtime.IProgressMonitor,
392          * org.eclipse.core.runtime.IStatus, java.lang.String)
393          */

394         public void showBlocked(IProgressMonitor blocking,
395                 IStatus blockingStatus, String JavaDoc blockedName) {
396             // No default behaviour
397
}
398
399         /*
400          * (non-Javadoc)
401          *
402          * @see org.eclipse.jface.dialogs.IDialogBlockedHandler#showBlocked(org.eclipse.swt.widgets.Shell,
403          * org.eclipse.core.runtime.IProgressMonitor,
404          * org.eclipse.core.runtime.IStatus, java.lang.String)
405          */

406         public void showBlocked(Shell parentShell, IProgressMonitor blocking,
407                 IStatus blockingStatus, String JavaDoc blockedName) {
408             // No default behaviour
409
}
410     };
411
412     /**
413      * Creates a dialog instance. Note that the window will have no visual
414      * representation (no widgets) until it is told to open. By default,
415      * <code>open</code> blocks for dialogs.
416      *
417      * @param parentShell
418      * the parent shell, or <code>null</code> to create a top-level
419      * shell
420      */

421     protected Dialog(Shell parentShell) {
422         this(new SameShellProvider(parentShell));
423         if (parentShell == null && Policy.DEBUG_DIALOG_NO_PARENT) {
424             Policy.getLog().log(
425                     new Status(IStatus.INFO, Policy.JFACE, IStatus.INFO, this
426                             .getClass()
427                             + " created with no shell",//$NON-NLS-1$
428
new Exception JavaDoc()));
429         }
430     }
431
432     /**
433      * Creates a dialog with the given parent.
434      *
435      * @param parentShell
436      * object that returns the current parent shell
437      *
438      * @since 3.1
439      */

440     protected Dialog(IShellProvider parentShell) {
441         super(parentShell);
442         setShellStyle(SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL
443                 | getDefaultOrientation());
444         setBlockOnOpen(true);
445     }
446
447     /**
448      * Notifies that this dialog's button with the given id has been pressed.
449      * <p>
450      * The <code>Dialog</code> implementation of this framework method calls
451      * <code>okPressed</code> if the ok button is the pressed, and
452      * <code>cancelPressed</code> if the cancel button is the pressed. All
453      * other button presses are ignored. Subclasses may override to handle other
454      * buttons, but should call <code>super.buttonPressed</code> if the
455      * default handling of the ok and cancel buttons is desired.
456      * </p>
457      *
458      * @param buttonId
459      * the id of the button that was pressed (see
460      * <code>IDialogConstants.*_ID</code> constants)
461      */

462     protected void buttonPressed(int buttonId) {
463         if (IDialogConstants.OK_ID == buttonId) {
464             okPressed();
465         } else if (IDialogConstants.CANCEL_ID == buttonId) {
466             cancelPressed();
467         }
468     }
469
470     /**
471      * Notifies that the cancel button of this dialog has been pressed.
472      * <p>
473      * The <code>Dialog</code> implementation of this framework method sets
474      * this dialog's return code to <code>Window.CANCEL</code> and closes the
475      * dialog. Subclasses may override if desired.
476      * </p>
477      */

478     protected void cancelPressed() {
479         setReturnCode(CANCEL);
480         close();
481     }
482
483     /**
484      * Returns the number of pixels corresponding to the height of the given
485      * number of characters.
486      * <p>
487      * This method may only be called after <code>initializeDialogUnits</code>
488      * has been called.
489      * </p>
490      * <p>
491      * Clients may call this framework method, but should not override it.
492      * </p>
493      *
494      * @param chars
495      * the number of characters
496      * @return the number of pixels
497      */

498     protected int convertHeightInCharsToPixels(int chars) {
499         // test for failure to initialize for backward compatibility
500
if (fontMetrics == null) {
501             return 0;
502         }
503         return convertHeightInCharsToPixels(fontMetrics, chars);
504     }
505
506     /**
507      * Returns the number of pixels corresponding to the given number of
508      * horizontal dialog units.
509      * <p>
510      * This method may only be called after <code>initializeDialogUnits</code>
511      * has been called.
512      * </p>
513      * <p>
514      * Clients may call this framework method, but should not override it.
515      * </p>
516      *
517      * @param dlus
518      * the number of horizontal dialog units
519      * @return the number of pixels
520      */

521     protected int convertHorizontalDLUsToPixels(int dlus) {
522         // test for failure to initialize for backward compatibility
523
if (fontMetrics == null) {
524             return 0;
525         }
526         return convertHorizontalDLUsToPixels(fontMetrics, dlus);
527     }
528
529     /**
530      * Returns the number of pixels corresponding to the given number of
531      * vertical dialog units.
532      * <p>
533      * This method may only be called after <code>initializeDialogUnits</code>
534      * has been called.
535      * </p>
536      * <p>
537      * Clients may call this framework method, but should not override it.
538      * </p>
539      *
540      * @param dlus
541      * the number of vertical dialog units
542      * @return the number of pixels
543      */

544     protected int convertVerticalDLUsToPixels(int dlus) {
545         // test for failure to initialize for backward compatibility
546
if (fontMetrics == null) {
547             return 0;
548         }
549         return convertVerticalDLUsToPixels(fontMetrics, dlus);
550     }
551
552     /**
553      * Returns the number of pixels corresponding to the width of the given
554      * number of characters.
555      * <p>
556      * This method may only be called after <code>initializeDialogUnits</code>
557      * has been called.
558      * </p>
559      * <p>
560      * Clients may call this framework method, but should not override it.
561      * </p>
562      *
563      * @param chars
564      * the number of characters
565      * @return the number of pixels
566      */

567     protected int convertWidthInCharsToPixels(int chars) {
568         // test for failure to initialize for backward compatibility
569
if (fontMetrics == null) {
570             return 0;
571         }
572         return convertWidthInCharsToPixels(fontMetrics, chars);
573     }
574
575     /**
576      * Creates a new button with the given id.
577      * <p>
578      * The <code>Dialog</code> implementation of this framework method creates
579      * a standard push button, registers it for selection events including
580      * button presses, and registers default buttons with its shell. The button
581      * id is stored as the button's client data. If the button id is
582      * <code>IDialogConstants.CANCEL_ID</code>, the new button will be
583      * accessible from <code>getCancelButton()</code>. If the button id is
584      * <code>IDialogConstants.OK_ID</code>, the new button will be accesible
585      * from <code>getOKButton()</code>. Note that the parent's layout is
586      * assumed to be a <code>GridLayout</code> and the number of columns in
587      * this layout is incremented. Subclasses may override.
588      * </p>
589      *
590      * @param parent
591      * the parent composite
592      * @param id
593      * the id of the button (see <code>IDialogConstants.*_ID</code>
594      * constants for standard dialog button ids)
595      * @param label
596      * the label from the button
597      * @param defaultButton
598      * <code>true</code> if the button is to be the default button,
599      * and <code>false</code> otherwise
600      *
601      * @return the new button
602      *
603      * @see #getCancelButton
604      * @see #getOKButton()
605      */

606     protected Button createButton(Composite parent, int id, String JavaDoc label,
607             boolean defaultButton) {
608         // increment the number of columns in the button bar
609
((GridLayout) parent.getLayout()).numColumns++;
610         Button button = new Button(parent, SWT.PUSH);
611         button.setText(label);
612         button.setFont(JFaceResources.getDialogFont());
613         button.setData(new Integer JavaDoc(id));
614         button.addSelectionListener(new SelectionAdapter() {
615             public void widgetSelected(SelectionEvent event) {
616                 buttonPressed(((Integer JavaDoc) event.widget.getData()).intValue());
617             }
618         });
619         if (defaultButton) {
620             Shell shell = parent.getShell();
621             if (shell != null) {
622                 shell.setDefaultButton(button);
623             }
624         }
625         buttons.put(new Integer JavaDoc(id), button);
626         setButtonLayoutData(button);
627         return button;
628     }
629
630     /**
631      * Creates and returns the contents of this dialog's button bar.
632      * <p>
633      * The <code>Dialog</code> implementation of this framework method lays
634      * out a button bar and calls the <code>createButtonsForButtonBar</code>
635      * framework method to populate it. Subclasses may override.
636      * </p>
637      * <p>
638      * The returned control's layout data must be an instance of
639      * <code>GridData</code>.
640      * </p>
641      *
642      * @param parent
643      * the parent composite to contain the button bar
644      * @return the button bar control
645      */

646     protected Control createButtonBar(Composite parent) {
647         Composite composite = new Composite(parent, SWT.NONE);
648         // create a layout with spacing and margins appropriate for the font
649
// size.
650
GridLayout layout = new GridLayout();
651         layout.numColumns = 0; // this is incremented by createButton
652
layout.makeColumnsEqualWidth = true;
653         layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
654         layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
655         layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
656         layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
657         composite.setLayout(layout);
658         GridData data = new GridData(GridData.HORIZONTAL_ALIGN_END
659                 | GridData.VERTICAL_ALIGN_CENTER);
660         composite.setLayoutData(data);
661         composite.setFont(parent.getFont());
662         
663         // Add the buttons to the button bar.
664
createButtonsForButtonBar(composite);
665         return composite;
666     }
667
668     /**
669      * Adds buttons to this dialog's button bar.
670      * <p>
671      * The <code>Dialog</code> implementation of this framework method adds
672      * standard ok and cancel buttons using the <code>createButton</code>
673      * framework method. These standard buttons will be accessible from
674      * <code>getCancelButton</code>, and <code>getOKButton</code>.
675      * Subclasses may override.
676      * </p>
677      *
678      * @param parent
679      * the button bar composite
680      */

681     protected void createButtonsForButtonBar(Composite parent) {
682         // create OK and Cancel buttons by default
683
createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL,
684                 true);
685         createButton(parent, IDialogConstants.CANCEL_ID,
686                 IDialogConstants.CANCEL_LABEL, false);
687     }
688
689     /*
690      * @see Window.initializeBounds()
691      */

692     protected void initializeBounds() {
693         String JavaDoc platform = SWT.getPlatform();
694         if ("carbon".equals(platform)) { //$NON-NLS-1$
695
// On Mac OS X the default button must be the right-most button
696
Shell shell = getShell();
697             if (shell != null) {
698                 Button defaultButton = shell.getDefaultButton();
699                 if (defaultButton != null
700                         && isContained(buttonBar, defaultButton)) {
701                     defaultButton.moveBelow(null);
702                 }
703             }
704         }
705         
706         super.initializeBounds();
707     }
708
709     /**
710      * Returns true if the given Control is a direct or indirect child of
711      * container.
712      *
713      * @param container
714      * the potential parent
715      * @param control
716      * @return boolean <code>true</code> if control is a child of container
717      */

718     private boolean isContained(Control container, Control control) {
719         Composite parent;
720         while ((parent = control.getParent()) != null) {
721             if (parent == container) {
722                 return true;
723             }
724             control = parent;
725         }
726         return false;
727     }
728
729     /**
730      * The <code>Dialog</code> implementation of this <code>Window</code>
731      * method creates and lays out the top level composite for the dialog, and
732      * determines the appropriate horizontal and vertical dialog units based on
733      * the font size. It then calls the <code>createDialogArea</code> and
734      * <code>createButtonBar</code> methods to create the dialog area and
735      * button bar, respectively. Overriding <code>createDialogArea</code> and
736      * <code>createButtonBar</code> are recommended rather than overriding
737      * this method.
738      */

739     protected Control createContents(Composite parent) {
740         // create the top level composite for the dialog
741
Composite composite = new Composite(parent, 0);
742         GridLayout layout = new GridLayout();
743         layout.marginHeight = 0;
744         layout.marginWidth = 0;
745         layout.verticalSpacing = 0;
746         composite.setLayout(layout);
747         composite.setLayoutData(new GridData(GridData.FILL_BOTH));
748         applyDialogFont(composite);
749         // initialize the dialog units
750
initializeDialogUnits(composite);
751         // create the dialog area and button bar
752
dialogArea = createDialogArea(composite);
753         buttonBar = createButtonBar(composite);
754                 
755         return composite;
756     }
757
758     /**
759      * Creates and returns the contents of the upper part of this dialog (above
760      * the button bar).
761      * <p>
762      * The <code>Dialog</code> implementation of this framework method creates
763      * and returns a new <code>Composite</code> with standard margins and
764      * spacing.
765      * </p>
766      * <p>
767      * The returned control's layout data must be an instance of
768      * <code>GridData</code>. This method must not modify the parent's
769      * layout.
770      * </p>
771      * <p>
772      * Subclasses must override this method but may call <code>super</code> as
773      * in the following example:
774      * </p>
775      *
776      * <pre>
777      * Composite composite = (Composite) super.createDialogArea(parent);
778      * //add controls to composite as necessary
779      * return composite;
780      * </pre>
781      *
782      * @param parent
783      * the parent composite to contain the dialog area
784      * @return the dialog area control
785      */

786     protected Control createDialogArea(Composite parent) {
787         // create a composite with standard margins and spacing
788
Composite composite = new Composite(parent, SWT.NONE);
789         GridLayout layout = new GridLayout();
790         layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
791         layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
792         layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
793         layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
794         composite.setLayout(layout);
795         composite.setLayoutData(new GridData(GridData.FILL_BOTH));
796         applyDialogFont(composite);
797         return composite;
798     }
799
800     /**
801      * Returns the button created by the method <code>createButton</code> for
802      * the specified ID as defined on <code>IDialogConstants</code>. If
803      * <code>createButton</code> was never called with this ID, or if
804      * <code>createButton</code> is overridden, this method will return
805      * <code>null</code>.
806      *
807      * @param id
808      * the id of the button to look for
809      *
810      * @return the button for the ID or <code>null</code>
811      *
812      * @see #createButton(Composite, int, String, boolean)
813      * @since 2.0
814      */

815     protected Button getButton(int id) {
816         return (Button) buttons.get(new Integer JavaDoc(id));
817     }
818
819     /**
820      * Returns the button bar control.
821      * <p>
822      * Clients may call this framework method, but should not override it.
823      * </p>
824      *
825      * @return the button bar, or <code>null</code> if the button bar has not
826      * been created yet
827      */

828     protected Control getButtonBar() {
829         return buttonBar;
830     }
831
832     /**
833      * Returns the button created when <code>createButton</code> is called
834      * with an ID of <code>IDialogConstants.CANCEL_ID</code>. If
835      * <code>createButton</code> was never called with this parameter, or if
836      * <code>createButton</code> is overridden, <code>getCancelButton</code>
837      * will return <code>null</code>.
838      *
839      * @return the cancel button or <code>null</code>
840      *
841      * @see #createButton(Composite, int, String, boolean)
842      * @since 2.0
843      * @deprecated Use <code>getButton(IDialogConstants.CANCEL_ID)</code>
844      * instead. This method will be removed soon.
845      */

846     protected Button getCancelButton() {
847         return getButton(IDialogConstants.CANCEL_ID);
848     }
849
850     /**
851      * Returns the dialog area control.
852      * <p>
853      * Clients may call this framework method, but should not override it.
854      * </p>
855      *
856      * @return the dialog area, or <code>null</code> if the dialog area has
857      * not been created yet
858      */

859     protected Control getDialogArea() {
860         return dialogArea;
861     }
862
863     /**
864      * Returns the standard dialog image with the given key. Note that these
865      * images are managed by the dialog framework, and must not be disposed by
866      * another party.
867      *
868      * @param key
869      * one of the <code>Dialog.DLG_IMG_* </code> constants
870      * @return the standard dialog image
871      *
872      * NOTE: Dialog does not use the following images in the registry
873      * DLG_IMG_ERROR DLG_IMG_INFO DLG_IMG_QUESTION DLG_IMG_WARNING
874      *
875      * They are now coming directly from SWT, see ImageRegistry. For backwards
876      * compatibility they are still supported, however new code should use SWT
877      * for these.
878      *
879      * @see Display#getSystemImage(int)
880      */

881     public static Image getImage(String JavaDoc key) {
882         return JFaceResources.getImageRegistry().get(key);
883     }
884
885     /**
886      * Returns the button created when <code>createButton</code> is called
887      * with an ID of <code>IDialogConstants.OK_ID</code>. If
888      * <code>createButton</code> was never called with this parameter, or if
889      * <code>createButton</code> is overridden, <code>getOKButton</code>
890      * will return <code>null</code>.
891      *
892      * @return the OK button or <code>null</code>
893      *
894      * @see #createButton(Composite, int, String, boolean)
895      * @since 2.0
896      * @deprecated Use <code>getButton(IDialogConstants.OK_ID)</code> instead.
897      * This method will be removed soon.
898      */

899     protected Button getOKButton() {
900         return getButton(IDialogConstants.OK_ID);
901     }
902
903     /**
904      * Initializes the computation of horizontal and vertical dialog units based
905      * on the size of current font.
906      * <p>
907      * This method must be called before any of the dialog unit based conversion
908      * methods are called.
909      * </p>
910      *
911      * @param control
912      * a control from which to obtain the current font
913      */

914     protected void initializeDialogUnits(Control control) {
915         // Compute and store a font metric
916
GC gc = new GC(control);
917         gc.setFont(JFaceResources.getDialogFont());
918         fontMetrics = gc.getFontMetrics();
919         gc.dispose();
920     }
921
922     /**
923      * Notifies that the ok button of this dialog has been pressed.
924      * <p>
925      * The <code>Dialog</code> implementation of this framework method sets
926      * this dialog's return code to <code>Window.OK</code> and closes the
927      * dialog. Subclasses may override.
928      * </p>
929      */

930     protected void okPressed() {
931         setReturnCode(OK);
932         close();
933     }
934
935     /**
936      * Set the layout data of the button to a GridData with appropriate heights
937      * and widths.
938      *
939      * @param button
940      */

941     protected void setButtonLayoutData(Button button) {
942         GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
943         int widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
944         Point minSize = button.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
945         data.widthHint = Math.max(widthHint, minSize.x);
946         button.setLayoutData(data);
947     }
948
949     /**
950      * Set the layout data of the button to a FormData with appropriate heights
951      * and widths.
952      *
953      * @param button
954      */

955     protected void setButtonLayoutFormData(Button button) {
956         FormData data = new FormData();
957         int widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
958         Point minSize = button.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
959         data.width = Math.max(widthHint, minSize.x);
960         button.setLayoutData(data);
961     }
962
963     /**
964      * @see org.eclipse.jface.window.Window#close()
965      */

966     public boolean close() {
967         if (getShell() != null && !getShell().isDisposed()) {
968             saveDialogBounds(getShell());
969         }
970
971         boolean returnValue = super.close();
972         if (returnValue) {
973             buttons = new HashMap JavaDoc();
974             buttonBar = null;
975             dialogArea = null;
976         }
977         return returnValue;
978     }
979
980     /**
981      * Applies the dialog font to all controls that currently have the default
982      * font.
983      *
984      * @param control
985      * the control to apply the font to. Font will also be applied to
986      * its children. If the control is <code>null</code> nothing
987      * happens.
988      */

989     public static void applyDialogFont(Control control) {
990         if (control == null || dialogFontIsDefault()) {
991             return;
992         }
993         Font dialogFont = JFaceResources.getDialogFont();
994         applyDialogFont(control, dialogFont);
995     }
996
997     /**
998      * Sets the dialog font on the control and any of its children if thier font
999      * is not otherwise set.
1000     *
1001     * @param control
1002     * the control to apply the font to. Font will also be applied to
1003     * its children.
1004     * @param dialogFont
1005     * the dialog font to set
1006     */

1007    private static void applyDialogFont(Control control, Font dialogFont) {
1008        if (hasDefaultFont(control)) {
1009            control.setFont(dialogFont);
1010        }
1011        if (control instanceof Composite) {
1012            Control[] children = ((Composite) control).getChildren();
1013            for (int i = 0; i < children.length; i++) {
1014                applyDialogFont(children[i], dialogFont);
1015            }
1016        }
1017    }
1018
1019    /**
1020     * Return whether or not this control has the same font as it's default.
1021     *
1022     * @param control
1023     * Control
1024     * @return boolean
1025     */

1026    private static boolean hasDefaultFont(Control control) {
1027        FontData[] controlFontData = control.getFont().getFontData();
1028        FontData[] defaultFontData = getDefaultFont(control).getFontData();
1029        if (controlFontData.length == defaultFontData.length) {
1030            for (int i = 0; i < controlFontData.length; i++) {
1031                if (controlFontData[i].equals(defaultFontData[i])) {
1032                    continue;
1033                }
1034                return false;
1035            }
1036            return true;
1037        }
1038        return false;
1039    }
1040
1041    /**
1042     * Get the default font for this type of control.
1043     *
1044     * @param control
1045     * @return the default font
1046     */

1047    private static Font getDefaultFont(Control control) {
1048        String JavaDoc fontName = "DEFAULT_FONT_" + control.getClass().getName(); //$NON-NLS-1$
1049
if (JFaceResources.getFontRegistry().hasValueFor(fontName)) {
1050            return JFaceResources.getFontRegistry().get(fontName);
1051        }
1052        Font cached = control.getFont();
1053        control.setFont(null);
1054        Font defaultFont = control.getFont();
1055        control.setFont(cached);
1056        JFaceResources.getFontRegistry().put(fontName,
1057                defaultFont.getFontData());
1058        return defaultFont;
1059    }
1060
1061    /**
1062     * Return whether or not the dialog font is currently the same as the
1063     * default font.
1064     *
1065     * @return boolean if the two are the same
1066     */

1067    protected static boolean dialogFontIsDefault() {
1068        FontData[] dialogFontData = JFaceResources.getFontRegistry()
1069                .getFontData(JFaceResources.DIALOG_FONT);
1070        FontData[] defaultFontData = JFaceResources.getFontRegistry()
1071                .getFontData(JFaceResources.DEFAULT_FONT);
1072        return Arrays.equals(dialogFontData, defaultFontData);
1073    }
1074
1075    /*
1076     * (non-Javadoc)
1077     *
1078     * @see org.eclipse.jface.window.Window#create()
1079     */

1080    public void create() {
1081        super.create();
1082        applyDialogFont(buttonBar);
1083    }
1084
1085    /**
1086     * Get the IDialogBlockedHandler to be used by WizardDialogs and
1087     * ModalContexts.
1088     *
1089     * @return Returns the blockedHandler.
1090     */

1091    public static IDialogBlockedHandler getBlockedHandler() {
1092        return blockedHandler;
1093    }
1094
1095    /**
1096     * Set the IDialogBlockedHandler to be used by WizardDialogs and
1097     * ModalContexts.
1098     *
1099     * @param blockedHandler
1100     * The blockedHandler for the dialogs.
1101     */

1102    public static void setBlockedHandler(IDialogBlockedHandler blockedHandler) {
1103        Dialog.blockedHandler = blockedHandler;
1104    }
1105
1106    /**
1107     * Gets the dialog settings that should be used for remembering the bounds of
1108     * of the dialog, according to the dialog bounds strategy.
1109     *
1110     * @return settings the dialog settings used to store the dialog's location
1111     * and/or size, or <code>null</code> if the dialog's bounds should
1112     * never be stored.
1113     *
1114     * @since 3.2
1115     * @see Dialog#getDialogBoundsStrategy()
1116     */

1117    protected IDialogSettings getDialogBoundsSettings() {
1118        return null;
1119    }
1120
1121    /**
1122     * Get the integer constant that describes the strategy for persisting the
1123     * dialog bounds. This strategy is ignored if the implementer does not also
1124     * specify the dialog settings for storing the bounds in
1125     * Dialog.getDialogBoundsSettings().
1126     *
1127     * @return the constant describing the strategy for persisting the dialog
1128     * bounds.
1129     *
1130     * @since 3.2
1131     * @see Dialog#DIALOG_PERSISTLOCATION
1132     * @see Dialog#DIALOG_PERSISTSIZE
1133     * @see Dialog#getDialogBoundsSettings()
1134     */

1135    protected int getDialogBoundsStrategy() {
1136        return DIALOG_PERSISTLOCATION | DIALOG_PERSISTSIZE;
1137    }
1138
1139    /**
1140     * Saves the bounds of the shell in the appropriate dialog settings. The
1141     * bounds are recorded relative to the parent shell, if there is one, or
1142     * display coordinates if there is no parent shell.
1143     *
1144     * @param shell
1145     * The shell whose bounds are to be stored
1146     *
1147     * @since 3.2
1148     */

1149    private void saveDialogBounds(Shell shell) {
1150        IDialogSettings settings = getDialogBoundsSettings();
1151        if (settings != null) {
1152            Point shellLocation = shell.getLocation();
1153            Point shellSize = shell.getSize();
1154            Shell parent = getParentShell();
1155            if (parent != null) {
1156                Point parentLocation = parent.getLocation();
1157                shellLocation.x -= parentLocation.x;
1158                shellLocation.y -= parentLocation.y;
1159            }
1160            int strategy = getDialogBoundsStrategy();
1161            if ((strategy & DIALOG_PERSISTLOCATION) != 0) {
1162                settings.put(DIALOG_ORIGIN_X, shellLocation.x);
1163                settings.put(DIALOG_ORIGIN_Y, shellLocation.y);
1164            }
1165            if ((strategy & DIALOG_PERSISTSIZE) != 0) {
1166                settings.put(DIALOG_WIDTH, shellSize.x);
1167                settings.put(DIALOG_HEIGHT, shellSize.y);
1168                FontData [] fontDatas = JFaceResources.getDialogFont().getFontData();
1169                if (fontDatas.length > 0) {
1170                    settings.put(DIALOG_FONT_DATA, fontDatas[0].toString());
1171                }
1172            }
1173        }
1174    }
1175
1176    /**
1177     * Returns the initial size to use for the shell. Overridden
1178     * to check whether a size has been stored in dialog settings.
1179     * If a size has been stored, it is returned.
1180     *
1181     * @return the initial size of the shell
1182     *
1183     * @since 3.2
1184     * @see #getDialogBoundsSettings()
1185     * @see #getDialogBoundsStrategy()
1186     */

1187    protected Point getInitialSize() {
1188        Point result = super.getInitialSize();
1189        
1190        // Check the dialog settings for a stored size.
1191
if ((getDialogBoundsStrategy() & DIALOG_PERSISTSIZE)!= 0) {
1192            IDialogSettings settings = getDialogBoundsSettings();
1193            if (settings != null) {
1194                // Check that the dialog font matches the font used
1195
// when the bounds was stored. If the font has changed,
1196
// we do not honor the stored settings.
1197
// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=132821
1198
boolean useStoredBounds = true;
1199                String JavaDoc previousDialogFontData = settings.get(DIALOG_FONT_DATA);
1200                // There is a previously stored font, so we will check it.
1201
// Note that if we haven't stored the font before, then we will
1202
// use the stored bounds. This allows restoring of dialog bounds
1203
// that were stored before we started storing the fontdata.
1204
if (previousDialogFontData != null && previousDialogFontData.length() > 0) {
1205                    FontData [] fontDatas = JFaceResources.getDialogFont().getFontData();
1206                    if (fontDatas.length > 0) {
1207                        String JavaDoc currentDialogFontData = fontDatas[0].toString();
1208                        useStoredBounds = currentDialogFontData.equalsIgnoreCase(previousDialogFontData);
1209                    }
1210                }
1211                if (useStoredBounds) {
1212                    try {
1213                        // Get the stored width and height.
1214
int width = settings.getInt(DIALOG_WIDTH);
1215                        if (width != DIALOG_DEFAULT_BOUNDS) {
1216                            result.x = width;
1217                        }
1218                        int height = settings.getInt(DIALOG_HEIGHT);
1219                        if (height != DIALOG_DEFAULT_BOUNDS) {
1220                            result.y = height;
1221                        }
1222        
1223                    } catch (NumberFormatException JavaDoc e) {
1224                    }
1225                }
1226            }
1227        }
1228        // No attempt is made to constrain the bounds. The default
1229
// constraining behavior in Window will be used.
1230
return result;
1231    }
1232
1233    /**
1234     * Returns the initial location to use for the shell. Overridden
1235     * to check whether the bounds of the dialog have been stored in
1236     * dialog settings. If a location has been stored, it is returned.
1237     *
1238     * @param initialSize
1239     * the initial size of the shell, as returned by
1240     * <code>getInitialSize</code>.
1241     * @return the initial location of the shell
1242     *
1243     * @since 3.2
1244     * @see #getDialogBoundsSettings()
1245     * @see #getDialogBoundsStrategy()
1246     */

1247    protected Point getInitialLocation(Point initialSize) {
1248        Point result = super.getInitialLocation(initialSize);
1249        if ((getDialogBoundsStrategy() & DIALOG_PERSISTLOCATION)!= 0) {
1250            IDialogSettings settings = getDialogBoundsSettings();
1251            if (settings != null) {
1252                try {
1253                    int x = settings.getInt(DIALOG_ORIGIN_X);
1254                    int y = settings.getInt(DIALOG_ORIGIN_Y);
1255                    result = new Point(x, y);
1256                    // The coordinates were stored relative to the parent shell.
1257
// Convert to display coordinates.
1258
Shell parent = getParentShell();
1259                    if (parent != null) {
1260                        Point parentLocation = parent.getLocation();
1261                        result.x += parentLocation.x;
1262                        result.y += parentLocation.y;
1263                    }
1264                } catch (NumberFormatException JavaDoc e) {
1265                }
1266            }
1267        }
1268        // No attempt is made to constrain the bounds. The default
1269
// constraining behavior in Window will be used.
1270
return result;
1271    }
1272}
1273
Popular Tags