Notice: This Wiki is now read only and edits are no longer possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.
Graphical Modeling Framework/Recipes
Recipe: HowTo reorder children in a GMF compartment with Drag & Drop
Problem:
You have created a node class which can contain other nodes. E.g. a class bookshelf that contains objects of the class book. Therefore you created a compartment. After adding books to the bookshelf in your editor, you want to rearrange the books by drag & drop. But it doesn't work...
Solution:
In the xxxCompartmentEditPart class rewrite the createFigure() method:
public IFigure createFigure() {
ResizableCompartmentFigure rcf = (ResizableCompartmentFigure) super.createFigure();
FlowLayout layout = new FlowLayout();
layout.setMajorSpacing(getMapMode().DPtoLP(5));
layout.setMinorSpacing(getMapMode().DPtoLP(5));
layout.setHorizontal(false);
rcf.getContentPane().setLayoutManager(layout);
rcf.setTitleVisibility(false);
return rcf;
}
In the createDefaultEditPolicies() method of the xxxCompartmentEditPart class add an EditPolicy:
installEditPolicy(EditPolicy.LAYOUT_ROLE, new CompartmentEditPolicy(xxxPackage.Literals.xxx));
Note: xxxPackage.Literals.xxx has to be the EStructuralFeature of the EList Attribute that contains the Objects which should be reordered.
Use the classes CompartmentEditPolicy and CompartmentRepositionEObjectCommand:
package whatever.package.you.want;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.gef.EditPart;
import org.eclipse.gmf.runtime.common.core.command.CommandResult;
import org.eclipse.gmf.runtime.diagram.core.util.ViewUtil;
import org.eclipse.gmf.runtime.emf.commands.core.commands.RepositionEObjectCommand;
import org.eclipse.gmf.runtime.notation.View;
public class CompartmentRepositionEObjectCommand extends RepositionEObjectCommand {
EditPart childToMove = null;
int newIndex = 0;
public CompartmentRepositionEObjectCommand(
TransactionalEditingDomain editingDomain, String label,
EList elements, EObject element, int displacement) {
super(editingDomain, label, elements, element, displacement);
}
public CompartmentRepositionEObjectCommand(EditPart childToMove,
TransactionalEditingDomain editingDomain, String label,
EList elements, EObject element, int displacement, int newIndex) {
super(editingDomain, label, elements, element, displacement);
this.childToMove = childToMove;
this.newIndex = newIndex;
}
public CommandResult doExecuteWithResult(
IProgressMonitor progressMonitor, IAdaptable info)
throws ExecutionException {
CommandResult rs = super.doExecuteWithResult(progressMonitor, info);
EditPart compartment = childToMove.getParent();
ViewUtil.repositionChildAt((View)compartment.getModel(), (View)childToMove.getModel(), newIndex);
compartment.refresh();
return rs;
}
}
package whatever.package.you.want;
import whatever.package.you.want.CompartmentRepositionEObjectCommand;
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.diagram.core.commands.AddCommand;
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.emf.commands.core.commands.RepositionEObjectCommand;
import org.eclipse.gmf.runtime.emf.core.util.EObjectAdapter;
import org.eclipse.gmf.runtime.notation.View;
public class CompartmentEditPolicy extends org.eclipse.gef.editpolicies.FlowLayoutEditPolicy {
private EStructuralFeature feature = null;
protected Command createAddCommand(EditPart child, EditPart after) {
int index = getHost().getChildren().indexOf(after);
TransactionalEditingDomain editingDomain = ((IGraphicalEditPart) getHost()).getEditingDomain();
AddCommand command = new AddCommand(editingDomain, new EObjectAdapter((View)getHost().getModel()),
new EObjectAdapter((View)child.getModel()), index);
return new ICommandProxy(command);
}
protected EditPolicy createChildEditPolicy(EditPart child) {
ResizableEditPolicyEx policy = new ResizableEditPolicyEx();
policy.setResizeDirections(0);
return policy;
}
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) {
public CommandResult doExecuteWithResult(
IProgressMonitor progressMonitor, IAdaptable info) {
// remove target feedback after dropping
eraseLayoutTargetFeedback(null);
return super.doExecuteWithResult(progressMonitor, info);
}
};
return new ICommandProxy(command);
}
protected Command getCreateCommand(CreateRequest request) {
return null;
}
protected Command getDeleteDependantCommand(Request request) {
return null;
}
protected Command getOrphanChildrenCommand(Request request) {
return null;
}
/**
* @param feature has to be an EList
*/
public CompartmentEditPolicy(EStructuralFeature feature) {
super();
this.feature = feature;
}
}
Recipe: HowTo add children in a GMF compartment at a specific position
Problem:
You have created a node class which can contain other nodes. E.g. a class bookshelf that contains objects of the class book. Therefore you created a compartment. Now you want to add a book to the bookshelf at a specific position and not always at the end.
Solution:
In the xxxCompartmentEditPart class rewrite the createFigure() method:
public IFigure createFigure() {
ResizableCompartmentFigure rcf = (ResizableCompartmentFigure) super.createFigure();
FlowLayout layout = new FlowLayout();
layout.setMajorSpacing(getMapMode().DPtoLP(5));
layout.setMinorSpacing(getMapMode().DPtoLP(5));
layout.setHorizontal(false);
rcf.getContentPane().setLayoutManager(layout);
rcf.setTitleVisibility(false);
return rcf;
}
In the createDefaultEditPolicies() method of the xxxCompartmentEditPart class change the following EditPolicy:
- change installEditPolicy(EditPolicyRoles.CREATION_ROLE, new CreationEditPolicy()); + to installEditPolicy(EditPolicyRoles.CREATION_ROLE, new CompartmentChildCreationEditPolicy());
and add the CompartmentChildCreateCommand and CompartmentChildCreationEditPolicy classes:
package org.diagram.edit.commands;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.gmf.runtime.common.core.command.CommandResult;
import org.eclipse.gmf.runtime.diagram.core.services.ViewService;
import org.eclipse.gmf.runtime.diagram.ui.commands.CreateCommand;
import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewRequest.ViewDescriptor;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.jface.util.Assert;
public class CompartmentChildCreateCommand extends CreateCommand {
int index;
public CompartmentChildCreateCommand (TransactionalEditingDomain editingDomain, ViewDescriptor viewDescriptor,
View containerView, int index) {
super(editingDomain, viewDescriptor, containerView);
this.index = index;
}
@Override
protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info)
throws ExecutionException {
View view =
ViewService.getInstance().createView(
viewDescriptor.getViewKind(),
viewDescriptor.getElementAdapter(),
containerView,
viewDescriptor.getSemanticHint(),
index,
viewDescriptor.isPersisted(),
viewDescriptor.getPreferencesHint());
Assert.isNotNull(view, "failed to create a view"); //$NON-NLS-1$
viewDescriptor.setView(view);
return CommandResult.newOKCommandResult(viewDescriptor);
}
}
package org.diagram.edit.policies;
import java.util.Iterator;
import java.util.List;
import org.diagram.edit.commands.CompartmentChildCreateCommand;
import org.eclipse.draw2d.FlowLayout;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.draw2d.geometry.Transposer;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
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.requests.DropRequest;
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.CreationEditPolicy;
import org.eclipse.gmf.runtime.diagram.ui.l10n.DiagramUIMessages;
import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewRequest;
import org.eclipse.gmf.runtime.emf.commands.core.command.CompositeTransactionalCommand;
import org.eclipse.gmf.runtime.notation.View;
public class CompartmentChildCreationEditPolicy extends CreationEditPolicy {
@Override
protected Command getCreateCommand(CreateViewRequest request) {
TransactionalEditingDomain editingDomain = ((IGraphicalEditPart) getHost())
.getEditingDomain();
CompositeTransactionalCommand cc = new CompositeTransactionalCommand(
editingDomain, DiagramUIMessages.AddCommand_Label);
Iterator descriptors = request.getViewDescriptors().iterator();
while (descriptors.hasNext()) {
CreateViewRequest.ViewDescriptor descriptor =
(CreateViewRequest.ViewDescriptor)descriptors.next();
CreateCommand createCommand =
new CompartmentChildCreateCommand(editingDomain,
descriptor,
(View)(getHost().getModel()), getFeedbackIndexFor(request));
cc.compose(createCommand);
}
return new ICommandProxy(cc.reduce());
}
protected int getFeedbackIndexFor(Request request) {
List children = getHost().getChildren();
if (children.isEmpty())
return -1;
Transposer transposer = new Transposer();
transposer.setEnabled (!isHorizontal());
Point p = transposer.t(getLocationFromRequest(request));
// Current row bottom, initialize to above the top.
int rowBottom = Integer.MIN_VALUE;
int candidate = -1;
for (int i = 0; i < children.size(); i++) {
EditPart child = (EditPart) children.get(i);
Rectangle rect = transposer.t(getAbsoluteBounds(((GraphicalEditPart)child)));
if (rect.y > rowBottom) {
/*
* We are in a new row, so if we don't have a candidate but yet are within the
* previous row, then the current entry becomes the candidate. This is because
* we know we must be to the right of center of the last Figure in the
* previous row, so this Figure (which is at the start of a new row) is the
* candidate.
*/
if (p.y <= rowBottom) {
if (candidate == -1)
candidate = i;
break;
} else
candidate = -1; // Mouse's Y is outside the row, so reset the candidate
}
rowBottom = Math.max(rowBottom, rect.bottom());
if (candidate == -1) {
/*
* See if we have a possible candidate. It is a candidate if the cursor is
* left of the center of this candidate.
*/
if (p.x <= rect.x + (rect.width / 2))
candidate = i;
}
if (candidate != -1) {
// We have a candidate, see if the rowBottom has grown to include the mouse Y.
if (p.y <= rowBottom) {
/*
* Now we have determined that the cursor.Y is above the bottom of the
* current row of figures. Stop now, to prevent the next row from being
* searched
*/
break;
}
}
}
return candidate;
}
protected boolean isHorizontal() {
IFigure figure = ((GraphicalEditPart)getHost()).getContentPane();
return ((FlowLayout)figure.getLayoutManager()).isHorizontal();
}
private Point getLocationFromRequest(Request request) {
return ((DropRequest)request).getLocation();
}
private Rectangle getAbsoluteBounds(GraphicalEditPart ep) {
Rectangle bounds = ep.getFigure().getBounds().getCopy();
ep.getFigure().translateToAbsolute(bounds);
return bounds;
}
}