/*******************************************************************************
 * Copyright (c) 2004, 2010 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.gef.ui.palette;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.swt.SWT;
import org.eclipse.swt.accessibility.ACC;
import org.eclipse.swt.accessibility.AccessibleAdapter;
import org.eclipse.swt.accessibility.AccessibleControlAdapter;
import org.eclipse.swt.accessibility.AccessibleControlEvent;
import org.eclipse.swt.accessibility.AccessibleEvent;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.MouseTrackListener;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.ControlPaintHandler;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Tracker;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Plugin;
import org.eclipse.core.runtime.Preferences;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.TransferDropTargetListener;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IPerspectiveDescriptor;
import org.eclipse.ui.IPerspectiveListener;
import org.eclipse.ui.IViewReference;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.XMLMemento;
import org.eclipse.ui.internal.dnd.IDropTarget;

import org.eclipse.draw2d.ActionEvent;
import org.eclipse.draw2d.ActionListener;
import org.eclipse.draw2d.Border;
import org.eclipse.draw2d.Button;
import org.eclipse.draw2d.ButtonBorder;
import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.FocusEvent;
import org.eclipse.draw2d.FocusListener;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.LightweightSystem;
import org.eclipse.draw2d.MarginBorder;
import org.eclipse.draw2d.PositionConstants;
import org.eclipse.draw2d.Triangle;
import org.eclipse.draw2d.geometry.Dimension;

import org.eclipse.gef.GraphicalViewer;
import org.eclipse.gef.SharedCursors;
import org.eclipse.gef.dnd.TemplateTransfer;
import org.eclipse.gef.internal.GEFMessages;
import org.eclipse.gef.internal.InternalImages;
import org.eclipse.gef.internal.ui.palette.PaletteColorUtil;
import org.eclipse.gef.ui.views.palette.PaletteView;

/**
 * The FlyoutPaletteComposite is used to show a flyout palette alongside another
 * control. The flyout palette auto-hides (thus maximizing space) when not in
 * use, but can also be pinned open if so desired. It will only be visible when
 * the PaletteView is not.
 * 
 * @author Pratik Shah
 * @since 3.0
 */
public class FlyoutPaletteComposite extends Composite {

	private static final FontManager FONT_MGR = new FontManager();

	private static final String PROPERTY_PALETTE_WIDTH = "org.eclipse.gef.ui.palette.fpa.paletteWidth"; //$NON-NLS-1$
	private static final String PROPERTY_STATE = "org.eclipse.gef.ui.palette.fpa.state"; //$NON-NLS-1$
	private static final String PROPERTY_DOCK_LOCATION = "org.eclipse.gef.ui.palette.fpa.dock"; //$NON-NLS-1$

	private static final int DEFAULT_PALETTE_SIZE = 125;
	private static final int MIN_PALETTE_SIZE = 20;
	private static final int MAX_PALETTE_SIZE = 500;

	private static final int STATE_HIDDEN = 8;
	private static final int STATE_EXPANDED = 1;

	private static final Dimension ARROW_SIZE = new Dimension(6, 11);
	private static final int SASH_BUTTON_WIDTH = 11;

	/**
	 * One of the two possible initial states of the flyout palette. This is the
	 * default one. When in this state, only the flyout palette's sash is
	 * visible.
	 */
	public static final int STATE_COLLAPSED = 2;
	/**
	 * One of the two possible initial states of the flyout palette. When in
	 * this state, the flyout palette is completely visible and pinned open so
	 * that it doesn't disappear when the user wanders away from the flyout.
	 */
	public static final int STATE_PINNED_OPEN = 4;

	private PropertyChangeSupport listeners = new PropertyChangeSupport(this);
	private Composite paletteContainer;
	private PaletteViewer pViewer, externalViewer;
	private IMemento capturedPaletteState;
	private Control graphicalControl;
	private Composite sash;
	private PaletteViewerProvider provider;
	private FlyoutPreferences prefs;
	private Point cachedBounds = new Point(0, 0);
	/*
	 * Fix for Bug# 71525 transferFocus is used to transfer focus from the
	 * button in the vertical sash title to the button in the horizontal
	 * paletteComposite title. When either button is pressed it is set to true,
	 * and when either the sash or the paletteComposite gets notified of the
	 * change in state, they transfer the focus to their button if this flag is
	 * set to true and if that button is visible.
	 */
	private boolean transferFocus = false;
	private int dock = PositionConstants.EAST;
	private int paletteState = STATE_HIDDEN;
	private int paletteWidth = DEFAULT_PALETTE_SIZE;
	private int minWidth = MIN_PALETTE_SIZE;
	private int cachedSize = -1, cachedState = -1, cachedLocation = -1;
	private int cachedTitleHeight = 24; // give it a default value

	private IPerspectiveListener perspectiveListener = new IPerspectiveListener() {
		public void perspectiveActivated(IWorkbenchPage page,
				IPerspectiveDescriptor perspective) {
			handlePerspectiveActivated(page, perspective);
		}

		public void perspectiveChanged(IWorkbenchPage page,
				IPerspectiveDescriptor perspective, String changeId) {
			handlePerspectiveChanged(page, perspective, changeId);
		}
	};

	/**
	 * Constructor
	 * 
	 * @param parent
	 *            The parent Composite
	 * @param style
	 *            The style of the widget to construct; only SWT.BORDER is
	 *            allowed
	 * @param page
	 *            The current workbench page
	 * @param pvProvider
	 *            The provider that is to be used to create the flyout palette
	 * @param preferences
	 *            To save/retrieve the preferences for the flyout
	 */
	public FlyoutPaletteComposite(Composite parent, int style,
			IWorkbenchPage page, PaletteViewerProvider pvProvider,
			FlyoutPreferences preferences) {
		super(parent, style & SWT.BORDER);
		provider = pvProvider;
		prefs = preferences;
		sash = createSash();
		paletteContainer = createPaletteContainer();
		hookIntoWorkbench(page.getWorkbenchWindow());

		// Initialize the state properly
		if (prefs.getPaletteWidth() <= 0)
			prefs.setPaletteWidth(DEFAULT_PALETTE_SIZE);
		setPaletteWidth(prefs.getPaletteWidth());
		setDockLocation(prefs.getDockLocation());
		updateState(page);

		addListener(SWT.Resize, new Listener() {
			public void handleEvent(Event event) {
				Rectangle area = getClientArea();
				/*
				 * @TODO:Pratik Sometimes, the editor is resized to 1,1 or 0,0
				 * (depending on the platform) when the editor is closed or
				 * maximized. We have to ignore such resizes. See Bug# 62748
				 */
				if (area.width > minWidth)
					layout(true);
			}
		});

		listeners.addPropertyChangeListener(new PropertyChangeListener() {
			public void propertyChange(PropertyChangeEvent evt) {
				String property = evt.getPropertyName();
				if (property.equals(PROPERTY_PALETTE_WIDTH))
					prefs.setPaletteWidth(paletteWidth);
				else if (property.equals(PROPERTY_DOCK_LOCATION))
					prefs.setDockLocation(dock);
				else if (property.equals(PROPERTY_STATE))
					if (paletteState == STATE_COLLAPSED
							|| paletteState == STATE_PINNED_OPEN)
						prefs.setPaletteState(paletteState);
			}
		});
	}

	private void addListenerToCtrlHierarchy(Control parent, int eventType,
			Listener listener) {
		parent.addListener(eventType, listener);
		if (!(parent instanceof Composite))
			return;
		Control[] children = ((Composite) parent).getChildren();
		for (int i = 0; i < children.length; i++) {
			addListenerToCtrlHierarchy(children[i], eventType, listener);
		}
	}

	private IMemento capturePaletteState(PaletteViewer viewer) {
		IMemento memento = XMLMemento.createWriteRoot("paletteState"); //$NON-NLS-1$
		try {
			viewer.saveState(memento);
		} catch (RuntimeException re) {
			// Bug 74843 -- See comment #1
			// If there's a problem with saving the palette's state, it simply
			// won't be
			// transferred to the new palette
			memento = null;
			/*
			 * @TODO:Pratik You should log this exception.
			 */
		}
		return memento;
	}

	private Control createFlyoutControlButton(Composite parent) {
		return new ButtonCanvas(parent);
	}

	/**
	 * This is a convenient method to get a default FlyoutPreferences object.
	 * The returned FlyoutPreferences does not save any changes made to the
	 * given {@link Preferences Preferences}. It's upto the owner plugin to
	 * {@link Plugin#savePluginPreferences() save} the changes before it
	 * {@link Plugin#stop(org.osgi.framework.BundleContext) stops}.
	 * 
	 * @param prefs
	 *            {@link Plugin#getPluginPreferences() a plugin's Preferences}
	 * @return a default implementation of FlyoutPreferences that stores the
	 *         settings in the given Preferences
	 * @since 3.2
	 */
	public static FlyoutPreferences createFlyoutPreferences(Preferences prefs) {
		return new DefaultFlyoutPreferences(prefs);
	}

	private Composite createPaletteContainer() {
		return new PaletteComposite(this, SWT.NONE);
	}

	private Composite createSash() {
		return new Sash(this, SWT.NONE);
	}

	private Control createTitle(Composite parent, boolean isHorizontal) {
		return new TitleCanvas(parent, isHorizontal);
	}

	private Control getPaletteViewerControl() {
		Control result = null;
		if (pViewer != null)
			result = pViewer.getControl();
		// Fix for bug 101703 -- pViewer.getControl().getParent() might be
		// parented
		// by paletteContainer
		if (result != null && !result.isDisposed()
				&& result.getParent() != paletteContainer)
			result = result.getParent();
		return result;
	}

	private void handlePerspectiveActivated(IWorkbenchPage page,
			IPerspectiveDescriptor perspective) {
		updateState(page);
	}

	private void handlePerspectiveChanged(IWorkbenchPage page,
			IPerspectiveDescriptor perspective, String changeId) {
		if (changeId.equals(IWorkbenchPage.CHANGE_VIEW_SHOW)
				|| changeId.equals(IWorkbenchPage.CHANGE_VIEW_HIDE))
			updateState(page);
	}

	// Will return false if the ancestor or descendant is null
	private boolean isDescendantOf(Control ancestor, Control descendant) {
		if (ancestor == null || descendant == null)
			return false;
		while (descendant != null) {
			if (ancestor == descendant)
				return true;
			descendant = descendant.getParent();
		}
		return false;
	}

	private boolean isInState(int state) {
		return (paletteState & state) != 0;
	}

	private boolean isMirrored() {
		return (getStyle() & org.eclipse.draw2d.rap.swt.SWT.MIRRORED) != 0;
	}

	/**
	 * @see Composite#layout(boolean)
	 */
	public void layout(boolean changed) {
		if (graphicalControl == null || graphicalControl.isDisposed())
			return;

		Rectangle area = getClientArea();
		if (area.width == 0 || area.height == 0)
			return;

		int sashWidth = sash.computeSize(-1, -1).x;
		int pWidth = paletteWidth;
		int maxWidth = Math.min(area.width / 2, MAX_PALETTE_SIZE);
		maxWidth = Math.max(maxWidth, minWidth);
		pWidth = Math.max(pWidth, minWidth);
		pWidth = Math.min(pWidth, maxWidth);

		/*
		 * Fix for Bug# 65892 Laying out only when necessary helps reduce
		 * flicker on GTK in the case where the flyout palette is being resized
		 * past its maximum size.
		 */
		if (paletteState == cachedState && pWidth == cachedSize
				&& cachedLocation == dock && cachedBounds == getSize())
			return;
		cachedState = paletteState;
		cachedSize = pWidth;
		cachedLocation = dock;
		cachedBounds = getSize();

		setRedraw(false);
		if (isInState(STATE_HIDDEN)) {
			sash.setVisible(false);
			paletteContainer.setVisible(false);
			graphicalControl.setBounds(area);
		} else if (dock == PositionConstants.EAST)
			layoutComponentsEast(area, sashWidth, pWidth);
		else
			layoutComponentsWest(area, sashWidth, pWidth);
		sash.layout();
		setRedraw(true);
		update();
	}

	private void layoutComponentsEast(Rectangle area, int sashWidth, int pWidth) {
		if (isInState(STATE_COLLAPSED)) {
			paletteContainer.setVisible(false);
			sash.setBounds(area.x + area.width - sashWidth, area.y, sashWidth,
					area.height);
			graphicalControl.setBounds(area.x, area.y, area.width - sashWidth,
					area.height);
			sash.setVisible(true);
		} else if (isInState(STATE_EXPANDED)) {
			paletteContainer.moveAbove(graphicalControl);
			sash.moveAbove(paletteContainer);
			paletteContainer.setBounds(area.x + area.width - pWidth, area.y,
					pWidth, area.height);
			sash.setBounds(area.x + area.width - pWidth - sashWidth, area.y,
					sashWidth, area.height);
			graphicalControl.setBounds(area.x, area.y, area.width - sashWidth,
					area.height);
			sash.setVisible(true);
			paletteContainer.setVisible(true);
		} else if (isInState(STATE_PINNED_OPEN)) {
			paletteContainer.setBounds(area.x + area.width - pWidth, area.y,
					pWidth, area.height);
			sash.setBounds(area.x + area.width - pWidth - sashWidth, area.y,
					sashWidth, area.height);
			graphicalControl.setBounds(area.x, area.y, area.width - sashWidth
					- pWidth, area.height);
			sash.setVisible(true);
			paletteContainer.setVisible(true);
		}
	}

	private void layoutComponentsWest(Rectangle area, int sashWidth, int pWidth) {
		if (isInState(STATE_COLLAPSED)) {
			sash.setVisible(true);
			paletteContainer.setVisible(false);
			sash.setBounds(area.x, area.y, sashWidth, area.height);
			graphicalControl.setBounds(area.x + sashWidth, area.y, area.width
					- sashWidth, area.height);
		} else if (isInState(STATE_EXPANDED)) {
			sash.setVisible(true);
			paletteContainer.setVisible(true);
			paletteContainer.moveAbove(graphicalControl);
			sash.moveAbove(paletteContainer);
			paletteContainer.setBounds(area.x, area.y, pWidth, area.height);
			sash.setBounds(area.x + pWidth, area.y, sashWidth, area.height);
			graphicalControl.setBounds(area.x + sashWidth, area.y, area.width
					- sashWidth, area.height);
		} else if (isInState(STATE_PINNED_OPEN)) {
			sash.setVisible(true);
			paletteContainer.setVisible(true);
			paletteContainer.setBounds(area.x, area.y, pWidth, area.height);
			sash.setBounds(area.x + pWidth, area.y, sashWidth, area.height);
			graphicalControl.setBounds(area.x + pWidth + sashWidth, area.y,
					area.width - sashWidth - pWidth, area.height);
		}
	}

	private void hookIntoWorkbench(final IWorkbenchWindow window) {
		window.addPerspectiveListener(perspectiveListener);
		addDisposeListener(new DisposeListener() {
			public void widgetDisposed(DisposeEvent e) {
				window.removePerspectiveListener(perspectiveListener);
				perspectiveListener = null;
			}
		});
	}

	private boolean restorePaletteState(PaletteViewer newPalette, IMemento state) {
		if (state != null) {
			try {
				return newPalette.restoreState(state);
			} catch (RuntimeException re) {
				/*
				 * @TODO:Pratik You should log this exception
				 */
			}
		}
		return false;
	}

	/**
	 * If an external palette viewer is provided, palette state (that is
	 * captured in {@link PaletteViewer#saveState(IMemento)} -- active tool,
	 * drawer expansion state, drawer pin state, etc.) will be maintained when
	 * switching between the two viewers. Providing an external viewer, although
	 * recommended, is optional.
	 * 
	 * @param viewer
	 *            The palette viewer used in the PaletteView
	 */
	public void setExternalViewer(PaletteViewer viewer) {
		if (viewer == null && externalViewer != null)
			capturedPaletteState = capturePaletteState(externalViewer);
		externalViewer = viewer;
		if (externalViewer != null && pViewer != null)
			transferState(pViewer, externalViewer);
	}

	private void setDockLocation(int position) {
		if (position != PositionConstants.EAST
				&& position != PositionConstants.WEST)
			return;
		if (position != dock) {
			int oldPosition = dock;
			dock = position;
			listeners.firePropertyChange(PROPERTY_DOCK_LOCATION, oldPosition,
					dock);
			if (pViewer != null)
				layout(true);
		}
	}

	private void setPaletteWidth(int newSize) {
		if (paletteWidth != newSize) {
			int oldValue = paletteWidth;
			paletteWidth = newSize;
			listeners.firePropertyChange(PROPERTY_PALETTE_WIDTH, oldValue,
					paletteWidth);
			if (pViewer != null)
				layout(true);
		}
	}

	/**
	 * Sets the control along the side of which the palette is to be displayed.
	 * The given Control should be a child of this Composite. This method should
	 * only be invoked once.
	 * 
	 * @param graphicalViewer
	 *            the control of the graphical viewer; cannot be
	 *            <code>null</code>
	 */
	public void setGraphicalControl(Control graphicalViewer) {
		Assert.isTrue(graphicalViewer != null);
		Assert.isTrue(graphicalViewer.getParent() == this);
		Assert.isTrue(graphicalControl == null);
		graphicalControl = graphicalViewer;
		// UNSUPPORTED - api not implemented in RAP
		// addListenerToCtrlHierarchy(graphicalControl, SWT.MouseEnter, new
		// Listener()
		// {
		// public void handleEvent(Event event)
		// {
		// if (!isInState(STATE_EXPANDED))
		// return;
		// Display.getCurrent().timerExec(250, new Runnable()
		// {
		// public void run()
		// {
		// if (isDescendantOf(graphicalControl,
		// Display.getCurrent().getCursorControl()) &&
		// isInState(STATE_EXPANDED))
		// setState(STATE_COLLAPSED);
		// }
		// });
		// }
		// });
	}

	/*
	 * @TODO:Pratik For 4.0, change the parameter of this method to be
	 * EditpartViewer instead of GraphicalViewer.
	 */
	/**
	 * This method hooks a DropTargetListener that collapses the flyout patette
	 * when the user drags something from the palette and moves the cursor to
	 * the primary viewer's control. If the auto-hide feature of the palette is
	 * to work properly when dragging, this method should be called before any
	 * other drop target listeners are added to the primary viewer.
	 * 
	 * @param viewer
	 *            the primary viewer
	 */
	public void hookDropTargetListener(GraphicalViewer viewer) {
		viewer.addDropTargetListener(new TransferDropTargetListener() {
			public void dragEnter(DropTargetEvent event) {
			}

			public void dragLeave(DropTargetEvent event) {
			}

			public void dragOperationChanged(DropTargetEvent event) {
			}

			public void dragOver(DropTargetEvent event) {
			}

			public void drop(DropTargetEvent event) {
			}

			public void dropAccept(DropTargetEvent event) {
			}

			public Transfer getTransfer() {
				return TemplateTransfer.getInstance();
			}

			public boolean isEnabled(DropTargetEvent event) {
				if (isInState(STATE_EXPANDED))
					setState(STATE_COLLAPSED);
				return false;
			}
		});
	}

	/*
	 * If the given state is invalid (as could be the case when
	 * FlyoutPreferences.getPaletteState() is invoked for the first time), it
	 * will be defaulted to STATE_COLLAPSED.
	 */
	private void setState(int newState) {
		/*
		 * Fix for Bug# 69617 and Bug# 81248 FlyoutPreferences.getPaletteState()
		 * could return an invalid state if none is stored. In that case, we use
		 * the default state: STATE_COLLAPSED.
		 */
		if (newState != STATE_HIDDEN && newState != STATE_PINNED_OPEN
				&& newState != STATE_EXPANDED)
			newState = STATE_COLLAPSED;
		if (paletteState == newState)
			return;
		int oldState = paletteState;
		paletteState = newState;
		switch (paletteState) {
		case STATE_EXPANDED:
		case STATE_COLLAPSED:
		case STATE_PINNED_OPEN:
			if (pViewer == null) {
				pViewer = provider.createPaletteViewer(paletteContainer);
				if (externalViewer != null)
					transferState(externalViewer, pViewer);
				else
					restorePaletteState(pViewer, capturedPaletteState);
				capturedPaletteState = null;
				minWidth = Math.max(pViewer.getControl().computeSize(0, 0).x,
						MIN_PALETTE_SIZE);
			}
			break;
		case STATE_HIDDEN:
			if (pViewer == null)
				break;
			if (externalViewer != null) {
				provider.getEditDomain().setPaletteViewer(externalViewer);
				transferState(pViewer, externalViewer);
			}
			if (provider.getEditDomain().getPaletteViewer() == pViewer)
				provider.getEditDomain().setPaletteViewer(null);
			Control pViewerCtrl = getPaletteViewerControl();
			if (pViewerCtrl != null && !pViewerCtrl.isDisposed())
				pViewerCtrl.dispose();
			pViewer = null;
		}
		/*
		 * Fix for Bug# 63901 When the flyout collapses, if the palette has
		 * focus, throw focus to the graphical control. That way, hitting ESC
		 * will still deactivate the current tool and load the default one. Note
		 * that focus is being set on RulerComposite and not GraphicalViewer's
		 * control. But this is okay since RulerComposite passes the focus on to
		 * its first child, which is the graphical viewer's control.
		 */
		if (paletteState == STATE_COLLAPSED
				&& pViewer.getControl().isFocusControl())
			graphicalControl.setFocus();
		layout(true);
		listeners.firePropertyChange(PROPERTY_STATE, oldState, newState);
	}

	private void transferState(PaletteViewer src, PaletteViewer dest) {
		restorePaletteState(dest, capturePaletteState(src));
	}

	private void updateState(IWorkbenchPage page) {
		IViewReference view = page.findViewReference(PaletteView.ID);
		if (view == null && isInState(STATE_HIDDEN))
			setState(prefs.getPaletteState());
		if (view != null && !isInState(STATE_HIDDEN))
			setState(STATE_HIDDEN);
	}

	/**
	 * FlyoutPreferences is used to save/load the preferences for the flyout
	 * palette.
	 * 
	 * @author Pratik Shah
	 * @since 3.0
	 */
	public interface FlyoutPreferences {
		/**
		 * Should return {@link PositionConstants#EAST} or
		 * {@link PositionConstants#WEST}. Any other int will be ignored and the
		 * default dock location (EAST) will be used instead.
		 * 
		 * @return the saved dock location of the Palette
		 */
		int getDockLocation();

		/**
		 * When there is no saved state, this method can return any non-positive
		 * int (which will result in the palette using the default state --
		 * collapsed), or {@link FlyoutPaletteComposite#STATE_COLLAPSED}, or
		 * {@link FlyoutPaletteComposite#STATE_PINNED_OPEN}
		 * 
		 * @return the saved state of the palette
		 */
		int getPaletteState();

		/**
		 * When there is no saved width, this method can return any int
		 * (preferrably a non-positive int). Returning a non-positive int will
		 * cause the palette to be sized to the default size, whereas returning
		 * a postive int will find the closest match in the valid range (>=
		 * minimum and <= maximum)
		 * 
		 * @return the saved width of the flyout palette
		 */
		int getPaletteWidth();

		/**
		 * This method is invoked when the flyout palette's dock location is
		 * changed. The provided dock location should be persisted and returned
		 * in {@link #getDockLocation()}.
		 * 
		 * @param location
		 *            {@link PositionConstants#EAST} or
		 *            {@link PositionConstants#WEST}
		 */
		void setDockLocation(int location);

		/**
		 * This method is invoked when the flyout palette's state is changed
		 * (the new state becomes the default). The provided state should be
		 * persisted and returned in {@link #getPaletteState()}.
		 * 
		 * @param state
		 *            {@link FlyoutPaletteComposite#STATE_COLLAPSED} or
		 *            {@link FlyoutPaletteComposite#STATE_PINNED_OPEN}
		 */
		void setPaletteState(int state);

		/**
		 * This method is invoked when the flyout palette is resized. The
		 * provided width should be persisted and returned in
		 * {@link #getPaletteWidth()}.
		 * 
		 * @param width
		 *            the new size of the flyout palette
		 */
		void setPaletteWidth(int width);
	}

	private class Sash extends Composite {
		private Control button;
		private ControlPaintHandler helper;

		public Sash(Composite parent, int style) {
			super(parent, style);
			helper = new ControlPaintHandler(this);
			button = createFlyoutControlButton(this);
			new SashDragManager();
			// UNSUPPORTED - api not implemented in RAP
			// addMouseTrackListener(new MouseTrackAdapter()
			// {
			// public void mouseHover(MouseEvent e)
			// {
			// if (isInState(STATE_COLLAPSED))
			// setState(STATE_EXPANDED);
			// }
			// });

			helper.addPaintListener(new PaintListener() {
				public void paintControl(org.eclipse.swt.events.PaintEvent event) {
					paintSash(event.gc);
				};
			});

			addListener(SWT.Resize, new Listener() {
				public void handleEvent(Event event) {
					layout(true);
				}
			});

			listeners.addPropertyChangeListener(new PropertyChangeListener() {
				public void propertyChange(PropertyChangeEvent evt) {
					if (evt.getPropertyName().equals(PROPERTY_STATE))
						updateState();
				}
			});
		}

		public Point computeSize(int wHint, int hHint, boolean changed) {
			if (isInState(STATE_PINNED_OPEN))
				return new Point(3, 3);

			// button size plus two pixels for the two lines to be drawn
			return new Point(SASH_BUTTON_WIDTH + 2, cachedTitleHeight);
		}

		private void handleSashDragged(int shiftAmount) {
			int newSize = paletteContainer.getBounds().width
					+ (dock == PositionConstants.EAST ? -shiftAmount
							: shiftAmount);
			setPaletteWidth(newSize);
		}

		public void layout(boolean changed) {
			if (button == null)
				return;

			if (isInState(STATE_PINNED_OPEN)) {
				button.setVisible(false);
				return;
			}

			button.setVisible(true);
			Rectangle area = getClientArea();
			button.setBounds(area.x + 1, area.y + 1, SASH_BUTTON_WIDTH,
					cachedTitleHeight - 1);

			if (transferFocus) {
				transferFocus = false;
				button.setFocus();
			}
		}

		private void paintSash(GC gc) {
			Rectangle bounds = getBounds();
			if (isInState(STATE_PINNED_OPEN)) {
				gc.setBackground(PaletteColorUtil.WIDGET_BACKGROUND);
				gc.fillRectangle(0, 0, bounds.width, bounds.height);

				gc.setForeground(PaletteColorUtil.WIDGET_LIST_BACKGROUND);
				gc.drawLine(0, 0, bounds.width, 0);
				gc.setForeground(PaletteColorUtil.WIDGET_NORMAL_SHADOW);
				gc.drawLine(0, bounds.height - 1, bounds.width - 1,
						bounds.height - 1);
				gc.setForeground(PaletteColorUtil.WIDGET_LIST_BACKGROUND);
				gc.drawLine(0, 0, 0, bounds.height);
				gc.setForeground(PaletteColorUtil.WIDGET_NORMAL_SHADOW);
				gc.drawLine(bounds.width - 1, 0, bounds.width - 1,
						bounds.height - 1);
			} else {
				gc.setForeground(PaletteColorUtil.WIDGET_NORMAL_SHADOW);
				gc.drawLine(0, 0, 0, bounds.height);
				gc.drawLine(bounds.width - 1, 0, bounds.width - 1,
						bounds.height);

				gc.setForeground(PaletteColorUtil.WIDGET_LIST_BACKGROUND);
				gc.drawLine(1, 0, 1, bounds.height);

				gc.setForeground(PaletteColorUtil.WIDGET_BACKGROUND_LIST_BACKGROUND_85);
				gc.drawLine(2, 0, 2, bounds.height);
			}
		}

		private void updateState() {
			setCursor(isInState(STATE_EXPANDED | STATE_PINNED_OPEN) ? SharedCursors.SIZEWE
					: null);
		}

		private class SashDragManager extends MouseAdapter implements
				MouseMoveListener {
			protected boolean dragging = false;
			protected boolean correctState = false;
			protected boolean mouseDown = false;
			protected int origX;
			protected Listener keyListener = new Listener() {
				public void handleEvent(Event event) {
					if (event.keyCode == SWT.ALT || event.keyCode == SWT.ESC) {
						dragging = false;
						Display.getCurrent().removeFilter(SWT.KeyDown, this);
					}
					event.doit = false;
					event.type = SWT.None;
				}
			};

			public SashDragManager() {
				// UNSUPPORTED - api not implemented in RAP
				// Sash.this.addMouseMoveListener(this);
				Sash.this.addMouseListener(this);
			}

			public void mouseDown(MouseEvent me) {
				if (me.button != 1)
					return;
				mouseDown = true;
				correctState = isInState(STATE_EXPANDED | STATE_PINNED_OPEN);
				origX = me.x;
				Display.getCurrent().addFilter(SWT.KeyDown, keyListener);
			}

			public void mouseMove(MouseEvent me) {
				if (mouseDown)
					dragging = true;
				if (dragging && correctState)
					handleSashDragged(me.x - origX);
			}

			public void mouseUp(MouseEvent me) {
				Display.getCurrent().removeFilter(SWT.KeyDown, keyListener);
				if (!dragging && me.button == 1) {
					if (isInState(STATE_COLLAPSED))
						setState(STATE_EXPANDED);
					else if (isInState(STATE_EXPANDED))
						setState(STATE_COLLAPSED);
				}
				dragging = false;
				correctState = false;
				mouseDown = false;
			}
		}
	}

	private class ResizeAction extends Action {
		public ResizeAction() {
			super(PaletteMessages.RESIZE_LABEL);
		}

		public boolean isEnabled() {
			return !isInState(STATE_COLLAPSED);
		}

		public void run() {
			final Tracker tracker = new Tracker(FlyoutPaletteComposite.this,
					SWT.RIGHT | SWT.LEFT);
			Rectangle[] rects = new Rectangle[1];
			rects[0] = sash.getBounds();
			tracker.setCursor(SharedCursors.SIZEE);
			tracker.setRectangles(rects);
			if (tracker.open()) {
				int deltaX = sash.getBounds().x - tracker.getRectangles()[0].x;
				if (dock == PositionConstants.WEST)
					deltaX = -deltaX;
				setPaletteWidth(paletteContainer.getBounds().width + deltaX);
			}
			tracker.dispose();
		}
	}

	private class TitleDragManager extends MouseAdapter implements Listener,
			MouseTrackListener {
		protected boolean switchDock = false;
		protected boolean dragging = false;
		protected int threshold;

		public TitleDragManager(Control ctrl) {
			ctrl.addListener(SWT.DragDetect, this);
			ctrl.addMouseListener(this);
			// UNSUPPORTED - api not implemented in RAP
			// ctrl.addMouseTrackListener(this);
		}

		public void handleEvent(Event event) {
			dragging = true;
			switchDock = false;
			threshold = dock == PositionConstants.EAST ? Integer.MAX_VALUE / 2
					: -1;
			final Composite flyout = FlyoutPaletteComposite.this;
			final Rectangle flyoutBounds = flyout.getBounds();
			final int switchThreshold = flyoutBounds.x
					+ (flyoutBounds.width / 2);
			Rectangle bounds = sash.getBounds();
			if (paletteContainer.getVisible())
				bounds = bounds.union(paletteContainer.getBounds());
			final Rectangle origBounds = Display.getCurrent().map(flyout, null,
					bounds);
			final Tracker tracker = new Tracker(Display.getDefault(), SWT.NULL);
			tracker.setRectangles(new Rectangle[] { origBounds });
			final Display display = Display.getCurrent();
			tracker.setStippled(true);
			tracker.addListener(SWT.Move, new Listener() {
				public void handleEvent(final Event evt) {
					display.syncExec(new Runnable() {
						public void run() {
							Control ctrl = display.getCursorControl();
							Point location = display.getCursorLocation(); // evt.x,
																			// evt.y
							Point pt = flyout.toControl(location.x, location.y);
							switchDock = isDescendantOf(graphicalControl, ctrl)
									&& ((dock == PositionConstants.WEST && pt.x > threshold - 10) || (dock == PositionConstants.EAST && pt.x < threshold + 10));
							boolean invalid = false;
							if (!switchDock)
								invalid = !isDescendantOf(
										FlyoutPaletteComposite.this, ctrl);
							if (switchDock) {
								if (dock == PositionConstants.WEST) {
									threshold = Math.max(threshold, pt.x);
									threshold = Math.min(threshold,
											switchThreshold);
								} else {
									threshold = Math.min(threshold, pt.x);
									threshold = Math.max(threshold,
											switchThreshold);
								}
							}
							Rectangle placeHolder = origBounds;
							if (switchDock) {
								if (dock == PositionConstants.EAST)
									placeHolder = new Rectangle(0, 0,
											origBounds.width, origBounds.height);
								else
									placeHolder = new Rectangle(
											flyoutBounds.width
													- origBounds.width, 0,
											origBounds.width, origBounds.height);
								placeHolder = display.map(flyout, null,
										placeHolder);
							}
							// update the cursor
							int cursor;
							if (invalid)
								cursor = DragCursors.INVALID;
							else if ((!switchDock && dock == PositionConstants.EAST)
									|| (switchDock && dock == PositionConstants.WEST))
								cursor = DragCursors.RIGHT;
							else
								cursor = DragCursors.LEFT;
							if (isMirrored()) {
								if (cursor == DragCursors.RIGHT)
									cursor = DragCursors.LEFT;
								else if (cursor == DragCursors.LEFT)
									cursor = DragCursors.RIGHT;
							}
							tracker.setCursor(DragCursors.getCursor(cursor));
							// update the rectangle only if it has changed
							if (!tracker.getRectangles()[0].equals(placeHolder))
								tracker.setRectangles(new Rectangle[] { placeHolder });
						}
					});
				}
			});

			// HACK for DND in RAP
			Job dragJob = new Job("Drag-Job") {
				protected IStatus run(IProgressMonitor monitor) {

					if (tracker.open()) {

						display.asyncExec(new Runnable() {
							public void run() {
								IDropTarget dropTarget = null;
								Point finalLocation = display
										.getCursorLocation();
								Control targetControl = display
										.getCursorControl();
								if (switchDock) {
									setDockLocation(PositionConstants.EAST_WEST
											& ~dock);
									// mouse up is received by the tracker and
									// by this listener, so
									// we set dragging
									// to be false
									dragging = false;
								}
								// Cleanup...
								tracker.dispose();
							}
						});
					}
					return Status.OK_STATUS;
				}
			};
			dragJob.setSystem(true);
			dragJob.schedule();
		}

		public void mouseEnter(MouseEvent e) {
		}

		public void mouseExit(MouseEvent e) {
		}

		public void mouseHover(MouseEvent e) {
			/*
			 * @TODO:Pratik Mouse hover events are received if the hover occurs
			 * just before you finish or cancel the drag. Open a bugzilla about
			 * it?
			 */
			if (isInState(STATE_COLLAPSED))
				setState(STATE_EXPANDED);
		}

		public void mouseUp(MouseEvent me) {
			if (me.button != 1)
				return;
			if (isInState(STATE_COLLAPSED))
				setState(STATE_EXPANDED);
			else if (isInState(STATE_EXPANDED))
				setState(STATE_COLLAPSED);
		}
	}

	private class PaletteComposite extends Composite {
		protected Control button, title;

		public PaletteComposite(Composite parent, int style) {
			super(parent, style);
			createComponents();

			listeners.addPropertyChangeListener(new PropertyChangeListener() {
				public void propertyChange(PropertyChangeEvent evt) {
					if (evt.getPropertyName().equals(PROPERTY_STATE))
						updateState();
					else if (evt.getPropertyName().equals(
							PROPERTY_DOCK_LOCATION))
						if (getVisible())
							layout(true);
				}
			});

			addListener(SWT.Resize, new Listener() {
				public void handleEvent(Event event) {
					layout(true);
				}
			});

			updateState();
		}

		protected void createComponents() {
			title = createTitle(this, true);
			button = createFlyoutControlButton(this);
		}

		public void layout(boolean changed) {
			Control pCtrl = getPaletteViewerControl();
			if (pCtrl == null || pCtrl.isDisposed())
				return;

			Rectangle area = getClientArea();
			boolean buttonVisible = button.getVisible();
			Point titleSize = title.computeSize(-1, -1);
			Point buttonSize = buttonVisible ? button.computeSize(-1, -1)
					: new Point(0, 0);
			cachedTitleHeight = Math.max(titleSize.y, buttonSize.y);
			if (buttonVisible) {
				buttonSize.x = Math.max(cachedTitleHeight, buttonSize.x);
			}
			if (dock == PositionConstants.EAST) {
				int buttonX = area.width - buttonSize.x;
				button.setBounds(buttonX, 0, buttonSize.x, cachedTitleHeight);
				title.setBounds(0, 0, buttonX, cachedTitleHeight);
			} else {
				int titleX = buttonSize.x;
				button.setBounds(0, 0, buttonSize.x, cachedTitleHeight);
				title.setBounds(titleX, 0, area.width - titleX,
						cachedTitleHeight);
			}
			area.y += cachedTitleHeight;
			area.height -= cachedTitleHeight;
			pCtrl.setBounds(area);
		}

		protected void updateState() {
			button.setVisible(isInState(STATE_PINNED_OPEN));
			if (transferFocus && button.getVisible()) {
				transferFocus = false;
				button.setFocus();
			}
			layout(true);
		}
	}

	private static class TitleLabel extends Label {
		protected static final Border BORDER = new MarginBorder(4, 3, 4, 3);
		protected static final Border TOOL_TIP_BORDER = new MarginBorder(0, 2,
				0, 2);

		public TitleLabel(boolean isHorizontal) {
			super(GEFMessages.Palette_Label, InternalImages
					.get(InternalImages.IMG_PALETTE));
			setLabelAlignment(PositionConstants.LEFT);
			setBorder(BORDER);
			Label tooltip = new Label(getText());
			tooltip.setBorder(TOOL_TIP_BORDER);
			setToolTip(tooltip);
			setForegroundColor(ColorConstants.listForeground);
		}

		public IFigure getToolTip() {
			if (isTextTruncated())
				return super.getToolTip();
			return null;
		}

		protected void paintFigure(Graphics graphics) {

			// paint the gradient
			graphics.pushState();
			org.eclipse.draw2d.geometry.Rectangle r = org.eclipse.draw2d.geometry.Rectangle.SINGLETON;
			r.setBounds(getBounds());
			graphics.setForegroundColor(PaletteColorUtil.WIDGET_LIST_BACKGROUND);
			graphics.setBackgroundColor(PaletteColorUtil.WIDGET_BACKGROUND);
			graphics.fillGradient(r, true);

			// draw bottom border
			graphics.setForegroundColor(PaletteColorUtil.WIDGET_NORMAL_SHADOW);
			graphics.drawLine(r.getBottomLeft().getTranslated(0, -1), r
					.getBottomRight().getTranslated(0, -1));

			graphics.popState();

			// paint the text and icon
			super.paintFigure(graphics);

			// paint the focus rectangle around the text
			if (hasFocus()) {
				org.eclipse.draw2d.geometry.Rectangle textBounds = getTextBounds();
				// We reduce the width by 1 because FigureUtilities grows it by
				// 1 unnecessarily
				textBounds.width--;
				graphics.drawFocus(bounds.getResized(-1, -1).intersect(
						textBounds.getExpanded(getInsets())));
			}
		}
	}

	private class ButtonCanvas extends Canvas {
		private LightweightSystem lws;

		public ButtonCanvas(Composite parent) {
			super(parent, SWT.NO_REDRAW_RESIZE | SWT.NO_BACKGROUND);
			init();
			provideAccSupport();
		}

		public Point computeSize(int wHint, int hHint, boolean changed) {
			Dimension size = lws.getRootFigure().getPreferredSize(wHint, hHint);
			size.union(new Dimension(wHint, hHint));
			return new org.eclipse.swt.graphics.Point(size.width, size.height);
		}

		private int getArrowDirection() {
			int direction = PositionConstants.EAST;
			if (isInState(STATE_EXPANDED | STATE_PINNED_OPEN))
				direction = dock == PositionConstants.WEST ? PositionConstants.WEST
						: PositionConstants.EAST;
			else
				direction = dock == PositionConstants.WEST ? PositionConstants.EAST
						: PositionConstants.WEST;
			if (isMirrored()) {
				if (direction == PositionConstants.WEST)
					direction = PositionConstants.EAST;
				else
					direction = PositionConstants.WEST;
			}
			return direction;
		}

		private String getButtonTooltipText() {
			if (isInState(STATE_COLLAPSED))
				return PaletteMessages.PALETTE_SHOW;
			return PaletteMessages.PALETTE_HIDE;
		}

		private void init() {
			setCursor(SharedCursors.ARROW);
			lws = new LightweightSystem();
			lws.setControl(this);
			final ArrowButton b = new ArrowButton(getArrowDirection());
			b.setRolloverEnabled(true);
			b.setBorder(new ButtonBorder(ButtonBorder.SCHEMES.TOOLBAR));
			b.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent event) {
					transferFocus = true;
					if (isInState(STATE_COLLAPSED))
						setState(STATE_PINNED_OPEN);
					else
						setState(STATE_COLLAPSED);
				}
			});
			listeners.addPropertyChangeListener(new PropertyChangeListener() {
				public void propertyChange(PropertyChangeEvent evt) {
					if (evt.getPropertyName().equals(PROPERTY_STATE)) {
						b.setDirection(getArrowDirection());
						setToolTipText(getButtonTooltipText());
					} else if (evt.getPropertyName().equals(
							PROPERTY_DOCK_LOCATION))
						b.setDirection(getArrowDirection());
				}
			});
			lws.setContents(b);
		}

		private void provideAccSupport() {
			getAccessible().addAccessibleListener(new AccessibleAdapter() {
				public void getDescription(AccessibleEvent e) {
					e.result = PaletteMessages.ACC_DESC_PALETTE_BUTTON;
				}

				public void getHelp(AccessibleEvent e) {
					getDescription(e);
				}

				public void getName(AccessibleEvent e) {
					e.result = getToolTipText();
				}
			});
			getAccessible().addAccessibleControlListener(
					new AccessibleControlAdapter() {
						public void getRole(AccessibleControlEvent e) {
							e.detail = ACC.ROLE_PUSHBUTTON;
						}
					});
		}

		private class ArrowButton extends Button {

			private Triangle triangle;

			/**
			 * Creates a new instance
			 * 
			 * @param direction
			 *            the direction the arrow should face
			 *            (PositionConstants.RIGHT or PositionConstants.LEFT)
			 */
			public ArrowButton(int direction) {
				super();
				setDirection(direction);

				triangle = new Triangle();
				triangle.setOutline(true);
				triangle.setBackgroundColor(PaletteColorUtil.WIDGET_LIST_BACKGROUND);
				triangle.setForegroundColor(PaletteColorUtil.WIDGET_DARK_SHADOW);
				setContents(triangle);
			}

			public void setDirection(int direction) {
				if (triangle != null) {
					triangle.setDirection(direction);
				}
			}

			protected void layout() {
				org.eclipse.draw2d.geometry.Rectangle clientArea = getBounds();

				triangle.setBounds(new org.eclipse.draw2d.geometry.Rectangle(
						clientArea.getCenter().getTranslated(
								-ARROW_SIZE.width / 2, -ARROW_SIZE.height / 2),
						ARROW_SIZE));
			}

			protected void paintFigure(Graphics graphics) {
				super.paintFigure(graphics);

				// paint the gradient
				graphics.pushState();
				org.eclipse.draw2d.geometry.Rectangle r = org.eclipse.draw2d.geometry.Rectangle.SINGLETON;
				r.setBounds(getBounds());
				graphics.setForegroundColor(PaletteColorUtil.WIDGET_LIST_BACKGROUND);
				graphics.setBackgroundColor(PaletteColorUtil.WIDGET_BACKGROUND);
				graphics.fillGradient(r, true);
				graphics.popState();

				// draw bottom border
				graphics.setForegroundColor(PaletteColorUtil.WIDGET_NORMAL_SHADOW);
				graphics.drawLine(r.getBottomLeft().getTranslated(0, -1), r
						.getBottomRight().getTranslated(0, -1));
			}
		}
	}

	private class TitleCanvas extends Canvas {
		private LightweightSystem lws;

		public TitleCanvas(Composite parent, boolean horizontal) {
			super(parent, SWT.NO_REDRAW_RESIZE | SWT.NO_BACKGROUND);
			init(horizontal);
			provideAccSupport();
		}

		/**
		 * @see org.eclipse.swt.widgets.Control#computeSize(int, int, boolean)
		 */
		public Point computeSize(int wHint, int hHint, boolean changed) {
			Dimension size = lws.getRootFigure().getPreferredSize(wHint, hHint);
			size.union(new Dimension(wHint, hHint));
			return new org.eclipse.swt.graphics.Point(size.width, size.height);
		}

		private void init(boolean isHorizontal) {
			final IFigure contents = new TitleLabel(true);
			contents.setRequestFocusEnabled(true);
			contents.setFocusTraversable(true);
			contents.addFocusListener(new FocusListener() {
				public void focusGained(FocusEvent fe) {
					fe.gainer.repaint();
				}

				public void focusLost(FocusEvent fe) {
					fe.loser.repaint();
				}
			});

			lws = new LightweightSystem();
			lws.setControl(this);
			lws.setContents(contents);
			setCursor(SharedCursors.SIZEALL);
			FONT_MGR.register(this);
			new TitleDragManager(this);
			final MenuManager manager = new MenuManager();
			MenuManager mgr = new MenuManager(PaletteMessages.DOCK_LABEL);
			mgr.add(new ChangeDockAction(PaletteMessages.LEFT_LABEL,
					PositionConstants.WEST));
			mgr.add(new ChangeDockAction(PaletteMessages.RIGHT_LABEL,
					PositionConstants.EAST));
			manager.add(new ResizeAction());
			manager.add(mgr);
			setMenu(manager.createContextMenu(this));
			mgr.addMenuListener(new IMenuListener() {
				public void menuAboutToShow(IMenuManager menuMgr) {
					IContributionItem[] items = menuMgr.getItems();
					for (int i = 0; i < items.length; i++) {
						((ActionContributionItem) items[i]).update();
					}
				}
			});

			addDisposeListener(new DisposeListener() {
				public void widgetDisposed(DisposeEvent e) {
					FONT_MGR.unregister(TitleCanvas.this);
					manager.dispose();
				}
			});
		}

		private void provideAccSupport() {
			getAccessible().addAccessibleListener(new AccessibleAdapter() {
				public void getDescription(AccessibleEvent e) {
					e.result = PaletteMessages.ACC_DESC_PALETTE_TITLE;
				}

				public void getHelp(AccessibleEvent e) {
					getDescription(e);
				}

				public void getName(AccessibleEvent e) {
					e.result = GEFMessages.Palette_Label;
				}
			});
			getAccessible().addAccessibleControlListener(
					new AccessibleControlAdapter() {
						public void getRole(AccessibleControlEvent e) {
							e.detail = ACC.ROLE_LABEL;
						}
					});
		}

		public void setFont(Font font) {
			((IFigure) lws.getRootFigure().getChildren().get(0)).setFont(font);
			if (isVisible()) {
				/*
				 * If this canvas is in the sash, we want the
				 * FlyoutPaletteComposite to layout (which will cause the sash
				 * to be resized and laid out). However, if this canvas is in
				 * the paletteContainer, the paletteContainer's bounds won't
				 * change, and hence it won't layout. Thus, we also invoke
				 * getParent().layout().
				 */
				FlyoutPaletteComposite.this.layout(true);
				getParent().layout(true);
			}
		}
	}

	private class ChangeDockAction extends Action {
		private int position;

		/**
		 * Constructor
		 * 
		 * @param text
		 *            this action's text
		 * @param position
		 *            the dock side that this action represents:
		 *            PositionConstants.EAST or PositionConstants.WEST
		 */
		public ChangeDockAction(String text, int position) {
			super(text, IAction.AS_RADIO_BUTTON);
			this.position = position;
		}

		/**
		 * This Action is checked when the palette is docked on the side this
		 * action represents
		 * 
		 * @see org.eclipse.jface.action.IAction#isChecked()
		 */
		public boolean isChecked() {
			return dock == position;
		}

		/**
		 * Changes the palette's dock location to the side this action
		 * represents
		 * 
		 * @see org.eclipse.jface.action.IAction#run()
		 */
		public void run() {
			setDockLocation(position);
		}
	}

	private static class FontManager {
		private final String fontName = getFontType();
		private List registrants = new ArrayList();
		private Font titleFont;
		private final IPropertyChangeListener fontListener = new IPropertyChangeListener() {
			public void propertyChange(
					org.eclipse.jface.util.PropertyChangeEvent event) {
				if (fontName.equals(event.getProperty()))
					handleFontChanged();
			}
		};

		private FontManager() {
		}

		protected final Font createTitleFont() {
			return JFaceResources.getFont(fontName);
		}

		protected void dispose() {
			titleFont = null;
			JFaceResources.getFontRegistry().removeListener(fontListener);
		}

		protected String getFontType() {
			return JFaceResources.DIALOG_FONT;
		}

		protected void handleFontChanged() {
			if (titleFont == null)
				return;
			Font oldFont = titleFont;
			titleFont = createTitleFont();
			for (Iterator iter = registrants.iterator(); iter.hasNext();)
				((Control) iter.next()).setFont(titleFont);
			oldFont.dispose();
		}

		protected void init() {
			titleFont = createTitleFont();
			JFaceResources.getFontRegistry().addListener(fontListener);
		}

		public void register(Control ctrl) {
			if (titleFont == null)
				init();
			ctrl.setFont(titleFont);
			registrants.add(ctrl);
		}

		public void unregister(Control ctrl) {
			registrants.remove(ctrl);
			if (registrants.isEmpty())
				dispose();
		}
	}

	/**
	 * Default implementation of FlyoutPreferences that stores the flyout
	 * palette settings in the given Preferences.
	 * 
	 * @author Pratik Shah
	 * @since 3.2
	 */
	private static class DefaultFlyoutPreferences implements FlyoutPreferences {
		/*
		 * There's no need to set the default for these properties since the
		 * default-default of 0 for ints will suffice.
		 */
		private static final String PALETTE_DOCK_LOCATION = "org.eclipse.gef.pdock"; //$NON-NLS-1$
		private static final String PALETTE_SIZE = "org.eclipse.gef.psize"; //$NON-NLS-1$
		private static final String PALETTE_STATE = "org.eclipse.gef.pstate"; //$NON-NLS-1$

		private Preferences prefs;

		private DefaultFlyoutPreferences(Preferences preferences) {
			prefs = preferences;
		}

		public int getDockLocation() {
			return prefs.getInt(PALETTE_DOCK_LOCATION);
		}

		public int getPaletteState() {
			return prefs.getInt(PALETTE_STATE);
		}

		public int getPaletteWidth() {
			return prefs.getInt(PALETTE_SIZE);
		}

		public void setDockLocation(int location) {
			prefs.setValue(PALETTE_DOCK_LOCATION, location);
		}

		public void setPaletteState(int state) {
			prefs.setValue(PALETTE_STATE, state);
		}

		public void setPaletteWidth(int width) {
			prefs.setValue(PALETTE_SIZE, width);
		}
	}

	private static class DragCursors {
		public static final int INVALID = 0;

		public static final int LEFT = 1;

		public static final int RIGHT = 2;

		private final static Cursor cursors[] = new Cursor[3];

		/**
		 * Return the cursor for a drop scenario, as identified by code. Code
		 * must be one of INVALID, LEFT, RIGHT. If the code is not found default
		 * to INVALID. Note that since these three cursors are static, they will
		 * only be created once for the lifetime of the eclipse session and
		 * shared (i.e this is not an image leak).
		 * 
		 * @param code
		 *            the code
		 * @return the cursor
		 */
		public static Cursor getCursor(int code) {
			Display display = Display.getCurrent();
			// UNSUPPORTED - custom cursors not available in RAP
			// if (cursors[code] == null) {
			// ImageDescriptor source = null;
			// ImageDescriptor mask = null;
			// switch (code) {
			// case LEFT:
			// source = PlatformUI
			// .getWorkbench()
			// .getSharedImages()
			// .getImageDescriptor(
			// ISharedImages.IMG_OBJS_DND_LEFT_SOURCE);
			// mask = PlatformUI
			// .getWorkbench()
			// .getSharedImages()
			// .getImageDescriptor(
			// ISharedImages.IMG_OBJS_DND_LEFT_MASK);
			// cursors[LEFT] = new Cursor(display, source.getImageData(),
			// mask.getImageData(), 16, 16);
			// break;
			// case RIGHT:
			// source = PlatformUI
			// .getWorkbench()
			// .getSharedImages()
			// .getImageDescriptor(
			// ISharedImages.IMG_OBJS_DND_RIGHT_SOURCE);
			// mask = PlatformUI
			// .getWorkbench()
			// .getSharedImages()
			// .getImageDescriptor(
			// ISharedImages.IMG_OBJS_DND_RIGHT_MASK);
			// cursors[RIGHT] = new Cursor(display, source.getImageData(),
			// mask.getImageData(), 16, 16);
			// break;
			// default:
			// case INVALID:
			// source = PlatformUI
			// .getWorkbench()
			// .getSharedImages()
			// .getImageDescriptor(
			// ISharedImages.IMG_OBJS_DND_INVALID_SOURCE);
			// mask = PlatformUI
			// .getWorkbench()
			// .getSharedImages()
			// .getImageDescriptor(
			// ISharedImages.IMG_OBJS_DND_INVALID_MASK);
			// cursors[INVALID] = new Cursor(display,
			// source.getImageData(), mask.getImageData(), 16, 16);
			// break;
			// }
			// }
			// return cursors[code];
			return null;
		}

	}
}
