/*******************************************************************************
 * 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.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.draw2d.rap.swt.SWT;

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() & 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.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;
		}

	}
}
