blob: b9fe7b2e7e79c8fd1178c4ef4a767a79d1d2bcd6 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2010 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.gef.editpolicies;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.Request;
import org.eclipse.gef.TreeEditPart;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.requests.ChangeBoundsRequest;
import org.eclipse.gef.requests.CreateRequest;
import org.eclipse.gef.requests.DropRequest;
/**
* An EditPolicy for handling ADDS, MOVES, and CREATES on a {@link TreeEditPart}
* .
* <P>
* This EditPolicy is responsible for displaying the insertion feedback in the
* Tree during the appropriate interactions.
* <P>
* This EditPolicy factors the {@link #getCommand(Request)} into three different
* abstract methods which subclasses must implement.
*
* @since 2.0
*/
public abstract class TreeContainerEditPolicy extends AbstractEditPolicy {
/**
* Returns a Command for adding the children to the container.
*
* @param request
* the Request to add.
* @return Command <code>null</code> or a Command to perform the add
*/
protected abstract Command getAddCommand(ChangeBoundsRequest request);
/**
* Returns a Command for creating the object inside the container.
*
* @param request
* the CreateRequest
* @return Command <code>null</code> or a Command to perform the create
*/
protected abstract Command getCreateCommand(CreateRequest request);
/**
* Returns a Command for moving the children within the container.
*
* @param request
* the Request to move
* @return Command <code>null</code> or a Command to perform the move
*/
protected abstract Command getMoveChildrenCommand(
ChangeBoundsRequest request);
private void eraseDropFeedback(Request req) {
// UNSUPPORTED - api not implemented in RAP
// getTree().setInsertMark(null, true);
}
/**
* @see org.eclipse.gef.EditPolicy#eraseTargetFeedback(Request)
*/
public void eraseTargetFeedback(Request req) {
if (req.getType().equals(REQ_MOVE) || req.getType().equals(REQ_ADD)
|| req.getType().equals(REQ_CREATE))
eraseDropFeedback(req);
}
/**
* Calculates the index of the TreeItem at given point.
*
* @param pt
* the Point in the Viewer
* @return the index of the TreeItem
*/
protected final int findIndexOfTreeItemAt(
org.eclipse.draw2d.geometry.Point pt) {
int index = -1;
TreeItem item = findTreeItemAt(pt);
if (item != null) {
index = getHost().getChildren().indexOf(item.getData());
if (index >= 0 && !isInUpperHalf(item.getBounds(), pt))
index++;
}
return index;
}
/**
* Calculates the <code>TreeItem</code> at a specified
* {@link org.eclipse.draw2d.geometry.Point}.
*
* @param pt
* the draw2d Point
* @return <code>null</code> or the TreeItem
*/
protected final TreeItem findTreeItemAt(org.eclipse.draw2d.geometry.Point pt) {
return getTree().getItem(new Point(pt.x, pt.y));
}
/**
* @see org.eclipse.gef.EditPolicy#getCommand(Request)
*/
public Command getCommand(Request req) {
if (req.getType().equals(REQ_MOVE_CHILDREN))
return getMoveChildrenCommand((ChangeBoundsRequest) req);
if (req.getType().equals(REQ_ADD))
return getAddCommand((ChangeBoundsRequest) req);
if (req.getType().equals(REQ_CREATE))
return getCreateCommand((CreateRequest) req);
return null;
}
/**
* Returns the host EditPart when appropriate. Targeting is done by checking
* if the mouse is clearly over the host's TreeItem.
*
* @see org.eclipse.gef.EditPolicy#getTargetEditPart(Request)
*/
public EditPart getTargetEditPart(Request req) {
if (req.getType().equals(REQ_ADD) || req.getType().equals(REQ_MOVE)
|| req.getType().equals(REQ_CREATE)) {
DropRequest drop = (DropRequest) req;
Point where = new Point(drop.getLocation().x, drop.getLocation().y);
Widget widget = ((TreeEditPart) getHost()).getWidget();
if (widget instanceof Tree)
return getHost();
TreeItem treeitem = (TreeItem) widget;
Rectangle bounds = treeitem.getBounds();
int fudge = bounds.height / 5;
Rectangle inner = new Rectangle(bounds.x, bounds.y + fudge,
bounds.width, bounds.height
- (treeitem.getExpanded() ? 0 : fudge * 2));
// Point is either outside the Treeitem, or inside the inner Rect.
if (!bounds.contains(where) || inner.contains(where))
return getHost();
}
return null;
}
private Tree getTree() {
Widget widget = ((TreeEditPart) getHost()).getWidget();
if (widget instanceof Tree)
return (Tree) widget;
else
return ((TreeItem) widget).getParent();
}
private void insertMarkAfterLastChild(TreeItem[] children) {
if (children != null && children.length > 0) {
TreeItem item = children[children.length - 1];
// UNSUPPORTED - api not implemented in RAP
// getTree().setInsertMark(item, false);
}
}
private boolean isInUpperHalf(Rectangle rect,
org.eclipse.draw2d.geometry.Point pt) {
Rectangle tempRect = new Rectangle(rect.x, rect.y, rect.width,
rect.height / 2);
return tempRect.contains(new Point(pt.x, pt.y));
}
private void showDropFeedback(DropRequest request) {
Widget hostWidget = ((TreeEditPart) getHost()).getWidget();
Tree tree = getTree();
org.eclipse.draw2d.geometry.Point pt = request.getLocation();
TreeItem item = findTreeItemAt(pt);
if (item == null) {
if (hostWidget == tree) {
insertMarkAfterLastChild(tree.getItems());
}
} else if (item == hostWidget) {
// UNSUPPORTED - api not implemented in RAP
// tree.setInsertMark(null, true);
} else {
boolean before = isInUpperHalf(item.getBounds(), pt);
// UNSUPPORTED - api not implemented in RAP
// tree.setInsertMark(item, before);
}
}
/**
* @see org.eclipse.gef.EditPolicy#showTargetFeedback(Request)
*/
public void showTargetFeedback(Request req) {
if (req.getType().equals(REQ_MOVE) || req.getType().equals(REQ_ADD)
|| req.getType().equals(REQ_CREATE))
showDropFeedback((DropRequest) req);
}
}