/*******************************************************************************
 * Copyright (c) 2000, 2005 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jface.wizard;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.jface.dialogs.ControlEnableState;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.dialogs.IPageChangeProvider;
import org.eclipse.jface.dialogs.IPageChangedListener;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.PageChangedEvent;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.operation.ModalContext;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.util.Assert;
import org.eclipse.jface.util.SafeRunnable;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.events.HelpEvent;
import org.eclipse.swt.events.HelpListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Cursor;
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.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.swt.widgets.Shell;

/**
 * A dialog to show a wizard to the end user. 
 * <p>
 * In typical usage, the client instantiates this class with 
 * a particular wizard. The dialog serves as the wizard container
 * and orchestrates the presentation of its pages.
 * <p>
 * The standard layout is roughly as follows: 
 * it has an area at the top containing both the
 * wizard's title, description, and image; the actual wizard page
 * appears in the middle; below that is a progress indicator
 * (which is made visible if needed); and at the bottom
 * of the page is message line and a button bar containing 
 * Help, Next, Back, Finish, and Cancel buttons (or some subset).
 * </p>
 * <p>
 * Clients may subclass <code>WizardDialog</code>, although this
 * is rarely required.
 * </p>
 */
public class WizardDialog extends TitleAreaDialog implements IWizardContainer2, IPageChangeProvider {
    /**
     * Image registry key for error message image (value <code>"dialog_title_error_image"</code>).
     */
    public static final String WIZ_IMG_ERROR = "dialog_title_error_image"; //$NON-NLS-1$

    // The wizard the dialog is currently showing.
    private IWizard wizard;

    // Wizards to dispose
    private ArrayList createdWizards = new ArrayList();

    // Current nested wizards
    private ArrayList nestedWizards = new ArrayList();

    // The currently displayed page.
    private IWizardPage currentPage = null;

    // The number of long running operation executed from the dialog.	
    private long activeRunningOperations = 0;

    // The current page message and description
    private String pageMessage;

    private int pageMessageType = IMessageProvider.NONE;

    private String pageDescription;

    // The progress monitor
    private ProgressMonitorPart progressMonitorPart;

    private Cursor waitCursor;

    private Cursor arrowCursor;

    private MessageDialog windowClosingDialog;

    // Navigation buttons
    private Button backButton;

    private Button nextButton;

    private Button finishButton;

    private Button cancelButton;

    private Button helpButton;

    private SelectionAdapter cancelListener;

    private boolean isMovingToPreviousPage = false;

    private Composite pageContainer;

    private PageContainerFillLayout pageContainerLayout = new PageContainerFillLayout(
            5, 5, 300, 225);

    private int pageWidth = SWT.DEFAULT;

    private int pageHeight = SWT.DEFAULT;

    private static final String FOCUS_CONTROL = "focusControl"; //$NON-NLS-1$

    private boolean lockedUI = false;
	
    private ListenerList pageChangedListeners = new ListenerList();

    /**
     * A layout for a container which includes several pages, like
     * a notebook, wizard, or preference dialog. The size computed by
     * this layout is the maximum width and height of all pages currently
     * inserted into the container.
     */
    protected class PageContainerFillLayout extends Layout {
        /**
         * The margin width; <code>5</code> pixels by default.
         */
        public int marginWidth = 5;

        /**
         * The margin height; <code>5</code> pixels by default.
         */
        public int marginHeight = 5;

        /**
         * The minimum width; <code>0</code> pixels by default.
         */
        public int minimumWidth = 0;

        /**
         * The minimum height; <code>0</code> pixels by default.
         */
        public int minimumHeight = 0;

        /**
         * Creates new layout object.
         *
         * @param mw the margin width
         * @param mh the margin height
         * @param minW the minimum width
         * @param minH the minimum height
         */
        public PageContainerFillLayout(int mw, int mh, int minW, int minH) {
            marginWidth = mw;
            marginHeight = mh;
            minimumWidth = minW;
            minimumHeight = minH;
        }

        /* (non-Javadoc)
         * Method declared on Layout.
         */
        public Point computeSize(Composite composite, int wHint, int hHint,
                boolean force) {
            if (wHint != SWT.DEFAULT && hHint != SWT.DEFAULT)
                return new Point(wHint, hHint);
            Point result = null;
            Control[] children = composite.getChildren();
            if (children.length > 0) {
                result = new Point(0, 0);
                for (int i = 0; i < children.length; i++) {
                    Point cp = children[i].computeSize(wHint, hHint, force);
                    result.x = Math.max(result.x, cp.x);
                    result.y = Math.max(result.y, cp.y);
                }
                result.x = result.x + 2 * marginWidth;
                result.y = result.y + 2 * marginHeight;
            } else {
                Rectangle rect = composite.getClientArea();
                result = new Point(rect.width, rect.height);
            }
            result.x = Math.max(result.x, minimumWidth);
            result.y = Math.max(result.y, minimumHeight);
            if (wHint != SWT.DEFAULT)
                result.x = wHint;
            if (hHint != SWT.DEFAULT)
                result.y = hHint;
            return result;
        }

        /**
         * Returns the client area for the given composite according to this layout.
         *
         * @param c the composite
         * @return the client area rectangle
         */
        public Rectangle getClientArea(Composite c) {
            Rectangle rect = c.getClientArea();
            rect.x = rect.x + marginWidth;
            rect.y = rect.y + marginHeight;
            rect.width = rect.width - 2 * marginWidth;
            rect.height = rect.height - 2 * marginHeight;
            return rect;
        }

        /* (non-Javadoc)
         * Method declared on Layout.
         */
        public void layout(Composite composite, boolean force) {
            Rectangle rect = getClientArea(composite);
            Control[] children = composite.getChildren();
            for (int i = 0; i < children.length; i++) {
                children[i].setBounds(rect);
            }
        }

        /**
         * Lays outs the page according to this layout.
         *
         * @param w the control
         */
        public void layoutPage(Control w) {
            w.setBounds(getClientArea(w.getParent()));
        }

        /**
         * Sets the location of the page so that its origin is in the
         * upper left corner.
         *
         * @param w the control
         */
        public void setPageLocation(Control w) {
            w.setLocation(marginWidth, marginHeight);
        }
    }

    /**
     * Creates a new wizard dialog for the given wizard. 
     *
     * @param parentShell the parent shell
     * @param newWizard the wizard this dialog is working on
     */
    public WizardDialog(Shell parentShell, IWizard newWizard) {
        super(parentShell);
        setShellStyle(SWT.CLOSE | SWT.TITLE | SWT.BORDER
                | SWT.APPLICATION_MODAL | SWT.RESIZE | getDefaultOrientation());
        setWizard(newWizard);
        // since VAJava can't initialize an instance var with an anonymous
        // class outside a constructor we do it here:
        cancelListener = new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                cancelPressed();
            }
        };
    }

    /**
     * About to start a long running operation triggered through
     * the wizard. Shows the progress monitor and disables the wizard's
     * buttons and controls.
     *
     * @param enableCancelButton <code>true</code> if the Cancel button should
     *   be enabled, and <code>false</code> if it should be disabled
     * @return the saved UI state
     */
    private Object aboutToStart(boolean enableCancelButton) {
        Map savedState = null;
        if (getShell() != null) {
            // Save focus control
            Control focusControl = getShell().getDisplay().getFocusControl();
            if (focusControl != null && focusControl.getShell() != getShell())
                focusControl = null;
            boolean needsProgressMonitor = wizard.needsProgressMonitor();
            cancelButton.removeSelectionListener(cancelListener);
            // Set the busy cursor to all shells.
            Display d = getShell().getDisplay();
            waitCursor = new Cursor(d, SWT.CURSOR_WAIT);
            setDisplayCursor(waitCursor);
            // Set the arrow cursor to the cancel component.
            arrowCursor = new Cursor(d, SWT.CURSOR_ARROW);
            cancelButton.setCursor(arrowCursor);
            // Deactivate shell
            savedState = saveUIState(needsProgressMonitor && enableCancelButton);
            if (focusControl != null)
                savedState.put(FOCUS_CONTROL, focusControl);
            // Attach the progress monitor part to the cancel button
            if (needsProgressMonitor) {
                progressMonitorPart.attachToCancelComponent(cancelButton);
                progressMonitorPart.setVisible(true);
            }
        }
        return savedState;
    }

    /**
     * The Back button has been pressed.
     */
    protected void backPressed() {
        IWizardPage page = currentPage.getPreviousPage();
        if (page == null)
            // should never happen since we have already visited the page
            return;
        // set flag to indicate that we are moving back
        isMovingToPreviousPage = true;
        // show the page
        showPage(page);
    }

    /* (non-Javadoc)
     * Method declared on Dialog.
     */
    protected void buttonPressed(int buttonId) {
        switch (buttonId) {
        case IDialogConstants.HELP_ID: {
            helpPressed();
            break;
        }
        case IDialogConstants.BACK_ID: {
            backPressed();
            break;
        }
        case IDialogConstants.NEXT_ID: {
            nextPressed();
            break;
        }
        case IDialogConstants.FINISH_ID: {
            finishPressed();
            break;
        }
        // The Cancel button has a listener which calls cancelPressed directly
        }
    }

    /**
     * Calculates the difference in size between the given
     * page and the page container. A larger page results 
     * in a positive delta.
     *
     * @param page the page
     * @return the size difference encoded
     *   as a <code>new Point(deltaWidth,deltaHeight)</code>
     */
    private Point calculatePageSizeDelta(IWizardPage page) {
        Control pageControl = page.getControl();
        if (pageControl == null)
            // control not created yet
            return new Point(0, 0);
        Point contentSize = pageControl.computeSize(SWT.DEFAULT, SWT.DEFAULT,
                true);
        Rectangle rect = pageContainerLayout.getClientArea(pageContainer);
        Point containerSize = new Point(rect.width, rect.height);
        return new Point(Math.max(0, contentSize.x - containerSize.x), Math
                .max(0, contentSize.y - containerSize.y));
    }

    /* (non-Javadoc)
     * Method declared on Dialog.
     */
    protected void cancelPressed() {
        if (activeRunningOperations <= 0) {
            // Close the dialog. The check whether the dialog can be
            // closed or not is done in <code>okToClose</code>.
            // This ensures that the check is also evaluated when the user
            // presses the window's close button.
            setReturnCode(CANCEL);
            close();
        } else {
            cancelButton.setEnabled(false);
        }
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.jface.window.Window#close()
     */
    public boolean close() {
        if (okToClose())
            return hardClose();
        return false;
    }

    /* (non-Javadoc)
     * Method declared on Window.
     */
    protected void configureShell(Shell newShell) {
        super.configureShell(newShell);
        // Register help listener on the shell
        newShell.addHelpListener(new HelpListener() {
            public void helpRequested(HelpEvent event) {
                // call perform help on the current page
                if (currentPage != null) {
                    currentPage.performHelp();
                }
            }
        });
    }

    /**
     * Creates and returns the contents of this dialog's 
     * button bar.
     * <p>
     * The <code>WizardDialog</code> implementation of this framework method
     * prevents the composite's columns from being made equal width in order
     * to remove the margin between the Back and Next buttons.
     * </p>
     *
     * @param parent the parent composite to contain the button bar
     * @return the button bar control
     */
    protected Control createButtonBar(Composite parent) {
        Composite composite = (Composite) super.createButtonBar(parent);
        ((GridLayout) composite.getLayout()).makeColumnsEqualWidth = false;
        return composite;
    }

    /* (non-Javadoc)
     * Method declared on Dialog.
     */
    protected void createButtonsForButtonBar(Composite parent) {
        if (wizard.isHelpAvailable()) {
            helpButton = createButton(parent, IDialogConstants.HELP_ID,
                    IDialogConstants.HELP_LABEL, false);
        }
        if (wizard.needsPreviousAndNextButtons())
            createPreviousAndNextButtons(parent);
        finishButton = createButton(parent, IDialogConstants.FINISH_ID,
                IDialogConstants.FINISH_LABEL, true);
        cancelButton = createCancelButton(parent);
    }

    /**
     * Creates the Cancel button for this wizard dialog.
     * Creates a standard (<code>SWT.PUSH</code>) button and registers for its
     * selection events. Note that the number of columns in the button bar composite
     * is incremented. The Cancel button is created specially to give it a 
     * removeable listener.
     *
     * @param parent the parent button bar
     * @return the new Cancel button
     */
    private Button createCancelButton(Composite parent) {
        // increment the number of columns in the button bar
        ((GridLayout) parent.getLayout()).numColumns++;
        Button button = new Button(parent, SWT.PUSH);
        button.setText(IDialogConstants.CANCEL_LABEL);
        setButtonLayoutData(button);
        button.setFont(parent.getFont());
        button.setData(new Integer(IDialogConstants.CANCEL_ID));
        button.addSelectionListener(cancelListener);
        return button;
    }

    /**
     * Return the cancel button if the id is a the cancel id.
     * @param id the button id
     * @return the button corresponding to the button id
     */
    protected Button getButton(int id) {
        if (id == IDialogConstants.CANCEL_ID)
            return cancelButton;
        return super.getButton(id);
    }

    /**
     * The <code>WizardDialog</code> implementation of this <code>Window</code>
     * method calls call <code>IWizard.addPages</code> to allow the current
     * wizard to add extra pages, then <code>super.createContents</code> to create
     * the controls. It then calls <code>IWizard.createPageControls</code>
     * to allow the wizard to pre-create their page controls prior to opening,
     * so that the wizard opens to the correct size. And finally it
     * shows the first page.
     */
    protected Control createContents(Composite parent) {
        // Allow the wizard to add pages to itself
        // Need to call this now so page count is correct
        // for determining if next/previous buttons are needed
        wizard.addPages();
        Control contents = super.createContents(parent);
        // Allow the wizard pages to precreate their page controls
        createPageControls();
        // Show the first page
        showStartingPage();
        return contents;
    }

    /* (non-Javadoc)
     * Method declared on Dialog.
     */
    protected Control createDialogArea(Composite parent) {
        Composite composite = (Composite) super.createDialogArea(parent);
        // Build the Page container
        pageContainer = createPageContainer(composite);
        GridData gd = new GridData(GridData.FILL_BOTH);
        gd.widthHint = pageWidth;
        gd.heightHint = pageHeight;
        pageContainer.setLayoutData(gd);
        pageContainer.setFont(parent.getFont());
        // Insert a progress monitor 
        GridLayout pmlayout = new GridLayout();
        pmlayout.numColumns = 1;
        progressMonitorPart = createProgressMonitorPart(composite, pmlayout);
        progressMonitorPart
                .setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
        progressMonitorPart.setVisible(false);
        // Build the separator line
        Label separator = new Label(composite, SWT.HORIZONTAL | SWT.SEPARATOR);
        separator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

        applyDialogFont(progressMonitorPart);
        return composite;
    }

    /**
     * Create the progress monitor part in the receiver.
     * @param composite
     * @param pmlayout
     * @return ProgressMonitorPart
     */
    protected ProgressMonitorPart createProgressMonitorPart(
            Composite composite, GridLayout pmlayout) {
        return new ProgressMonitorPart(composite, pmlayout, SWT.DEFAULT) {
            String currentTask = null;

            /* (non-Javadoc)
             * @see org.eclipse.jface.wizard.ProgressMonitorPart#setBlocked(org.eclipse.core.runtime.IStatus)
             */
            public void setBlocked(IStatus reason) {
                super.setBlocked(reason);
                if (!lockedUI)//Do not show blocked if we are locking the UI
                    getBlockedHandler().showBlocked(getShell(), this, reason,
                            currentTask);
            }

            /* (non-Javadoc)
             * @see org.eclipse.jface.wizard.ProgressMonitorPart#clearBlocked()
             */
            public void clearBlocked() {
                super.clearBlocked();
                if (!lockedUI)//Do not vlear if we never set it
                    getBlockedHandler().clearBlocked();
            }

            /* (non-Javadoc)
             * @see org.eclipse.jface.wizard.ProgressMonitorPart#beginTask(java.lang.String, int)
             */
            public void beginTask(String name, int totalWork) {
                super.beginTask(name, totalWork);
                currentTask = name;
            }

            /* (non-Javadoc)
             * @see org.eclipse.jface.wizard.ProgressMonitorPart#setTaskName(java.lang.String)
             */
            public void setTaskName(String name) {
                super.setTaskName(name);
                currentTask = name;
            }

            /* (non-Javadoc)
             * @see org.eclipse.jface.wizard.ProgressMonitorPart#subTask(java.lang.String)
             */
            public void subTask(String name) {
                super.subTask(name);
                //If we haven't got anything yet use this value for more context
                if (currentTask == null)
                    currentTask = name;
            }
        };
    }

    /**
     * Creates the container that holds all pages.
     * @param parent
     * @return Composite
     */
    private Composite createPageContainer(Composite parent) {
        Composite result = new Composite(parent, SWT.NULL);
        result.setLayout(pageContainerLayout);
        return result;
    }

    /**
     * Allow the wizard's pages to pre-create their page controls.
     * This allows the wizard dialog to open to the correct size.
     */
    private void createPageControls() {
        // Allow the wizard pages to precreate their page controls
        // This allows the wizard to open to the correct size
        wizard.createPageControls(pageContainer);
        // Ensure that all of the created pages are initially not visible
        IWizardPage[] pages = wizard.getPages();
        for (int i = 0; i < pages.length; i++) {
            IWizardPage page = pages[i];
            if (page.getControl() != null)
                page.getControl().setVisible(false);
        }
    }

    /**
     * Creates the Previous and Next buttons for this wizard dialog.
     * Creates standard (<code>SWT.PUSH</code>) buttons and registers for their
     * selection events. Note that the number of columns in the button bar composite
     * is incremented. These buttons are created specially to prevent any space 
     * between them.
     *
     * @param parent the parent button bar
     * @return a composite containing the new buttons
     */
    private Composite createPreviousAndNextButtons(Composite parent) {
        // increment the number of columns in the button bar
        ((GridLayout) parent.getLayout()).numColumns++;
        Composite composite = new Composite(parent, SWT.NONE);
        // create a layout with spacing and margins appropriate for the font size.
        GridLayout layout = new GridLayout();
        layout.numColumns = 0; // will be incremented by createButton
        layout.marginWidth = 0;
        layout.marginHeight = 0;
        layout.horizontalSpacing = 0;
        layout.verticalSpacing = 0;
        composite.setLayout(layout);
        GridData data = new GridData(GridData.HORIZONTAL_ALIGN_CENTER
                | GridData.VERTICAL_ALIGN_CENTER);
        composite.setLayoutData(data);
        composite.setFont(parent.getFont());
        backButton = createButton(composite, IDialogConstants.BACK_ID,
                IDialogConstants.BACK_LABEL, false);
        nextButton = createButton(composite, IDialogConstants.NEXT_ID,
                IDialogConstants.NEXT_LABEL, false);
        return composite;
    }

    /**
     * Creates and return a new wizard closing dialog without openiong it.
     * @return MessageDalog
     */
    private MessageDialog createWizardClosingDialog() {
        MessageDialog result = new MessageDialog(getShell(), JFaceResources
                .getString("WizardClosingDialog.title"), //$NON-NLS-1$
                null, JFaceResources.getString("WizardClosingDialog.message"), //$NON-NLS-1$
                MessageDialog.QUESTION,
                new String[] { IDialogConstants.OK_LABEL }, 0);
        return result;
    }

    /**
     * The Finish button has been pressed.
     */
    protected void finishPressed() {
        // Wizards are added to the nested wizards list in setWizard.
        // This means that the current wizard is always the last wizard in the list.
        // Note that we first call the current wizard directly (to give it a chance to 
        // abort, do work, and save state) then call the remaining n-1 wizards in the 
        // list (to save state).
        if (wizard.performFinish()) {
            // Call perform finish on outer wizards in the nested chain
            // (to allow them to save state for example)
            for (int i = 0; i < nestedWizards.size() - 1; i++) {
                ((IWizard) nestedWizards.get(i)).performFinish();
            }
            // Hard close the dialog. 
            setReturnCode(OK);
            hardClose();
        }
    }

    /* (non-Javadoc)
     * Method declared on IWizardContainer.
     */
    public IWizardPage getCurrentPage() {
        return currentPage;
    }

    /**
     * Returns the progress monitor for this wizard dialog (if it has one).
     *
     * @return the progress monitor, or <code>null</code> if
     *   this wizard dialog does not have one
     */
    protected IProgressMonitor getProgressMonitor() {
        return progressMonitorPart;
    }

    /**
     * Returns the wizard this dialog is currently displaying.
     *
     * @return the current wizard
     */
    protected IWizard getWizard() {
        return wizard;
    }

    /**
     * Closes this window.
     *
     * @return <code>true</code> if the window is (or was already) closed, 
     *   and <code>false</code> if it is still open
     */
    private boolean hardClose() {
        // inform wizards
        for (int i = 0; i < createdWizards.size(); i++) {
            IWizard createdWizard = (IWizard) createdWizards.get(i);
            createdWizard.dispose();
            // Remove this dialog as a parent from the managed wizard.
            // Note that we do this after calling dispose as the wizard or
            // its pages may need access to the container during
            // dispose code
            createdWizard.setContainer(null);
        }
        return super.close();
    }

    /**
     * The Help button has been pressed.
     */
    protected void helpPressed() {
        if (currentPage != null) {
            currentPage.performHelp();
        }
    }

    /**
     * The Next button has been pressed.
     */
    protected void nextPressed() {
        IWizardPage page = currentPage.getNextPage();
        if (page == null) {
            // something must have happend getting the next page
            return;
        }
        // show the next page
        showPage(page);
    }

    /**
     * Checks whether it is alright to close this wizard dialog
     * and performed standard cancel processing. If there is a
     * long running operation in progress, this method posts an
     * alert message saying that the wizard cannot be closed.
     * 
     * @return <code>true</code> if it is alright to close this dialog, and
     *  <code>false</code> if it is not
     */
    private boolean okToClose() {
        if (activeRunningOperations > 0) {
            synchronized (this) {
                windowClosingDialog = createWizardClosingDialog();
            }
            windowClosingDialog.open();
            synchronized (this) {
                windowClosingDialog = null;
            }
            return false;
        }
        return wizard.performCancel();
    }

    /**
     * Restores the enabled/disabled state of the given control.
     *
     * @param w the control
     * @param h the map (key type: <code>String</code>, element type:
     *   <code>Boolean</code>)
     * @param key the key
     * @see #saveEnableStateAndSet
     */
    private void restoreEnableState(Control w, Map h, String key) {
        if (w != null) {
            Boolean b = (Boolean) h.get(key);
            if (b != null)
                w.setEnabled(b.booleanValue());
        }
    }

    /**
     * Restores the enabled/disabled state of the wizard dialog's
     * buttons and the tree of controls for the currently showing page.
     *
     * @param state a map containing the saved state as returned by 
     *   <code>saveUIState</code>
     * @see #saveUIState
     */
    private void restoreUIState(Map state) {
        restoreEnableState(backButton, state, "back"); //$NON-NLS-1$
        restoreEnableState(nextButton, state, "next"); //$NON-NLS-1$
        restoreEnableState(finishButton, state, "finish"); //$NON-NLS-1$
        restoreEnableState(cancelButton, state, "cancel"); //$NON-NLS-1$
        restoreEnableState(helpButton, state, "help"); //$NON-NLS-1$
        Object pageValue = state.get("page"); //$NON-NLS-1$
        if (pageValue != null)//page may never have been created
            ((ControlEnableState) pageValue).restore();
    }

    /**
     * This implementation of IRunnableContext#run(boolean, boolean,
     * IRunnableWithProgress) blocks until the runnable has been run,
     * regardless of the value of <code>fork</code>.
     * It is recommended that <code>fork</code> is set to
     * true in most cases. If <code>fork</code> is set to <code>false</code>,
     * the runnable will run in the UI thread and it is the runnable's
     * responsibility to call <code>Display.readAndDispatch()</code>
     * to ensure UI responsiveness.
     * 
     * UI state is saved prior to executing the long-running operation and is 
     * restored after the long-running operation completes executing.  Any attempt  
     * to change the UI state of the wizard in the long-running operation will be 
     * nullified when original UI state is restored.
     * 
     */
    public void run(boolean fork, boolean cancelable,
            IRunnableWithProgress runnable) throws InvocationTargetException,
            InterruptedException {
        // The operation can only be canceled if it is executed in a separate thread.
        // Otherwise the UI is blocked anyway.
        Object state = null;
        if (activeRunningOperations == 0)
            state = aboutToStart(fork && cancelable);
        activeRunningOperations++;
        try {
            if (!fork)//If we are not forking do not open other dialogs
                lockedUI = true;
            ModalContext.run(runnable, fork, getProgressMonitor(), getShell()
                    .getDisplay());
            lockedUI = false;
        } finally {
            activeRunningOperations--;
            //Stop if this is the last one
            if (state != null)
                stopped(state);
        }
    }

    /**
     * Saves the enabled/disabled state of the given control in the
     * given map, which must be modifiable.
     *
     * @param w the control, or <code>null</code> if none
     * @param h the map (key type: <code>String</code>, element type:
     *   <code>Boolean</code>)
     * @param key the key
     * @param enabled <code>true</code> to enable the control, 
     *   and <code>false</code> to disable it
     * @see #restoreEnableState(Control, Map, String)
     */
    private void saveEnableStateAndSet(Control w, Map h, String key,
            boolean enabled) {
        if (w != null) {
            h.put(key, new Boolean(w.getEnabled()));
            w.setEnabled(enabled);
        }
    }

    /**
     * Captures and returns the enabled/disabled state of the wizard dialog's
     * buttons and the tree of controls for the currently showing page. All
     * these controls are disabled in the process, with the possible excepton of
     * the Cancel button.
     *
     * @param keepCancelEnabled <code>true</code> if the Cancel button should
     *   remain enabled, and <code>false</code> if it should be disabled
     * @return a map containing the saved state suitable for restoring later
     *   with <code>restoreUIState</code>
     * @see #restoreUIState
     */
    private Map saveUIState(boolean keepCancelEnabled) {
        Map savedState = new HashMap(10);
        saveEnableStateAndSet(backButton, savedState, "back", false); //$NON-NLS-1$
        saveEnableStateAndSet(nextButton, savedState, "next", false); //$NON-NLS-1$
        saveEnableStateAndSet(finishButton, savedState, "finish", false); //$NON-NLS-1$
        saveEnableStateAndSet(cancelButton, savedState,
                "cancel", keepCancelEnabled); //$NON-NLS-1$
        saveEnableStateAndSet(helpButton, savedState, "help", false); //$NON-NLS-1$
        if (currentPage != null)
            savedState
                    .put(
                            "page", ControlEnableState.disable(currentPage.getControl())); //$NON-NLS-1$
        return savedState;
    }

    /**
     * Sets the given cursor for all shells currently active
     * for this window's display.
     *
     * @param c the cursor
     */
    private void setDisplayCursor(Cursor c) {
        Shell[] shells = getShell().getDisplay().getShells();
        for (int i = 0; i < shells.length; i++)
            shells[i].setCursor(c);
    }

    /**
     * Sets the minimum page size used for the pages.
     *
     * @param minWidth the minimum page width
     * @param minHeight the minimum page height
     * @see #setMinimumPageSize(Point)
     */
    public void setMinimumPageSize(int minWidth, int minHeight) {
        Assert.isTrue(minWidth >= 0 && minHeight >= 0);
        pageContainerLayout.minimumWidth = minWidth;
        pageContainerLayout.minimumHeight = minHeight;
    }

    /**
     * Sets the minimum page size used for the pages.
     *
     * @param size the page size encoded as
     *   <code>new Point(width,height)</code>
     * @see #setMinimumPageSize(int,int)
     */
    public void setMinimumPageSize(Point size) {
        setMinimumPageSize(size.x, size.y);
    }

    /**
     * Sets the size of all pages.
     * The given size takes precedence over computed sizes.
     *
     * @param width the page width
     * @param height the page height
     * @see #setPageSize(Point)
     */
    public void setPageSize(int width, int height) {
        pageWidth = width;
        pageHeight = height;
    }

    /**
     * Sets the size of all pages.
     * The given size takes precedence over computed sizes.
     *
     * @param size the page size encoded as
     *   <code>new Point(width,height)</code>
     * @see #setPageSize(int,int)
     */
    public void setPageSize(Point size) {
        setPageSize(size.x, size.y);
    }

    /**
     * Sets the wizard this dialog is currently displaying.
     *
     * @param newWizard the wizard
     */
    protected void setWizard(IWizard newWizard) {
        wizard = newWizard;
        wizard.setContainer(this);
        if (!createdWizards.contains(wizard)) {
            createdWizards.add(wizard);
            // New wizard so just add it to the end of our nested list
            nestedWizards.add(wizard);
            if (pageContainer != null) {
                // Dialog is already open	
                // Allow the wizard pages to precreate their page controls
                // This allows the wizard to open to the correct size
                createPageControls();
                // Ensure the dialog is large enough for the wizard
                updateSizeForWizard(wizard);
                pageContainer.layout(true);
            }
        } else {
            // We have already seen this wizard, if it is the previous wizard
            // on the nested list then we assume we have gone back and remove 
            // the last wizard from the list
            int size = nestedWizards.size();
            if (size >= 2 && nestedWizards.get(size - 2) == wizard)
                nestedWizards.remove(size - 1);
            else
                // Assume we are going forward to revisit a wizard
                nestedWizards.add(wizard);
        }
    }

    /* (non-Javadoc)
     * Method declared on IWizardContainer.
     */
    public void showPage(IWizardPage page) {
        if (page == null || page == currentPage) {
            return;
        }
        if (!isMovingToPreviousPage)
            // remember my previous page.
            page.setPreviousPage(currentPage);
        else
            isMovingToPreviousPage = false;
        //Update for the new page ina busy cursor if possible
        if (getContents() == null)
            updateForPage(page);

        else {
            final IWizardPage finalPage = page;
            BusyIndicator.showWhile(getContents().getDisplay(), new Runnable() {
                public void run() {
                    updateForPage(finalPage);
                }
            });
        }
    }

    /**
     * Update the receiver for the new page.
     * @param page
     */
    private void updateForPage(IWizardPage page) {
        // ensure this page belongs to the current wizard
        if (wizard != page.getWizard())
            setWizard(page.getWizard());
        // ensure that page control has been created
        // (this allows lazy page control creation)
        if (page.getControl() == null) {
            page.createControl(pageContainer);
            // the page is responsible for ensuring the created control is accessable
            // via getControl.
            Assert.isNotNull(page.getControl());
            // ensure the dialog is large enough for this page
            updateSize(page);
        }
        // make the new page visible
        IWizardPage oldPage = currentPage;
        currentPage = page;
        currentPage.setVisible(true);
        if (oldPage != null)
            oldPage.setVisible(false);
        // update the dialog controls
        update();
    }

    /**	
     * Shows the starting page of the wizard.
     */
    private void showStartingPage() {
        currentPage = wizard.getStartingPage();
        if (currentPage == null) {
            // something must have happend getting the page
            return;
        }
        // ensure the page control has been created
        if (currentPage.getControl() == null) {
            currentPage.createControl(pageContainer);
            // the page is responsible for ensuring the created control is accessable
            // via getControl.
            Assert.isNotNull(currentPage.getControl());
            // we do not need to update the size since the call
            // to initialize bounds has not been made yet.
        }
        // make the new page visible
        currentPage.setVisible(true);
        // update the dialog controls
        update();
    }

    /**
     * A long running operation triggered through the wizard
     * was stopped either by user input or by normal end.
     * Hides the progress monitor and restores the enable state
     * wizard's buttons and controls.
     *
     * @param savedState the saved UI state as returned by <code>aboutToStart</code>
     * @see #aboutToStart
     */
    private void stopped(Object savedState) {
        if (getShell() != null) {
            if (wizard.needsProgressMonitor()) {
                progressMonitorPart.setVisible(false);
                progressMonitorPart.removeFromCancelComponent(cancelButton);
            }
            Map state = (Map) savedState;
            restoreUIState(state);
            cancelButton.addSelectionListener(cancelListener);
            setDisplayCursor(null);
            cancelButton.setCursor(null);
            waitCursor.dispose();
            waitCursor = null;
            arrowCursor.dispose();
            arrowCursor = null;
            Control focusControl = (Control) state.get(FOCUS_CONTROL);
            if (focusControl != null)
                focusControl.setFocus();
        }
    }

    /**
     * Updates this dialog's controls to reflect the current page.
     */
    protected void update() {
        // Update the window title
        updateWindowTitle();
        // Update the title bar
        updateTitleBar();
        // Update the buttons
        updateButtons();
		// Fires the page change event
		firePageChanged(new PageChangedEvent(this, getCurrentPage()));
    }

    /* (non-Javadoc)
     * Method declared on IWizardContainer.
     */
    public void updateButtons() {
        boolean canFlipToNextPage = false;
        boolean canFinish = wizard.canFinish();
        if (backButton != null)
            backButton.setEnabled(currentPage.getPreviousPage() != null);
        if (nextButton != null) {
            canFlipToNextPage = currentPage.canFlipToNextPage();
            nextButton.setEnabled(canFlipToNextPage);
        }
        finishButton.setEnabled(canFinish);
        // finish is default unless it is diabled and next is enabled
        if (canFlipToNextPage && !canFinish)
            getShell().setDefaultButton(nextButton);
        else
            getShell().setDefaultButton(finishButton);
    }

    /**
     * Update the message line with the page's description.
     * <p>
     * A discription is shown only if there is no message or error message.
     * </p>
     */
    private void updateDescriptionMessage() {
        pageDescription = currentPage.getDescription();
        if (pageMessage == null)
            setMessage(currentPage.getDescription());
    }

    /* (non-Javadoc)
     * Method declared on IWizardContainer.
     */
    public void updateMessage() {

        if (currentPage == null)
            return;

        pageMessage = currentPage.getMessage();
        if (pageMessage != null && currentPage instanceof IMessageProvider)
            pageMessageType = ((IMessageProvider) currentPage).getMessageType();
        else
            pageMessageType = IMessageProvider.NONE;
        if (pageMessage == null)
            setMessage(pageDescription);
        else
            setMessage(pageMessage, pageMessageType);
        setErrorMessage(currentPage.getErrorMessage());
    }

    /**
     * Changes the shell size to the given size, ensuring that
     * it is no larger than the display bounds.
     * 
     * @param width the shell width
     * @param height the shell height
     */
    private void setShellSize(int width, int height) {
        Rectangle size = getShell().getBounds();
        size.height = height;
        size.width = width;
        getShell().setBounds(getConstrainedShellBounds(size));
    }

    /**
     * Computes the correct dialog size for the current page and resizes 
     * its shell if nessessary. Also causes the container to refresh its
     * layout.
     * 
     * @param page the wizard page to use to resize the dialog
     * @since 2.0
     */
    protected void updateSize(IWizardPage page) {
        if (page == null || page.getControl() == null)
            return;
        updateSizeForPage(page);
        pageContainerLayout.layoutPage(page.getControl());
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.wizard.IWizardContainer2#updateSize()
     */
    public void updateSize() {
        updateSize(currentPage);
    }

    /**
     * Computes the correct dialog size for the given page and resizes 
     * its shell if nessessary.
     *
     * @param page the wizard page
     */
    private void updateSizeForPage(IWizardPage page) {
        // ensure the page container is large enough
        Point delta = calculatePageSizeDelta(page);
        if (delta.x > 0 || delta.y > 0) {
            // increase the size of the shell 
            Shell shell = getShell();
            Point shellSize = shell.getSize();
            setShellSize(shellSize.x + delta.x, shellSize.y + delta.y);
            constrainShellSize();
        }
    }

    /**
     * Computes the correct dialog size for the given wizard and resizes 
     * its shell if nessessary.
     *
     * @param sizingWizard the wizard
     */
    private void updateSizeForWizard(IWizard sizingWizard) {
        Point delta = new Point(0, 0);
        IWizardPage[] pages = sizingWizard.getPages();
        for (int i = 0; i < pages.length; i++) {
            // ensure the page container is large enough
            Point pageDelta = calculatePageSizeDelta(pages[i]);
            delta.x = Math.max(delta.x, pageDelta.x);
            delta.y = Math.max(delta.y, pageDelta.y);
        }
        if (delta.x > 0 || delta.y > 0) {
            // increase the size of the shell 
            Shell shell = getShell();
            Point shellSize = shell.getSize();
            setShellSize(shellSize.x + delta.x, shellSize.y + delta.y);
        }
    }

    /* (non-Javadoc)
     * Method declared on IWizardContainer.
     */
    public void updateTitleBar() {
        String s = null;
        if (currentPage != null)
            s = currentPage.getTitle();
        if (s == null)
            s = ""; //$NON-NLS-1$
        setTitle(s);
        if (currentPage != null) {
            setTitleImage(currentPage.getImage());
            updateDescriptionMessage();
        }
        updateMessage();
    }

    /* (non-Javadoc)
     * Method declared on IWizardContainer.
     */
    public void updateWindowTitle() {
        if (getShell() == null)
            // Not created yet
            return;
        String title = wizard.getWindowTitle();
        if (title == null)
            title = ""; //$NON-NLS-1$
        getShell().setText(title);
    }

	/* (non-Javadoc)
	 * @see org.eclipse.jface.dialogs.IPageChangeProvider#getSelectedPage()
	 */
	public Object getSelectedPage() {
		return getCurrentPage();
	}

   /* (non-Javadoc)
    * @see org.eclipse.jface.dialog.IPageChangeProvider#addPageChangedListener()
    */
	public void addPageChangedListener(IPageChangedListener listener) {
		pageChangedListeners.add(listener);
	}
   /* (non-Javadoc)
    * @see org.eclipse.jface.dialog.IPageChangeProvider#removePageChangedListener()
    */
	public void removePageChangedListener(IPageChangedListener listener) {
		pageChangedListeners.remove(listener);		
	}
 
	/**
     * Notifies any selection changed listeners that the selected page
     * has changed.
     * Only listeners registered at the time this method is called are notified.
     *
     * @param event a selection changed event
     *
     * @see IPageChangedListener#pageChanged
     * 
     * @since 3.1
     */
    protected void firePageChanged(final PageChangedEvent event) {
        Object[] listeners = pageChangedListeners.getListeners();
        for (int i = 0; i < listeners.length; ++i) {
            final IPageChangedListener l = (IPageChangedListener) listeners[i];
            SafeRunnable.run(new SafeRunnable() {
                public void run() {
                    l.pageChanged(event);
                }
            });
        }
    }
}
