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