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

import java.util.ArrayList;

import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.util.Assert;
import org.eclipse.jface.util.Geometry;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.events.ShellListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
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.Layout;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Monitor;
import org.eclipse.swt.widgets.Shell;

/**
 * A JFace window is an object that has no visual representation (no widgets)
 * until it is told to open.
 * <p>
 * Creating a window involves the following steps:
 * <ul>
 * <li>creating an instance of a concrete subclass of <code>Window</code>
 * </li>
 * <li>creating the window's shell and widget tree by calling
 * <code>create</code> (optional)</li>
 * <li>assigning the window to a window manager using
 * <code>WindowManager.add</code> (optional)</li>
 * <li>opening the window by calling <code>open</code></li>
 * </ul>
 * Opening the window will create its shell and widget tree if they have not
 * already been created. When the window is closed, the shell and widget tree
 * are disposed of and are no longer referenced, and the window is automatically
 * removed from its window manager. A window may be reopened.
 * </p>
 * <p>
 * The JFace window framework (this package) consists of this class,
 * <code>Window</code>, the abstract base of all windows, and one concrete
 * window classes (<code>ApplicationWindow</code>) which may also be
 * subclassed. Clients may define additional window subclasses as required.
 * </p>
 * <p>
 * The <code>Window</code> class provides methods that subclasses may 
 * override to configure the window, including:
 * <ul>
 * <li><code>close</code>- extend to free other SWT resources</li>
 * <li><code>configureShell</code>- extend or reimplement to set shell
 * properties before window opens</li>
 * <li><code>createContents</code>- extend or reimplement to create controls
 * before window opens</li>
 * <li><code>getInitialSize</code>- reimplement to give the initial size for
 * the shell</li>
 * <li><code>getInitialLocation</code>- reimplement to give the initial
 * location for the shell</li>
 * <li><code>getShellListener</code>- extend or reimplement to receive shell
 * events</li>
 * <li><code>handleFontChange</code>- reimplement to respond to font changes
 * </li>
 * <li><code>handleShellCloseEvent</code>- extend or reimplement to handle
 * shell closings</li>
 * </ul>
 * </p>
 */
public abstract class Window implements IShellProvider {

	/**
	 * Standard return code constant (value 0) indicating that the window was
	 * opened.
	 * 
	 * @see #open
	 */
	public static final int OK = 0;

	/**
	 * Standard return code constant (value 1) indicating that the window was
	 * canceled.
	 * 
	 * @see #open
	 */
	public static final int CANCEL = 1;

	/**
	 * An array of images to be used for the window. It is expected that the
	 * array will contain the same icon rendered at different resolutions.
	 */
	private static Image[] defaultImages;

	/**
	 * This interface defines a Exception Handler which can be set as a global
	 * handler and will be called if an exception happens in the event loop.
	 */
	public static interface IExceptionHandler {
		/**
		 * Handle the exception.
		 * 
		 * @param t
		 *            The exception that occured.
		 */
		public void handleException(Throwable t);
	}

	/**
	 * Defines a default exception handler.
	 */
	private static class DefaultExceptionHandler implements IExceptionHandler {
		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.jface.window.Window.IExceptionHandler#handleException(java.lang.Throwable)
		 */
		public void handleException(Throwable t) {
			if (t instanceof ThreadDeath)
				// Don't catch ThreadDeath as this is a normal occurrence when
				// the thread dies
				throw (ThreadDeath) t;
			// Try to keep running.
			t.printStackTrace();
		}
	}

	/**
	 * The exception handler for this application.
	 */
	private static IExceptionHandler exceptionHandler = new DefaultExceptionHandler();
	
	/**
	 * The default orientation of the window. By default
	 * it is SWT#NONE but it can also be SWT#LEFT_TO_RIGHT
	 * or SWT#RIGHT_TO_LEFT
	 */
	private static int orientation = SWT.NONE;

    /**
     * Object used to locate the default parent for modal shells
     */
    private static IShellProvider defaultModalParent = new IShellProvider() {
        public Shell getShell() {
            Display d = Display.getCurrent();
            
            if (d == null) {
                return null;
            }

            Shell parent = d.getActiveShell();
            
            // Make sure we don't pick a parent that has a modal child (this can lock the app)
            if (parent == null) {
                // If this is a top-level window, then there must not be any open modal windows.
                parent = getModalChild(Display.getCurrent().getShells());
            } else {
                // If we picked a parent with a modal child, use the modal child instead
                Shell modalChild = getModalChild(parent.getShells());
                if (modalChild != null) {
                    parent = modalChild;
                }
            }
            
            return parent;
        }
    };
    
	/**
	 * Object that returns the parent shell.
	 */
	private IShellProvider parentShell;

	/**
	 * Shell style bits.
	 * 
	 * @see #setShellStyle
	 */
	private int shellStyle = SWT.SHELL_TRIM;

	/**
	 * Window manager, or <code>null</code> if none.
	 * 
	 * @see #setWindowManager
	 */
	private WindowManager windowManager;

	/**
	 * Window shell, or <code>null</code> if none.
	 */
	private Shell shell;

	/**
	 * Top level SWT control, or <code>null</code> if none
	 */
	private Control contents;

	/**
	 * Window return code; initially <code>OK</code>.
	 * 
	 * @see #setReturnCode
	 */
	private int returnCode = OK;

	/**
	 * <code>true</code> if the <code>open</code> method should not return
	 * until the window closes, and <code>false</code> if the
	 * <code>open</code> method should return immediately; initially
	 * <code>false</code> (non-blocking).
	 * 
	 * @see #setBlockOnOpen
	 */
	private boolean block = false;

	/**
	 * Internal class for informing this window when fonts change.
	 */
	private class FontChangeListener implements IPropertyChangeListener {
		public void propertyChange(PropertyChangeEvent event) {
			handleFontChange(event);
		}
	}

	/**
	 * Internal font change listener.
	 */
	private FontChangeListener fontChangeListener;

	/**
	 * Internal fields to detect if shell size has been set
	 */
	private boolean resizeHasOccurred = false;

	private Listener resizeListener;
 
	/**
	 * Creates a window instance, whose shell will be created under the given
	 * parent shell. Note that the window will have no visual representation
	 * until it is told to open. By default, <code>open</code> does not block.
	 * 
	 * @param parentShell
	 *            the parent shell, or <code>null</code> to create a top-level
	 *            shell. Try passing "(Shell)null" to this method instead of "null"
     *            if your compiler complains about an ambiguity error.
	 * @see #setBlockOnOpen
	 * @see #getDefaultOrientation()
	 */
	protected Window(Shell parentShell) {
        this(new SameShellProvider(parentShell));
        
        if(parentShell == null)//Inherit the style from the parent if there is one
            setShellStyle(getShellStyle() | getDefaultOrientation());
	}
    
    /**
     * Creates a new window which will create its shell as a child of whatever
     * the given shellProvider returns.
     * 
     * @param shellProvider object that will return the current parent shell. Not null.
     * 
     * @since 3.1
     */
    protected Window(IShellProvider shellProvider) {
        Assert.isNotNull(shellProvider);
        this.parentShell = shellProvider;   
    }

	/**
	 * Determines if the window should handle the close event or do nothing.
	 * <p>
	 * The default implementation of this framework method returns
	 * <code>true</code>, which will allow the
	 * <code>handleShellCloseEvent</code> method to be called. Subclasses may
	 * extend or reimplement.
	 * </p>
	 * 
	 * @return whether the window should handle the close event.
	 */
	protected boolean canHandleShellCloseEvent() {
		return true;
	}

	/**
	 * Closes this window, disposes its shell, and removes this window from its
	 * window manager (if it has one).
	 * <p>
	 * This framework 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() {
		
		// stop listening for font changes
		if (fontChangeListener != null) {
			JFaceResources.getFontRegistry().removeListener(fontChangeListener);
			fontChangeListener = null;
		}
		
		// remove this window from a window manager if it has one
		if (windowManager != null) {
			windowManager.remove(this);
			windowManager = null;
		}

		if (shell == null || shell.isDisposed())
			return true;

		// If we "close" the shell recursion will occur.
		// Instead, we need to "dispose" the shell to remove it from the
		// display.
		shell.dispose();
		shell = null;
		contents = null;

		return true;
	}

	/**
	 * Configures the given shell in preparation for opening this window in it.
	 * <p>
	 * The default implementation of this framework method sets the shell's
	 * image and gives it a grid layout. Subclasses may extend or reimplement.
	 * </p>
	 * 
	 * @param newShell
	 *            the shell
	 */
	protected void configureShell(Shell newShell) {

		// The single image version of this code had a comment related to bug
		// 46624,
		// and some code that did nothing if the stored image was already
		// disposed.
		// The equivalent in the multi-image version seems to be to remove the
		// disposed images from the array passed to the shell.
		if (defaultImages != null && defaultImages.length > 0) {
			ArrayList nonDisposedImages = new ArrayList(defaultImages.length);
			for (int i = 0; i < defaultImages.length; ++i)
				if (defaultImages[i] != null && !defaultImages[i].isDisposed())
					nonDisposedImages.add(defaultImages[i]);

			if (nonDisposedImages.size() <= 0)
				System.err.println("Window.configureShell: images disposed"); //$NON-NLS-1$
			else {
				Image[] array = new Image[nonDisposedImages.size()];
				nonDisposedImages.toArray(array);
				newShell.setImages(array);
			}
		}

		Layout layout = getLayout();
		if (layout != null)
			newShell.setLayout(layout);
	}

	/**
	 * Creates the layout for the shell. The layout created here will be
	 * attached to the composite passed into createContents. The default
	 * implementation returns a GridLayout with no margins. Subclasses that
	 * change the layout type by overriding this method should also override
	 * createContents.
	 * 
	 * <p>
	 * A return value of null indicates that no layout should be attached to the
	 * composite. In this case, the layout may be attached within
	 * createContents.
	 * </p>
	 * 
	 * @return a newly created Layout or null if no layout should be attached.
	 * @since 3.0
	 */
	protected Layout getLayout() {
		GridLayout layout = new GridLayout();
		layout.marginHeight = 0;
		layout.marginWidth = 0;
		return layout;
	}

	/**
	 * Constrain the shell size to be no larger than the display bounds.
	 * 
	 * @since 2.0
	 */
	protected void constrainShellSize() {
		// limit the shell size to the display size
		Rectangle bounds = shell.getBounds();
		Rectangle constrained = getConstrainedShellBounds(bounds);
		if (!bounds.equals(constrained)) {
			shell.setBounds(constrained);
		}
	}

	/**
	 * Creates this window's widgetry in a new top-level shell.
	 * <p>
	 * The default implementation of this framework method creates this window's
	 * shell (by calling <code>createShell</code>), and its controls (by
	 * calling <code>createContents</code>), then initializes this window's
	 * shell bounds (by calling <code>initializeBounds</code>).
	 * </p>
	 */
	public void create() {
		shell = createShell();
		contents = createContents(shell);

		//initialize the bounds of the shell to that appropriate for the
		// contents
		initializeBounds();
	}

	/**
	 * Creates and returns this window's contents. Subclasses may attach any
	 * number of children to the parent. As a convenience, the return value of
	 * this method will be remembered and returned by subsequent calls to
	 * getControl(). Subclasses may modify the parent's layout if they overload
	 * getLayout() to return null.
	 * 
	 * <p>
	 * It is common practise to create and return a single composite that
	 * contains the entire window contents.
	 * </p>
	 * 
	 * <p>
	 * The default implementation of this framework method creates an instance
	 * of <code>Composite</code>. Subclasses may override.
	 * </p>
	 * 
	 * @param parent
	 *            the parent composite for the controls in this window. The type
	 *            of layout used is determined by getLayout()
	 * 
	 * @return the control that will be returned by subsequent calls to
	 *         getControl()
	 */
	protected Control createContents(Composite parent) {
		// by default, just create a composite
		return new Composite(parent, SWT.NONE);
	}

	/**
	 * Creates and returns this window's shell.
	 * <p>
	 * The default implementation of this framework method creates a new shell
	 * and configures it using <code/>configureShell</code>. Rather than
	 * override this method, subclasses should instead override
	 * <code/>configureShell</code>.
	 * </p>
	 * 
	 * @return the shell
	 */
	protected final Shell createShell() {

		Shell newParent = getParentShell();
		if(newParent != null &&  newParent.isDisposed()){
			parentShell = new SameShellProvider(null);
			newParent = getParentShell();//Find a better parent
		}
		
		//Create the shell
		Shell newShell = new Shell(newParent, getShellStyle());

		resizeListener = new Listener() {
			public void handleEvent(Event e) {
				resizeHasOccurred = true;
			}
		};

		newShell.addListener(SWT.Resize, resizeListener);
		newShell.setData(this);

		//Add a listener
		newShell.addShellListener(getShellListener());

		//Set the layout
		configureShell(newShell);

		//Register for font changes
		if (fontChangeListener == null) {
			fontChangeListener = new FontChangeListener();
		}
		JFaceResources.getFontRegistry().addListener(fontChangeListener);

		return newShell;
	}

	/**
	 * Returns the top level control for this window. The parent of this control
	 * is the shell.
	 * 
	 * @return the top level control, or <code>null</code> if this window's
	 *         control has not been created yet
	 */
	protected Control getContents() {
		return contents;
	}

	/**
	 * Returns the default image. This is the image that will be used for
	 * windows that have no shell image at the time they are opened. There is no
	 * default image unless one is installed via <code>setDefaultImage</code>.
	 * 
	 * @return the default image, or <code>null</code> if none
	 * @see #setDefaultImage
	 */
	public static Image getDefaultImage() {
		return (defaultImages == null || defaultImages.length < 1) ? null
				: defaultImages[0];
	}

	/**
	 * Returns the array of default images to use for newly opened windows. It
	 * is expected that the array will contain the same icon rendered at
	 * different resolutions.
	 * 
	 * @see org.eclipse.swt.widgets.Decorations#setImages(org.eclipse.swt.graphics.Image[])
	 * 
	 * @return the array of images to be used when a new window is opened
	 * @see #setDefaultImages
	 * @since 3.0
	 */
	public static Image[] getDefaultImages() {
		return (defaultImages == null ? new Image[0] : defaultImages);
	}

	/**
	 * Returns the initial location to use for the shell. The default
	 * implementation centers the shell horizontally (1/2 of the difference to
	 * the left and 1/2 to the right) and vertically (1/3 above and 2/3 below)
	 * relative to the parent shell, or display bounds if there is no parent
	 * shell.
	 * 
	 * @param initialSize
	 *            the initial size of the shell, as returned by
	 *            <code>getInitialSize</code>.
	 * @return the initial location of the shell
	 */
	protected Point getInitialLocation(Point initialSize) {
		Composite parent = shell.getParent();

		Monitor monitor = shell.getDisplay().getPrimaryMonitor();
		if (parent != null) {
			monitor = parent.getMonitor();
		}

		Rectangle monitorBounds = monitor.getClientArea();
		Point centerPoint;
		if (parent != null) {
			centerPoint = Geometry.centerPoint(parent.getBounds());
		} else {
			centerPoint = Geometry.centerPoint(monitorBounds);
		}

		return new Point(centerPoint.x - (initialSize.x / 2), Math.max(
				monitorBounds.y, Math.min(centerPoint.y
						- (initialSize.y * 2 / 3), monitorBounds.y
						+ monitorBounds.height - initialSize.y)));
	}

	/**
	 * Returns the initial size to use for the shell. The default implementation
	 * returns the preferred size of the shell, using
	 * <code>Shell.computeSize(SWT.DEFAULT, SWT.DEFAULT, true)</code>.
	 * 
	 * @return the initial size of the shell
	 */
	protected Point getInitialSize() {
		return shell.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
	}

    /**
     * Returns the most specific modal child from the given list of Shells. 
     * 
     * @param toSearch shells to search for modal children
     * @return the most specific modal child, or null if none
     * 
     * @since 3.1
     */
    private static Shell getModalChild(Shell[] toSearch) {
        int modal = SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL | SWT.PRIMARY_MODAL;
        
        for (int i = toSearch.length - 1; i >= 0; i--) {
            Shell shell = toSearch[i];
            
            // Check if this shell has a modal child
            Shell[] children = shell.getShells();
            Shell modalChild = getModalChild(children);
            if (modalChild != null) {
                return modalChild;
            }
            
            // If not, check if this shell is modal itself
            if (shell.isVisible() && (shell.getStyle() & modal) != 0) {
                return shell;
            }
        }
        
        return null;
    }
    
	/**
	 * Returns parent shell, under which this window's shell is created.
	 * 
	 * @return the parent shell, or <code>null</code> if there is no parent
	 *         shell
	 */
	protected Shell getParentShell() {
        Shell parent = parentShell.getShell();
        
        int modal = SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL | SWT.PRIMARY_MODAL;
        
        if ((getShellStyle() & modal) != 0) {
            // If this is a modal shell with no parent, pick a shell using defaultModalParent.
            if (parent == null) {
                parent = defaultModalParent.getShell();
            }
        }
        
        return parent;
	}

	/**
	 * Returns this window's return code. A window's return codes are
	 * window-specific, although two standard return codes are predefined:
	 * <code>OK</code> and <code>CANCEL</code>.
	 * 
	 * @return the return code
	 */
	public int getReturnCode() {
		return returnCode;
	}

	/**
	 * Returns this window's shell.
	 * 
	 * @return this window's shell, or <code>null</code> if this window's
	 *         shell has not been created yet
	 */
	public Shell getShell() {
		return shell;
	}

	/**
	 * Returns a shell listener. This shell listener gets registered with this
	 * window's shell.
	 * <p>
	 * The default implementation of this framework method returns a new
	 * listener that makes this window the active window for its window manager
	 * (if it has one) when the shell is activated, and calls the framework
	 * method <code>handleShellCloseEvent</code> when the shell is closed.
	 * Subclasses may extend or reimplement.
	 * </p>
	 * 
	 * @return a shell listener
	 */
	protected ShellListener getShellListener() {
		return new ShellAdapter() {
			public void shellClosed(ShellEvent event) {
				event.doit = false; // don't close now
				if (canHandleShellCloseEvent())
					handleShellCloseEvent();
			}
		};
	}

	/**
	 * Returns the shell style bits.
	 * <p>
	 * The default value is <code>SWT.CLOSE|SWT.MIN|SWT.MAX|SWT.RESIZE</code>.
	 * Subclassers should call <code>setShellStyle</code> to change this
	 * value, rather than overriding this method.
	 * </p>
	 * 
	 * @return the shell style bits
	 */
	protected int getShellStyle() {
		return shellStyle;
	}

	/**
	 * Returns the window manager of this window.
	 * 
	 * @return the WindowManager, or <code>null</code> if none
	 */
	public WindowManager getWindowManager() {
		return windowManager;
	}

	/**
	 * Notifies of a font property change.
	 * <p>
	 * The default implementation of this framework method does nothing.
	 * Subclasses may reimplement.
	 * </p>
	 * 
	 * @param event
	 *            the property change event detailing what changed
	 */
	protected void handleFontChange(PropertyChangeEvent event) {
		// do nothing
	}

	/**
	 * Notifies that the window's close button was pressed, the close menu was
	 * selected, or the ESCAPE key pressed.
	 * <p>
	 * The default implementation of this framework method sets the window's
	 * return code to <code>CANCEL</code> and closes the window using
	 * <code>close</code>. Subclasses may extend or reimplement.
	 * </p>
	 */
	protected void handleShellCloseEvent() {
		setReturnCode(CANCEL);
		close();
	}

	/**
	 * Initializes the location and size of this window's SWT shell after it has
	 * been created.
	 * <p>
	 * This framework method is called by the <code>create</code> framework
	 * method. The default implementation calls <code>getInitialSize</code>
	 * and <code>getInitialLocation</code> and passes the results to
	 * <code>Shell.setBounds</code>. This is only done if the bounds of the
	 * shell have not already been modified. Subclasses may extend or
	 * reimplement.
	 * </p>
	 */
	protected void initializeBounds() {
		if (resizeListener != null) {
			shell.removeListener(SWT.Resize, resizeListener);
		}
		if (resizeHasOccurred) { // Check if shell size has been set already.
			return;
		}

		Point size = getInitialSize();
		Point location = getInitialLocation(size);
		shell.setBounds(getConstrainedShellBounds(new Rectangle(location.x,
				location.y, size.x, size.y)));
	}

	/**
	 * Opens this window, creating it first if it has not yet been created.
	 * <p>
	 * If this window has been configured to block on open (
	 * <code>setBlockOnOpen</code>), this method waits until the window is
	 * closed by the end user, and then it returns the window's return code;
	 * otherwise, this method returns immediately. A window's return codes are
	 * window-specific, although two standard return codes are predefined:
	 * <code>OK</code> and <code>CANCEL</code>.
	 * </p>
	 * 
	 * @return the return code
	 * 
	 * @see #create()
	 */
	public int open() {
        
		if (shell == null || shell.isDisposed()) {
            shell = null;
			// create the window
			create();
		}

		// limit the shell size to the display size
		constrainShellSize();

		// open the window
		shell.open();

		// run the event loop if specified
		if (block)
			runEventLoop(shell);

		return returnCode;
	}

	/**
	 * Runs the event loop for the given shell.
	 * 
	 * @param loopShell
	 *            the shell
	 */
	private void runEventLoop(Shell loopShell) {

		//Use the display provided by the shell if possible
		Display display;
		if (shell == null)
			display = Display.getCurrent();
		else
			display = loopShell.getDisplay();

		while (loopShell != null && !loopShell.isDisposed()) {
			try {
				if (!display.readAndDispatch())
					display.sleep();
			} catch (Throwable e) {
				exceptionHandler.handleException(e);
			}
		}
		display.update();
	}

	/**
	 * Sets whether the <code>open</code> method should block until the window
	 * closes.
	 * 
	 * @param shouldBlock
	 *            <code>true</code> if the <code>open</code> method should
	 *            not return until the window closes, and <code>false</code>
	 *            if the <code>open</code> method should return immediately
	 */
	public void setBlockOnOpen(boolean shouldBlock) {
		block = shouldBlock;
	}

	/**
	 * Sets the default image. This is the image that will be used for windows
	 * that have no shell image at the time they are opened. There is no default
	 * image unless one is installed via this method.
	 * 
	 * @param image
	 *            the default image, or <code>null</code> if none
	 */
	public static void setDefaultImage(Image image) {
		defaultImages = image == null ? null : new Image[] { image };
	}

	/**
	 * Sets the array of default images to use for newly opened windows. It is
	 * expected that the array will contain the same icon rendered at different
	 * resolutions.
	 * 
	 * @see org.eclipse.swt.widgets.Decorations#setImages(org.eclipse.swt.graphics.Image[])
	 * 
	 * @param images
	 *            the array of images to be used when this window is opened
	 * @since 3.0
	 */
	public static void setDefaultImages(Image[] images) {
		Image[] newArray = new Image[images.length];
		System.arraycopy(images, 0, newArray, 0, newArray.length);
		defaultImages = newArray;
	}
	
	/**
     * Changes the parent shell. This is only safe to use when the shell is not
     * yet realized (i.e., created). Once the shell is created, it must be
     * disposed (i.e., closed) before this method can be called.
     * 
     * @param newParentShell
     *            The new parent shell; this value may be <code>null</code> if
     *            there is to be no parent.
     * @since 3.1
     */
    protected void setParentShell(final Shell newParentShell) {
        Assert.isTrue((shell == null), "There must not be an existing shell."); //$NON-NLS-1$
        parentShell = new SameShellProvider(newParentShell);
    }

	/**
	 * Sets this window's return code. The return code is automatically returned
	 * by <code>open</code> if block on open is enabled. For non-blocking
	 * opens, the return code needs to be retrieved manually using
	 * <code>getReturnCode</code>.
	 * 
	 * @param code
	 *            the return code
	 */
	protected void setReturnCode(int code) {
		returnCode = code;
	}

	/**
	 * Returns the monitor whose client area contains the given point. If no
	 * monitor contains the point, returns the monitor that is closest to the
	 * point. If this is ever made public, it should be moved into a separate
	 * utility class.
	 * 
	 * @param toSearch
	 *            point to find (display coordinates)
	 * @param toFind
	 *            point to find (display coordinates)
	 * @return the montor closest to the given point
	 */
	private static Monitor getClosestMonitor(Display toSearch, Point toFind) {
		int closest = Integer.MAX_VALUE;

		Monitor[] monitors = toSearch.getMonitors();
		Monitor result = monitors[0];

		for (int idx = 0; idx < monitors.length; idx++) {
			Monitor current = monitors[idx];

			Rectangle clientArea = current.getClientArea();

			if (clientArea.contains(toFind)) {
				return current;
			}

			int distance = Geometry.distanceSquared(Geometry
					.centerPoint(clientArea), toFind);
			if (distance < closest) {
				closest = distance;
				result = current;
			}
		}

		return result;
	}

	/**
	 * Given the desired position of the window, this method returns an adjusted
	 * position such that the window is no larger than its monitor, and does not
	 * extend beyond the edge of the monitor. This is used for computing the
	 * initial window position, and subclasses can use this as a utility method
	 * if they want to limit the region in which the window may be moved.
	 * 
	 * @param preferredSize
	 *            the preferred position of the window
	 * @return a rectangle as close as possible to preferredSize that does not
	 *         extend outside the monitor
	 * 
	 * @since 3.0
	 */
	protected Rectangle getConstrainedShellBounds(Rectangle preferredSize) {
		Rectangle result = new Rectangle(preferredSize.x, preferredSize.y,
				preferredSize.width, preferredSize.height);

		Monitor mon = getClosestMonitor(getShell().getDisplay(), Geometry
				.centerPoint(result));

		Rectangle bounds = mon.getClientArea();

		if (result.height > bounds.height) {
			result.height = bounds.height;
		}

		if (result.width > bounds.width) {
			result.width = bounds.width;
		}

		result.x = Math.max(bounds.x, Math.min(result.x, bounds.x
				+ bounds.width - result.width));
		result.y = Math.max(bounds.y, Math.min(result.y, bounds.y
				+ bounds.height - result.height));

		return result;
	}

	/**
	 * Sets the shell style bits. This method has no effect after the shell is
	 * created.
	 * <p>
	 * The shell style bits are used by the framework method
	 * <code>createShell</code> when creating this window's shell.
	 * </p>
	 * 
	 * @param newShellStyle
	 *            the new shell style bits
	 */
	protected void setShellStyle(int newShellStyle) {
		shellStyle = newShellStyle;
	}

	/**
	 * Sets the window manager of this window.
	 * <p>
	 * Note that this method is used by <code>WindowManager</code> to maintain
	 * a backpointer. Clients must not call the method directly.
	 * </p>
	 * 
	 * @param manager
	 *            the window manager, or <code>null</code> if none
	 */
	public void setWindowManager(WindowManager manager) {
		windowManager = manager;

		// Code to detect invalid usage

		if (manager != null) {
			Window[] windows = manager.getWindows();
			for (int i = 0; i < windows.length; i++) {
				if (windows[i] == this)
					return;
			}
			manager.add(this);
		}
	}

	/**
	 * Sets the exception handler for this application.
	 * <p>
	 * Note that only one handler may be set. Other calls to this method will be
	 * ignored.
	 * <p>
	 * 
	 * @param handler
	 *            the exception handler for the application.
	 */
	public static void setExceptionHandler(IExceptionHandler handler) {
		if (exceptionHandler instanceof DefaultExceptionHandler)
			exceptionHandler = handler;
	}
    
    /**
     * Sets the default parent for modal Windows. This will be used to locate
     * the parent for any modal Window constructed with a null parent.
     * 
     * @param provider shell provider that will be used to locate the parent shell
     * whenever a Window is created with a null parent
     * @since 3.1
     */
    public static void setDefaultModalParent(IShellProvider provider) {
        defaultModalParent = provider;
    }
    
	/**
	 * Gets the default orientation for windows. If it is not
	 * set the default value will be unspecified (SWT#NONE).
	 * 
	 * 
	 * @return SWT#NONE, SWT.RIGHT_TO_LEFT or SWT.LEFT_TO_RIGHT
	 * @see SWT#RIGHT_TO_LEFT
	 * @see SWT#LEFT_TO_RIGHT
	 * @see SWT#NONE
	 * @since 3.1
	 */
	public static int getDefaultOrientation() {
		return orientation;

	}

	/**
	 * Sets the default orientation of windows.
	 * @param defaultOrientation one of 
	 * 	SWT#RIGHT_TO_LEFT, SWT#LEFT_TO_RIGHT ,SWT#NONE
	 * @see SWT#RIGHT_TO_LEFT
	 * @see SWT#LEFT_TO_RIGHT
	 * @see SWT#NONE
	 * @since 3.1
	 */
	public static void setDefaultOrientation(int defaultOrientation) {
		orientation = defaultOrientation;
		
	}

}
