| /******************************************************************************* |
| * 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); |
| } |
| |
| } |