/** * Copyright (c) 2009 Borland Software Corp. * * 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: * Alexander Shatalin (Borland) - initial API and implementation */ package org.eclipse.gmf.graphdef.editor.edit.policies; import java.util.Collections; import java.util.List; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.draw2d.ColorConstants; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.RoundedRectangle; import org.eclipse.draw2d.geometry.Point; import org.eclipse.draw2d.geometry.Rectangle; import org.eclipse.emf.workspace.util.WorkspaceSynchronizer; import org.eclipse.gef.EditPart; import org.eclipse.gef.EditPolicy; import org.eclipse.gef.Request; import org.eclipse.gef.commands.Command; import org.eclipse.gef.commands.UnexecutableCommand; import org.eclipse.gef.editpolicies.ConstrainedLayoutEditPolicy; import org.eclipse.gef.requests.ChangeBoundsRequest; import org.eclipse.gef.requests.CreateRequest; import org.eclipse.gef.requests.DropRequest; import org.eclipse.gef.requests.GroupRequest; import org.eclipse.gmf.gmfgraph.RealFigure; import org.eclipse.gmf.graphdef.editor.edit.parts.AbstractFigureEditPart; import org.eclipse.gmf.runtime.common.core.command.CommandResult; import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy; import org.eclipse.gmf.runtime.diagram.ui.requests.RequestConstants; import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Color; public class GridLayoutEditPolicy extends ConstrainedLayoutEditPolicy { private static final Color FEEDBACK_COLOR = ColorConstants.lightBlue; private static final Color GRID_COLOR = ColorConstants.lightGreen; private static final Color INNER_FIGURES_COLOR = ColorConstants.red; private RoundedRectangle myFeedbackFigure; private GridLayoutHelper myFeedbackBoundsHelper; private GridFigure myGridFigure; @Override protected void showLayoutTargetFeedback(Request request) { if (/* RequestConstants.REQ_CREATE.equals(request.getType()) || */RequestConstants.REQ_MOVE.equals(request.getType())) { // [1] DropRequest dropRequest = (DropRequest) request; IFigure figure = getLayoutContainer(); Point where = dropRequest.getLocation().getCopy(); figure.translateToRelative(where); figure.translateFromParent(where); where.translate(getLayoutOrigin().getNegated()); if (myFeedbackBoundsHelper == null) { myFeedbackBoundsHelper = new GridLayoutHelper(getAbstractFigureEditPart()); } if (myGridFigure == null) { myGridFigure = new GridFigure(myFeedbackBoundsHelper.getGrid(), myFeedbackBoundsHelper.getHeights(), myFeedbackBoundsHelper.getWidths(), myFeedbackBoundsHelper.getGridLayout()); Rectangle bounds = figure.getBounds().getCopy(); figure.translateToAbsolute(bounds); getFeedbackLayer().translateToRelative(bounds); myGridFigure.setBounds(bounds); myGridFigure.setForegroundColor(GRID_COLOR); myGridFigure.setInnerFigureBoundsColor(INNER_FIGURES_COLOR); myGridFigure.setLineWidth(2); getFeedbackLayer().add(myGridFigure); } IFigure childFigure = null; if (dropRequest instanceof GroupRequest) { List editParts = ((GroupRequest) dropRequest).getEditParts(); assert editParts.size() == 1; childFigure = ((AbstractFigureEditPart) editParts.get(0)).getFigure(); } Rectangle feedbackBounds = myFeedbackBoundsHelper.getFeedbackBounds(where, childFigure); if (feedbackBounds == null) { eraseTargetFeedback(request); return; } figure.translateToParent(feedbackBounds); figure.translateToAbsolute(feedbackBounds); getFeedbackLayer().translateToRelative(feedbackBounds); if (myFeedbackFigure == null) { myFeedbackFigure = new RoundedRectangle(); myFeedbackFigure.setFill(false); myFeedbackFigure.setOutline(true); myFeedbackFigure.setForegroundColor(FEEDBACK_COLOR); myFeedbackFigure.setLineWidth(1); myFeedbackFigure.setAntialias(SWT.ON); myFeedbackFigure.setBounds(feedbackBounds); getFeedbackLayer().add(myFeedbackFigure); } else { myFeedbackFigure.setBounds(feedbackBounds); } //[2] // ChangeBoundsRequest changeBoundsRequest = (ChangeBoundsRequest) request; // IFigure figure = getLayoutContainer(); // Point where = changeBoundsRequest.getLocation().getCopy(); // figure.translateToRelative(where); // figure.translateFromParent(where); // where.translate(getLayoutOrigin().getNegated()); // // if (changeBoundsRequest.getEditParts().size() != 1) { // // capable of moving only one child element at a time // return; // } // // final AbstractFigureEditPart childEditPart = (AbstractFigureEditPart) changeBoundsRequest.getEditParts().get(0); // final int newChildPosition = new GridLayoutHelper(getAbstractFigureEditPart()).getNewChildPosition(where); // getAbstractFigureEditPart().removeChildVisual(childEditPart); // getAbstractFigureEditPart().addChildVisual(childEditPart, newChildPosition); } } @Override public void eraseTargetFeedback(Request request) { /** * RequestConstants.REQ_DROP can be used here together with * RequestConstants.REQ_MOVE due to the current * DragEditPartsTrackerEx.handleDragInProgress() implementation. * * Currently .handleDragInProgress() calls: * * 1. updateTargetRequest() setting targetRequest type to * getCommandName() (RequestConstants.REQ_MOVE) * * 2. updateTargetUnderMouse(), showTargetFeedback(), * showSourceFeedback() using current target request with the type set * on step 1. * * 3. setCurrentCommand(getCommand()); where (in addSourceCommands()) * request type will be set to RequestConstants.REQ_DROP * * So, showTargetFeedback(), showSourceFeedback() methods should be able * to react on RequestConstants.REQ_MOVE. In the same time * eraseTargetFeedback() should be sensitive to * RequestConstants.REQ_MOVE (if it was called from * updateTargetUnderMouse() then EditPart was exited) and * RequestConstants.REQ_DROP (if it was called from handleButtonUp()) * * See code for more details. */ if (/* RequestConstants.REQ_CREATE.equals(request.getType()) || */RequestConstants.REQ_MOVE.equals(request.getType()) || RequestConstants.REQ_DROP.equals(request.getType())) { //[1] if (myFeedbackFigure != null) { getFeedbackLayer().remove(myFeedbackFigure); myFeedbackFigure = null; } if (myGridFigure != null) { getFeedbackLayer().remove(myGridFigure); myGridFigure = null; } myFeedbackBoundsHelper = null; //[2] // getAbstractFigureEditPart().refresh(); } else { super.eraseTargetFeedback(request); } } /** * With Grid layout move means reorder but not change layout constraints. * Handling it in a different way. */ @Override protected Command getMoveChildrenCommand(Request request) { ChangeBoundsRequest changeBoundsRequest = (ChangeBoundsRequest) request; IFigure figure = getLayoutContainer(); Point where = changeBoundsRequest.getLocation().getCopy(); figure.translateToRelative(where); figure.translateFromParent(where); where.translate(getLayoutOrigin().getNegated()); if (changeBoundsRequest.getEditParts().size() != 1) { // capable of moving only one child element at a time return UnexecutableCommand.INSTANCE; } final AbstractFigureEditPart childEditPart = (AbstractFigureEditPart) changeBoundsRequest.getEditParts().get(0); final int newChildPosition = new GridLayoutHelper(getAbstractFigureEditPart()).getNewChildPosition(where); return newChildPosition == -1 ? UnexecutableCommand.INSTANCE : new ICommandProxy(new AbstractTransactionalCommand(childEditPart.getEditingDomain(), "Moving child figure", Collections .singletonList(WorkspaceSynchronizer.getFile(getRealFigure().eResource()))) { @Override protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { getRealFigure().getChildren().move(newChildPosition, childEditPart.getRealFigure()); getAbstractFigureEditPart().getNotationView().persistChildren(); getAbstractFigureEditPart().getNotationView().getPersistedChildren().move(newChildPosition, childEditPart.getNotationView()); // getAbstractFigureEditPart().getNotationView().getChildren().remove(childEditPart.getNotationView()); // getAbstractFigureEditPart().getNotationView().getChildren().add(newChildPosition, // childEditPart.getNotationView()); return CommandResult.newOKCommandResult(); } }); } /* * (non-Javadoc) * * @seeorg.eclipse.gef.editpolicies.ConstrainedLayoutEditPolicy# * createChangeConstraintCommand(org.eclipse.gef.EditPart, java.lang.Object) */ @Override protected Command createChangeConstraintCommand(EditPart child, Object constraint) { // TODO Auto-generated method stub return null; } /* * (non-Javadoc) * * @see * org.eclipse.gef.editpolicies.ConstrainedLayoutEditPolicy#getConstraintFor * (org.eclipse.draw2d.geometry.Point) */ @Override protected Object getConstraintFor(Point point) { // TODO Auto-generated method stub return null; } /* * (non-Javadoc) * * @see * org.eclipse.gef.editpolicies.ConstrainedLayoutEditPolicy#getConstraintFor * (org.eclipse.draw2d.geometry.Rectangle) */ @Override protected Object getConstraintFor(Rectangle rect) { // TODO Auto-generated method stub return null; } /* * (non-Javadoc) * * @see * org.eclipse.gef.editpolicies.LayoutEditPolicy#getCreateCommand(org.eclipse * .gef.requests.CreateRequest) */ @Override protected Command getCreateCommand(CreateRequest request) { // TODO Auto-generated method stub return null; } @Override protected EditPolicy createChildEditPolicy(EditPart child) { return new ResizableEditPolicy(); } private AbstractFigureEditPart getAbstractFigureEditPart() { return (AbstractFigureEditPart) getHost(); } private RealFigure getRealFigure() { return ((AbstractFigureEditPart) getHost()).getRealFigure(); } }