/**
 * File:    GraphicalElementEditPartHelper.java
 * Created: 03.04.2006
 *
/*******************************************************************************
 * Copyright (c) 2005-2011
 * University of Augsburg, Germany <www.ds-lab.org>
 *
 * 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:
 *    Markus Bauer, Programming distributed Systems Lab, University of Augsburg 
 *    	- initial API and implementation
 *******************************************************************************/

package org.eclipse.jwt.we.parts.core;

import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPartListener;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.editparts.AbstractEditPart;
import org.eclipse.jwt.meta.model.core.GraphicalElement;
import org.eclipse.jwt.we.editors.WEEditor;
import org.eclipse.jwt.we.misc.views.LayoutDataManager;
import org.eclipse.jwt.we.model.view.Diagram;
import org.eclipse.jwt.we.model.view.LayoutData;
import org.eclipse.jwt.we.model.view.ViewPackage;

/**
 * Helper for an EditPart for a {@link GraphicalElement}.
 * 
 * <p>
 * This is not an EditPart because the GraphicalElement is inherited as multiple
 * inheritence. So this is only a helper to the real EditPart.
 * </p>
 * 
 * <p>
 * The helper (re-)places the figure of the EditPart on any changes of the size
 * and location. This is done when the {@link GraphicalElement#getSize() size}
 * or {@link GraphicalElement#getLocation() location} is set to a new value and
 * also if an internal value ({@link Point#getX() x}, {@link Point#getY() y},
 * {@link Dimension#getWidth() width} or {@link Dimension#getHeight() height})
 * changes.
 * </p>
 * 
 * <p>
 * The following methods from the EditPart must be delegated to the helper:
 * </p>
 * <ul>
 * <li>{@link AbstractEditPart#refreshVisuals}</li>
 * </ul>
 * 
 * @version $Id: GraphicalElementEditPartHelper.java,v 1.4.2.1 2009/01/20
 *          15:25:39 chsaad Exp $
 * @author Markus Bauer (markusbauer@users.sourceforge.net), Programming
 *         distributed Systems Lab, University of Augsburg, Germany,
 *         www.ds-lab.org
 */
public class GraphicalElementEditPartHelper extends AdapterImpl implements
		EditPartListener
{

	/**
	 * The EditPart this helper supports.
	 * 
	 * <p>
	 * Never <code>null</code>.
	 * </p>
	 */
	private final EditPart editPart;


	/**
	 * @param editPart
	 *            The EditPart this helper supports.
	 */
	public GraphicalElementEditPartHelper(EditPart editPart)
	{
		this.editPart = editPart;

		// this also asserts editPart != null
		editPart.addEditPartListener(this);
	}


	/**
	 * @return The model element.
	 */
	public GraphicalElement getModel()
	{
		return (GraphicalElement) editPart.getModel();
	}


	/**
	 * Adds this class as adapter to a notifier.
	 * 
	 * @param notifier
	 *            The notifier.
	 */
	private void addNotify(Notifier notifier)
	{
		if (notifier != null)
		{
			notifier.eAdapters().add(this);
		}
	}


	/**
	 * Removes this class from a notifier.
	 * 
	 * @param notifier
	 *            The notifier.
	 */
	private void removeNotify(Notifier notifier)
	{
		if (notifier != null)
		{
			notifier.eAdapters().remove(this);
		}
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.emf.common.notify.impl.AdapterImpl#notifyChanged(org.eclipse
	 * .emf.common .notify.Notification)
	 */
	@Override
	public void notifyChanged(Notification notification)
	{
		// if layoutdata changed, update visuals
		if (notification.getNotifier() instanceof LayoutData)
		{
			int featureId = notification.getFeatureID(LayoutData.class);

			switch (notification.getEventType())
			{
				case Notification.SET:
				case Notification.UNSET:
					switch (featureId)
					{
						case ViewPackage.LAYOUT_DATA__X:
						case ViewPackage.LAYOUT_DATA__Y:
						case ViewPackage.LAYOUT_DATA__WIDTH:
						case ViewPackage.LAYOUT_DATA__HEIGHT:
							refreshVisuals();
							break;
					}
			}
		}

		// if layoutdata added, update visuals
		if (notification.getNotifier() instanceof Diagram
				&& notification.getFeatureID(Diagram.class) == ViewPackage.DIAGRAM__LAYOUT_DATA)
		{
			refreshVisuals();
		}
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.gef.EditPartListener#partActivated(org.eclipse.gef.EditPart)
	 */
	public void partActivated(EditPart editpart)
	{
		addNotify(getModel());
		// addNotify(LayoutDataManager.getLayoutData(getModel()));
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.gef.EditPartListener#partDeactivated(org.eclipse.gef.EditPart
	 * )
	 */
	public void partDeactivated(EditPart editpart)
	{
		removeNotify(getModel());
		// removeNotify(LayoutDataManager.getLayoutData(getModel()));
	}


	/**
	 * Places the figure into its parent.
	 * 
	 * <p>
	 * The size and the location are set as contraints at the parent.
	 * </p>
	 */
	public void refreshVisuals()
	{
		if (!(editPart instanceof GraphicalEditPart))
		{
			// non GraphicalEditParts are not handled
			return;
		}

		IFigure figure = ((GraphicalEditPart) editPart).getFigure();

		WEEditor weeditor = ((GraphicalModelElementEditPart) editPart).getWEEditor();

		Rectangle figureBounds = new Rectangle(LayoutDataManager.getX(weeditor,
				getModel()), LayoutDataManager.getY(weeditor, getModel()), -1, -1);

		// make sure the figure has at least the size stored in the model
		// but not smaller than the preferred size
		figure.setMinimumSize(new org.eclipse.draw2d.geometry.Dimension(LayoutDataManager
				.getWidth(weeditor, getModel()), LayoutDataManager.getHeight(weeditor,
				getModel())));

		// this sets the location and size of the figure
		// if width and height are -1 the dimension is taken from
		// getPreferredSize()
		if (editPart.getParent() instanceof GraphicalEditPart)
		{
			((GraphicalEditPart) editPart.getParent()).setLayoutConstraint(editPart,
					figure, figureBounds);
		}
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.gef.EditPartListener#removingChild(org.eclipse.gef.EditPart,
	 * int)
	 */
	public void removingChild(EditPart child, int index)
	{
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.gef.EditPartListener#childAdded(org.eclipse.gef.EditPart,
	 * int)
	 */
	public void childAdded(EditPart child, int index)
	{
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.gef.EditPartListener#selectedStateChanged(org.eclipse.gef
	 * .EditPart)
	 */
	public void selectedStateChanged(EditPart editpart)
	{
	}
}
