| /******************************************************************************* |
| * Copyright (c) 2000, 2005 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jface.dialogs; |
| |
| import java.util.Arrays; |
| import java.util.HashMap; |
| |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.jface.resource.ImageDescriptor; |
| import org.eclipse.jface.resource.ImageRegistry; |
| import org.eclipse.jface.resource.JFaceResources; |
| import org.eclipse.jface.util.Policy; |
| import org.eclipse.jface.window.IShellProvider; |
| import org.eclipse.jface.window.SameShellProvider; |
| import org.eclipse.jface.window.Window; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.MouseAdapter; |
| import org.eclipse.swt.events.MouseEvent; |
| import org.eclipse.swt.events.MouseListener; |
| import org.eclipse.swt.events.SelectionAdapter; |
| import org.eclipse.swt.events.SelectionEvent; |
| import org.eclipse.swt.graphics.Font; |
| import org.eclipse.swt.graphics.FontData; |
| import org.eclipse.swt.graphics.FontMetrics; |
| import org.eclipse.swt.graphics.GC; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.swt.graphics.Point; |
| import org.eclipse.swt.graphics.Rectangle; |
| import org.eclipse.swt.layout.FormData; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.widgets.Button; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Shell; |
| |
| /** |
| * A dialog is a specialized window used for narrow-focused communication with |
| * the user. |
| * <p> |
| * Dialogs are usually modal. Consequently, it is generally bad practice to open |
| * a dialog without a parent. A modal dialog without a parent is not prevented |
| * from disappearing behind the application's other windows, making it very |
| * confusing for the user. |
| * </p> |
| * <p> |
| * If there is more than one modal dialog is open the second one should be |
| * parented off of the shell of the first one otherwise it is possible that the |
| * OS will give focus to the first dialog potentially blocking the UI. |
| * </p> |
| */ |
| public abstract class Dialog extends Window { |
| /** |
| * Image registry key for error image (value |
| * <code>"dialog_error_image"</code>). |
| * |
| * @deprecated use |
| * org.eclipse.swt.widgets.Display.getSystemImage(SWT.ICON_ERROR) |
| */ |
| public static final String DLG_IMG_ERROR = "dialog_error_image"; //$NON-NLS-1$ |
| |
| /** |
| * Image registry key for info image (value <code>"dialog_info_image"</code>). |
| * |
| * @deprecated use |
| * org.eclipse.swt.widgets.Display.getSystemImage(SWT.ICON_INFORMATION) |
| */ |
| public static final String DLG_IMG_INFO = "dialog_info_imageg"; //$NON-NLS-1$ |
| |
| /** |
| * Image registry key for question image (value |
| * <code>"dialog_question_image"</code>). |
| * |
| * @deprecated org.eclipse.swt.widgets.Display.getSystemImage(SWT.ICON_QUESTION) |
| */ |
| public static final String DLG_IMG_QUESTION = "dialog_question_image"; //$NON-NLS-1$ |
| |
| /** |
| * Image registry key for warning image (value |
| * <code>"dialog_warning_image"</code>). |
| * |
| * @deprecated use |
| * org.eclipse.swt.widgets.Display.getSystemImage(SWT.ICON_WARNING) |
| */ |
| public static final String DLG_IMG_WARNING = "dialog_warning_image"; //$NON-NLS-1$ |
| |
| /** |
| * Image registry key for info message image (value |
| * <code>"dialog_messasge_info_image"</code>). |
| * |
| * @since 2.0 |
| */ |
| public static final String DLG_IMG_MESSAGE_INFO = "dialog_messasge_info_image"; //$NON-NLS-1$ |
| |
| /** |
| * Image registry key for info message image (value |
| * <code>"dialog_messasge_warning_image"</code>). |
| * |
| * @since 2.0 |
| */ |
| public static final String DLG_IMG_MESSAGE_WARNING = "dialog_messasge_warning_image"; //$NON-NLS-1$ |
| |
| /** |
| * Image registry key for info message image (value |
| * <code>"dialog_message_error_image"</code>). |
| * |
| * @since 2.0 |
| */ |
| public static final String DLG_IMG_MESSAGE_ERROR = "dialog_message_error_image"; //$NON-NLS-1$ |
| |
| /** |
| * The ellipsis is the string that is used to represent shortened text. |
| * |
| * @since 3.0 |
| */ |
| public static final String ELLIPSIS = "..."; //$NON-NLS-1$ |
| |
| /** |
| * The dialog settings key name for stored dialog x location. |
| * |
| * @since 3.2 |
| */ |
| private static final String DIALOG_ORIGIN_X = "DIALOG_X_ORIGIN"; //$NON-NLS-1$ |
| |
| /** |
| * The dialog settings key name for stored dialog y location. |
| * |
| * @since 3.2 |
| */ |
| private static final String DIALOG_ORIGIN_Y = "DIALOG_Y_ORIGIN"; //$NON-NLS-1$ |
| |
| /** |
| * The dialog settings key name for stored dialog width. |
| * |
| * @since 3.2 |
| */ |
| private static final String DIALOG_WIDTH = "DIALOG_WIDTH"; //$NON-NLS-1$ |
| |
| /** |
| * The dialog settings key name for stored dialog height. |
| * |
| * @since 3.2 |
| */ |
| private static final String DIALOG_HEIGHT = "DIALOG_HEIGHT"; //$NON-NLS-1$ |
| |
| /** |
| * A value that can be used for stored dialog width or height that |
| * indicates that the default bounds should be used. |
| * |
| * @since 3.2 |
| */ |
| public static final int DIALOG_DEFAULT_BOUNDS = -1; |
| |
| /** |
| * Constants that can be used for specifying the strategy for persisting |
| * dialog bounds. These constants represent bit masks that can be used |
| * together. |
| * |
| *@since 3.2 |
| */ |
| |
| /** |
| * Persist the last location of the dialog. |
| * @since 3.2 |
| */ |
| public static final int DIALOG_PERSISTLOCATION = 0x0001; |
| /** |
| * Persist the last known size of the dialog. |
| * @since 3.2 |
| */ |
| public static final int DIALOG_PERSISTSIZE = 0x0002; |
| |
| |
| /** |
| * NOTE: Dialog does not the following images in the registry DLG_IMG_ERROR |
| * DLG_IMG_INFO DLG_IMG_QUESTION DLG_IMG_WARNING |
| * |
| * They are now coming directly from SWT see ImageRegistry. For backwards |
| * compatibility they are still supported, however new code should use SWT |
| * for these. |
| * |
| * @see Display#getSystemIcon(int ID) |
| */ |
| static { |
| ImageRegistry reg = JFaceResources.getImageRegistry(); |
| reg.put(DLG_IMG_MESSAGE_INFO, ImageDescriptor.createFromFile( |
| Dialog.class, "images/message_info.gif")); //$NON-NLS-1$ |
| reg.put(DLG_IMG_MESSAGE_WARNING, ImageDescriptor.createFromFile( |
| Dialog.class, "images/message_warning.gif")); //$NON-NLS-1$ |
| reg.put(DLG_IMG_MESSAGE_ERROR, ImageDescriptor.createFromFile( |
| Dialog.class, "images/message_error.gif")); //$NON-NLS-1$ |
| } |
| |
| /** |
| * The dialog area; <code>null</code> until dialog is layed out. |
| */ |
| protected Control dialogArea; |
| |
| /** |
| * The button bar; <code>null</code> until dialog is layed out. |
| */ |
| public Control buttonBar; |
| |
| /** |
| * A mouse listener that can be used to restore the default size |
| * of a dialog. |
| * |
| * @since 3.2 |
| */ |
| private MouseListener restoreSizeMouseListener = new MouseAdapter() { |
| public void mouseDoubleClick(MouseEvent event) { |
| restoreDialogToComputedSize(); |
| } |
| }; |
| |
| /** |
| * Collection of buttons created by the <code>createButton</code> method. |
| */ |
| private HashMap buttons = new HashMap(); |
| |
| /** |
| * Font metrics to use for determining pixel sizes. |
| */ |
| private FontMetrics fontMetrics; |
| |
| /** |
| * Point used for storing initial computed size of the dialog so |
| * that it may be restored. |
| */ |
| private Point computedSize; |
| |
| /** |
| * Number of horizontal dialog units per character, value <code>4</code>. |
| */ |
| private static final int HORIZONTAL_DIALOG_UNIT_PER_CHAR = 4; |
| |
| /** |
| * Number of vertical dialog units per character, value <code>8</code>. |
| */ |
| private static final int VERTICAL_DIALOG_UNITS_PER_CHAR = 8; |
| |
| /** |
| * Returns the number of pixels corresponding to the height of the given |
| * number of characters. |
| * <p> |
| * The required <code>FontMetrics</code> parameter may be created in the |
| * following way: <code> |
| * GC gc = new GC(control); |
| * gc.setFont(control.getFont()); |
| * fontMetrics = gc.getFontMetrics(); |
| * gc.dispose(); |
| * </code> |
| * </p> |
| * |
| * @param fontMetrics |
| * used in performing the conversion |
| * @param chars |
| * the number of characters |
| * @return the number of pixels |
| * @since 2.0 |
| */ |
| public static int convertHeightInCharsToPixels(FontMetrics fontMetrics, |
| int chars) { |
| return fontMetrics.getHeight() * chars; |
| } |
| |
| /** |
| * Returns the number of pixels corresponding to the given number of |
| * horizontal dialog units. |
| * <p> |
| * The required <code>FontMetrics</code> parameter may be created in the |
| * following way: <code> |
| * GC gc = new GC(control); |
| * gc.setFont(control.getFont()); |
| * fontMetrics = gc.getFontMetrics(); |
| * gc.dispose(); |
| * </code> |
| * </p> |
| * |
| * @param fontMetrics |
| * used in performing the conversion |
| * @param dlus |
| * the number of horizontal dialog units |
| * @return the number of pixels |
| * @since 2.0 |
| */ |
| public static int convertHorizontalDLUsToPixels(FontMetrics fontMetrics, |
| int dlus) { |
| // round to the nearest pixel |
| return (fontMetrics.getAverageCharWidth() * dlus + HORIZONTAL_DIALOG_UNIT_PER_CHAR / 2) |
| / HORIZONTAL_DIALOG_UNIT_PER_CHAR; |
| } |
| |
| /** |
| * Returns the number of pixels corresponding to the given number of |
| * vertical dialog units. |
| * <p> |
| * The required <code>FontMetrics</code> parameter may be created in the |
| * following way: <code> |
| * GC gc = new GC(control); |
| * gc.setFont(control.getFont()); |
| * fontMetrics = gc.getFontMetrics(); |
| * gc.dispose(); |
| * </code> |
| * </p> |
| * |
| * @param fontMetrics |
| * used in performing the conversion |
| * @param dlus |
| * the number of vertical dialog units |
| * @return the number of pixels |
| * @since 2.0 |
| */ |
| public static int convertVerticalDLUsToPixels(FontMetrics fontMetrics, |
| int dlus) { |
| // round to the nearest pixel |
| return (fontMetrics.getHeight() * dlus + VERTICAL_DIALOG_UNITS_PER_CHAR / 2) |
| / VERTICAL_DIALOG_UNITS_PER_CHAR; |
| } |
| |
| /** |
| * Returns the number of pixels corresponding to the width of the given |
| * number of characters. |
| * <p> |
| * The required <code>FontMetrics</code> parameter may be created in the |
| * following way: <code> |
| * GC gc = new GC(control); |
| * gc.setFont(control.getFont()); |
| * fontMetrics = gc.getFontMetrics(); |
| * gc.dispose(); |
| * </code> |
| * </p> |
| * |
| * @param fontMetrics |
| * used in performing the conversion |
| * @param chars |
| * the number of characters |
| * @return the number of pixels |
| * @since 2.0 |
| */ |
| public static int convertWidthInCharsToPixels(FontMetrics fontMetrics, |
| int chars) { |
| return fontMetrics.getAverageCharWidth() * chars; |
| } |
| |
| /** |
| * Shortens the given text <code>textValue</code> so that its width in |
| * pixels does not exceed the width of the given control. Overrides |
| * characters in the center of the original string with an ellipsis ("...") |
| * if necessary. If a <code>null</code> value is given, <code>null</code> |
| * is returned. |
| * |
| * @param textValue |
| * the original string or <code>null</code> |
| * @param control |
| * the control the string will be displayed on |
| * @return the string to display, or <code>null</code> if null was passed |
| * in |
| * |
| * @since 3.0 |
| */ |
| public static String shortenText(String textValue, Control control) { |
| if (textValue == null) |
| return null; |
| GC gc = new GC(control); |
| int maxWidth = control.getBounds().width - 5; |
| if (gc.textExtent(textValue).x < maxWidth) { |
| gc.dispose(); |
| return textValue; |
| } |
| int length = textValue.length(); |
| int pivot = length / 2; |
| int start = pivot; |
| int end = pivot + 1; |
| while (start >= 0 && end < length) { |
| String s1 = textValue.substring(0, start); |
| String s2 = textValue.substring(end, length); |
| String s = s1 + ELLIPSIS + s2; |
| int l = gc.textExtent(s).x; |
| if (l < maxWidth) { |
| gc.dispose(); |
| return s; |
| } |
| start--; |
| end++; |
| } |
| gc.dispose(); |
| return textValue; |
| } |
| |
| /** |
| * Create a default instance of the blocked handler which does not do |
| * anything. |
| */ |
| public static IDialogBlockedHandler blockedHandler = new IDialogBlockedHandler() { |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.jface.dialogs.IDialogBlockedHandler#clearBlocked() |
| */ |
| public void clearBlocked() { |
| // No default behaviour |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.jface.dialogs.IDialogBlockedHandler#showBlocked(org.eclipse.core.runtime.IProgressMonitor, |
| * org.eclipse.core.runtime.IStatus, java.lang.String) |
| */ |
| public void showBlocked(IProgressMonitor blocking, |
| IStatus blockingStatus, String blockedName) { |
| // No default behaviour |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.jface.dialogs.IDialogBlockedHandler#showBlocked(org.eclipse.swt.widgets.Shell, |
| * org.eclipse.core.runtime.IProgressMonitor, |
| * org.eclipse.core.runtime.IStatus, java.lang.String) |
| */ |
| public void showBlocked(Shell parentShell, IProgressMonitor blocking, |
| IStatus blockingStatus, String blockedName) { |
| // No default behaviour |
| } |
| }; |
| |
| /** |
| * Creates a dialog instance. Note that the window will have no visual |
| * representation (no widgets) until it is told to open. By default, |
| * <code>open</code> blocks for dialogs. |
| * |
| * @param parentShell |
| * the parent shell, or <code>null</code> to create a top-level |
| * shell |
| */ |
| protected Dialog(Shell parentShell) { |
| this(new SameShellProvider(parentShell)); |
| if (parentShell == null && Policy.DEBUG_DIALOG_NO_PARENT) |
| Policy.getLog().log( |
| new Status(IStatus.INFO, Policy.JFACE, IStatus.INFO, this |
| .getClass() |
| + " created with no shell",//$NON-NLS-1$ |
| new Exception())); |
| } |
| |
| /** |
| * Creates a dialog with the given parent. |
| * |
| * @param parentShell |
| * object that returns the current parent shell |
| * |
| * @since 3.1 |
| */ |
| protected Dialog(IShellProvider parentShell) { |
| super(parentShell); |
| setShellStyle(SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL |
| | getDefaultOrientation()); |
| setBlockOnOpen(true); |
| } |
| |
| /** |
| * Notifies that this dialog's button with the given id has been pressed. |
| * <p> |
| * The <code>Dialog</code> implementation of this framework method calls |
| * <code>okPressed</code> if the ok button is the pressed, and |
| * <code>cancelPressed</code> if the cancel button is the pressed. All |
| * other button presses are ignored. Subclasses may override to handle other |
| * buttons, but should call <code>super.buttonPressed</code> if the |
| * default handling of the ok and cancel buttons is desired. |
| * </p> |
| * |
| * @param buttonId |
| * the id of the button that was pressed (see |
| * <code>IDialogConstants.*_ID</code> constants) |
| */ |
| protected void buttonPressed(int buttonId) { |
| if (IDialogConstants.OK_ID == buttonId) |
| okPressed(); |
| else if (IDialogConstants.CANCEL_ID == buttonId) |
| cancelPressed(); |
| } |
| |
| /** |
| * Notifies that the cancel button of this dialog has been pressed. |
| * <p> |
| * The <code>Dialog</code> implementation of this framework method sets |
| * this dialog's return code to <code>Window.CANCEL</code> and closes the |
| * dialog. Subclasses may override if desired. |
| * </p> |
| */ |
| protected void cancelPressed() { |
| setReturnCode(CANCEL); |
| close(); |
| } |
| |
| /** |
| * Returns the number of pixels corresponding to the height of the given |
| * number of characters. |
| * <p> |
| * This method may only be called after <code>initializeDialogUnits</code> |
| * has been called. |
| * </p> |
| * <p> |
| * Clients may call this framework method, but should not override it. |
| * </p> |
| * |
| * @param chars |
| * the number of characters |
| * @return the number of pixels |
| */ |
| protected int convertHeightInCharsToPixels(int chars) { |
| // test for failure to initialize for backward compatibility |
| if (fontMetrics == null) |
| return 0; |
| return convertHeightInCharsToPixels(fontMetrics, chars); |
| } |
| |
| /** |
| * Returns the number of pixels corresponding to the given number of |
| * horizontal dialog units. |
| * <p> |
| * This method may only be called after <code>initializeDialogUnits</code> |
| * has been called. |
| * </p> |
| * <p> |
| * Clients may call this framework method, but should not override it. |
| * </p> |
| * |
| * @param dlus |
| * the number of horizontal dialog units |
| * @return the number of pixels |
| */ |
| protected int convertHorizontalDLUsToPixels(int dlus) { |
| // test for failure to initialize for backward compatibility |
| if (fontMetrics == null) |
| return 0; |
| return convertHorizontalDLUsToPixels(fontMetrics, dlus); |
| } |
| |
| /** |
| * Returns the number of pixels corresponding to the given number of |
| * vertical dialog units. |
| * <p> |
| * This method may only be called after <code>initializeDialogUnits</code> |
| * has been called. |
| * </p> |
| * <p> |
| * Clients may call this framework method, but should not override it. |
| * </p> |
| * |
| * @param dlus |
| * the number of vertical dialog units |
| * @return the number of pixels |
| */ |
| protected int convertVerticalDLUsToPixels(int dlus) { |
| // test for failure to initialize for backward compatibility |
| if (fontMetrics == null) |
| return 0; |
| return convertVerticalDLUsToPixels(fontMetrics, dlus); |
| } |
| |
| /** |
| * Returns the number of pixels corresponding to the width of the given |
| * number of characters. |
| * <p> |
| * This method may only be called after <code>initializeDialogUnits</code> |
| * has been called. |
| * </p> |
| * <p> |
| * Clients may call this framework method, but should not override it. |
| * </p> |
| * |
| * @param chars |
| * the number of characters |
| * @return the number of pixels |
| */ |
| protected int convertWidthInCharsToPixels(int chars) { |
| // test for failure to initialize for backward compatibility |
| if (fontMetrics == null) |
| return 0; |
| return convertWidthInCharsToPixels(fontMetrics, chars); |
| } |
| |
| /** |
| * Creates a new button with the given id. |
| * <p> |
| * The <code>Dialog</code> implementation of this framework method creates |
| * a standard push button, registers it for selection events including |
| * button presses, and registers default buttons with its shell. The button |
| * id is stored as the button's client data. If the button id is |
| * <code>IDialogConstants.CANCEL_ID</code>, the new button will be |
| * accessible from <code>getCancelButton()</code>. If the button id is |
| * <code>IDialogConstants.OK_ID</code>, the new button will be accesible |
| * from <code>getOKButton()</code>. Note that the parent's layout is |
| * assumed to be a <code>GridLayout</code> and the number of columns in |
| * this layout is incremented. Subclasses may override. |
| * </p> |
| * |
| * @param parent |
| * the parent composite |
| * @param id |
| * the id of the button (see <code>IDialogConstants.*_ID</code> |
| * constants for standard dialog button ids) |
| * @param label |
| * the label from the button |
| * @param defaultButton |
| * <code>true</code> if the button is to be the default button, |
| * and <code>false</code> otherwise |
| * |
| * @return the new button |
| * |
| * @see #getCancelButton |
| * @see #getOKButton() |
| */ |
| protected Button createButton(Composite parent, int id, String label, |
| boolean defaultButton) { |
| // increment the number of columns in the button bar |
| ((GridLayout) parent.getLayout()).numColumns++; |
| Button button = new Button(parent, SWT.PUSH); |
| button.setText(label); |
| button.setFont(JFaceResources.getDialogFont()); |
| button.setData(new Integer(id)); |
| button.addSelectionListener(new SelectionAdapter() { |
| public void widgetSelected(SelectionEvent event) { |
| buttonPressed(((Integer) event.widget.getData()).intValue()); |
| } |
| }); |
| if (defaultButton) { |
| Shell shell = parent.getShell(); |
| if (shell != null) { |
| shell.setDefaultButton(button); |
| } |
| } |
| buttons.put(new Integer(id), button); |
| setButtonLayoutData(button); |
| return button; |
| } |
| |
| /** |
| * Creates and returns the contents of this dialog's button bar. |
| * <p> |
| * The <code>Dialog</code> implementation of this framework method lays |
| * out a button bar and calls the <code>createButtonsForButtonBar</code> |
| * framework method to populate it. Subclasses may override. |
| * </p> |
| * <p> |
| * The returned control's layout data must be an instance of |
| * <code>GridData</code>. |
| * </p> |
| * |
| * @param parent |
| * the parent composite to contain the button bar |
| * @return the button bar control |
| */ |
| protected Control createButtonBar(Composite parent) { |
| Composite composite = new Composite(parent, SWT.NONE); |
| // create a layout with spacing and margins appropriate for the font |
| // size. |
| GridLayout layout = new GridLayout(); |
| layout.numColumns = 0; // this is incremented by createButton |
| layout.makeColumnsEqualWidth = true; |
| layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN); |
| layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN); |
| layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING); |
| layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING); |
| composite.setLayout(layout); |
| GridData data = new GridData(GridData.HORIZONTAL_ALIGN_END |
| | GridData.VERTICAL_ALIGN_CENTER); |
| composite.setLayoutData(data); |
| composite.setFont(parent.getFont()); |
| |
| // Add the buttons to the button bar. |
| createButtonsForButtonBar(composite); |
| return composite; |
| } |
| |
| /** |
| * Adds buttons to this dialog's button bar. |
| * <p> |
| * The <code>Dialog</code> implementation of this framework method adds |
| * standard ok and cancel buttons using the <code>createButton</code> |
| * framework method. These standard buttons will be accessible from |
| * <code>getCancelButton</code>, and <code>getOKButton</code>. |
| * Subclasses may override. |
| * </p> |
| * |
| * @param parent |
| * the button bar composite |
| */ |
| protected void createButtonsForButtonBar(Composite parent) { |
| // create OK and Cancel buttons by default |
| createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, |
| true); |
| createButton(parent, IDialogConstants.CANCEL_ID, |
| IDialogConstants.CANCEL_LABEL, false); |
| } |
| |
| /* |
| * @see Window.initializeBounds() |
| */ |
| protected void initializeBounds() { |
| String platform = SWT.getPlatform(); |
| if ("carbon".equals(platform)) { //$NON-NLS-1$ |
| // On Mac OS X the default button must be the right-most button |
| Shell shell = getShell(); |
| if (shell != null) { |
| Button defaultButton = shell.getDefaultButton(); |
| if (defaultButton != null |
| && isContained(buttonBar, defaultButton)) |
| defaultButton.moveBelow(null); |
| } |
| } |
| |
| // Store the computed size for the dialog. Must be done here before |
| // any dialog settings are applied. We don't do this in the create methods |
| // because the dialog font is applied after creation and before the bounds |
| // are initialized. |
| computedSize = getShell().computeSize(SWT.DEFAULT, SWT.DEFAULT, true); |
| |
| super.initializeBounds(); |
| } |
| |
| /** |
| * Returns true if the given Control is a direct or indirect child of |
| * container. |
| * |
| * @param container |
| * the potential parent |
| * @param control |
| * @return boolean <code>true</code> if control is a child of container |
| */ |
| private boolean isContained(Control container, Control control) { |
| Composite parent; |
| while ((parent = control.getParent()) != null) { |
| if (parent == container) |
| return true; |
| control = parent; |
| } |
| return false; |
| } |
| |
| /** |
| * The <code>Dialog</code> implementation of this <code>Window</code> |
| * method creates and lays out the top level composite for the dialog, and |
| * determines the appropriate horizontal and vertical dialog units based on |
| * the font size. It then calls the <code>createDialogArea</code> and |
| * <code>createButtonBar</code> methods to create the dialog area and |
| * button bar, respectively. Overriding <code>createDialogArea</code> and |
| * <code>createButtonBar</code> are recommended rather than overriding |
| * this method. |
| */ |
| protected Control createContents(Composite parent) { |
| // create the top level composite for the dialog |
| Composite composite = new Composite(parent, 0); |
| GridLayout layout = new GridLayout(); |
| layout.marginHeight = 0; |
| layout.marginWidth = 0; |
| layout.verticalSpacing = 0; |
| composite.setLayout(layout); |
| composite.setLayoutData(new GridData(GridData.FILL_BOTH)); |
| applyDialogFont(composite); |
| // initialize the dialog units |
| initializeDialogUnits(composite); |
| // create the dialog area and button bar |
| dialogArea = createDialogArea(composite); |
| buttonBar = createButtonBar(composite); |
| |
| return composite; |
| } |
| |
| /** |
| * Creates and returns the contents of the upper part of this dialog (above |
| * the button bar). |
| * <p> |
| * The <code>Dialog</code> implementation of this framework method creates |
| * and returns a new <code>Composite</code> with standard margins and |
| * spacing. |
| * </p> |
| * <p> |
| * The returned control's layout data must be an instance of |
| * <code>GridData</code>. This method must not modify the parent's |
| * layout. |
| * </p> |
| * <p> |
| * Subclasses must override this method but may call <code>super</code> as |
| * in the following example: |
| * </p> |
| * |
| * <pre> |
| * Composite composite = (Composite) super.createDialogArea(parent); |
| * //add controls to composite as necessary |
| * return composite; |
| * </pre> |
| * |
| * @param parent |
| * the parent composite to contain the dialog area |
| * @return the dialog area control |
| */ |
| protected Control createDialogArea(Composite parent) { |
| // create a composite with standard margins and spacing |
| Composite composite = new Composite(parent, SWT.NONE); |
| GridLayout layout = new GridLayout(); |
| layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN); |
| layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN); |
| layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING); |
| layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING); |
| composite.setLayout(layout); |
| composite.setLayoutData(new GridData(GridData.FILL_BOTH)); |
| applyDialogFont(composite); |
| return composite; |
| } |
| |
| /** |
| * Returns the button created by the method <code>createButton</code> for |
| * the specified ID as defined on <code>IDialogConstants</code>. If |
| * <code>createButton</code> was never called with this ID, or if |
| * <code>createButton</code> is overridden, this method will return |
| * <code>null</code>. |
| * |
| * @param id |
| * the id of the button to look for |
| * |
| * @return the button for the ID or <code>null</code> |
| * |
| * @see #createButton(Composite, int, String, boolean) |
| * @since 2.0 |
| */ |
| protected Button getButton(int id) { |
| return (Button) buttons.get(new Integer(id)); |
| } |
| |
| /** |
| * Returns the button bar control. |
| * <p> |
| * Clients may call this framework method, but should not override it. |
| * </p> |
| * |
| * @return the button bar, or <code>null</code> if the button bar has not |
| * been created yet |
| */ |
| protected Control getButtonBar() { |
| return buttonBar; |
| } |
| |
| /** |
| * Returns the button created when <code>createButton</code> is called |
| * with an ID of <code>IDialogConstants.CANCEL_ID</code>. If |
| * <code>createButton</code> was never called with this parameter, or if |
| * <code>createButton</code> is overridden, <code>getCancelButton</code> |
| * will return <code>null</code>. |
| * |
| * @return the cancel button or <code>null</code> |
| * |
| * @see #createButton(Composite, int, String, boolean) |
| * @since 2.0 |
| * @deprecated Use <code>getButton(IDialogConstants.CANCEL_ID)</code> |
| * instead. This method will be removed soon. |
| */ |
| protected Button getCancelButton() { |
| return getButton(IDialogConstants.CANCEL_ID); |
| } |
| |
| /** |
| * Returns the dialog area control. |
| * <p> |
| * Clients may call this framework method, but should not override it. |
| * </p> |
| * |
| * @return the dialog area, or <code>null</code> if the dialog area has |
| * not been created yet |
| */ |
| protected Control getDialogArea() { |
| return dialogArea; |
| } |
| |
| /** |
| * Returns the standard dialog image with the given key. Note that these |
| * images are managed by the dialog framework, and must not be disposed by |
| * another party. |
| * |
| * @param key |
| * one of the <code>Dialog.DLG_IMG_* </code> constants |
| * @return the standard dialog image |
| */ |
| public static Image getImage(String key) { |
| return JFaceResources.getImageRegistry().get(key); |
| } |
| |
| /** |
| * Returns the button created when <code>createButton</code> is called |
| * with an ID of <code>IDialogConstants.OK_ID</code>. If |
| * <code>createButton</code> was never called with this parameter, or if |
| * <code>createButton</code> is overridden, <code>getOKButton</code> |
| * will return <code>null</code>. |
| * |
| * @return the OK button or <code>null</code> |
| * |
| * @see #createButton(Composite, int, String, boolean) |
| * @since 2.0 |
| * @deprecated Use <code>getButton(IDialogConstants.OK_ID)</code> instead. |
| * This method will be removed soon. |
| */ |
| protected Button getOKButton() { |
| return getButton(IDialogConstants.OK_ID); |
| } |
| |
| /** |
| * Initializes the computation of horizontal and vertical dialog units based |
| * on the size of current font. |
| * <p> |
| * This method must be called before any of the dialog unit based conversion |
| * methods are called. |
| * </p> |
| * |
| * @param control |
| * a control from which to obtain the current font |
| */ |
| protected void initializeDialogUnits(Control control) { |
| // Compute and store a font metric |
| GC gc = new GC(control); |
| gc.setFont(JFaceResources.getDialogFont()); |
| fontMetrics = gc.getFontMetrics(); |
| gc.dispose(); |
| } |
| |
| /** |
| * Notifies that the ok button of this dialog has been pressed. |
| * <p> |
| * The <code>Dialog</code> implementation of this framework method sets |
| * this dialog's return code to <code>Window.OK</code> and closes the |
| * dialog. Subclasses may override. |
| * </p> |
| */ |
| protected void okPressed() { |
| setReturnCode(OK); |
| close(); |
| } |
| |
| /** |
| * Set the layout data of the button to a GridData with appropriate heights |
| * and widths. |
| * |
| * @param button |
| */ |
| protected void setButtonLayoutData(Button button) { |
| GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL); |
| int widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH); |
| Point minSize = button.computeSize(SWT.DEFAULT, SWT.DEFAULT, true); |
| data.widthHint = Math.max(widthHint, minSize.x); |
| button.setLayoutData(data); |
| } |
| |
| /** |
| * Set the layout data of the button to a FormData with appropriate heights |
| * and widths. |
| * |
| * @param button |
| */ |
| protected void setButtonLayoutFormData(Button button) { |
| FormData data = new FormData(); |
| int widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH); |
| Point minSize = button.computeSize(SWT.DEFAULT, SWT.DEFAULT, true); |
| data.width = Math.max(widthHint, minSize.x); |
| button.setLayoutData(data); |
| } |
| |
| /** |
| * @see org.eclipse.jface.window.Window#close() |
| */ |
| public boolean close() { |
| if (getShell() != null && !getShell().isDisposed()) |
| saveDialogBounds(getShell()); |
| |
| removeRestoreSizeMouseListeners(); |
| |
| boolean returnValue = super.close(); |
| if (returnValue) { |
| buttons = new HashMap(); |
| buttonBar = null; |
| dialogArea = null; |
| } |
| return returnValue; |
| } |
| |
| /** |
| * Applies the dialog font to all controls that currently have the default |
| * font. |
| * |
| * @param control |
| * the control to apply the font to. Font will also be applied to |
| * its children. If the control is <code>null</code> nothing |
| * happens. |
| */ |
| public static void applyDialogFont(Control control) { |
| if (control == null || dialogFontIsDefault()) |
| return; |
| Font dialogFont = JFaceResources.getDialogFont(); |
| applyDialogFont(control, dialogFont); |
| } |
| |
| /** |
| * Sets the dialog font on the control and any of its children if thier font |
| * is not otherwise set. |
| * |
| * @param control |
| * the control to apply the font to. Font will also be applied to |
| * its children. |
| * @param dialogFont |
| * the dialog font to set |
| */ |
| private static void applyDialogFont(Control control, Font dialogFont) { |
| if (hasDefaultFont(control)) |
| control.setFont(dialogFont); |
| if (control instanceof Composite) { |
| Control[] children = ((Composite) control).getChildren(); |
| for (int i = 0; i < children.length; i++) |
| applyDialogFont(children[i], dialogFont); |
| } |
| } |
| |
| /** |
| * Return whether or not this control has the same font as it's default. |
| * |
| * @param control |
| * Control |
| * @return boolean |
| */ |
| private static boolean hasDefaultFont(Control control) { |
| FontData[] controlFontData = control.getFont().getFontData(); |
| FontData[] defaultFontData = getDefaultFont(control).getFontData(); |
| if (controlFontData.length == defaultFontData.length) { |
| for (int i = 0; i < controlFontData.length; i++) { |
| if (controlFontData[i].equals(defaultFontData[i])) |
| continue; |
| return false; |
| } |
| return true; |
| } |
| return false; |
| } |
| |
| /** |
| * Get the default font for this type of control. |
| * |
| * @param control |
| * @return the default font |
| */ |
| private static Font getDefaultFont(Control control) { |
| String fontName = "DEFAULT_FONT_" + control.getClass().getName(); //$NON-NLS-1$ |
| if (JFaceResources.getFontRegistry().hasValueFor(fontName)) |
| return JFaceResources.getFontRegistry().get(fontName); |
| Font cached = control.getFont(); |
| control.setFont(null); |
| Font defaultFont = control.getFont(); |
| control.setFont(cached); |
| JFaceResources.getFontRegistry().put(fontName, |
| defaultFont.getFontData()); |
| return defaultFont; |
| } |
| |
| /** |
| * Return whether or not the dialog font is currently the same as the |
| * default font. |
| * |
| * @return boolean if the two are the same |
| */ |
| protected static boolean dialogFontIsDefault() { |
| FontData[] dialogFontData = JFaceResources.getFontRegistry() |
| .getFontData(JFaceResources.DIALOG_FONT); |
| FontData[] defaultFontData = JFaceResources.getFontRegistry() |
| .getFontData(JFaceResources.DEFAULT_FONT); |
| return Arrays.equals(dialogFontData, defaultFontData); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.jface.window.Window#create() |
| */ |
| public void create() { |
| super.create(); |
| applyDialogFont(buttonBar); |
| |
| // Register a mouse listener so that the user can restore this |
| // size with a double-click. |
| // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=116906 |
| addRestoreSizeMouseListeners(); |
| } |
| |
| /** |
| * Get the IDialogBlockedHandler to be used by WizardDialogs and |
| * ModalContexts. |
| * |
| * @return Returns the blockedHandler. |
| */ |
| public static IDialogBlockedHandler getBlockedHandler() { |
| return blockedHandler; |
| } |
| |
| /** |
| * Set the IDialogBlockedHandler to be used by WizardDialogs and |
| * ModalContexts. |
| * |
| * @param blockedHandler |
| * The blockedHandler for the dialogs. |
| */ |
| public static void setBlockedHandler(IDialogBlockedHandler blockedHandler) { |
| Dialog.blockedHandler = blockedHandler; |
| } |
| |
| /** |
| * Gets the dialog settings that should be used for remembering the bounds of |
| * of the dialog, according to the dialog bounds strategy. |
| * |
| * @return settings the dialog settings used to store the dialog's location |
| * and/or size, or <code>null</code> if the dialog's bounds should |
| * never be stored. |
| * |
| * @since 3.2 |
| * @see Dialog#getDialogBoundsStrategy() |
| */ |
| protected IDialogSettings getDialogBoundsSettings() { |
| return null; |
| } |
| |
| /** |
| * Get the integer constant that describes the strategy for persisting the |
| * dialog bounds. This strategy is ignored if the implementer does not also |
| * specify the dialog settings for storing the bounds in |
| * Dialog.getDialogBoundsSettings(). |
| * |
| * @return the constant describing the strategy for persisting the dialog |
| * bounds. |
| * |
| * @since 3.2 |
| * @see Dialog#DIALOG_PERSISTLOCATION |
| * @see Dialog#DIALOG_PERSISTSIZE |
| * @see Dialog#getDialogBoundsSettings() |
| */ |
| protected int getDialogBoundsStrategy() { |
| return DIALOG_PERSISTLOCATION | DIALOG_PERSISTSIZE; |
| } |
| |
| /** |
| * Saves the bounds of the shell in the appropriate dialog settings. The |
| * bounds are recorded relative to the parent shell, if there is one, or |
| * display coordinates if there is no parent shell. |
| * |
| * @param shell |
| * The shell whose bounds are to be stored |
| * |
| * @since 3.2 |
| */ |
| private void saveDialogBounds(Shell shell) { |
| IDialogSettings settings = getDialogBoundsSettings(); |
| if (settings != null) { |
| Point shellLocation = shell.getLocation(); |
| Point shellSize = shell.getSize(); |
| Shell parent = getParentShell(); |
| if (parent != null) { |
| Point parentLocation = parent.getLocation(); |
| shellLocation.x -= parentLocation.x; |
| shellLocation.y -= parentLocation.y; |
| } |
| int strategy = getDialogBoundsStrategy(); |
| if ((strategy & DIALOG_PERSISTLOCATION) != 0) { |
| settings.put(DIALOG_ORIGIN_X, shellLocation.x); |
| settings.put(DIALOG_ORIGIN_Y, shellLocation.y); |
| } |
| if ((strategy & DIALOG_PERSISTSIZE) != 0) { |
| settings.put(DIALOG_WIDTH, shellSize.x); |
| settings.put(DIALOG_HEIGHT, shellSize.y); |
| } |
| } |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.jface.window.Window#getInitialSize() |
| * |
| * @since 3.2 |
| */ |
| protected Point getInitialSize() { |
| Point result = super.getInitialSize(); |
| |
| // Check the dialog settings for a stored size. |
| if ((getDialogBoundsStrategy() & DIALOG_PERSISTSIZE)!= 0) { |
| IDialogSettings settings = getDialogBoundsSettings(); |
| if (settings != null) { |
| try { |
| // Get the stored width and height. |
| int width = settings.getInt(DIALOG_WIDTH); |
| if (width != DIALOG_DEFAULT_BOUNDS) |
| result.x = width; |
| int height = settings.getInt(DIALOG_HEIGHT); |
| if (height != DIALOG_DEFAULT_BOUNDS) |
| result.y = height; |
| |
| } catch (NumberFormatException e) { |
| } |
| } |
| } |
| // No attempt is made to constrain the bounds. The default |
| // constraining behavior in Window will be used. |
| return result; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.jface.window.Window#getInitialLocation(org.eclipse.swt.graphics.Point) |
| * |
| * @since 3.2 |
| */ |
| protected Point getInitialLocation(Point initialSize) { |
| Point result = super.getInitialLocation(initialSize); |
| if ((getDialogBoundsStrategy() & DIALOG_PERSISTLOCATION)!= 0) { |
| IDialogSettings settings = getDialogBoundsSettings(); |
| if (settings != null) { |
| try { |
| int x = settings.getInt(DIALOG_ORIGIN_X); |
| int y = settings.getInt(DIALOG_ORIGIN_Y); |
| result = new Point(x, y); |
| // The coordinates were stored relative to the parent shell. |
| // Convert to display coordinates. |
| Shell parent = getParentShell(); |
| if (parent != null) { |
| Point parentLocation = parent.getLocation(); |
| result.x += parentLocation.x; |
| result.y += parentLocation.y; |
| } |
| } catch (NumberFormatException e) { |
| } |
| } |
| } |
| // No attempt is made to constrain the bounds. The default |
| // constraining behavior in Window will be used. |
| return result; |
| } |
| |
| /** |
| * Add mouse listeners as needed to provide dialog size restore |
| * behavior. Double-clicking in unused areas will restore |
| * the dialog size. |
| * |
| * @since 3.2 |
| */ |
| private void addRestoreSizeMouseListeners() { |
| // Hook a double click event for restoring the dialog's computed |
| // size. We hook onto the button bar and the contents, and any |
| // nested composites in between, in order to accomodate different |
| // layout and construction styles. |
| Control dialogContents = getContents(); |
| if (buttonBar != null) { |
| buttonBar.addMouseListener(restoreSizeMouseListener); |
| Control control = buttonBar.getParent(); |
| while (control != dialogContents && control != null) { |
| control.addMouseListener(restoreSizeMouseListener); |
| control = control.getParent(); |
| } |
| } |
| if (dialogContents != null) |
| dialogContents.addMouseListener(restoreSizeMouseListener); |
| } |
| |
| /** |
| * Remove any mouse listeners that were registered. |
| * |
| * @since 3.2 |
| */ |
| private void removeRestoreSizeMouseListeners() { |
| Control dialogContents = getContents(); |
| if (buttonBar != null && !buttonBar.isDisposed()) { |
| buttonBar.removeMouseListener(restoreSizeMouseListener); |
| Control control = buttonBar.getParent(); |
| while (control != dialogContents && control != null && !control.isDisposed()) { |
| control.removeMouseListener(restoreSizeMouseListener); |
| control = control.getParent(); |
| } |
| } |
| if (dialogContents != null && !dialogContents.isDisposed()) |
| dialogContents.removeMouseListener(restoreSizeMouseListener); |
| } |
| |
| /** |
| * Restore the dialog to its initially computed size, resetting |
| * any bounds that may have been stored in dialog settings. |
| * |
| * @since 3.2 |
| */ |
| private void restoreDialogToComputedSize() { |
| // The computed size was never stored. This should not typically |
| // happen, but could if a client completely override the bounds initialization. |
| if (computedSize == null) |
| return; |
| |
| Shell shell = getShell(); |
| Point shellSize = shell.getSize(); |
| Point shellLocation = shell.getLocation(); |
| |
| // If the size has not changed, do nothing |
| if (shellSize.equals(computedSize)) |
| return; |
| |
| // Now reset the bounds |
| shell.setBounds(getConstrainedShellBounds(new Rectangle(shellLocation.x, |
| shellLocation.y, computedSize.x, computedSize.y))); |
| |
| // If we do store the bounds, update the value so default bounds |
| // will be used. |
| IDialogSettings settings = getDialogBoundsSettings(); |
| if (settings != null) { |
| int strategy = getDialogBoundsStrategy(); |
| if ((strategy & DIALOG_PERSISTSIZE) != 0) { |
| settings.put(DIALOG_WIDTH, DIALOG_DEFAULT_BOUNDS); |
| settings.put(DIALOG_HEIGHT, DIALOG_DEFAULT_BOUNDS); |
| } |
| } |
| |
| |
| |
| } |
| } |