/*******************************************************************************
 * Copyright (c) 2006, 2010 Soyatec (http://www.soyatec.com) 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:
 *     Soyatec - initial API and implementation
 *******************************************************************************/
package org.eclipse.xwt.tools.ui.designer.policies.layout;

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

import org.eclipse.draw2d.FigureListener;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.PositionConstants;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.xwt.tools.ui.palette.Entry;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPartListener;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.Request;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.commands.CompoundCommand;
import org.eclipse.gef.commands.UnexecutableCommand;
import org.eclipse.gef.editpolicies.LayoutEditPolicy;
import org.eclipse.gef.requests.ChangeBoundsRequest;
import org.eclipse.gef.requests.CreateRequest;
import org.eclipse.gef.requests.DropRequest;
import org.eclipse.gef.requests.ForwardedRequest;
import org.eclipse.gef.requests.GroupRequest;
import org.eclipse.swt.widgets.Display;
import org.eclipse.xwt.tools.ui.designer.commands.GridLayoutCommandsFactory;
import org.eclipse.xwt.tools.ui.designer.commands.NoOpCommand;
import org.eclipse.xwt.tools.ui.designer.editor.palette.CreateReqHelper;
import org.eclipse.xwt.tools.ui.designer.editor.palette.EntryHelper;
import org.eclipse.xwt.tools.ui.designer.layouts.LayoutType;
import org.eclipse.xwt.tools.ui.designer.parts.CompositeEditPart;
import org.eclipse.xwt.tools.ui.designer.parts.MenuBarEditPart;
import org.eclipse.xwt.tools.ui.designer.policies.NewNonResizeEditPolicy;
import org.eclipse.xwt.tools.ui.designer.policies.NewResizableEditPolicy;
import org.eclipse.xwt.tools.ui.designer.policies.feedback.FeedbackHelper;
import org.eclipse.xwt.tools.ui.designer.policies.feedback.FeedbackManager;
import org.eclipse.xwt.tools.ui.designer.policies.layout.grid.GridController;
import org.eclipse.xwt.tools.ui.designer.policies.layout.grid.GridLayoutAddedCellFeedbackFigure;
import org.eclipse.xwt.tools.ui.designer.policies.layout.grid.GridLayoutColumnFigure;
import org.eclipse.xwt.tools.ui.designer.policies.layout.grid.GridLayoutFeedbackFigure;
import org.eclipse.xwt.tools.ui.designer.policies.layout.grid.GridLayoutGridFigure;
import org.eclipse.xwt.tools.ui.designer.policies.layout.grid.GridLayoutPolicyHelper;
import org.eclipse.xwt.tools.ui.designer.policies.layout.grid.GridLayoutRequest;
import org.eclipse.xwt.tools.ui.designer.policies.layout.grid.GridLayoutRowFigure;
import org.eclipse.xwt.tools.ui.designer.policies.layout.grid.GridLayoutSpanFeedbackFigure;
import org.eclipse.xwt.tools.ui.designer.policies.layout.grid.GridSpanHandle;
import org.eclipse.xwt.tools.ui.designer.policies.layout.grid.IGridListener;
import org.eclipse.xwt.tools.ui.xaml.XamlNode;

/**
 * @author jliu jin.liu@soyatec.com
 */
public class GridLayoutEditPolicy extends LayoutEditPolicy implements
		IGridListener, ILayoutEditPolicy {

	public static final String REQ_GRIDLAYOUT_SPAN = "GridLayout span cells"; //$NON-NLS-1$

	public static final int DEFAULT_CELL_WIDTH = 40;
	public static final int DEFAULT_CELL_HEIGHT = 35;
	private static final int ADDEDCELLBORDER = 3; // How much to expand cell for
													// added cell to draw the
													// new border.
	private GridController gridController;
	private boolean fShowGrid = false;
	private GridLayoutGridFigure fGridLayoutGridFigure;
	private GridLayoutSpanFeedbackFigure fGridLayoutSpanFigure;
	private GridLayoutFeedbackFigure fGridLayoutCellFigure;
	private IFigure fRowColFigure = null;
	private EditPartListener editPartListener;
	private GridLayoutPolicyHelper helper = new GridLayoutPolicyHelper();

	private FeedbackManager fbm = new FeedbackManager(this);

	protected FigureListener hostFigureListener = new FigureListener() {
		public void figureMoved(IFigure source) {
			refresh();
		}
	};

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.gef.editpolicies.LayoutEditPolicy#activate()
	 */
	public void activate() {
		helper.setHost((CompositeEditPart) getHost());
		gridController = new GridController();
		GridController.registerEditPart(getHost(), gridController);
		gridController.addGridListener(this);
		getHostFigure().addFigureListener(hostFigureListener);
		if (getHost().getSelected() == EditPart.SELECTED
				|| getHost().getSelected() == EditPart.SELECTED_PRIMARY) {
			gridController.setGridShowing(true);
		}
		editPartListener = createEditPartListener();
		getHost().addEditPartListener(editPartListener);
		List children = getHost().getChildren();
		Iterator iterator = children.iterator();
		while (iterator.hasNext())
			((EditPart) iterator.next()).addEditPartListener(editPartListener);
		super.activate();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.gef.editpolicies.LayoutEditPolicy#createChildEditPolicy(org
	 * .eclipse.gef.EditPart)
	 */
	protected EditPolicy createChildEditPolicy(EditPart child) {
		if (child instanceof MenuBarEditPart) {
			return new NewNonResizeEditPolicy(false);
		}
		// return new NonResizableSpannableEditPolicy(this);
		return new NewResizableEditPolicy(PositionConstants.SOUTH
				| PositionConstants.EAST, true);
	}

	private EditPartListener createEditPartListener() {
		return new EditPartListener.Stub() {
			public void childAdded(EditPart editpart, int index) {
				if (editPartListener != null)
					editpart.addEditPartListener(editPartListener);
				helper.refresh();
				refreshGridFigure();
			}

			public void removingChild(EditPart editpart, int index) {
				if (editPartListener != null)
					editpart.removeEditPartListener(editPartListener);
				helper.refresh();
				refreshGridFigure();
			}

			public void selectedStateChanged(EditPart editpart) {
				if ((editpart == null)
						|| (editpart == getHost())
						|| (isChildEditPart(editpart))
						&& (editpart.getSelected() == EditPart.SELECTED || editpart
								.getSelected() == EditPart.SELECTED_PRIMARY)) {
					if (gridController != null) {
						gridController.setGridShowing(true);
					} else {
						if (gridController != null)
							gridController.setGridShowing(false);
					}
				} else {
					// Hide the grid just in case we were show before and
					// changed the prefs
					if (gridController != null
							&& gridController.isGridShowing())
						gridController.setGridShowing(false);
				}
			}
		};
	}

	private GridLayoutRequest createGridLayoutRequest(Point position) {
		return getGridLayoutGridFigure().getGridLayoutRequest(position, helper);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.gef.editpolicies.LayoutEditPolicy#deactivate()
	 */
	public void deactivate() {

		GridController gridController = GridController
				.getGridController(getHost());
		eraseGridFigure();
		if (gridController != null) {
			gridController.removeGridListener(this);
			GridController.unregisterEditPart(getHost());
		}

		getHostFigure().removeFigureListener(hostFigureListener);
		if (editPartListener != null) {
			getHost().removeEditPartListener(editPartListener);
			List children = getHost().getChildren();
			Iterator iterator = children.iterator();
			while (iterator.hasNext())
				((EditPart) iterator.next())
						.removeEditPartListener(editPartListener);
			editPartListener = null;
		}
		super.deactivate();
	}

	/**
	 * erase grid figure.
	 */
	private void eraseGridFigure() {
		if (fGridLayoutGridFigure != null) {
			if (fGridLayoutGridFigure.getParent() != null)
				removeFeedback(fGridLayoutGridFigure);
			fGridLayoutGridFigure = null;
		}
		fShowGrid = false;
	}

	public void eraseTargetFeedback(Request request) {
		fbm.eraseFeedback(request);
		if (!fShowGrid)
			if (fGridLayoutGridFigure != null) {
				if (fGridLayoutGridFigure.getParent() != null)
					removeFeedback(fGridLayoutGridFigure);
				fGridLayoutGridFigure = null;
			}
		if (fGridLayoutSpanFigure != null) {
			removeFeedback(fGridLayoutSpanFigure);
			fGridLayoutSpanFigure = null;
		}
		if (fGridLayoutCellFigure != null) {
			removeFeedback(fGridLayoutCellFigure);
			fGridLayoutCellFigure = null;
		}
		if (fRowColFigure != null) {
			removeFeedback(fRowColFigure);
			fRowColFigure = null;
		}
		super.eraseTargetFeedback(request);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.gef.editpolicies.LayoutEditPolicy#getCommand(org.eclipse.
	 * gef.Request)
	 */
	public Command getCommand(Request request) {
		// if (REQ_GRIDLAYOUT_SPAN.equals(request.getType())) {
		// return getSpanChildrenCommand(request);
		// }
		if (REQ_RESIZE_CHILDREN.equals(request.getType())) {
			return getResizeCommand(request);
		}
		return super.getCommand(request);
	}

	private Command getResizeCommand(Request request) {
		ChangeBoundsRequest req = (ChangeBoundsRequest) request;
		CompoundCommand resize = new CompoundCommand();
		Command c;
		GraphicalEditPart child;
		List children = req.getEditParts();

		for (int i = 0; i < children.size(); i++) {
			child = (GraphicalEditPart) children.get(i);
			c = createResizeChildrenCommand(request, child, req.getSizeDelta());
			resize.add(c);
		}
		return resize.unwrap();
	}

	protected Command createResizeChildrenCommand(Request request,
			EditPart child, Object newSize) {
		GridLayoutCommandsFactory factory = new GridLayoutCommandsFactory(
				(CompositeEditPart) getHost());
		return factory.getResizeChildrenCommand(child,
				(ChangeBoundsRequest) request);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.gef.editpolicies.LayoutEditPolicy#getAddCommand(org.eclipse
	 * .gef.Request)
	 */
	protected Command getAddCommand(Request request) {
		return getMoveChildrenCommand(request);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.gef.editpolicies.LayoutEditPolicy#getCreateCommand(org.eclipse
	 * .gef.requests.CreateRequest)
	 */
	protected Command getCreateCommand(CreateRequest request) {
		CreateReqHelper reqHelper = new CreateReqHelper(request);
		if (!reqHelper.canCreate(getHost())) {
			return null;
		}
		if (fGridLayoutGridFigure == null) {
			// TODO: Maybe create layout here.
			return UnexecutableCommand.INSTANCE;
		}

		Point position = getLocationFromRequest(request).getCopy();
		GridLayoutRequest gridReq = createGridLayoutRequest(position);
		Point cell = new Point(gridReq.column, gridReq.row);

		Entry entry = (Entry) request.getNewObject();
		XamlNode newObject = EntryHelper.getNode(entry);
		if (newObject == null) {
			return UnexecutableCommand.INSTANCE;
		}
		Object requestType = request.getType();
		helper.startRequest();
		switch (gridReq.type) {
		case GridLayoutRequest.REPLACE_FILLER:
			helper.replaceFiller(newObject, requestType, cell);
			break;
		case GridLayoutRequest.INSERT_COLUMN_WITHIN_ROW:
			helper.insertColWithinRow(cell);
			helper.replaceFillerOrEmpty(newObject, requestType, cell);
			break;
		case GridLayoutRequest.INSERT_COLUMN:
		case GridLayoutRequest.ADD_COLUMN:
			helper.createNewCol(cell.x);
			helper.replaceFillerOrEmpty(newObject, requestType, cell);
			break;
		case GridLayoutRequest.INSERT_ROW:
		case GridLayoutRequest.ADD_ROW:
			helper.createNewRow(cell.y);
			helper.replaceFillerOrEmpty(newObject, requestType, cell);
			break;
		case GridLayoutRequest.ADD_TO_EMPTY_CELL:
			helper.replaceEmptyCell(newObject, requestType, cell);
			break;
		case GridLayoutRequest.ADD_ROW_COL:
			cell.setLocation(helper.getNumColumns(), helper.getNumRows());
			helper.createNewCol(cell.x);
			if (cell.x != 0 || cell.y != 0)
				helper.createNewRow(cell.y); // If other than (0,0) for add row
												// col, we need a new row. If it
												// was (0,0) then we are adding
												// the first entry to the grid.
			helper.replaceFillerOrEmpty(newObject, requestType, cell);
			break;
		case GridLayoutRequest.NO_ADD:
			return UnexecutableCommand.INSTANCE;
		}

		Command result = helper.stopRequest();
		return result;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.gef.editpolicies.LayoutEditPolicy#getDeleteDependantCommand
	 * (org.eclipse.gef.Request)
	 */
	protected Command getDeleteDependantCommand(Request request) {
		// Get the commands to insert filler labels into the cells where the
		// control used to be
		if (request instanceof ForwardedRequest) {
			EditPart editPart = ((ForwardedRequest) request).getSender();
			if (editPart instanceof CompositeEditPart) {
				helper.setHost((CompositeEditPart) editPart);
				helper.startRequest();
				helper.deleteChild((XamlNode) editPart.getModel());
				return helper.stopRequest();
			}
		}
		return UnexecutableCommand.INSTANCE;
	}

	protected Command getOrphanChildrenCommand(Request request) {
		// Get the commands to insert filler labels into the cells where the
		// control used to be
		if (request instanceof GroupRequest) {
			helper.startRequest();
			List children = getChildren((GroupRequest) request);
			helper.orphanChildren(children);
			return helper.stopRequest();
		} else
			return UnexecutableCommand.INSTANCE;
	}

	public List getChildren(GroupRequest request) {
		List cEP = request.getEditParts();
		List children = new ArrayList(cEP.size());
		Iterator itr = cEP.iterator();
		while (itr.hasNext()) {
			Object child = ((EditPart) itr.next()).getModel();
			children.add(child);
		}
		return children;
	}

	public Rectangle getFullCellBounds(EditPart child) {
		if (getGridLayoutGridFigure() == null)
			return new Rectangle();
		Rectangle dims = helper.getChildDimensions((EObject) child.getModel());
		Rectangle bounds;
		if (dims != null) {
			bounds = getGridLayoutGridFigure()
					.getGridBroundsForCellBounds(dims);
		} else
			bounds = new Rectangle();

		return bounds;
	}

	protected GridLayoutGridFigure getGridLayoutGridFigure() {
		if (fGridLayoutGridFigure == null) {
			fGridLayoutGridFigure = new GridLayoutGridFigure(helper);
		}
		return fGridLayoutGridFigure;
	}

	/**
	 * @return the helper
	 */
	public GridLayoutPolicyHelper getHelper() {
		return helper;
	}

	/*
	 * this gets the location from the request and then makes it absolute
	 * (relative to the bounds of the host figure). If we didn't do this the
	 * point is relative to the viewport that is displayed, not absolute wrt to
	 * the entire canvas.
	 */
	private Point getLocationFromRequest(Request request) {
		Point loc = ((DropRequest) request).getLocation().getCopy();
		getHostFigure().translateToRelative(loc);
		return loc;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.gef.editpolicies.LayoutEditPolicy#getMoveChildrenCommand(
	 * org.eclipse.gef.Request)
	 */
	protected Command getMoveChildrenCommand(Request request) {
		if (fGridLayoutGridFigure == null
				|| !(request instanceof ChangeBoundsRequest))
			return UnexecutableCommand.INSTANCE;
		ChangeBoundsRequest req = (ChangeBoundsRequest) request;
		List editparts = req.getEditParts();
		// Only allow one object to be moved
		if (editparts.size() > 1)
			return UnexecutableCommand.INSTANCE;

		XamlNode trueEObject = (XamlNode) ((EditPart) editparts.get(0))
				.getModel();
		if (trueEObject == null) {
			return UnexecutableCommand.INSTANCE;
		}

		Point position = getLocationFromRequest(request).getCopy();
		GridLayoutRequest gridReq = createGridLayoutRequest(position);
		Point cell = new Point(gridReq.column, gridReq.row);

		Object requestType = request.getType();

		helper.startRequest();
		switch (gridReq.type) {
		case GridLayoutRequest.REPLACE_FILLER:
			helper.replaceFiller(trueEObject, requestType, cell);
			break;
		case GridLayoutRequest.INSERT_COLUMN_WITHIN_ROW:
			helper.insertColWithinRow(cell);
			helper.replaceFillerOrEmpty(trueEObject, requestType, cell);
			break;
		case GridLayoutRequest.INSERT_COLUMN:
		case GridLayoutRequest.ADD_COLUMN:
			helper.createNewCol(cell.x);
			helper.replaceFillerOrEmpty(trueEObject, requestType, cell);
			break;
		case GridLayoutRequest.INSERT_ROW:
		case GridLayoutRequest.ADD_ROW:
			helper.createNewRow(cell.y);
			helper.replaceFillerOrEmpty(trueEObject, requestType, cell);
			break;
		case GridLayoutRequest.ADD_TO_EMPTY_CELL:
			helper.replaceEmptyCell(trueEObject, requestType, cell);
			break;
		case GridLayoutRequest.ADD_ROW_COL:
			cell.setLocation(helper.getNumColumns(), helper.getNumRows());
			helper.createNewCol(cell.x);
			if (cell.x != 0 || cell.y != 0)
				helper.createNewRow(cell.y); // If other than (0,0) for add row
												// col, we need a new row. If it
												// was (0,0) then we are adding
												// the first entry to the grid.
			helper.replaceFillerOrEmpty(trueEObject, requestType, cell);
			break;
		case GridLayoutRequest.NO_ADD:
			return UnexecutableCommand.INSTANCE;
		}

		Command command = helper.stopRequest();
		return command;
	}

	protected Command getSpanChildrenCommand(Request generic) {
		ChangeBoundsRequest request = (ChangeBoundsRequest) generic;
		List editParts = request.getEditParts();
		if (editParts.isEmpty() || editParts.size() > 1)
			return UnexecutableCommand.INSTANCE;

		// Get the cell location that the mouse was dragged to
		Point spanToPosition = getLocationFromRequest(request).getCopy();
		Point spanToCellLocation = getGridLayoutGridFigure().getCellLocation(
				spanToPosition.x, spanToPosition.y);
		// Get the cell location where we started the drag operation
		Dimension dim = request.getSizeDelta();
		int handleSizeOffset = GridSpanHandle.HANDLE_SIZE / 2;
		Point startPosition = new Point(spanToPosition.x - dim.width
				- handleSizeOffset, spanToPosition.y - dim.height
				- handleSizeOffset);
		// Get the cell location of the child component
		GraphicalEditPart ep = (GraphicalEditPart) editParts.get(0);
		EObject child = (EObject) ep.getModel();
		Point childCellLocation = helper.getChildDimensions(child)
				.getLocation();
		Point startCellLocation = getGridLayoutGridFigure().getCellLocation(
				startPosition);
		// If the cell location where the pointer is located is different from
		// the original cell location where we started,
		// create the commands to change the gridwidth or gridheight
		if ((spanToCellLocation.x >= childCellLocation.x && spanToCellLocation.y >= childCellLocation.y)
				&& (spanToCellLocation.x != startCellLocation.x || spanToCellLocation.y != startCellLocation.y)) {
			// Let the helper get the gridWidth or gridHeight commands based on
			// the cell location
			// where the pointer is and the span direction (EAST for gridwidth
			// or SOUTH for gridheight)
			helper.startRequest();
			helper.spanChild(child, new Point(spanToCellLocation.x
					- childCellLocation.x + 1, spanToCellLocation.y
					- childCellLocation.y + 1), request.getResizeDirection(),
					null);
			return helper.stopRequest();
		}
		return NoOpCommand.INSTANCE;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @seeorg.soyatec.xaml.ve.xwt.editpolicies.gridlayout.IGridListener#
	 * gridHeightChanged(int, int)
	 */
	public void gridHeightChanged(int gridHeight, int oldGridHeight) {
		// do nothing
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @seeorg.soyatec.xaml.ve.xwt.editpolicies.gridlayout.IGridListener#
	 * gridMarginChanged(int, int)
	 */
	public void gridMarginChanged(int gridMargin, int oldGridMargin) {
		// do nothing
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @seeorg.soyatec.xaml.ve.xwt.editpolicies.gridlayout.IGridListener#
	 * gridVisibilityChanged(boolean)
	 */
	public void gridVisibilityChanged(boolean showGrid) {
		if (showGrid) {
			showGridFigure();
		} else {
			eraseGridFigure();
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @seeorg.soyatec.xaml.ve.xwt.editpolicies.gridlayout.IGridListener#
	 * gridWidthChanged(int, int)
	 */
	public void gridWidthChanged(int gridWidth, int oldGridWidth) {
		// do nothing
	}

	/*
	 * Return true if ep is a child editpart of the host container
	 */
	private boolean isChildEditPart(EditPart ep) {
		if (ep != null) {
			List children = getHost().getChildren();
			if (!children.isEmpty())
				return (children.indexOf(ep) != -1);
		}
		return false;
	}

	/**
	 * 
	 */
	protected void refreshGridFigure() {
		Display.getDefault().asyncExec(new Runnable() {
			public void run() {
				if (fShowGrid) {
					eraseGridFigure();
					showGridFigure();
				} else {
					fGridLayoutGridFigure = null;
				}
			}
		});
	}

	/**
	 * Show the adding cell outside figure feedback.
	 * 
	 * @param cellBounds
	 * 
	 * @since 1.2.0
	 */
	protected void showAddedCellFeedback(Rectangle cellBounds) {
		cellBounds = cellBounds.getExpanded(cellBounds.width < 10 ? 20 : 0,
				cellBounds.height < 10 ? 20 : 0);
		fRowColFigure = new GridLayoutAddedCellFeedbackFigure();
		fRowColFigure.setBounds(cellBounds);
		addFeedback(fRowColFigure);
	}

	/**
	 * Show a new yellow column inserted into the grid near the column closest
	 * to position and only within that row
	 */
	protected void showColumnFeedBackWithinARow(Rectangle cellBounds) {
		cellBounds = cellBounds.getCopy();
		cellBounds.x -= 3; // start to the right by three from side of cell.
		cellBounds.width = 6; // But only six wide. So it will be centered over
								// the right side of the cell.
		fRowColFigure = new GridLayoutColumnFigure(cellBounds);
		addFeedback(fRowColFigure);
	}

	/**
	 * Show grid figure.
	 */
	private void showGridFigure() {
		if (!fShowGrid) {
			fShowGrid = true;
			addFeedback(getGridLayoutGridFigure());
		}
		fShowGrid = true;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.gef.editpolicies.LayoutEditPolicy#showTargetFeedback(org.
	 * eclipse.gef.Request)
	 */
	public void showTargetFeedback(Request request) {
		if (!(REQ_CREATE.equals(request.getType())
				&& request instanceof CreateRequest && FeedbackHelper
				.showCreationFeedback(fbm, (CreateRequest) request))) {
			super.showTargetFeedback(request);
		}
	}

	/**
	 * Shows an insertion line if there is one or more current children.
	 */
	protected void showLayoutTargetFeedback(Request request) {
		if (!(REQ_CREATE.equals(request.getType()) && FeedbackHelper
				.showCreationFeedback(fbm, (CreateRequest) request))) {
			super.showLayoutTargetFeedback(request);
		}
		if (!fShowGrid)
			addFeedback(getGridLayoutGridFigure());

		if (fRowColFigure != null) {
			removeFeedback(fRowColFigure);
			fRowColFigure = null;
		}

		if (fGridLayoutCellFigure != null) {
			removeFeedback(fGridLayoutCellFigure);
			fGridLayoutCellFigure = null;
		}

		Point position = getLocationFromRequest(request).getCopy();
		GridLayoutRequest gridReq = createGridLayoutRequest(position);

		Point cell = new Point(gridReq.column, gridReq.row);
		Rectangle cellBounds = getGridLayoutGridFigure().getCellBounds(cell);

		// Calculate the bounds of the target cell figure based on whether a
		// column is added,
		// row is added, or it's inserted before another control.
		switch (gridReq.type) {
		case GridLayoutRequest.INSERT_COLUMN:
			// If a column is added, show the target figure in between the two
			// columns
			showNewColumnFeedBack(gridReq.column);
			Rectangle colFigBounds = fRowColFigure.getBounds();
			// mapModelToFigure(cellBounds);
			cellBounds.width = DEFAULT_CELL_WIDTH;
			if (cellBounds.height < 10)
				cellBounds.expand(0, 20);
			cellBounds.x = colFigBounds.x + colFigBounds.width / 2
					- cellBounds.width / 2;
			break;
		case GridLayoutRequest.INSERT_ROW:
			// If a row is added, show the target figure in between the two rows
			showNewRowFeedBack(gridReq.row);
			Rectangle rowFigBounds = fRowColFigure.getBounds();
			// mapModelToFigure(cellBounds);
			cellBounds.height = DEFAULT_CELL_HEIGHT;
			if (cellBounds.width < 10)
				cellBounds.expand(20, 0);
			cellBounds.y = rowFigBounds.y + rowFigBounds.height / 2
					- cellBounds.height / 2;
			break;
		case GridLayoutRequest.INSERT_COLUMN_WITHIN_ROW:
			// In case cell is spanned vertically we need to have the complete
			// cellbounds.
			showColumnFeedBackWithinARow(cellBounds);
			// mapModelToFigure(cellBounds);
			colFigBounds = fRowColFigure.getBounds();
			cellBounds.width = DEFAULT_CELL_WIDTH;
			if (cellBounds.height < 10)
				cellBounds.expand(0, 20);
			cellBounds.x = colFigBounds.x + colFigBounds.width / 2
					- cellBounds.width / 2;
			break;
		case GridLayoutRequest.ADD_COLUMN:
		case GridLayoutRequest.ADD_ROW:
		case GridLayoutRequest.ADD_ROW_COL:
			showAddedCellFeedback(cellBounds);
			colFigBounds = fRowColFigure.getBounds();
			// Center the cell within these bounds.
			cellBounds = colFigBounds.getCopy().shrink(ADDEDCELLBORDER,
					ADDEDCELLBORDER);
			break;
		case GridLayoutRequest.NO_ADD:
			return; // No feedback.
		default:
			// mapModelToFigure(cellBounds.expand(cellBounds.width < 10 ? 20 :
			// 0, cellBounds.height < 10 ? 20 : 0));
			break;
		}

		if (fGridLayoutCellFigure == null) {
			fGridLayoutCellFigure = new GridLayoutFeedbackFigure();
		}
		fGridLayoutCellFigure.setBounds(cellBounds);
		addFeedback(fGridLayoutCellFigure);
	}

	/**
	 * Show a new yellow column inserted into the grid near the column closest
	 * to position
	 */
	protected void showNewColumnFeedBack(int col) {
		Rectangle rect = fGridLayoutGridFigure.getColumnRectangle(col);
		rect.x -= 3;
		rect.width = 6;
		fRowColFigure = new GridLayoutColumnFigure(rect);
		addFeedback(fRowColFigure);
	}

	/**
	 * Show a new yellow row inserted into the grid near the row closest to
	 * position
	 */
	protected void showNewRowFeedBack(int row) {
		Rectangle rect = fGridLayoutGridFigure.getRowRectangle(row);
		rect.translate(-2, -3);
		rect.width += 4;
		rect.height = 6;
		fRowColFigure = new GridLayoutRowFigure(rect);
		addFeedback(fRowColFigure);
	}

	/*
	 * Show target feedback when dragging the span handles of a component.
	 * Highlight the cells the component will occupy based on the begining cell
	 * position and end cell position of the pointer.
	 */
	public void showSpanTargetFeedback(ChangeBoundsRequest request) {
		// If the grid is not on, turn it on
		if (!fShowGrid)
			addFeedback(getGridLayoutGridFigure());

		Point spanToPosition = request.getLocation().getCopy();

		// Get the cell location of the child component
		GraphicalEditPart ep = (GraphicalEditPart) request.getEditParts()
				.get(0);
		EObject child = (EObject) ep.getModel();
		Rectangle childDim = getHelper().getChildDimensions(child);

		// Get the start and end cell bounds in order to determine the entire
		// bounds of the cell feedback figure.
		Rectangle startCellBounds = getGridLayoutGridFigure().getCellBounds(
				childDim.getLocation());
		Rectangle endCellChildBounds = getGridLayoutGridFigure().getCellBounds(
				childDim.getBottomRight().translate(-1, -1)); // This is the
																// lower right
																// of the child
																// itself.
		if (request.getResizeDirection() == PositionConstants.EAST
				|| request.getResizeDirection() == PositionConstants.WEST) {
			spanToPosition.y = endCellChildBounds.y; // This forces us to not
														// span north/south when
														// going east/west. And
														// it will make it tall
														// enough that entire
														// cell spanned height
														// is covered.
		} else {
			spanToPosition.x = endCellChildBounds.x + endCellChildBounds.width
					- 1; // This forces us to not span left/right when going
							// north/south. And it will make it wide enough that
							// entire cell spanned width is covered.
		}
		Rectangle endCellBounds = getGridLayoutGridFigure().getCellBounds(
				getGridLayoutGridFigure().getCellLocation(spanToPosition));
		if (endCellBounds == null || endCellBounds.x < startCellBounds.x
				|| endCellBounds.y < startCellBounds.y) {
			// End is not within a cell, or the end is before the start cell.
			if (fGridLayoutSpanFigure != null) {
				removeFeedback(fGridLayoutSpanFigure);
				fGridLayoutSpanFigure = null;
			}
			return;
		}

		Rectangle spanrect = startCellBounds.union(endCellBounds)
				.resize(-1, -1);
		if (fGridLayoutSpanFigure == null) {
			fGridLayoutSpanFigure = new GridLayoutSpanFeedbackFigure(request
					.getResizeDirection());
		}
		fGridLayoutSpanFigure.setLayoutFigureBounds(spanrect);
		addFeedback(fGridLayoutSpanFigure);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.xwt.tools.ui.designer.policies.layout.ILayoutEditPolicy
	 * #refresh()
	 */
	public void refresh() {
		helper.refresh();
		refreshGridFigure();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.xwt.tools.ui.designer.policies.layout.ILayoutEditPolicy
	 * #getType()
	 */
	public LayoutType getType() {
		return LayoutType.GridLayout;
	}

}
