/** * Copyright (c) 2011 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: * committers of YAKINDU - initial API and implementation * */ package org.yakindu.base.gmf.runtime.editpolicies; import java.util.Iterator; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.OrderedLayout; import org.eclipse.emf.common.util.AbstractEList; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.transaction.TransactionalEditingDomain; 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.requests.CreateRequest; import org.eclipse.gmf.runtime.common.core.command.CommandResult; import org.eclipse.gmf.runtime.diagram.core.commands.AddCommand; import org.eclipse.gmf.runtime.diagram.core.util.ViewUtil; import org.eclipse.gmf.runtime.diagram.ui.commands.CreateCommand; 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.editpolicies.ResizableEditPolicyEx; import org.eclipse.gmf.runtime.diagram.ui.l10n.DiagramUIMessages; import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewAndElementRequest; import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewRequest; import org.eclipse.gmf.runtime.emf.commands.core.command.CompositeTransactionalCommand; import org.eclipse.gmf.runtime.emf.commands.core.commands.RepositionEObjectCommand; import org.eclipse.gmf.runtime.emf.core.util.EObjectAdapter; import org.eclipse.gmf.runtime.emf.type.core.requests.CreateElementRequest; import org.eclipse.gmf.runtime.notation.View; import org.yakindu.base.gmf.runtime.commands.CompartmentChildCreateCommand; import org.yakindu.base.gmf.runtime.commands.CompartmentRepositionEObjectCommand; /** * @see http://wiki.eclipse.org/GMF/Recipes * */ public class CompartmentLayoutEditPolicy extends org.eclipse.gef.editpolicies.FlowLayoutEditPolicy { private EStructuralFeature feature = null; public static enum RequestParameterKeys { RegionFeedbackIndex } /** * Internal command which validates if a view is already a child of parent * and moving it to prefered index instead of adding it twice (What leads to * an exception see {@link AbstractEList#add(int index, E object)}). * * @author markus muehlbrandt * */ private class CompartmentAddCommand extends AddCommand { private IAdaptable parent; private IAdaptable child; private int index; public CompartmentAddCommand(TransactionalEditingDomain editingDomain, IAdaptable parent, IAdaptable child, int index) { super(editingDomain, parent, child, index); assert null != parent : "Null parent in CompartmentAddCommand";//$NON-NLS-1$ assert null != child : "Null child in CompartmentAddCommand";//$NON-NLS-1$ this.parent = parent; this.child = child; this.index = index; } @SuppressWarnings("unchecked") @Override protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { View childView = (View) child.getAdapter(View.class); View parentView = (View) parent.getAdapter(View.class); if (parentView.getPersistedChildren().contains(childView) && index != ViewUtil.APPEND) { parentView.getPersistedChildren().move(index, childView); } else if (index == ViewUtil.APPEND) { parentView.insertChild(childView); } else { parentView.insertChildAt(childView, index); } return CommandResult.newOKCommandResult(); } } /** * @param feature * has to be an EList */ public CompartmentLayoutEditPolicy(EStructuralFeature feature) { super(); this.feature = feature; } @Override protected Command createAddCommand(EditPart child, EditPart after) { int index = getHost().getChildren().indexOf(after); TransactionalEditingDomain editingDomain = ((IGraphicalEditPart) getHost()) .getEditingDomain(); AddCommand command = new CompartmentAddCommand(editingDomain, new EObjectAdapter((View) getHost().getModel()), new EObjectAdapter((View) child.getModel()), index); return new ICommandProxy(command); } @Override protected EditPolicy createChildEditPolicy(EditPart child) { ResizableEditPolicyEx policy = new ResizableEditPolicyEx(); policy.setResizeDirections(0); return policy; } @Override @SuppressWarnings("rawtypes") protected Command createMoveChildCommand(EditPart child, EditPart after) { int newIndex; int displacement; int childIndex = getHost().getChildren().indexOf(child); int afterIndex = getHost().getChildren().indexOf(after); if (afterIndex == -1) { newIndex = getHost().getChildren().size() - 1; displacement = newIndex - childIndex; } else { newIndex = afterIndex; displacement = afterIndex - childIndex; if (childIndex <= afterIndex) { newIndex--; displacement--; } } TransactionalEditingDomain editingDomain = ((IGraphicalEditPart) getHost()) .getEditingDomain(); RepositionEObjectCommand command = new CompartmentRepositionEObjectCommand( child, editingDomain, "", (EList) ((View) child.getParent() .getModel()).getElement().eGet(feature), ((View) child.getModel()).getElement(), displacement, newIndex); eraseLayoutTargetFeedback(null); return new ICommandProxy(command); } @SuppressWarnings("unchecked") @Override protected Command getCreateCommand(CreateRequest request) { if (request instanceof CreateViewAndElementRequest) { TransactionalEditingDomain editingDomain = ((IGraphicalEditPart) getHost()) .getEditingDomain(); CompositeTransactionalCommand cc = new CompositeTransactionalCommand( editingDomain, DiagramUIMessages.AddCommand_Label); Iterator<?> descriptors = ((CreateViewRequest) request) .getViewDescriptors().iterator(); while (descriptors.hasNext()) { CreateViewRequest.ViewDescriptor descriptor = (CreateViewRequest.ViewDescriptor) descriptors .next(); int feedBackIndex = getFeedbackIndexFor(request); // obtain CreateElementRequest and add initial region feedback // index to request map. This index is needed to add the // semantic element at the correct listIndex CreateElementRequest createElementRequest = (CreateElementRequest) ((CreateViewAndElementRequest) request) .getViewAndElementDescriptor() .getCreateElementRequestAdapter() .getAdapter(CreateElementRequest.class); if (createElementRequest != null) { createElementRequest.getParameters().put( RequestParameterKeys.RegionFeedbackIndex, feedBackIndex); } CreateCommand createCommand = new CompartmentChildCreateCommand( editingDomain, descriptor, (View) (getHost().getModel()), feedBackIndex); cc.compose(createCommand); } return new ICommandProxy(cc.reduce()); } return null; } @Override protected boolean isHorizontal() { IFigure figure = ((IGraphicalEditPart) getHost()).getContentPane(); if (figure.getLayoutManager() instanceof OrderedLayout) { return ((OrderedLayout) figure.getLayoutManager()).isHorizontal(); } return true; } @Override protected Command getDeleteDependantCommand(Request request) { return null; } @Override protected Command getOrphanChildrenCommand(Request request) { return null; } }