/*******************************************************************************
 * <copyright>
 *
 * Copyright (c) 2005, 2016 SAP AG.
 * 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:
 *    SAP AG - initial API, implementation and documentation
 *    Bug 336488 - DiagramEditor API
 *    mwenz - Bug 373298 - Possible Resource leaks in Graphiti
 *    fvelasco - Bug 396247 - ImageDescriptor changes
 *    mwenz - Bug 397303 - Accessibility issue with Graphiti diagram in High Contrast Mode
 *    pjpaulin - Bug 352120 - Now uses IDiagramContainerUI interface
 *    apupier - Bug 508133 - Use FontRegistry for Tooltip
 *
 * </copyright>
 *
 *******************************************************************************/
package org.eclipse.graphiti.ui.internal.contextbuttons;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.Shape;
import org.eclipse.draw2d.XYLayout;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.EditPart;
import org.eclipse.graphiti.internal.contextbuttons.IContextButtonPadDeclaration;
import org.eclipse.graphiti.internal.contextbuttons.IContextButtonPadDeclaration.PadStyle;
import org.eclipse.graphiti.internal.contextbuttons.PositionedContextButton;
import org.eclipse.graphiti.ui.editor.DiagramBehavior;
import org.eclipse.graphiti.ui.internal.IResourceRegistry;
import org.eclipse.graphiti.ui.internal.figures.GFFigureUtil;
import org.eclipse.graphiti.ui.internal.util.DataTypeTransformation;
import org.eclipse.graphiti.util.IColorConstant;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.MouseTrackAdapter;
import org.eclipse.swt.events.MouseTrackListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Path;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;

/**
 * A Shape depicting a context button pad. The context button pad contains
 * several {@link ContextButton} as children. The visual definition of the
 * context button pad is provided mostly by the
 * {@link IContextButtonPadDeclaration}, which is set in the constructor, and
 * not calculated in this class.
 * 
 * @noinstantiate This class is not intended to be instantiated by clients.
 * @noextend This class is not intended to be subclassed by clients.
 */
public class ContextButtonPad extends Shape implements ITransparencyProvider {

	/**
	 * The default duration of the animation in milliseconds.
	 */
	private static final int DEFAULT_ANIMATION_DURATION = 200;

	/**
	 * The start transparency of the animation in the range 0.0 to 1.0.
	 */
	private static final double ANIMATION_START_TRANSPARENCY = 0.0;

	/**
	 * The end transparency of the animation in the range 0.0 to 1.0.
	 */
	private static final double ANIMATION_END_TRANSPARENCY = 1.0;

	/**
	 * The context button pad declaration as described in
	 * {@link #getDeclaration()}.
	 */
	private IContextButtonPadDeclaration declaration;

	/**
	 * The zoom-level as described in {@link #getZoomLevel()}.
	 */
	private double zoomLevel;

	/**
	 * The container as described in {@link #getContainer()}.
	 */
	private DiagramBehavior diagramBehavior;

	/**
	 * The edit-part as described in {@link #getEditPart()}.
	 */
	private EditPart editPart;

	private Path pathOuterLine;

	private Path pathMiddleLine;

	private Path pathInnerLine;

	private Path pathFill;

	private List<Rectangle> containmentRectangles;

	private List<Rectangle> overlappingContainmentRectangles;

	private double currentTransparency = ANIMATION_END_TRANSPARENCY;

	private long animationDuration = DEFAULT_ANIMATION_DURATION;

	// ============================= listener =================================

	/**
	 * The mouse move listener hides the context button pad, when the mouse
	 * leaves the 'mouse relevant' area of the context button pad (see
	 * {@link #isMouseInOverlappingArea()}).
	 */
	private MouseMoveListener mouseMoveListener = new MouseMoveListener() {
		public void mouseMove(MouseEvent e) {
			if (!isMouseInOverlappingArea()) {
				getContextButtonManagerForPad().hideContextButtonsInstantly();
			}
		}
	};

	/**
	 * The mouse track listener hides the context button pad, when the mouse
	 * leaves the diagram control (e.g. when the mouse goes to the top-menu or
	 * other views/editors).
	 */
	private MouseTrackListener mouseTrackListener = new MouseTrackAdapter() {
		@Override
		public void mouseExit(MouseEvent e) {
			// TODO: discuss with Christian
			// This functionality will hide the context button pad, whenever the
			// mouse leaves the
			// diagram control (e.g. when the mouse goes to the top-menu or
			// other views/editors).
			// Unfortunately tooltips are also other controls, so the context
			// button pad would
			// be hidden, if the mouse is on the tooltip of the shape or of the
			// buttons.
			// Both behaviors are reasonable, but for now we decided not to hide
			// the
			// context button pad when the mouse leaves the control

			// getContextButtonManager().hideContextButtonsInstantly();
		}
	};

	private IResourceRegistry resourceRegistry;

	private ContextButtonManagerForPad contextButtonManagerForPad;

	// ============================ constructors ==============================

	/**
	 * Creates a new ContextButtonPad and calls {@link #initialize()}.
	 * 
	 * @param contextButtonManagerForPad
	 * 
	 * @param declaration
	 *            The context button pad declaration as described in
	 *            {@link #getDeclaration()}.
	 * @param zoomLevel
	 *            The zoom-level as described in {@link #getZoomLevel()}.
	 * @param container
	 *            The container as described in {@link #getContainer()}.
	 * @param editPart
	 *            The edit-part as described in {@link #getEditPart()}.
	 * @param resourceRegistry
	 */
	public ContextButtonPad(ContextButtonManagerForPad contextButtonManagerForPad,
			IContextButtonPadDeclaration declaration, double zoomLevel, DiagramBehavior diagramBehavior,
			EditPart editPart,
			IResourceRegistry resourceRegistry) {
		this.declaration = declaration;
		this.zoomLevel = zoomLevel;
		this.diagramBehavior = diagramBehavior;
		this.editPart = editPart;
		this.resourceRegistry = resourceRegistry;
		this.contextButtonManagerForPad = contextButtonManagerForPad;

		initialize();
	}

	// ====================== getter/setter for fields ========================

	/**
	 * Returns the declaration, which provides the visual definition and the
	 * context buttons for this context button pad. It is set in the constructor
	 * and not changed afterwards.
	 * 
	 * @return The declaration, which provides the visual definition and the
	 *         context buttons for this context button pad.
	 */
	public final IContextButtonPadDeclaration getDeclaration() {
		return declaration;
	}

	/**
	 * Returns the zoom-level, which shall be used when rendering the context
	 * button pad. It is set in the constructor and not changed afterwards. The
	 * values provided by the declaration (see {@link #getDeclaration()}) are
	 * always using a zoom-level 1.0, so they have to be adjusted by the
	 * zoom-level.
	 * 
	 * @return The zoom-level, which shall be used when rendering the context
	 *         button pad.
	 */
	public final double getZoomLevel() {
		return zoomLevel;
	}

	/**
	 * Returns the container for which the context button pad belongs. It can be
	 * used to access the environment. It is set in the constructor and not
	 * changed afterwards.
	 * 
	 * @return The container, which can be used to access the environment.
	 */
	public final DiagramBehavior getDiagramBehavior() {
		return diagramBehavior;
	}

	/**
	 * Returns the edit-part for which the context button pad is showing. It is
	 * used by the context buttons, which work on/with the edit-part. It is set
	 * in the constructor and not changed afterwards.
	 * 
	 * @return The container, which can be used to access the environment.
	 */
	public final EditPart getEditPart() {
		return editPart;
	}

	// =========================== initialization =============================

	/**
	 * Initializes several fields of this class. This method is called in the
	 * constructor and calls {@link #initializePathes()},
	 * {@link #initializeContainments()} and {@link #createContextButtons()}.
	 */
	private void initialize() {
		initializeContainments();
		createContextButtons();
	}

	/**
	 * Initializes the lists {@link #containmentRectangles} and
	 * {@link #overlappingContainmentRectangles}, by transforming the rectangles
	 * provided by the declaration (see {@link #getDeclaration()}) using
	 * {@link #transformGenericRectangle(java.awt.Rectangle, int)}. Then it sets
	 * the bounds of this figure dependent on the
	 * {@link #overlappingContainmentRectangles}.
	 */
	private void initializeContainments() {
		containmentRectangles = new ArrayList<Rectangle>();
		overlappingContainmentRectangles = new ArrayList<Rectangle>();

		for (java.awt.Rectangle rectangle : getDeclaration().getContainmentRectangles()) {
			Rectangle transformedRectangle = transformGenericRectangle(rectangle, 0);
			containmentRectangles.add(transformedRectangle);
		}
		for (java.awt.Rectangle rectangle : getDeclaration().getOverlappingContainmentRectangles()) {
			Rectangle transformedRectangle = transformGenericRectangle(rectangle, 0);
			overlappingContainmentRectangles.add(transformedRectangle);
		}

		if (overlappingContainmentRectangles.size() > 0) { // always true
			Rectangle unionRectangle = overlappingContainmentRectangles.get(0).getCopy();
			for (Rectangle containmentRectangle : overlappingContainmentRectangles) {
				unionRectangle.union(containmentRectangle);
			}
			unionRectangle.expand(2, 2); // expand slightly to avoid rounding
											// problems
			setBounds(unionRectangle);
		}
	}

	/**
	 * Creates a visual {@link ContextButton} for each logical
	 * {@link PositionedContextButton}, which are provided by the declaration
	 * {@link #getDeclaration()}. Those context buttons are then added to the
	 * context button pad at the correct location.
	 */
	private void createContextButtons() {
		List<PositionedContextButton> positionedButtons = getDeclaration().getPositionedContextButtons();

		setLayoutManager(new XYLayout());

		for (PositionedContextButton positionedButton : positionedButtons) {
			Rectangle position = transformGenericRectangle(positionedButton.getPosition(), 0);
			// translate position relative to bounds (after the bounds are set!)
			position.translate(-getBounds().getTopLeft().x, -getBounds().getTopLeft().y);
			ContextButton cb = new ContextButton(diagramBehavior.getDiagramTypeProvider().getProviderId(),
					positionedButton,
					this);
			add(cb, position);
		}
	}

	IResourceRegistry getResourceRegistry() {
		return resourceRegistry;
	}

	/**
	 * Initializes the fields for the paths {@link #pathOuterLine},
	 * {@link #pathMiddleLine}, {@link #pathInnerLine} and {@link #pathFill}.
	 * This is done by calling {@link #createPath(int)} with ascending values
	 * for 'shrink-lines'. As a result those four paths all have the same
	 * outline, but each path becomes one line smaller so that they lie directly
	 * in each other.
	 */
	private void createPathes() {
		pathOuterLine = createPath(0);
		pathMiddleLine = createPath(1);
		pathInnerLine = createPath(2);
		pathFill = createPath(3);
	}

	/**
	 * Disposes all paths, which were created in {@link #createPathes()}.
	 */
	private void disposePathes() {
		pathOuterLine.dispose();
		pathMiddleLine.dispose();
		pathInnerLine.dispose();
		pathFill.dispose();
		pathOuterLine = null;
		pathMiddleLine = null;
		pathInnerLine = null;
		pathFill = null;
	}

	/**
	 * Creates and returns a path outlining the context button pad. The path
	 * includes the three rectangles top, right and bottom, which are provided
	 * by the declaration (see {@link #getDeclaration()}). A parameter
	 * shrink-lines is used to shrink the path by the given number of lines to
	 * the inside.
	 * <p>
	 * Basically this method just forwards to
	 * {@link #createPath(Rectangle, Rectangle, Rectangle, int)}, but before it
	 * adjusts the rectangles and corner by the zoom-level and shrink-lines.
	 * 
	 * @param shrinkLines
	 *            The number of lines to shrink the path to the inside.
	 * @return A path outlining the context button pad.
	 */
	private Path createPath(int shrinkLines) {
		double zoom = getZoomLevel();
		int lw = shrinkLines * ((int) (getDeclaration().getPadLineWidth() * zoom));

		// adjust corner for the inner path (formula found by experimenting)
		double corner = (getDeclaration().getPadCornerRadius() * zoom);
		corner = Math.max(1, corner - (lw + corner / 64));

		Rectangle topAdjusted = transformGenericRectangle(getDeclaration().getTopPad(), shrinkLines);
		Rectangle rightAdjusted = transformGenericRectangle(getDeclaration().getRightPad(), shrinkLines);
		Rectangle bottomAdjusted = transformGenericRectangle(getDeclaration().getBottomPad(), shrinkLines);

		Path path = createPath(topAdjusted, rightAdjusted, bottomAdjusted, (int) corner);
		return path;
	}

	/**
	 * Creates and returns a path including the given rectangles and uses the
	 * given corner-radius. Note, that all those values are already adjusted to
	 * the given zoom-level and 'shrink-lines' (see {@link #createPath(int)}).
	 * 
	 * @param topOutside
	 *            The outside of the top rectangle to include. The path remains
	 *            inside the rectangle even for a big line-width.
	 * @param rightOutside
	 *            The outside of the right rectangle to include. The path
	 *            remains inside the rectangle even for a big line-width.
	 * @param bottomOutside
	 *            The outside of the bottom rectangle to include. The path
	 *            remains inside the rectangle even for a big line-width.
	 * @param corner
	 *            The corner radius to use for the path.
	 * @return A path surrounding the given rectangles and uses the given
	 *         corner-radius.
	 */
	private Path createPath(Rectangle topOutside, Rectangle rightOutside, Rectangle bottomOutside, int corner) {
		Path path = new Path(null);

		// currently we assume, that the inner corner radius is always half the
		// outer corner radius
		int innerCorner = corner / 2;

		// first shrink all rectangles by the half line-width, so that painting
		// remains inside the given 'outside' rectangles
		Rectangle top = GFFigureUtil.getAdjustedRectangle(topOutside, 1.0,
				(int) (getDeclaration().getPadLineWidth() * getZoomLevel()));
		Rectangle right = GFFigureUtil.getAdjustedRectangle(rightOutside, 1.0, (int) (getDeclaration()
				.getPadLineWidth() * getZoomLevel()));
		Rectangle bottom = GFFigureUtil.getAdjustedRectangle(bottomOutside, 1.0, (int) (getDeclaration()
				.getPadLineWidth() * getZoomLevel()));

		// differenciate the pad styles
		boolean hasTop = top != null;
		boolean hasRight = right != null;
		boolean hasStandardTop = hasTop && getDeclaration().getTopPadStyle().equals(PadStyle.STANDARD);
		boolean hasStandardRight = hasRight && getDeclaration().getRightPadStyle().equals(PadStyle.STANDARD);
		boolean hasAppendageTop = hasTop && getDeclaration().getTopPadStyle().equals(PadStyle.APPENDAGE);
		boolean hasAppendageRight = hasRight && getDeclaration().getRightPadStyle().equals(PadStyle.APPENDAGE);

		// create path

		if (hasStandardTop) {
			// curved line around top(top-right) -> top(top-left) ->
			// top(bottom-left)
			path.addArc(top.getTopRight().x - corner, top.getTopRight().y, corner, corner, 0, 90);
			path.addArc(top.getTopLeft().x, top.getTopLeft().y, corner, corner, 90, 90);
			path.addArc(top.getBottomLeft().x, top.getBottomLeft().y - corner, corner, corner, 180, 90);
		} else if (hasAppendageTop) {
			// curved line around top(top-left) -> top(bottom-left)
			int appendageCorner = Math.min(corner, top.height * 2); // adjust
																	// for small
																	// sizes
			path.addArc(top.getTopLeft().x, top.getTopLeft().y, appendageCorner, appendageCorner, 90, 90);
			path.lineTo(top.getBottomLeft().x, top.getBottomLeft().y);
		} else { // !hasTop
			// curved line around right(top-left)
			path.addArc(right.getTopLeft().x, right.getTopLeft().y, corner, corner, 90, 90);
		}

		if (hasTop && hasRight) {
			// inside open curve connecting top and right
			path.addArc(right.getLeft().x - innerCorner, top.getBottom().y, innerCorner, innerCorner, 90, -90);
		}

		if (hasStandardRight) {
			if (bottom == null) {
				// curved line around right(bottom-left)
				path.addArc(right.getBottomLeft().x, right.getBottomLeft().y - corner, corner, corner, 180, 90);
			} else {
				// inside open curve connection right and bottom
				path.addArc(right.getLeft().x - innerCorner, bottom.getTop().y - innerCorner, innerCorner, innerCorner,
						0, -90);
				// curved line around bottom(top-left) -> bottom(bottom-left) ->
				// bottom(bottom-right)
				path.addArc(bottom.getTopLeft().x, bottom.getTopLeft().y, corner, corner, 90, 90);
				path.addArc(bottom.getBottomLeft().x, bottom.getBottomLeft().y - corner, corner, corner, 180, 90);
				path.addArc(bottom.getBottomRight().x - corner, bottom.getBottomRight().y - corner, corner, corner,
						270, 90);
				// outside open curve connection bottom and right
				path.addArc(bottom.getRight().x, right.getBottom().y, corner, corner, 180, -90);
			}

			// curved line around right(bottom-right) -> right(top-right)
			path.addArc(right.getBottomRight().x - corner, right.getBottomRight().y - corner, corner, corner, 270, 90);
			path.addArc(right.getTopRight().x - corner, right.getTopRight().y, corner, corner, 0, 90);
		} else if (hasAppendageRight) {
			// curved line around right(bottom-left) -> right(bottom-right)
			int appendageCorner = Math.min(corner, right.width * 2); // adjust
																		// for
																		// small
																		// sizes
			path.lineTo(right.getBottomLeft().x, right.getBottomLeft().y);
			path.addArc(right.getBottomRight().x - appendageCorner, right.getBottomRight().y - appendageCorner,
					appendageCorner, appendageCorner, 270, 90);
		} else { // !hasRight
			// close curved rectangle around top (bottom-right)
			path.addArc(top.getBottomRight().x - corner, top.getBottomRight().y - corner, corner, corner, 270, 90);
		}

		if (hasStandardTop && hasStandardRight) {
			// outside open curve connecting right and top (appendages have
			// direct line)
			path.addArc(top.getRight().x, right.getTop().y - corner, corner, corner, 270, -90);
		}

		path.close();

		return path;
	}

	/**
	 * Returns a rectangle, which is calculating from the given rectangle by
	 * shrinking it the given number of lines and scaling it with the
	 * zoom-level. Note, that this method also makes a transformation from
	 * java.awt.Rectangle to org.eclipse.draw2d.geometry.Rectangle.
	 * 
	 * @param source
	 *            The source rectangle from which to calculate the result.
	 * @param shrinkLines
	 *            The number of lines to shrink the rectangle.
	 * @return A rectangle, which is calculating from the given rectangle by
	 *         shrinking it the given number of lines and scaling it with the
	 *         zoom-level.
	 */
	private Rectangle transformGenericRectangle(java.awt.Rectangle source, int shrinkLines) {
		if (source == null) {
			return null;
		}

		double zoom = getZoomLevel();
		int lw = shrinkLines * ((int) (getDeclaration().getPadLineWidth() * zoom));

		Rectangle target = new Rectangle(source.x, source.y, source.width, source.height);
		target.scale(zoom);
		// shrink, but take care not to end up with a negative width or height
		int widthShrink = Math.min(target.width / 2, lw);
		int heightShrink = Math.min(target.height / 2, lw);
		target.shrink(widthShrink, heightShrink);
		return target;
	}

	// =========================== event handling =============================

	/**
	 * Registers the listeners, when the context button pad is shown (when it is
	 * added to its parent).
	 */
	@Override
	public void addNotify() {
		super.addNotify();

		Control control = diagramBehavior.getDiagramContainer().getGraphicalViewer().getControl();
		control.addMouseMoveListener(mouseMoveListener);
		control.addMouseTrackListener(mouseTrackListener);

		// TODO: discuss with Christian
		// If the animation is running, then dragging the shape does not work
		// correctly. The dragging is interrupted, when the context button pad
		// disappears.
		// It is still unclear why this happens.
		// Workaround: switch off animation or set a very short animation time
		// Another problem is, that the pad sometimes (rarely) flickers,
		// which becomes more visible with short animation times.

		// doAnimation();
	}

	/**
	 * Deregisters the listeners, when the context button pad is hidden (when it
	 * is removed from its parent).
	 */
	@Override
	public void removeNotify() {
		Control control = diagramBehavior.getDiagramContainer().getGraphicalViewer().getControl();
		control.removeMouseMoveListener(mouseMoveListener);
		control.removeMouseTrackListener(mouseTrackListener);

		super.removeNotify();
	}

	// ============================== painting ================================

	/**
	 * Outlines this Shape on the given Graphics. This will draw the paths
	 * {@link #pathInnerLine}, {@link #pathMiddleLine} and
	 * {@link #pathOuterLine}.
	 * 
	 * @param graphics
	 *            The Graphics on which to outline this Shape.
	 */
	@Override
	protected void outlineShape(Graphics graphics) {
		int lw = (int) (getZoomLevel() * getDeclaration().getPadLineWidth());
		graphics.setLineWidth(lw);

		Color innerLineSwtColor;
		Color middleLineSwtColor;
		Color outerLineSwtColor;
		Display display = Display.getCurrent();
		if (display == null) {
			display = Display.getDefault();
		}
		if (display.getHighContrast()) {
			innerLineSwtColor = display.getSystemColor(SWT.COLOR_WIDGET_FOREGROUND);
			middleLineSwtColor = display.getSystemColor(SWT.COLOR_WIDGET_FOREGROUND);
			outerLineSwtColor = display.getSystemColor(SWT.COLOR_WIDGET_FOREGROUND);
		} else {
			IColorConstant padInnerLineColor = getDeclaration().getPadInnerLineColor();
			innerLineSwtColor = DataTypeTransformation.toSwtColor(resourceRegistry, padInnerLineColor);

			IColorConstant padMiddleLineColor = getDeclaration().getPadMiddleLineColor();
			middleLineSwtColor = DataTypeTransformation.toSwtColor(resourceRegistry, padMiddleLineColor);

			IColorConstant padOuterLineColor = getDeclaration().getPadOuterLineColor();
			outerLineSwtColor = DataTypeTransformation.toSwtColor(resourceRegistry, padOuterLineColor);
		}

		graphics.setForegroundColor(innerLineSwtColor);
		graphics.drawPath(pathInnerLine);
		graphics.setForegroundColor(middleLineSwtColor);
		graphics.drawPath(pathMiddleLine);
		graphics.setForegroundColor(outerLineSwtColor);
		graphics.drawPath(pathOuterLine);
	}

	/**
	 * First initializes the given Graphics with settings like alpha-value,
	 * antialias-value, ... Afterwards calls
	 * <code>super.paintFigure(graphics)</code> to continue with the default
	 * painting mechanisms.
	 * 
	 * @param graphics
	 *            The Graphics on which to paint.
	 */
	@Override
	public void paintFigure(Graphics graphics) {
		graphics.setAntialias(SWT.ON);

		// double padDefaultOpacity = getDeclaration().getPadDefaultOpacity();
		// int endAlpha = (int) (padDefaultOpacity * 255.0);

		graphics.setAlpha((int) (currentTransparency * getDeclaration().getPadDefaultOpacity() * 255));

		createPathes();
		super.paintFigure(graphics);
		disposePathes();
	}

	/**
	 * Fills this Shape on the given Graphics. This will draw and fill the path
	 * {@link #pathFill}.
	 * 
	 * @param graphics
	 *            The Graphics on which to fill this Shape.
	 */
	@Override
	protected void fillShape(Graphics graphics) {
		int lw = (int) (getZoomLevel() * getDeclaration().getPadLineWidth());
		graphics.setLineWidth(lw);

		Color swtColor;
		Display display = Display.getCurrent();
		if (display == null) {
			display = Display.getDefault();
		}
		if (display.getHighContrast()) {
			swtColor = display.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND);
		} else {
			IColorConstant padFillColor = getDeclaration().getPadFillColor();
			swtColor = DataTypeTransformation.toSwtColor(resourceRegistry, padFillColor);
		}

		graphics.setForegroundColor(swtColor);
		graphics.setBackgroundColor(swtColor);
		graphics.drawPath(pathFill);
		graphics.fillPath(pathFill);
	}

	/**
	 * Increases the current transparency (see {@link #getCurrentTransparency()}
	 * ) in a loop and forces a repaint after each increase. As a result this
	 * will seem to the user as if the context button pad slowly 'fades in' from
	 * invisible to visible.
	 */
	@SuppressWarnings("unused")
	private void doAnimation() {
		// set start values for animation
		long startTime = System.currentTimeMillis();
		long stepsDone = 0;
		currentTransparency = ANIMATION_START_TRANSPARENCY;
		while (isPadShowing() && (currentTransparency < ANIMATION_END_TRANSPARENCY)) {
			// repaint context button pad with current transparency
			forceRepaint();
			stepsDone++;

			// increase current transparency (self adjusting algorithm)
			long elapsedTime = Math.max(1, System.currentTimeMillis() - startTime);
			long restTime = Math.max(1, animationDuration - elapsedTime);
			double restSteps = (((double) (stepsDone * restTime)) / elapsedTime);
			double deltaTransparency = (ANIMATION_END_TRANSPARENCY - currentTransparency) / restSteps;
			currentTransparency += deltaTransparency;
			if (elapsedTime > animationDuration) { // safeguard in case of
													// rounding errors
				currentTransparency = ANIMATION_END_TRANSPARENCY;
			}
		}

		// finally paint using the end transparency
		currentTransparency = ANIMATION_END_TRANSPARENCY;
		forceRepaint();
	}

	/**
	 * Forces a repaint of this figure, by first calling repaint() and then
	 * waiting until all UI events are processed.
	 */
	private void forceRepaint() {
		if (isPadShowing()) {
			repaint();
			while (Display.getCurrent().readAndDispatch()) {
				// do nothing
			}
		}
	}

	// ========================== helper methods ==============================

	/**
	 * Returns true, if the mouse is in the overlapping area of the context
	 * button pad. The overlapping area is the union of all overlapping
	 * rectangles (see
	 * {@link IContextButtonPadDeclaration#getOverlappingContainmentRectangles()}
	 * ).
	 */
	public boolean isMouseInOverlappingArea() {
		// determine mouse location in correct coordinates
		Point editorMouseLocation = new Point(diagramBehavior.getMouseLocation());
		Point viewPortMouseLocation = diagramBehavior.calculateRealMouseLocation(editorMouseLocation);
		Point mouseLocation = viewPortMouseLocation.scale(getZoomLevel());
		// hide if mouse location outside overlapping containment rectangles
		boolean containsPointOverlapping = containsPointOverlapping(mouseLocation.x, mouseLocation.y);
		if (!containsPointOverlapping) {
			getContextButtonManagerForPad().hideContextButtonsInstantly();
			return true;
		}
		return containsPointOverlapping;
	}

	public ContextButtonManagerForPad getContextButtonManagerForPad() {
		return contextButtonManagerForPad;
	}

	/**
	 * Returns true, if the given point is contained inside one of the visible
	 * parts of the context button pad. Note, that this is a much smaller area
	 * than the bounds of this shape, because the bounds are the outer invisible
	 * rectangle around all visible parts of the context button pad.
	 * <p>
	 * Technically this is the union of all containment rectangles (see
	 * {@link IContextButtonPadDeclaration#getContainmentRectangles()}).
	 * 
	 * @param x
	 *            The x-coordinate of the point to check.
	 * @param y
	 *            The y-coordinate of the point to check.
	 * @return true, if the given point is contained inside one of the visible
	 *         parts of the context button pad.
	 */
	@Override
	public boolean containsPoint(int x, int y) {
		boolean ret = false;
		for (Rectangle rectangle : containmentRectangles) {
			if (rectangle.contains(x, y)) {
				ret = true;
				break;
			}
		}
		return ret;
	}

	/**
	 * Returns true, if the given point is contained inside the overlapping area
	 * of all visible parts of the context button pad. Note, that this is a much
	 * smaller area than the bounds of this shape, because the bounds are the
	 * outer invisible rectangle around all visible parts of the context button
	 * pad.
	 * 
	 * @param x
	 *            The x-coordinate of the point to check.
	 * @param y
	 *            The y-coordinate of the point to check.
	 * @return true, if the given point is contained inside the overlapping area
	 *         of all visible parts of the context button pad.
	 */
	public boolean containsPointOverlapping(int x, int y) {
		boolean ret = false;
		for (Rectangle rectangle : overlappingContainmentRectangles) {
			if (rectangle.contains(x, y)) {
				ret = true;
				break;
			}
		}
		return ret;
	}

	/**
	 * Returns the current transparency as described in
	 * {@link ITransparencyProvider}.
	 * 
	 * @return The current transparency as described in
	 *         {@link ITransparencyProvider}.
	 */
	public double getCurrentTransparency() {
		return currentTransparency;
	}

	/**
	 * Returns true, if the pad is currently showing.
	 * 
	 * @return true, if the pad is currently showing.
	 */
	private boolean isPadShowing() {
		// returns true in the time, between addNotify() and removeNotify()
		boolean hasParent = getParent() != null;
		return hasParent;
	}
}
