/****************************************************************************** * Copyright (c) 2002, 2006 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.gmf.runtime.diagram.ui.editpolicies; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.eclipse.emf.ecore.EObject; import org.eclipse.gef.EditPart; import org.eclipse.gef.Request; import org.eclipse.gef.commands.Command; import org.eclipse.gef.commands.CompoundCommand; import org.eclipse.gef.editpolicies.GraphicalEditPolicy; import org.eclipse.gef.requests.ChangeBoundsRequest; import org.eclipse.gef.tools.ToolUtilities; import org.eclipse.swt.dnd.DND; import org.eclipse.swt.graphics.Color; import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy; import org.eclipse.gmf.runtime.diagram.ui.commands.CommandProxy; import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart; import org.eclipse.gmf.runtime.diagram.ui.requests.DropObjectsRequest; import org.eclipse.gmf.runtime.diagram.ui.requests.RequestConstants; import org.eclipse.gmf.runtime.diagram.core.util.ViewUtil; import org.eclipse.gmf.runtime.draw2d.ui.figures.FigureUtilities; import org.eclipse.gmf.runtime.notation.View; /** * Abstract Implementation for all EditPolicies that deal with the * REQ_DRAG, REQ_DROP and REQ_DROP_EOBJECTS requests * as defined in <code>org.eclipse.gmf.runtime.diagram.ui.requests.RequestConstants<code> * * The default implementation REQ_DRAG is to cast it into a REQ_ORPHAN request * The default implementation REQ_DROP is to cast it into a REQ_ADD request * * * @author melaasar */ public class DragDropEditPolicy extends GraphicalEditPolicy { /** * the background feedback color */ private static final Color GRAY = new Color(null, 200, 200, 200); /** * the original background color */ protected Color revertColor; /** * the original opacity */ protected boolean opacity; /** * This will only return a command if the host is resolvable so that * trying to drop on an unresolved shape will not be allowed. * @see org.eclipse.gef.EditPolicy#getCommand(Request) */ public Command getCommand(Request request) { if (RequestConstants.REQ_DRAG.equals(request.getType())) { return getDragCommand((ChangeBoundsRequest) request); } else if (RequestConstants.REQ_DROP.equals(request.getType())) { return getDropCommand((ChangeBoundsRequest) request); } else if ( RequestConstants.REQ_DROP_OBJECTS.equals(request.getType())) { DropObjectsRequest dndRequest = (DropObjectsRequest) request; dndRequest.setRequiredDetail(getRequiredDragDetail(dndRequest)); return getDropObjectsCommand(dndRequest); } return null; } /** * gets a drag command * @param request the request * @return command */ protected Command getDragCommand(ChangeBoundsRequest request) { ChangeBoundsRequest req = new ChangeBoundsRequest(REQ_ORPHAN); req.setEditParts(request.getEditParts()); req.setMoveDelta(request.getMoveDelta()); req.setSizeDelta(request.getSizeDelta()); req.setLocation(request.getLocation()); req.setResizeDirection(request.getResizeDirection()); return getHost().getCommand(req); } /** * gets a drop command * @param request the request * @return command */ protected Command getDropCommand(ChangeBoundsRequest request) { ChangeBoundsRequest req = new ChangeBoundsRequest(REQ_ADD); req.setEditParts(request.getEditParts()); req.setMoveDelta(request.getMoveDelta()); req.setSizeDelta(request.getSizeDelta()); req.setLocation(request.getLocation()); req.setResizeDirection(request.getResizeDirection()); Command cmd = getHost().getCommand(req); if (cmd == null || !cmd.canExecute()) { return getDropObjectsCommand(castToDropObjectsRequest(request)); } return cmd; } /** * getDropElementCommand * Returns a command to handle a DropObjectsRequest of an EObject * * @param element EObject that is being dropped. * @param request DropObjectsRequest that the element has retrieved from. * @return Command that handles the dropping of the EObject element. */ protected Command getDropElementCommand(EObject element, DropObjectsRequest request) { return null; } /** * getDropObjectsCommand * This provides a generic implementation for handling the * DropObjectsRequest which checks for EObject and gets a command * from the getDropEementCommand method. * @param request DropObjectsRequest that is being handled * @return Command that handles the request. */ protected Command getDropObjectsCommand(DropObjectsRequest request) { CompoundCommand cm = new CompoundCommand(); Iterator elements = request.getObjects().iterator(); while (elements.hasNext()) { Object obj = elements.next(); if (obj instanceof EObject) { Command cmd = getDropElementCommand((EObject)obj, request); if (cmd != null) cm.add(cmd); } } if (cm.isEmpty()) return null; return new ICommandProxy(new CommandProxy(cm.unwrap())); } /** * @see org.eclipse.gef.EditPolicy#getTargetEditPart(Request) */ public EditPart getTargetEditPart(final Request request) { return understandsRequest(request) ? getHost() : null; } /** * Only understands DRAG, DROP and DROP_ELEMENTS requests. * * @return whether the request is supported */ public boolean understandsRequest(Request request) { return RequestConstants.REQ_MOVE.equals(request.getType()) || RequestConstants.REQ_DRAG.equals(request.getType()) || RequestConstants.REQ_DROP.equals(request.getType()) || RequestConstants.REQ_DROP_OBJECTS.equals(request.getType()); } /** * @see org.eclipse.gef.EditPolicy#showTargetFeedback(org.eclipse.gef.Request) */ public void showTargetFeedback(Request request) { Command c = getCommand(request); if (c != null && c.canExecute()) { if (revertColor == null) { revertColor = getHostFigure().getBackgroundColor(); opacity = getHostFigure().isOpaque(); getHostFigure().setBackgroundColor( FigureUtilities.mixColors(GRAY, revertColor)); getHostFigure().setOpaque(true); } } } /** * @see org.eclipse.gef.EditPolicy#eraseTargetFeedback(org.eclipse.gef.Request) */ public void eraseTargetFeedback(Request request) { if (revertColor != null) { getHostFigure().setBackgroundColor(revertColor); getHostFigure().setOpaque(opacity); revertColor = null; } } /** * * @param request * @return int */ protected int getRequiredDragDetail(Request request) { return DND.DROP_COPY; } /** * return the host Edit Part's semantic element, if the semantic element * is <code>null</code> or unresolvable it will return <code>null</code> * @return EObject */ protected EObject getHostObject() { return ViewUtil .resolveSemanticElement((View) ((IGraphicalEditPart) getHost()) .getModel()); } /** * Retrieves the list of elements being dropped * @param request the request * @return List of elements */ protected DropObjectsRequest castToDropObjectsRequest(ChangeBoundsRequest request) { Iterator editParts = ToolUtilities .getSelectionWithoutDependants(request.getEditParts()) .iterator(); List elements = new ArrayList(); while (editParts.hasNext()) { EditPart editPart = (EditPart) editParts.next(); if (editPart instanceof IGraphicalEditPart) { EObject element = ViewUtil .resolveSemanticElement((View) ((IGraphicalEditPart) editPart) .getModel()); if (element != null) elements.add(element); } } DropObjectsRequest req = new DropObjectsRequest(); req.setObjects(elements); req.setAllowedDetail(DND.DROP_COPY | DND.DROP_MOVE | DND.DROP_LINK); req.setLocation(request.getLocation()); req.setRequiredDetail(getRequiredDragDetail(request)); return req; } }