/*******************************************************************************
 * Copyright (c) 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.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.resource.ImageDescriptor;
import org.eclipse.jface.resource.JFaceResources;
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.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.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
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.
 * 
 * Note: This API is considered experimental. It is still evolving during 3.2
 * and is subject to change. It is being released to obtain feedback from early
 * adopters.
 * 
 * @since 3.2
 */
public class PopupDialog extends Window {

	/**
	 * 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.
	 */
	private static final String DIALOG_USE_PERSISTED_BOUNDS = "DIALOG_USE_PERSISTED_BOUNDS"; //$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(persistBounds);
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.jface.action.IAction#run()
		 */
		public void run() {
			persistBounds = 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.NO_TRIM;

	/**
	 * Shell style appropriate for an info popup that can get focus.
	 */
	public final static int INFOPOPUP_SHELLSTYLE = SWT.NO_TRIM;

	/**
	 * 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;

	/**
	 * Border thickness in pixels.
	 */
	private static final int BORDER_THICKNESS = 1;

	/**
	 * 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;

	/**
	 * The images for the dialog menu.
	 */
	private Image menuImage, disabledMenuImage = null;

	/**
	 * 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 a menu action allowing the user to choose whether
	 * the dialog bounds should be persisted is to be shown.
	 */
	private boolean showPersistAction = false;

	/**
	 * Flag specifying whether the bounds of the popup should be persisted. This
	 * flag is updated by a menu if the menu is shown.
	 */
	private boolean persistBounds = false;

	/**
	 * 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 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 showPersistAction
	 *            A boolean indicating whether an action allowing the user to
	 *            control the persisting of the dialog bounds 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()
	 */
	public PopupDialog(Shell parent, int shellStyle, boolean takeFocusOnOpen,
			boolean persistBounds, boolean showDialogMenu,
			boolean showPersistAction, String titleText, String infoText) {
		super(parent);
		setShellStyle(shellStyle);
		this.takeFocusOnOpen = takeFocusOnOpen;
		this.showDialogMenu = showDialogMenu;
		this.showPersistAction = showPersistAction;
		this.titleText = titleText;
		this.infoText = infoText;

		setBlockOnOpen(false);

		this.persistBounds = persistBounds;
		initializeWidgetState();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jface.window.Window#configureShell(Shell)
	 */
	protected void configureShell(Shell shell) {
		GridLayout layout;
		Display display = shell.getDisplay();
		shell.setBackground(display.getSystemColor(SWT.COLOR_BLACK));

		layout = new GridLayout(1, false);
		int border = ((getShellStyle() & SWT.NO_TRIM) == 0) ? 0
				: BORDER_THICKNESS;
		layout.marginHeight = border;
		layout.marginWidth = border;
		shell.setLayout(layout);

		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) {
					close();
				}
			}
		});
		// 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 = !"carbon".equals(SWT.getPlatform()); //$NON-NLS-1$
				}
			}
		});

		if ((getShellStyle() & SWT.ON_TOP) != 0 && shell.getParent() != null) {
			parentDeactivateListener= new Listener() {
				public void handleEvent(Event event) {
					if (listenToParentDeactivate) {
						close();
					} 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();
			}
		});
	}

	/**
	 * 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);
		GridLayout layout = new GridLayout(1, false);
		layout.marginHeight = POPUP_MARGINHEIGHT;
		layout.marginWidth = POPUP_MARGINWIDTH;
		layout.verticalSpacing = POPUP_VERTICALSPACING;
		layout.horizontalSpacing = POPUP_HORIZONTALSPACING;
		composite.setLayout(layout);
		GridData gd = new GridData(GridData.FILL_BOTH);
		composite.setLayoutData(gd);

		// 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) {
			dialogArea.setLayoutData(new GridData(GridData.FILL_BOTH));
		}
		
		// 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);
		GridLayout layout = new GridLayout();
		layout.marginHeight = POPUP_MARGINHEIGHT;
		layout.marginWidth = POPUP_MARGINWIDTH;
		layout.verticalSpacing = POPUP_VERTICALSPACING;
		layout.horizontalSpacing = POPUP_HORIZONTALSPACING;
		composite.setLayout(layout);
		GridData gd = new GridData(GridData.FILL_BOTH);
		composite.setLayoutData(gd);
		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);
		GridLayout layout = new GridLayout(2, false);
		layout.marginHeight = POPUP_MARGINHEIGHT;
		layout.marginWidth = POPUP_MARGINWIDTH;
		layout.verticalSpacing = POPUP_VERTICALSPACING;
		layout.horizontalSpacing = POPUP_HORIZONTALSPACING;
		titleAreaComposite.setLayout(layout);
		titleAreaComposite
				.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

		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);

		GridData gd = new GridData(GridData.FILL_HORIZONTAL);
		if (!showDialogMenu)
			gd.horizontalSpan = 2;
		titleLabel.setLayoutData(gd);
		
		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 (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);
		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);
		GridData gd = new GridData(GridData.FILL_HORIZONTAL
				| GridData.HORIZONTAL_ALIGN_BEGINNING
				| GridData.VERTICAL_ALIGN_BEGINNING);
		infoLabel.setLayoutData(gd);
		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);
		separator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		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);

		toolBar.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END));

		menuImage = ImageDescriptor.createFromFile(PopupDialog.class,
				"images/popup_menu.gif").createImage();//$NON-NLS-1$
		disabledMenuImage = ImageDescriptor.createFromFile(PopupDialog.class,
				"images/popup_menu_disabled.gif").createImage();//$NON-NLS-1$
		viewMenuButton.setImage(menuImage);
		viewMenuButton.setDisabledImage(disabledMenuImage);
		viewMenuButton.setToolTipText(JFaceResources
				.getString("PopupDialog.menuTooltip")); //$NON-NLS-1$
		viewMenuButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				showDialogMenu();
			}
		});
		viewMenuButton.addDisposeListener(new DisposeListener() {
			public void widgetDisposed(DisposeEvent e) {
				menuImage.dispose();
				menuImage = null;
				disabledMenuImage.dispose();
				disabledMenuImage = null;
			}
		});
	}

	/**
	 * 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 (showPersistAction) {
			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 = !"gtk".equals(SWT.getPlatform()); //$NON-NLS-1$

		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 <true> if the dialogs bounds will be persisted, false if it will
	 *         not.
	 */
	protected boolean getPersistBounds() {
		return persistBounds;
	}

	/**
	 * 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() {
		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;
			}
			if (persistBounds) {
				String prefix = getClass().getName();
				settings.put(prefix + DIALOG_ORIGIN_X, shellLocation.x);
				settings.put(prefix + DIALOG_ORIGIN_Y, shellLocation.y);
				settings.put(prefix + DIALOG_WIDTH, shellSize.x);
				settings.put(prefix + DIALOG_HEIGHT, shellSize.y);
			}
			if (showPersistAction && showDialogMenu)
				settings.put(
						getClass().getName() + DIALOG_USE_PERSISTED_BOUNDS,
						persistBounds);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jface.window.Window#getInitialSize()
	 */
	protected Point getInitialSize() {
		Point result = super.getInitialSize();
		if (persistBounds) {
			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;
	}

	/**
	 * 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 = super.getInitialLocation(initialSize);
		if (persistBounds) {
			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) {
		applyForegroundColor(getShell().getDisplay().getSystemColor(
				SWT.COLOR_INFO_FOREGROUND), composite,
				getForegroundColorExclusions());
		applyBackgroundColor(getShell().getDisplay().getSystemColor(
				SWT.COLOR_INFO_BACKGROUND), composite,
				getBackgroundColorExclusions());
	}

	/**
	 * Apply any desired fonts to the specified composite and its children.
	 * 
	 * @param composite
	 *            the contents composite
	 */
	private void applyFonts(Composite composite) {
		Dialog.applyDialogFont(composite);

	}

	/**
	 * 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.
	 * 
	 * @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
	 * <code>PopupDialog.getForegroundColorExclusions</code>.
	 * 
	 * @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 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
	 * <code>PopupDialog.getBackgroundColorExclusions</code>.
	 * 
	 * @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 (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 (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 && showPersistAction) {
			IDialogSettings settings = getDialogSettings();
			if (settings != null) {
				persistBounds = settings.getBoolean(getClass().getName()
						+ DIALOG_USE_PERSISTED_BOUNDS);
			}
		}

	}
	
	/**
	 * The dialog is being disposed.  Dispose of any resources allocated.
	 *
	 */
	private void handleDispose() {
		if (infoFont != null && !infoFont.isDisposed())
			infoFont.dispose();
		infoFont = null;
		if (titleFont != null && !titleFont.isDisposed())
			titleFont.dispose();
		titleFont = null;
	}
}
