/** * Copyright (c) 2012 committers of YAKINDU 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: * Markus Muehlbrandt - initial API and implementation * */ package org.yakindu.base.gmf.runtime.treelayout.policies; import java.util.List; 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.gef.EditPart; 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.requests.AlignmentRequest; import org.eclipse.gef.requests.ChangeBoundsRequest; import org.eclipse.gef.requests.CreateRequest; import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy; import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart; import org.eclipse.gmf.runtime.diagram.ui.editparts.LabelEditPart; import org.eclipse.gmf.runtime.diagram.ui.editpolicies.XYLayoutEditPolicy; import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewAndElementRequest; import org.yakindu.base.gmf.runtime.treelayout.TreeLayoutConstraint; import org.yakindu.base.gmf.runtime.treelayout.TreeLayoutUtil; import org.yakindu.base.gmf.runtime.treelayout.commands.UpdateAnnotationsOnCreationCommand; import org.yakindu.base.gmf.runtime.treelayout.commands.UpdateAnnotationsOnMoveCommand; /** * * @author Markus Muehlbrandt * */ public class TreeLayoutEditPolicy extends XYLayoutEditPolicy { private IFigure feedbackFigure; @Override protected Command getCreateCommand(CreateRequest request) { final CompoundCommand cmd = new CompoundCommand(); cmd.add(super.getCreateCommand(request)); if (request instanceof CreateViewAndElementRequest) { final CreateViewAndElementRequest req = (CreateViewAndElementRequest) request; if (shouldUpdateAnnotationsOnCreation(req)) { cmd.add(new ICommandProxy( new UpdateAnnotationsOnCreationCommand(getHost() .getEditingDomain(), req))); } } return cmd; } protected boolean shouldUpdateAnnotationsOnCreation( CreateViewAndElementRequest request) { return true; } @Override protected Object getConstraintFor(ChangeBoundsRequest request, GraphicalEditPart child) { if (request instanceof AlignmentRequest) { return super.getConstraintFor(request, child); } final Rectangle rect = (Rectangle) super.getConstraintFor(request, child); final Rectangle cons = getCurrentConstraintFor(child); final int newTreePosition = TreeLayoutUtil.getNewTreeNodePosition( request.getLocation(), TreeLayoutUtil.getSiblings((IGraphicalEditPart) child)); if (cons instanceof TreeLayoutConstraint) { final TreeLayoutConstraint treeLayoutConstraint = (TreeLayoutConstraint) cons; return new TreeLayoutConstraint(rect, treeLayoutConstraint.isRoot(), newTreePosition); } return new TreeLayoutConstraint(rect, false, newTreePosition); } @Override protected Command createChangeConstraintCommand(EditPart child, Object constraint) { if (constraint instanceof TreeLayoutConstraint) { if (((TreeLayoutConstraint) constraint).isRoot()) { return UnexecutableCommand.INSTANCE; } else { return new ICommandProxy(new UpdateAnnotationsOnMoveCommand( getHost().getEditingDomain(), (IGraphicalEditPart) child, (TreeLayoutConstraint) constraint)); } } return super.createChangeConstraintCommand(child, constraint); } @Override protected void showLayoutTargetFeedback(Request request) { if (request instanceof ChangeBoundsRequest) { final ChangeBoundsRequest changeBoundsRequest = (ChangeBoundsRequest) request; if (!changeBoundsRequest.getEditParts().isEmpty() && !(changeBoundsRequest.getEditParts().get(0) instanceof LabelEditPart)) { final IGraphicalEditPart editPart = (IGraphicalEditPart) changeBoundsRequest .getEditParts().get(0); final List<IGraphicalEditPart> siblingList = TreeLayoutUtil .getSiblings(editPart); if (!siblingList.isEmpty()) { final int newTreePosition = TreeLayoutUtil .getNewTreeNodePosition( changeBoundsRequest.getLocation(), TreeLayoutUtil.getSiblings(editPart)); Point point; if (newTreePosition == 0) { // top end point = getFeedBackFigurePoint(editPart.getFigure(), siblingList, 0, 0); } else if (newTreePosition == siblingList.size()) { // Bottom end point = getFeedBackFigurePoint(editPart.getFigure(), siblingList, siblingList.size(), siblingList.size()); } else { // Between siblings point = getFeedBackFigurePoint(editPart.getFigure(), siblingList, newTreePosition - 1, newTreePosition); } final Rectangle bounds = getFeedbackFigureBounds(); siblingList.get(0).getFigure().translateToAbsolute(bounds); bounds.setLocation(point); getFeedbackFigure().setBounds(bounds); getFeedbackFigure().translateToRelative( getFeedbackFigure().getBounds()); getFeedbackLayer().add(getFeedbackFigure()); getFeedbackLayer().repaint(); } } } } @Override protected void eraseLayoutTargetFeedback(Request request) { super.eraseLayoutTargetFeedback(request); getFeedbackLayer().getChildren().remove(getFeedbackFigure()); getFeedbackLayer().repaint(); } /** * Calculates FeedbackfigurePoint in absolute coordinates * * @param childFigure * @param siblingList * @param lowerIndex * @param upperIndex * @return */ private Point getFeedBackFigurePoint(IFigure childFigure, List<IGraphicalEditPart> siblingList, int lowerIndex, int upperIndex) { final Point point = new Point(); IFigure topFigure; IFigure bottomFigure; if (lowerIndex == siblingList.size()) { topFigure = siblingList.get(lowerIndex - 1).getFigure(); bottomFigure = siblingList.get(upperIndex - 1).getFigure(); } else { topFigure = siblingList.get(lowerIndex).getFigure(); bottomFigure = siblingList.get(upperIndex).getFigure(); } final Rectangle absTopFigBounds = topFigure.getBounds().getCopy(); topFigure.translateToAbsolute(absTopFigBounds); final Rectangle absBottomFigBounds = bottomFigure.getBounds().getCopy(); bottomFigure.translateToAbsolute(absBottomFigBounds); final Rectangle feedbackFigBounds = getFeedbackFigureBounds(); topFigure.translateToAbsolute(feedbackFigBounds); point.x = absTopFigBounds.x - (feedbackFigBounds.width - absTopFigBounds.width) / 2; if (lowerIndex == 0 && upperIndex == 0) { // Top end point.y = absTopFigBounds.y + (absBottomFigBounds.y - absTopFigBounds.y) / 2 - 5; } else if (lowerIndex == siblingList.size() && upperIndex == siblingList.size()) { // bottom end point.y = absTopFigBounds.y + (absBottomFigBounds.y - absTopFigBounds.y) / 2 + absBottomFigBounds.height + 5; } else { point.y = absTopFigBounds.y + (absBottomFigBounds.y - absTopFigBounds.y) / 2 + absBottomFigBounds.height / 2; } return point; } private IFigure getFeedbackFigure() { if (feedbackFigure == null) { final RoundedRectangle pl = new RoundedRectangle(); pl.setForegroundColor(ColorConstants.black); pl.setBackgroundColor(ColorConstants.black); pl.setBounds(getFeedbackFigureBounds()); feedbackFigure = pl; } return feedbackFigure; } private Rectangle getFeedbackFigureBounds() { return new Rectangle(0, 0, 120, 2); } @Override public IGraphicalEditPart getHost() { return (IGraphicalEditPart) super.getHost(); } }