Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "Graphical Modeling Framework/Recipes"

(Recipe: HowTo reorder children in a GMF compartment with Drag & Drop)
(Recipe: HowTo reorder children in a GMF compartment with Drag & Drop)
Line 146: Line 146:
 
}
 
}
 
}
 
}
 +
</pre>
 +
 +
 +
== 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 createDefaultEditPolicies() method of the xxxCompartmentEditPart class change the following EditPolicy:
 +
<pre>
 +
  - change
 +
installEditPolicy(EditPolicyRoles.CREATION_ROLE, new CreationEditPolicy());
 +
  + to
 +
installEditPolicy(EditPolicyRoles.CREATION_ROLE, new CompartmentChildCreationEditPolicy());
 +
</pre>
 +
 +
and add the CompartmentChildCreateCommand and CompartmentChildCreationEditPolicy classes:
 +
 +
 +
<pre>
 +
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);
 +
}
 +
 +
}
 +
 +
</pre>
 +
 +
<pre>
 +
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;
 +
}
 +
}
 +
 
</pre>
 
</pre>
  
 
[[Category:GMF]]
 
[[Category:GMF]]

Revision as of 07:02, 20 March 2008

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:

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);	

		//TODO ev. reintroduce target feedback (actual problem: line is not deleted after dropping)
		eraseLayoutTargetFeedback(null);

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

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


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

Copyright © Eclipse Foundation, Inc. All Rights Reserved.