gt: 				String key = getClass().getName() + DIALOG_USE_PERSISTED_SIZE;
context: /*******************************************************************************
   * Copyright (c) 2005, 2008 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
   *     Stefan Xenos, IBM - bug 156790: Adopt GridLayoutFactory within JFace
   *******************************************************************************/
  package org.eclipse.jface.dialogs;
  
  import java.util.ArrayList;
  import java.util.List;
  
  import org.eclipse.jface.action.Action;
  import org.eclipse.jface.action.GroupMarker;
  import org.eclipse.jface.action.IAction;
  import org.eclipse.jface.action.IMenuManager;
  import org.eclipse.jface.action.MenuManager;
  import org.eclipse.jface.action.Separator;
  import org.eclipse.jface.layout.GridDataFactory;
  import org.eclipse.jface.layout.GridLayoutFactory;
  import org.eclipse.jface.resource.JFaceResources;
  import org.eclipse.jface.util.Util;
  import org.eclipse.jface.window.Window;
  import org.eclipse.swt.SWT;
  import org.eclipse.swt.events.DisposeEvent;
  import org.eclipse.swt.events.DisposeListener;
  import org.eclipse.swt.events.MouseAdapter;
  import org.eclipse.swt.events.MouseEvent;
  import org.eclipse.swt.events.SelectionAdapter;
  import org.eclipse.swt.events.SelectionEvent;
  import org.eclipse.swt.graphics.Color;
  import org.eclipse.swt.graphics.Font;
  import org.eclipse.swt.graphics.FontData;
  import org.eclipse.swt.graphics.Point;
  import org.eclipse.swt.graphics.Rectangle;
  import org.eclipse.swt.widgets.Composite;
  import org.eclipse.swt.widgets.Control;
  import org.eclipse.swt.widgets.Event;
  import org.eclipse.swt.widgets.Label;
  import org.eclipse.swt.widgets.Listener;
  import org.eclipse.swt.widgets.Menu;
  import org.eclipse.swt.widgets.Shell;
  import org.eclipse.swt.widgets.ToolBar;
  import org.eclipse.swt.widgets.ToolItem;
  import org.eclipse.swt.widgets.Tracker;
  
  /**
   * A lightweight, transient dialog that is popped up to show contextual or
   * temporal information and is easily dismissed. Clients control whether the
   * dialog should be able to receive input focus. An optional title area at the
   * top and an optional info area at the bottom can be used to provide additional
   * information.
   * <p>
   * Because the dialog is short-lived, most of the configuration of the dialog is
   * done in the constructor. Set methods are only provided for those values that
   * are expected to be dynamically computed based on a particular instance's
   * internal state.
   * <p>
   * Clients are expected to override the creation of the main dialog area, and
   * may optionally override the creation of the title area and info area in order
   * to add content. In general, however, the creation of stylistic features, such
   * as the dialog menu, separator styles, and fonts, is kept private so that all
   * popup dialogs will have a similar appearance.
   * 
   * @since 3.2
   */
  public class PopupDialog extends Window {
  
  	/**
  	 * 
  	 */
  	private static final GridDataFactory LAYOUTDATA_GRAB_BOTH = GridDataFactory
  			.fillDefaults().grab(true, true);
  
  	/**
  	 * The dialog settings key name for stored dialog x location.
  	 */
  	private static final String DIALOG_ORIGIN_X = "DIALOG_X_ORIGIN"; //$NON-NLS-1$
  
  	/**
  	 * The dialog settings key name for stored dialog y location.
  	 */
  	private static final String DIALOG_ORIGIN_Y = "DIALOG_Y_ORIGIN"; //$NON-NLS-1$
  
  	/**
  	 * The dialog settings key name for stored dialog width.
  	 */
  	private static final String DIALOG_WIDTH = "DIALOG_WIDTH"; //$NON-NLS-1$
  
  	/**
  	 * The dialog settings key name for stored dialog height.
  	 */
  	private static final String DIALOG_HEIGHT = "DIALOG_HEIGHT"; //$NON-NLS-1$
  
  	/**
  	 * The dialog settings key name for remembering if the persisted bounds
  	 * should be accessed.
  	 * 
  	 * @deprecated Since 3.4, this is retained only for backward compatibility.
  	 */
  	private static final String DIALOG_USE_PERSISTED_BOUNDS = "DIALOG_USE_PERSISTED_BOUNDS"; //$NON-NLS-1$
  
  	/**
  	 * The dialog settings key name for remembering if the bounds persisted
  	 * prior to 3.4 have been migrated to the 3.4 settings.
  	 * 
  	 * @since 3.4
  	 * @deprecated This is marked deprecated at its introduction to discourage
  	 *             future dependency
  	 */
  	private static final String DIALOG_VALUE_MIGRATED_TO_34 = "hasBeenMigratedTo34"; //$NON-NLS-1$
  
  	/**
  	 * The dialog settings key name for remembering if the persisted size should
  	 * be accessed.
  	 */
  	private static final String DIALOG_USE_PERSISTED_SIZE = "DIALOG_USE_PERSISTED_SIZE"; //$NON-NLS-1$
  
  	/**
  	 * The dialog settings key name for remembering if the persisted location
  	 * should be accessed.
  	 */
  	private static final String DIALOG_USE_PERSISTED_LOCATION = "DIALOG_USE_PERSISTED_LOCATION"; //$NON-NLS-1$
  
  	/**
  	 * Move action for the dialog.
  	 */
  	private class MoveAction extends Action {
  
  		MoveAction() {
  			super(JFaceResources.getString("PopupDialog.move"), //$NON-NLS-1$
  					IAction.AS_PUSH_BUTTON);
  		}
  
  		/*
  		 * (non-Javadoc)
  		 * 
  		 * @see org.eclipse.jface.action.IAction#run()
  		 */
  		public void run() {
  			performTrackerAction(SWT.NONE);
  		}
  
  	}
  
  	/**
  	 * Resize action for the dialog.
  	 */
  	private class ResizeAction extends Action {
  
  		ResizeAction() {
  			super(JFaceResources.getString("PopupDialog.resize"), //$NON-NLS-1$
  					IAction.AS_PUSH_BUTTON);
  		}
  
  		/*
  		 * @see org.eclipse.jface.action.Action#run()
  		 */
  		public void run() {
  			performTrackerAction(SWT.RESIZE);
  		}
  	}
  
  	/**
  	 * 
  	 * Remember bounds action for the dialog.
  	 */
  	private class PersistBoundsAction extends Action {
  
  		PersistBoundsAction() {
  			super(JFaceResources.getString("PopupDialog.persistBounds"), //$NON-NLS-1$
  					IAction.AS_CHECK_BOX);
  			setChecked(persistLocation && persistSize);
  		}
  
  		/*
  		 * (non-Javadoc)
  		 * 
  		 * @see org.eclipse.jface.action.IAction#run()
  		 */
  		public void run() {
  			persistSize = isChecked();
  			persistLocation = persistSize;
  		}
  	}
  
  	/**
  	 * 
  	 * Remember bounds action for the dialog.
  	 */
  	private class PersistSizeAction extends Action {
  
  		PersistSizeAction() {
  			super(JFaceResources.getString("PopupDialog.persistSize"), //$NON-NLS-1$
  					IAction.AS_CHECK_BOX);
  			setChecked(persistSize);
  		}
  
  		/*
  		 * (non-Javadoc)
  		 * 
  		 * @see org.eclipse.jface.action.IAction#run()
  		 */
  		public void run() {
  			persistSize = isChecked();
  		}
  	}
  
  	/**
  	 * 
  	 * Remember location action for the dialog.
  	 */
  	private class PersistLocationAction extends Action {
  
  		PersistLocationAction() {
  			super(JFaceResources.getString("PopupDialog.persistLocation"), //$NON-NLS-1$
  					IAction.AS_CHECK_BOX);
  			setChecked(persistLocation);
  		}
  
  		/*
  		 * (non-Javadoc)
  		 * 
  		 * @see org.eclipse.jface.action.IAction#run()
  		 */
  		public void run() {
  			persistLocation = isChecked();
  		}
  	}
  
  	/**
  	 * Shell style appropriate for a simple hover popup that cannot get focus.
  	 * 
  	 */
  	public final static int HOVER_SHELLSTYLE = SWT.NO_FOCUS | SWT.ON_TOP
  			| SWT.TOOL;
  
  	/**
  	 * Shell style appropriate for an info popup that can get focus.
  	 */
  	public final static int INFOPOPUP_SHELLSTYLE = SWT.TOOL;
  
  	/**
  	 * Shell style appropriate for a resizable info popup that can get focus.
  	 */
  	public final static int INFOPOPUPRESIZE_SHELLSTYLE = SWT.RESIZE;
  
  	/**
  	 * Margin width (in pixels) to be used in layouts inside popup dialogs
  	 * (value is 0).
  	 */
  	public final static int POPUP_MARGINWIDTH = 0;
  
  	/**
  	 * Margin height (in pixels) to be used in layouts inside popup dialogs
  	 * (value is 0).
  	 */
  	public final static int POPUP_MARGINHEIGHT = 0;
  
  	/**
  	 * Vertical spacing (in pixels) between cells in the layouts inside popup
  	 * dialogs (value is 1).
  	 */
  	public final static int POPUP_VERTICALSPACING = 1;
  
  	/**
  	 * Vertical spacing (in pixels) between cells in the layouts inside popup
  	 * dialogs (value is 1).
  	 */
  	public final static int POPUP_HORIZONTALSPACING = 1;
  
  	/**
  	 * Image registry key for menu image.
  	 * 
  	 * @since 3.4
  	 */
  	public static final String POPUP_IMG_MENU = "popup_menu_image"; //$NON-NLS-1$
  
  	/**
  	 * Image registry key for disabled menu image.
  	 * 
  	 * @since 3.4
  	 */
  	public static final String POPUP_IMG_MENU_DISABLED = "popup_menu_image_diabled"; //$NON-NLS-1$
  
  	/**
  	 * 
  	 */
  	private static final GridLayoutFactory POPUP_LAYOUT_FACTORY = GridLayoutFactory
  			.fillDefaults().margins(POPUP_MARGINWIDTH, POPUP_MARGINHEIGHT)
  			.spacing(POPUP_HORIZONTALSPACING, POPUP_VERTICALSPACING);
  
  	/**
  	 * The dialog's toolbar for the move and resize capabilities.
  	 */
  	private ToolBar toolBar = null;
  
  	/**
  	 * The dialog's menu manager.
  	 */
  	private MenuManager menuManager = null;
  
  	/**
  	 * The control representing the main dialog area.
  	 */
  	private Control dialogArea;
  
  	/**
  	 * Labels that contain title and info text. Cached so they can be updated
  	 * dynamically if possible.
  	 */
  	private Label titleLabel, infoLabel;
  
  	/**
  	 * Separator controls. Cached so they can be excluded from color changes.
  	 */
  	private Control titleSeparator, infoSeparator;
  
  	/**
  	 * Font to be used for the info area text. Computed based on the dialog's
  	 * font.
  	 */
  	private Font infoFont;
  
  	/**
  	 * Font to be used for the title area text. Computed based on the dialog's
  	 * font.
  	 */
  	private Font titleFont;
  
  	/**
  	 * Flags indicating whether we are listening for shell deactivate events,
  	 * either those or our parent's. Used to prevent closure when a menu command
  	 * is chosen or a secondary popup is launched.
  	 */
  	private boolean listenToDeactivate;
  
  	private boolean listenToParentDeactivate;
  
  	private Listener parentDeactivateListener;
  
  	/**
  	 * Flag indicating whether focus should be taken when the dialog is opened.
  	 */
  	private boolean takeFocusOnOpen = false;
  
  	/**
  	 * Flag specifying whether a menu should be shown that allows the user to
  	 * move and resize.
  	 */
  	private boolean showDialogMenu = false;
  
  	/**
  	 * Flag specifying whether menu actions allowing the user to choose whether
  	 * the dialog bounds and location should be persisted are to be shown.
  	 */
  	private boolean showPersistActions = false;
  
  	/**
  	 * Flag specifying whether the size of the popup should be persisted. This
  	 * flag is used as initial default and updated by the menu if it is shown.
  	 */
  	private boolean persistSize = false;
  
  	/**
  	 * Flag specifying whether the location of the popup should be persisted.
  	 * This flag is used as initial default and updated by the menu if it is
  	 * shown.
  	 */
  	private boolean persistLocation = false;
  	/**
  	 * Flag specifying whether to use new 3.4 API instead of the old one.
  	 * 
  	 * @since 3.4
  	 */
  	private boolean isUsing34API = true;
  
  	/**
  	 * Text to be shown in an optional title area (on top).
  	 */
  	private String titleText;
  
  	/**
  	 * Text to be shown in an optional info area (at the bottom).
  	 */
  	private String infoText;
  
  	/**
  	 * Constructs a new instance of <code>PopupDialog</code>.
  	 * 
  	 * @param parent
  	 *            The parent shell.
  	 * @param shellStyle
  	 *            The shell style.
  	 * @param takeFocusOnOpen
  	 *            A boolean indicating whether focus should be taken by this
  	 *            popup when it opens.
  	 * @param persistBounds
  	 *            A boolean indicating whether the bounds (size and location) of
  	 *            the dialog should be persisted upon close of the dialog. The
  	 *            bounds can only be persisted if the dialog settings for
  	 *            persisting the bounds are also specified. If a menu action
  	 *            will be provided that allows the user to control this feature,
  	 *            then the last known value of the user's setting will be used
  	 *            instead of this flag.
  	 * @param showDialogMenu
  	 *            A boolean indicating whether a menu for moving and resizing
  	 *            the popup should be provided.
  	 * @param showPersistActions
  	 *            A boolean indicating whether actions allowing the user to
  	 *            control the persisting of the dialog size and location should
  	 *            be shown in the dialog menu. This parameter has no effect if
  	 *            <code>showDialogMenu</code> is <code>false</code>.
  	 * @param titleText
  	 *            Text to be shown in an upper title area, or <code>null</code>
  	 *            if there is no title.
  	 * @param infoText
  	 *            Text to be shown in a lower info area, or <code>null</code>
  	 *            if there is no info area.
  	 * 
  	 * @see PopupDialog#getDialogSettings()
  	 * @deprecated As of 3.4, replaced by
  	 *             {@link #PopupDialog(Shell, int, boolean, boolean, boolean, boolean, boolean, String, String)}
  	 */
  	public PopupDialog(Shell parent, int shellStyle, boolean takeFocusOnOpen,
  			boolean persistBounds, boolean showDialogMenu,
  			boolean showPersistActions, String titleText, String infoText) {
  		this(parent, shellStyle, takeFocusOnOpen, persistBounds, persistBounds,
  				showDialogMenu, showPersistActions, titleText, infoText, false);
  	}
  
  	/**
  	 * Constructs a new instance of <code>PopupDialog</code>.
  	 * 
  	 * @param parent
  	 *            The parent shell.
  	 * @param shellStyle
  	 *            The shell style.
  	 * @param takeFocusOnOpen
  	 *            A boolean indicating whether focus should be taken by this
  	 *            popup when it opens.
  	 * @param persistSize
  	 *            A boolean indicating whether the size should be persisted upon
  	 *            close of the dialog. The size can only be persisted if the
  	 *            dialog settings for persisting the bounds are also specified.
  	 *            If a menu action will be provided that allows the user to
  	 *            control this feature and the user hasn't changed that setting,
  	 *            then this flag is used as initial default for the menu.
  	 * @param persistLocation
  	 *            A boolean indicating whether the location should be persisted
  	 *            upon close of the dialog. The location can only be persisted
  	 *            if the dialog settings for persisting the bounds are also
  	 *            specified. If a menu action will be provided that allows the
  	 *            user to control this feature and the user hasn't changed that
  	 *            setting, then this flag is used as initial default for the
  	 *            menu. default for the menu until the user changed it.
  	 * @param showDialogMenu
  	 *            A boolean indicating whether a menu for moving and resizing
  	 *            the popup should be provided.
  	 * @param showPersistActions
  	 *            A boolean indicating whether actions allowing the user to
  	 *            control the persisting of the dialog bounds and location
  	 *            should be shown in the dialog menu. This parameter has no
  	 *            effect if <code>showDialogMenu</code> is <code>false</code>.
  	 * @param titleText
  	 *            Text to be shown in an upper title area, or <code>null</code>
  	 *            if there is no title.
  	 * @param infoText
  	 *            Text to be shown in a lower info area, or <code>null</code>
  	 *            if there is no info area.
  	 * 
  	 * @see PopupDialog#getDialogSettings()
  	 * 
  	 * @since 3.4
  	 */
  	public PopupDialog(Shell parent, int shellStyle, boolean takeFocusOnOpen,
  			boolean persistSize, boolean persistLocation,
  			boolean showDialogMenu, boolean showPersistActions,
  			String titleText, String infoText) {
  		this(parent, shellStyle, takeFocusOnOpen, persistSize, persistLocation,
  				showDialogMenu, showPersistActions, titleText, infoText, true);
  
  	}
  
  	/**
  	 * Constructs a new instance of <code>PopupDialog</code>.
  	 * 
  	 * @param parent
  	 *            The parent shell.
  	 * @param shellStyle
  	 *            The shell style.
  	 * @param takeFocusOnOpen
  	 *            A boolean indicating whether focus should be taken by this
  	 *            popup when it opens.
  	 * @param persistSize
  	 *            A boolean indicating whether the size should be persisted upon
  	 *            close of the dialog. The size can only be persisted if the
  	 *            dialog settings for persisting the bounds are also specified.
  	 *            If a menu action will be provided that allows the user to
  	 *            control this feature and the user hasn't changed that setting,
  	 *            then this flag is used as initial default for the menu.
  	 * @param persistLocation
  	 *            A boolean indicating whether the location should be persisted
  	 *            upon close of the dialog. The location can only be persisted
  	 *            if the dialog settings for persisting the bounds are also
  	 *            specified. If a menu action will be provided that allows the
  	 *            user to control this feature and the user hasn't changed that
  	 *            setting, then this flag is used as initial default for the
  	 *            menu. default for the menu until the user changed it.
  	 * @param showDialogMenu
  	 *            A boolean indicating whether a menu for moving and resizing
  	 *            the popup should be provided.
  	 * @param showPersistActions
  	 *            A boolean indicating whether actions allowing the user to
  	 *            control the persisting of the dialog bounds and location
  	 *            should be shown in the dialog menu. This parameter has no
  	 *            effect if <code>showDialogMenu</code> is <code>false</code>.
  	 * @param titleText
  	 *            Text to be shown in an upper title area, or <code>null</code>
  	 *            if there is no title.
  	 * @param infoText
  	 *            Text to be shown in a lower info area, or <code>null</code>
  	 *            if there is no info area.
  	 * @param use34API
  	 *            <code>true</code> if 3.4 API should be used
  	 * 
  	 * @see PopupDialog#getDialogSettings()
  	 * 
  	 * @since 3.4
  	 */
  	private PopupDialog(Shell parent, int shellStyle, boolean takeFocusOnOpen,
  			boolean persistSize, boolean persistLocation,
  			boolean showDialogMenu, boolean showPersistActions,
  			String titleText, String infoText, boolean use34API) {
  		super(parent);
  		// Prior to 3.4, we encouraged use of SWT.NO_TRIM and provided a
  		// border using a black composite background and margin. Now we
  		// use SWT.TOOL to get the border for some cases and this conflicts
  		// with SWT.NO_TRIM. Clients who previously have used SWT.NO_TRIM
  		// and still had a border drawn for them would find their border go
  		// away unless we do the following:
  		// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=219743
  		if ((shellStyle & SWT.NO_TRIM) != 0) {
  			shellStyle &= ~(SWT.NO_TRIM | SWT.SHELL_TRIM);
  		}
  
  		setShellStyle(shellStyle);
  		this.takeFocusOnOpen = takeFocusOnOpen;
  		this.showDialogMenu = showDialogMenu;
  		this.showPersistActions = showPersistActions;
  		this.titleText = titleText;
  		this.infoText = infoText;
  
  		setBlockOnOpen(false);
  
  		this.isUsing34API = use34API;
  
  		this.persistSize = persistSize;
  		this.persistLocation = persistLocation;
  
  		migrateBoundsSetting();
  
  		initializeWidgetState();
  	}
  
  	/*
  	 * (non-Javadoc)
  	 * 
  	 * @see org.eclipse.jface.window.Window#configureShell(Shell)
  	 */
  	protected void configureShell(Shell shell) {
  		GridLayoutFactory.fillDefaults().margins(0, 0).spacing(5, 5).applyTo(
  				shell);
  
  		shell.addListener(SWT.Deactivate, new Listener() {
  			public void handleEvent(Event event) {
  				/*
  				 * Close if we are deactivating and have no child shells. If we
  				 * have child shells, we are deactivating due to their opening.
  				 * On X, we receive this when a menu child (such as the system
  				 * menu) of the shell opens, but I have not found a way to
  				 * distinguish that case here. Hence bug #113577 still exists.
  				 */
  				if (listenToDeactivate && event.widget == getShell()
  						&& getShell().getShells().length == 0) {
  					asyncClose();
  				} else {
  					/*
  					 * We typically ignore deactivates to work around
  					 * platform-specific event ordering. Now that we've ignored
  					 * whatever we were supposed to, start listening to
  					 * deactivates. Example issues can be found in
  					 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=123392
  					 */
  					listenToDeactivate = true;
  				}
  			}
  		});
  		// Set this true whenever we activate. It may have been turned
  		// off by a menu or secondary popup showing.
  		shell.addListener(SWT.Activate, new Listener() {
  			public void handleEvent(Event event) {
  				// ignore this event if we have launched a child
  				if (event.widget == getShell()
  						&& getShell().getShells().length == 0) {
  					listenToDeactivate = true;
  					// Typically we start listening for parent deactivate after
  					// we are activated, except on the Mac, where the deactivate
  					// is received after activate.
  					// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=100668
  					listenToParentDeactivate = !Util.isMac();
  				}
  			}
  		});
  
  		if ((getShellStyle() & SWT.ON_TOP) != 0 && shell.getParent() != null) {
  			parentDeactivateListener = new Listener() {
  				public void handleEvent(Event event) {
  					if (listenToParentDeactivate) {
  						asyncClose();
  					} else {
  						// Our first deactivate, now start listening on the Mac.
  						listenToParentDeactivate = listenToDeactivate;
  					}
  				}
  			};
  			shell.getParent().addListener(SWT.Deactivate,
  					parentDeactivateListener);
  		}
  
  		shell.addDisposeListener(new DisposeListener() {
  			public void widgetDisposed(DisposeEvent event) {
  				handleDispose();
  			}
  		});
  	}
  
  	private void asyncClose() {
  		// workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=152010
  		getShell().getDisplay().asyncExec(new Runnable() {
  			public void run() {
  				close();
  			}
  		});
  	}
  
  	/**
  	 * The <code>PopupDialog</code> implementation of this <code>Window</code>
  	 * method creates and lays out the top level composite for the dialog. It
  	 * then calls the <code>createTitleMenuArea</code>,
  	 * <code>createDialogArea</code>, and <code>createInfoTextArea</code>
  	 * methods to create an optional title and menu area on the top, a dialog
  	 * area in the center, and an optional info text area at the bottom.
  	 * Overriding <code>createDialogArea</code> and (optionally)
  	 * <code>createTitleMenuArea</code> and <code>createTitleMenuArea</code>
  	 * are recommended rather than overriding this method.
  	 * 
  	 * @param parent
  	 *            the composite used to parent the contents.
  	 * 
  	 * @return the control representing the contents.
  	 */
  	protected Control createContents(Composite parent) {
  		Composite composite = new Composite(parent, SWT.NONE);
  		POPUP_LAYOUT_FACTORY.applyTo(composite);
  		LAYOUTDATA_GRAB_BOTH.applyTo(composite);
  
  		// Title area
  		if (hasTitleArea()) {
  			createTitleMenuArea(composite);
  			titleSeparator = createHorizontalSeparator(composite);
  		}
  		// Content
  		dialogArea = createDialogArea(composite);
  		// Create a grid data layout data if one was not provided.
  		// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=118025
  		if (dialogArea.getLayoutData() == null) {
  			LAYOUTDATA_GRAB_BOTH.applyTo(dialogArea);
  		}
  
  		// Info field
  		if (hasInfoArea()) {
  			infoSeparator = createHorizontalSeparator(composite);
  			createInfoTextArea(composite);
  		}
  
  		applyColors(composite);
  		applyFonts(composite);
  		return composite;
  	}
  
  	/**
  	 * Creates and returns the contents of the dialog (the area below the title
  	 * area and above the info text area.
  	 * <p>
  	 * The <code>PopupDialog</code> implementation of this framework method
  	 * creates and returns a new <code>Composite</code> with standard margins
  	 * and spacing.
  	 * <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>
  	 * Subclasses must override this method but may call <code>super</code> as
  	 * in the following example:
  	 * 
  	 * <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) {
  		Composite composite = new Composite(parent, SWT.NONE);
  		POPUP_LAYOUT_FACTORY.applyTo(composite);
  		LAYOUTDATA_GRAB_BOTH.applyTo(composite);
  		return composite;
  	}
  
  	/**
  	 * Returns the control that should get initial focus. Subclasses may
  	 * override this method.
  	 * 
  	 * @return the Control that should receive focus when the popup opens.
  	 */
  	protected Control getFocusControl() {
  		return dialogArea;
  	}
  
  	/**
  	 * Sets the tab order for the popup. Clients should override to introduce
  	 * specific tab ordering.
  	 * 
  	 * @param composite
  	 *            the composite in which all content, including the title area
  	 *            and info area, was created. This composite's parent is the
  	 *            shell.
  	 */
  	protected void setTabOrder(Composite composite) {
  		// default is to do nothing
  	}
  
  	/**
  	 * Returns a boolean indicating whether the popup should have a title area
  	 * at the top of the dialog. Subclasses may override. Default behavior is to
  	 * have a title area if there is to be a menu or title text.
  	 * 
  	 * @return <code>true</code> if a title area should be created,
  	 *         <code>false</code> if it should not.
  	 */
  	protected boolean hasTitleArea() {
  		return titleText != null || showDialogMenu;
  	}
  
  	/**
  	 * Returns a boolean indicating whether the popup should have an info area
  	 * at the bottom of the dialog. Subclasses may override. Default behavior is
  	 * to have an info area if info text was provided at the time of creation.
  	 * 
  	 * @return <code>true</code> if a title area should be created,
  	 *         <code>false</code> if it should not.
  	 */
  	protected boolean hasInfoArea() {
  		return infoText != null;
  	}
  
  	/**
  	 * Creates the title and menu area. Subclasses typically need not override
  	 * this method, but instead should use the constructor parameters
  	 * <code>showDialogMenu</code> and <code>showPersistAction</code> to
  	 * indicate whether a menu should be shown, and
  	 * <code>createTitleControl</code> to to customize the presentation of the
  	 * title.
  	 * 
  	 * <p>
  	 * If this method is overridden, the returned control's layout data must be
  	 * an instance of <code>GridData</code>. This method must not modify the
  	 * parent's layout.
  	 * 
  	 * @param parent
  	 *            The parent composite.
  	 * @return The Control representing the title and menu area.
  	 */
  	protected Control createTitleMenuArea(Composite parent) {
  
  		Composite titleAreaComposite = new Composite(parent, SWT.NONE);
  		POPUP_LAYOUT_FACTORY.copy().numColumns(2).applyTo(titleAreaComposite);
  		GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).grab(true,
  				false).applyTo(titleAreaComposite);
  
  		createTitleControl(titleAreaComposite);
  
  		if (showDialogMenu) {
  			createDialogMenu(titleAreaComposite);
  		}
  		return titleAreaComposite;
  	}
  
  	/**
  	 * Creates the control to be used to represent the dialog's title text.
  	 * Subclasses may override if a different control is desired for
  	 * representing the title text, or if something different than the title
  	 * should be displayed in location where the title text typically is shown.
  	 * 
  	 * <p>
  	 * If this method is overridden, the returned control's layout data must be
  	 * an instance of <code>GridData</code>. This method must not modify the
  	 * parent's layout.
  	 * 
  	 * @param parent
  	 *            The parent composite.
  	 * @return The Control representing the title area.
  	 */
  	protected Control createTitleControl(Composite parent) {
  		titleLabel = new Label(parent, SWT.NONE);
  
  		GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).grab(true,
  				false).span(showDialogMenu ? 1 : 2, 1).applyTo(titleLabel);
  
  		if (titleText != null) {
  			titleLabel.setText(titleText);
  		}
  		return titleLabel;
  	}
  
  	/**
  	 * Creates the optional info text area. This method is only called if the
  	 * <code>hasInfoArea()</code> method returns true. Subclasses typically
  	 * need not override this method, but may do so.
  	 * 
  	 * <p>
  	 * If this method is overridden, the returned control's layout data must be
  	 * an instance of <code>GridData</code>. This method must not modify the
  	 * parent's layout.
  	 * 
  	 * 
  	 * @param parent
  	 *            The parent composite.
  	 * @return The control representing the info text area.
  	 * 
  	 * @see PopupDialog#hasInfoArea()
  	 * @see PopupDialog#createTitleControl(Composite)
  	 */
  	protected Control createInfoTextArea(Composite parent) {
  		// Status label
  		infoLabel = new Label(parent, SWT.RIGHT);
  		infoLabel.setText(infoText);
  		
  		GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL,
  				SWT.BEGINNING).applyTo(infoLabel);
  		infoLabel.setForeground(parent.getDisplay().getSystemColor(
  				SWT.COLOR_WIDGET_DARK_SHADOW));
  		return infoLabel;
  	}
  
  	/**
  	 * Create a horizontal separator for the given parent.
  	 * 
  	 * @param parent
  	 *            The parent composite.
  	 * @return The Control representing the horizontal separator.
  	 */
  	private Control createHorizontalSeparator(Composite parent) {
  		Label separator = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL
  				| SWT.LINE_DOT);
  		GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).grab(true,
  				false).applyTo(separator);
  		return separator;
  	}
  
  	/**
  	 * Create the dialog's menu for the move and resize actions.
  	 * 
  	 * @param parent
  	 *            The parent composite.
  	 */
  	private void createDialogMenu(Composite parent) {
  
  		toolBar = new ToolBar(parent, SWT.FLAT);
  		ToolItem viewMenuButton = new ToolItem(toolBar, SWT.PUSH, 0);
  
  		GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(
  				toolBar);
  		viewMenuButton.setImage(JFaceResources.getImage(POPUP_IMG_MENU));
  		viewMenuButton.setDisabledImage(JFaceResources
  				.getImage(POPUP_IMG_MENU_DISABLED));
  		viewMenuButton.setToolTipText(JFaceResources
  				.getString("PopupDialog.menuTooltip")); //$NON-NLS-1$
  		viewMenuButton.addSelectionListener(new SelectionAdapter() {
  			public void widgetSelected(SelectionEvent e) {
  				showDialogMenu();
  			}
  		});
  		// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=177183
  		toolBar.addMouseListener(new MouseAdapter() {
  			public void mouseDown(MouseEvent e) {
  				showDialogMenu();
  			}
  		});
  	}
  
  	/**
  	 * Fill the dialog's menu. Subclasses may extend or override.
  	 * 
  	 * @param dialogMenu
  	 *            The dialog's menu.
  	 */
  	protected void fillDialogMenu(IMenuManager dialogMenu) {
  		dialogMenu.add(new GroupMarker("SystemMenuStart")); //$NON-NLS-1$
  		dialogMenu.add(new MoveAction());
  		dialogMenu.add(new ResizeAction());
  		if (showPersistActions) {
  			if (isUsing34API) {
  				dialogMenu.add(new PersistLocationAction());
  				dialogMenu.add(new PersistSizeAction());
  			} else {
  				dialogMenu.add(new PersistBoundsAction());
  			}
  		}
  		dialogMenu.add(new Separator("SystemMenuEnd")); //$NON-NLS-1$
  	}
  
  	/**
  	 * Perform the requested tracker action (resize or move).
  	 * 
  	 * @param style
  	 *            The track style (resize or move).
  	 */
  	private void performTrackerAction(int style) {
  		Shell shell = getShell();
  		if (shell == null || shell.isDisposed()) {
  			return;
  		}
  
  		Tracker tracker = new Tracker(shell.getDisplay(), style);
  		tracker.setStippled(true);
  		Rectangle[] r = new Rectangle[] { shell.getBounds() };
  		tracker.setRectangles(r);
  
  		// Ignore any deactivate events caused by opening the tracker.
  		// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=120656
  		boolean oldListenToDeactivate = listenToDeactivate;
  		listenToDeactivate = false;
  		if (tracker.open()) {
  			if (shell != null && !shell.isDisposed()) {
  				shell.setBounds(tracker.getRectangles()[0]);
  			}
  		}
  		listenToDeactivate = oldListenToDeactivate;
  	}
  
  	/**
  	 * Show the dialog's menu. This message has no effect if the receiver was
  	 * not configured to show a menu. Clients may call this method in order to
  	 * trigger the menu via keystrokes or other gestures. Subclasses typically
  	 * do not override method.
  	 */
  	protected void showDialogMenu() {
  		if (!showDialogMenu) {
  			return;
  		}
  
  		if (menuManager == null) {
  			menuManager = new MenuManager();
  			fillDialogMenu(menuManager);
  		}
  		// Setting this flag works around a problem that remains on X only,
  		// whereby activating the menu deactivates our shell.
  		listenToDeactivate = !Util.isGtk();
  
  		Menu menu = menuManager.createContextMenu(getShell());
  		Rectangle bounds = toolBar.getBounds();
  		Point topLeft = new Point(bounds.x, bounds.y + bounds.height);
  		topLeft = getShell().toDisplay(topLeft);
  		menu.setLocation(topLeft.x, topLeft.y);
  		menu.setVisible(true);
  	}
  
  	/**
  	 * Set the text to be shown in the popup's info area. This message has no
  	 * effect if there was no info text supplied when the dialog first opened.
  	 * Subclasses may override this method.
  	 * 
  	 * @param text
  	 *            the text to be shown when the info area is displayed.
  	 * 
  	 */
  	protected void setInfoText(String text) {
  		infoText = text;
  		if (infoLabel != null) {
  			infoLabel.setText(text);
  		}
  	}
  
  	/**
  	 * Set the text to be shown in the popup's title area. This message has no
  	 * effect if there was no title label specified when the dialog was
  	 * originally opened. Subclasses may override this method.
  	 * 
  	 * @param text
  	 *            the text to be shown when the title area is displayed.
  	 * 
  	 */
  	protected void setTitleText(String text) {
  		titleText = text;
  		if (titleLabel != null) {
  			titleLabel.setText(text);
  		}
  	}
  
  	/**
  	 * Return a boolean indicating whether this dialog will persist its bounds.
  	 * This value is initially set in the dialog's constructor, but can be
  	 * modified if the persist bounds action is shown on the menu and the user
  	 * has changed its value. Subclasses may override this method.
  	 * 
  	 * @return <code>true</code> if the dialog's bounds will be persisted,
  	 *         <code>false</code> if it will not.
  	 * 
  	 * @deprecated As of 3.4, please use {@link #getPersistLocation()} or
  	 *             {@link #getPersistSize()} to determine separately whether
  	 *             size or location should be persisted.
  	 */
  	protected boolean getPersistBounds() {
  		return persistLocation && persistSize;
  	}
  
  	/**
  	 * Return a boolean indicating whether this dialog will persist its
  	 * location. This value is initially set in the dialog's constructor, but
  	 * can be modified if the persist location action is shown on the menu and
  	 * the user has changed its value. Subclasses may override this method.
  	 * 
  	 * @return <code>true</code> if the dialog's location will be persisted,
  	 *         <code>false</code> if it will not.
  	 * 
  	 * @see #getPersistSize()
  	 * @since 3.4
  	 */
  	protected boolean getPersistLocation() {
  		return persistLocation;
  	}
  
  	/**
  	 * Return a boolean indicating whether this dialog will persist its size.
  	 * This value is initially set in the dialog's constructor, but can be
  	 * modified if the persist size action is shown on the menu and the user has
  	 * changed its value. Subclasses may override this method.
  	 * 
  	 * @return <code>true</code> if the dialog's size will be persisted,
  	 *         <code>false</code> if it will not.
  	 * 
  	 * @see #getPersistLocation()
  	 * @since 3.4
  	 */
  	protected boolean getPersistSize() {
  		return persistSize;
  	}
  
  	/**
  	 * Opens this window, creating it first if it has not yet been created.
  	 * <p>
  	 * This method is reimplemented for special configuration of PopupDialogs.
  	 * It never blocks on open, immediately returning <code>OK</code> if the
  	 * open is successful, or <code>CANCEL</code> if it is not. It provides
  	 * framework hooks that allow subclasses to set the focus and tab order, and
  	 * avoids the use of <code>shell.open()</code> in cases where the focus
  	 * should not be given to the shell initially.
  	 * 
  	 * @return the return code
  	 * 
  	 * @see org.eclipse.jface.window.Window#open()
  	 */
  	public int open() {
  
  		Shell shell = getShell();
  		if (shell == null || shell.isDisposed()) {
  			shell = null;
  			// create the window
  			create();
  			shell = getShell();
  		}
  
  		// provide a hook for adjusting the bounds. This is only
  		// necessary when there is content driven sizing that must be
  		// adjusted each time the dialog is opened.
  		adjustBounds();
  
  		// limit the shell size to the display size
  		constrainShellSize();
  
  		// set up the tab order for the dialog
  		setTabOrder((Composite) getContents());
  
  		// initialize flags for listening to deactivate
  		listenToDeactivate = false;
  		listenToParentDeactivate = false;
  
  		// open the window
  		if (takeFocusOnOpen) {
  			shell.open();
  			getFocusControl().setFocus();
  		} else {
  			shell.setVisible(true);
  		}
  
  		return OK;
  
  	}
  
  	/**
  	 * Closes this window, disposes its shell, and removes this window from its
  	 * window manager (if it has one).
  	 * <p>
  	 * This method is extended to save the dialog bounds and initialize widget
  	 * state so that the widgets can be recreated if the dialog is reopened.
  	 * This method may be extended (<code>super.close</code> must be called).
  	 * </p>
  	 * 
  	 * @return <code>true</code> if the window is (or was already) closed, and
  	 *         <code>false</code> if it is still open
  	 */
  	public boolean close() {
  		// If already closed, there is nothing to do.
  		// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=127505
  		if (getShell() == null || getShell().isDisposed()) {
  			return true;
  		}
  
  		saveDialogBounds(getShell());
  		// Widgets are about to be disposed, so null out any state
  		// related to them that was not handled in dispose listeners.
  		// We do this before disposal so that any received activate or
  		// deactivate events are duly ignored.
  		initializeWidgetState();
  
  		if (parentDeactivateListener != null) {
  			getShell().getParent().removeListener(SWT.Deactivate,
  					parentDeactivateListener);
  			parentDeactivateListener = null;
  		}
  
  		return super.close();
  	}
  
  	/**
  	 * Gets the dialog settings that should be used for remembering the bounds
  	 * of the dialog. Subclasses should override this method when they wish to
  	 * persist the bounds of the dialog.
  	 * 
  	 * @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.
  	 */
  	protected IDialogSettings getDialogSettings() {
  		return null;
  	}
  
  	/**
  	 * 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. Subclasses typically
  	 * need not override this method, but may extend it (calling
  	 * <code>super.saveDialogBounds</code> if additional bounds information
  	 * should be stored. Clients may also call this method to persist the bounds
  	 * at times other than closing the dialog.
  	 * 
  	 * @param shell
  	 *            The shell whose bounds are to be stored
  	 */
  	protected void saveDialogBounds(Shell shell) {
  		IDialogSettings settings = getDialogSettings();
  		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;
  			}
  			String prefix = getClass().getName();
  			if (persistSize) {
  				settings.put(prefix + DIALOG_WIDTH, shellSize.x);
  				settings.put(prefix + DIALOG_HEIGHT, shellSize.y);
  			}
  			if (persistLocation) {
  				settings.put(prefix + DIALOG_ORIGIN_X, shellLocation.x);
  				settings.put(prefix + DIALOG_ORIGIN_Y, shellLocation.y);
  			}
  			if (showPersistActions && showDialogMenu) {
  				settings.put(getClass().getName() + DIALOG_USE_PERSISTED_SIZE,
  						persistSize);
  				settings.put(getClass().getName()
  						+ DIALOG_USE_PERSISTED_LOCATION, persistLocation);
  
  			}
  		}
  	}
  
  	/*
  	 * (non-Javadoc)
  	 * 
  	 * @see org.eclipse.jface.window.Window#getInitialSize()
  	 */
  	protected Point getInitialSize() {
  		Point result = getDefaultSize();
  		if (persistSize) {
  			IDialogSettings settings = getDialogSettings();
  			if (settings != null) {
  				try {
  					int width = settings.getInt(getClass().getName()
  							+ DIALOG_WIDTH);
  					int height = settings.getInt(getClass().getName()
  							+ DIALOG_HEIGHT);
  					result = new Point(width, height);
  
  				} catch (NumberFormatException e) {
  				}
  			}
  		}
  		// No attempt is made to constrain the bounds. The default
  		// constraining behavior in Window will be used.
  		return result;
  	}
  
  	/**
  	 * Return the default size to use for the shell. This default size is used
  	 * if the dialog does not have any persisted size to restore. The default
  	 * implementation returns the preferred size of the shell. Subclasses should
  	 * override this method when an alternate default size is desired, rather
  	 * than overriding {@link #getInitialSize()}.
  	 * 
  	 * @return the initial size of the shell
  	 * 
  	 * @see #getPersistSize()
  	 * @since 3.4
  	 */
  	protected Point getDefaultSize() {
  		return super.getInitialSize();
  	}
  
  	/**
  	 * Returns the default location to use for the shell. This default location
  	 * is used if the dialog does not have any persisted location to restore.
  	 * The default implementation uses the location computed by
  	 * {@link org.eclipse.jface.window.Window#getInitialLocation(Point)}.
  	 * Subclasses should override this method when an alternate default location
  	 * is desired, rather than overriding {@link #getInitialLocation(Point)}.
  	 * 
  	 * @param initialSize
  	 *            the initial size of the shell, as returned by
  	 *            <code>getInitialSize</code>.
  	 * @return the initial location of the shell
  	 * 
  	 * @see #getPersistLocation()
  	 * @since 3.4
  	 */
  	protected Point getDefaultLocation(Point initialSize) {
  		return super.getInitialLocation(initialSize);
  	}
  
  	/**
  	 * Adjust the bounds of the popup as necessary prior to opening the dialog.
  	 * Default is to do nothing, which honors any bounds set directly by clients
  	 * or those that have been saved in the dialog settings. Subclasses should
  	 * override this method when there are bounds computations that must be
  	 * checked each time the dialog is opened.
  	 */
  	protected void adjustBounds() {
  	}
  
  	/**
  	 * (non-Javadoc)
  	 * 
  	 * @see org.eclipse.jface.window.Window#getInitialLocation(org.eclipse.swt.graphics.Point)
  	 */
  	protected Point getInitialLocation(Point initialSize) {
  		Point result = getDefaultLocation(initialSize);
  		if (persistLocation) {
  			IDialogSettings settings = getDialogSettings();
  			if (settings != null) {
  				try {
  					int x = settings.getInt(getClass().getName()
  							+ DIALOG_ORIGIN_X);
  					int y = settings.getInt(getClass().getName()
  							+ 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;
  	}
  
  	/**
  	 * Apply any desired color to the specified composite and its children.
  	 * 
  	 * @param composite
  	 *            the contents composite
  	 */
  	private void applyColors(Composite composite) {
  		// The getForeground() and getBackground() methods
  		// should not answer null, but IColorProvider clients
  		// are accustomed to null meaning use the default, so we guard
  		// against this assumption.
  		Color color = getForeground();
  		if (color == null)
  			color = getDefaultForeground();
  		applyForegroundColor(color, composite, getForegroundColorExclusions());
  		color = getBackground();
  		if (color == null)
  			color = getDefaultBackground();
  		applyBackgroundColor(color, composite, getBackgroundColorExclusions());
  	}
  
  	/**
  	 * Get the foreground color that should be used for this popup. Subclasses
  	 * may override.
  	 * 
  	 * @return the foreground color to be used. Should not be <code>null</code>.
  	 * 
  	 * @since 3.4
  	 * 
  	 * @see #getForegroundColorExclusions()
  	 */
  	protected Color getForeground() {
  		return getDefaultForeground();
  	}
  
  	/**
  	 * Get the background color that should be used for this popup. Subclasses
  	 * may override.
  	 * 
  	 * @return the background color to be used. Should not be <code>null</code>.
  	 * 
  	 * @since 3.4
  	 * 
  	 * @see #getBackgroundColorExclusions()
  	 */
  	protected Color getBackground() {
  		return getDefaultBackground();
  	}
  
  	/**
  	 * Return the default foreground color used for popup dialogs.
  	 * 
  	 * @return the default foreground color.
  	 */
  	private Color getDefaultForeground() {
  		return getShell().getDisplay()
  				.getSystemColor(SWT.COLOR_INFO_FOREGROUND);
  	}
  
  	/**
  	 * Return the default background color used for popup dialogs.
  	 * 
  	 * @return the default background color
  	 */
  	private Color getDefaultBackground() {
  		return getShell().getDisplay()
  				.getSystemColor(SWT.COLOR_INFO_BACKGROUND);
  	}
  
  	/**
  	 * Apply any desired fonts to the specified composite and its children.
  	 * 
  	 * @param composite
  	 *            the contents composite
  	 */
  	private void applyFonts(Composite composite) {
  		Dialog.applyDialogFont(composite);
  
  		if (titleLabel != null) {
  			Font font = titleLabel.getFont();
  			FontData[] fontDatas = font.getFontData();
  			for (int i = 0; i < fontDatas.length; i++) {
  				fontDatas[i].setStyle(SWT.BOLD);
  			}
  			titleFont = new Font(titleLabel.getDisplay(), fontDatas);
  			titleLabel.setFont(titleFont);
  		}
  
  		if (infoLabel != null) {
  			Font font = infoLabel.getFont();
  			FontData[] fontDatas = font.getFontData();
  			for (int i = 0; i < fontDatas.length; i++) {
  				fontDatas[i].setHeight(fontDatas[i].getHeight() * 9 / 10);
  			}
  			infoFont = new Font(infoLabel.getDisplay(), fontDatas);
  			infoLabel.setFont(infoFont);
  		}
  	}
  
  	/**
  	 * Set the specified foreground color for the specified control and all of
  	 * its children, except for those specified in the list of exclusions.
  	 * 
  	 * @param color
  	 *            the color to use as the foreground color
  	 * @param control
  	 *            the control whose color is to be changed
  	 * @param exclusions
  	 *            a list of controls who are to be excluded from getting their
  	 *            color assigned
  	 */
  	private void applyForegroundColor(Color color, Control control,
  			List exclusions) {
  		if (!exclusions.contains(control)) {
  			control.setForeground(color);
  		}
  		if (control instanceof Composite) {
  			Control[] children = ((Composite) control).getChildren();
  			for (int i = 0; i < children.length; i++) {
  				applyForegroundColor(color, children[i], exclusions);
  			}
  		}
  	}
  
  	/**
  	 * Set the specified background color for the specified control and all of
  	 * its children, except for those specified in the list of exclusions.
  	 * 
  	 * @param color
  	 *            the color to use as the background color
  	 * @param control
  	 *            the control whose color is to be changed
  	 * @param exclusions
  	 *            a list of controls who are to be excluded from getting their
  	 *            color assigned
  	 */
  	private void applyBackgroundColor(Color color, Control control,
  			List exclusions) {
  		if (!exclusions.contains(control)) {
  			control.setBackground(color);
  		}
  		if (control instanceof Composite) {
  			Control[] children = ((Composite) control).getChildren();
  			for (int i = 0; i < children.length; i++) {
  				applyBackgroundColor(color, children[i], exclusions);
  			}
  		}
  	}
  
  	/**
  	 * Set the specified foreground color for the specified control and all of
  	 * its children. Subclasses may override this method, but typically do not.
  	 * If a subclass wishes to exclude a particular control in its contents from
  	 * getting the specified foreground color, it may instead override
  	 * {@link #getForegroundColorExclusions()}.
  	 * 
  	 * @param color
  	 *            the color to use as the foreground color
  	 * @param control
  	 *            the control whose color is to be changed
  	 * @see PopupDialog#getForegroundColorExclusions()
  	 */
  	protected void applyForegroundColor(Color color, Control control) {
  		applyForegroundColor(color, control, getForegroundColorExclusions());
  	}
  
  	/**
  	 * Set the specified background color for the specified control and all of
  	 * its children. Subclasses may override this method, but typically do not.
  	 * If a subclass wishes to exclude a particular control in its contents from
  	 * getting the specified background color, it may instead override
  	 * {@link #getBackgroundColorExclusions()}
  	 * 
  	 * @param color
  	 *            the color to use as the background color
  	 * @param control
  	 *            the control whose color is to be changed
  	 * @see PopupDialog#getBackgroundColorExclusions()
  	 */
  	protected void applyBackgroundColor(Color color, Control control) {
  		applyBackgroundColor(color, control, getBackgroundColorExclusions());
  	}
  
  	/**
  	 * Return a list of controls which should never have their foreground color
  	 * reset. Subclasses may extend this method, but should always call
  	 * <code>super.getForegroundColorExclusions</code> to aggregate the list.
  	 * 
  	 * 
  	 * @return the List of controls
  	 */
  	protected List getForegroundColorExclusions() {
  		List list = new ArrayList(3);
  		if (infoLabel != null) {
  			list.add(infoLabel);
  		}
  		if (titleSeparator != null) {
  			list.add(titleSeparator);
  		}
  		if (infoSeparator != null) {
  			list.add(infoSeparator);
  		}
  		return list;
  	}
  
  	/**
  	 * Return a list of controls which should never have their background color
  	 * reset. Subclasses may extend this method, but should always call
  	 * <code>super.getBackgroundColorExclusions</code> to aggregate the list.
  	 * 
  	 * @return the List of controls
  	 */
  	protected List getBackgroundColorExclusions() {
  		List list = new ArrayList(2);
  		if (titleSeparator != null) {
  			list.add(titleSeparator);
  		}
  		if (infoSeparator != null) {
  			list.add(infoSeparator);
  		}
  		return list;
  	}
  
  	/**
  	 * Initialize any state related to the widgetry that should be set up each
  	 * time widgets are created.
  	 */
  	private void initializeWidgetState() {
  		menuManager = null;
  		dialogArea = null;
  		titleLabel = null;
  		titleSeparator = null;
  		infoSeparator = null;
  		infoLabel = null;
  		toolBar = null;
  
  		// If the menu item for persisting bounds is displayed, use the stored
  		// value to determine whether any persisted bounds should be honored at
  		// all.
  		if (showDialogMenu && showPersistActions) {
  			IDialogSettings settings = getDialogSettings();
  			if (settings != null) {
  