/*******************************************************************************
 * <copyright>
 *
 * Copyright (c) 2005, 2013 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
 *
 * </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();

		// Notify the ContextButton children of this pad to free its resources
		// (holds a font). Introduced to fix bug 373298
		List<?> childrenList = getChildren();
		for (Object object : childrenList) {
			if (object instanceof ContextButton) {
				((ContextButton) object).dispose();
			}

		}
	}

	// ============================== 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;
	}
}
