blob: 92f7794470b12793389dd54b6e55724b58f6656a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2012 IBM Corporation 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.bpel.ui.editparts.policies;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.bpel.common.ui.layouts.AlignedFlowLayout;
import org.eclipse.bpel.ui.BPELUIPlugin;
import org.eclipse.bpel.ui.GraphicalBPELRootEditPart;
import org.eclipse.bpel.ui.IBPELUIConstants;
import org.eclipse.bpel.ui.commands.CompoundCommand;
import org.eclipse.bpel.ui.commands.InsertInContainerCommand;
import org.eclipse.bpel.ui.commands.ReorderInContainerCommand;
import org.eclipse.bpel.ui.commands.SetNameAndDirectEditCommand;
import org.eclipse.bpel.ui.editparts.BPELEditPart;
import org.eclipse.bpel.ui.editparts.CollapsableEditPart;
import org.eclipse.bpel.ui.editparts.CompositeActivityEditPart;
import org.eclipse.bpel.ui.editparts.ElseIfEditPart;
import org.eclipse.bpel.ui.editparts.IfEditPart;
import org.eclipse.bpel.ui.editparts.InvokeEditPart;
import org.eclipse.bpel.ui.editparts.ProcessEditPart;
import org.eclipse.bpel.ui.editparts.ScopeEditPart;
import org.eclipse.bpel.ui.editparts.StartNodeEditPart;
import org.eclipse.bpel.ui.figures.CenteredConnectionAnchor;
import org.eclipse.bpel.ui.util.ImplicitLinkHandlerConnectionRouter;
import org.eclipse.bpel.ui.util.ModelHelper;
import org.eclipse.draw2d.ConnectionAnchor;
import org.eclipse.draw2d.FlowLayout;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.LayoutManager;
import org.eclipse.draw2d.PolygonDecoration;
import org.eclipse.draw2d.PolylineConnection;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.LayerConstants;
import org.eclipse.gef.Request;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.editpolicies.FlowLayoutEditPolicy;
import org.eclipse.gef.requests.CreateRequest;
import org.eclipse.gef.requests.DropRequest;
import org.eclipse.gef.requests.GroupRequest;
import org.eclipse.swt.graphics.Color;
public class BPELOrderedLayoutEditPolicy extends FlowLayoutEditPolicy {
protected ArrayList<PolylineConnection> polyLineConnectionList = new ArrayList<PolylineConnection>();
// colour of the connection lines
protected Color arrowColor = BPELUIPlugin.INSTANCE.getColorRegistry().get(IBPELUIConstants.COLOR_IMPLICIT_LINK);
@Override
protected Command createAddCommand(EditPart child, EditPart before) {
return new InsertInContainerCommand((EObject)getHost().getModel(), (EObject)child.getModel(),
(before == null)? null : (EObject)before.getModel());
}
@Override
protected Command createMoveChildCommand(EditPart child, EditPart before) {
return new ReorderInContainerCommand((EObject)getHost().getModel(), (EObject)child.getModel(),
(before == null)? null : (EObject)before.getModel());
}
@Override
protected Command getCreateCommand(CreateRequest request) {
CompoundCommand command = null;
try {
EditPart before = getInsertionReference(request);
EObject parent = (EObject) getHost().getModel();
EObject child = (EObject) request.getNewObject();
EObject beforeObject = (EObject)(before != null ? before.getModel() : null);
command = new CompoundCommand();
command.add(new InsertInContainerCommand(parent, child, beforeObject));
command.add(new SetNameAndDirectEditCommand(child, getHost().getViewer()));
} catch( Exception e ) {
// nothing
}
return command;
}
@Override
protected Command getDeleteDependantCommand(Request request) {
return null;
}
/**
* Returns the part that we should insert before.
* If request is null insert at the end of the list.
*/
@Override
protected EditPart getInsertionReference(Request request) {
// TODO: what is this for?
if (request instanceof DropRequest) {
Point pt = ((DropRequest)request).getLocation();
if (pt == null) return null;
return super.getInsertionReference(request);
}
return null;
}
public void refreshConnections() {
// remove connections before redrawing
clearConnections();
if (hasChildren() && !isCollapsed()) {
if (isHorizontal()) {
this.polyLineConnectionList = createHorizontalConnections((BPELEditPart)getHost());
} else {
this.polyLineConnectionList = createVerticalConnections((BPELEditPart)getHost());
}
}
}
public void clearConnections() {
for (int i = 0; i < this.polyLineConnectionList.size(); i++) {
getLayer(LayerConstants.CONNECTION_LAYER).remove((this.polyLineConnectionList.get(i)));
}
this.polyLineConnectionList.clear();
}
// return implicit links for a Horizontal edit part (e.g. a Switch).
protected ArrayList<PolylineConnection> createHorizontalConnections(BPELEditPart parent) {
ArrayList<PolylineConnection> connections = new ArrayList<PolylineConnection>();
List<BPELEditPart> children = getConnectionChildren(parent);
BPELEditPart sourcePart, targetPart;
ConnectionAnchor sourceAnchor, targetAnchor;
sourcePart = parent;
sourceAnchor = sourcePart.getConnectionAnchor(CenteredConnectionAnchor.TOP_INNER);
if (children != null){
for (int i = 0; i < children.size(); i++) {
targetPart = children.get(i);
targetAnchor = targetPart.getConnectionAnchor(CenteredConnectionAnchor.TOP);
connections.add(createConnection(sourceAnchor,targetAnchor,this.arrowColor));
}
}
return connections;
}
// return list of children to create vertical connections for.
protected List<BPELEditPart> getConnectionChildren(BPELEditPart editPart) {
return editPart.getChildren();
}
// return implicit links for a Vertical edit part (e.g. a Sequence).
protected ArrayList<PolylineConnection> createVerticalConnections(BPELEditPart parent) {
ArrayList<PolylineConnection> connections = new ArrayList<PolylineConnection>();
List<BPELEditPart> children = getConnectionChildren(parent);
BPELEditPart sourcePart = null, targetPart = null;
ConnectionAnchor sourceAnchor = null, targetAnchor = null;
// TODO: Connections misaligned when there are no children
if (!children.isEmpty()) {
for (int i = 0; i <= children.size(); i++) {
if (i == 0) {
if (hasTopParentLink()) {
sourcePart = parent;
sourceAnchor = sourcePart.getConnectionAnchor(CenteredConnectionAnchor.TOP_INNER);
} else {
sourceAnchor = null;
}
} else {
sourcePart = children.get(i-1);
sourceAnchor = sourcePart.getConnectionAnchor(CenteredConnectionAnchor.BOTTOM);
}
if (i == children.size()) {
if (hasBottomParentLink()) {
targetPart = parent;
targetAnchor = targetPart.getConnectionAnchor(CenteredConnectionAnchor.BOTTOM_INNER);
} else {
targetAnchor = null;
}
} else {
targetPart = children.get(i);
targetAnchor = targetPart.getConnectionAnchor(CenteredConnectionAnchor.TOP);
}
if (sourceAnchor != null && targetAnchor != null) {
PolylineConnection connection = createConnection(sourceAnchor,targetAnchor,this.arrowColor);
if(sourcePart instanceof StartNodeEditPart || sourcePart instanceof ScopeEditPart || sourcePart instanceof InvokeEditPart){
boolean horizontal = ModelHelper.isHorizontalLayout(getHost().getModel());
connection.setConnectionRouter(new ImplicitLinkHandlerConnectionRouter(horizontal));
}
connections.add(connection);
}
}
}
return connections;
}
protected boolean hasTopParentLink() {
return !(getHost() instanceof ProcessEditPart);
}
protected boolean hasBottomParentLink() {
if (getHost() instanceof ProcessEditPart)
return false;
if (getHost() instanceof ElseIfEditPart)
return false;
if (getHost() instanceof IfEditPart)
return false;
return true;
}
protected List getSourceParts(Request request) {
List<Object> list = new ArrayList<Object>();
if (request instanceof CreateRequest) {
list.add(((CreateRequest) request).getNewObject());
} else if (request instanceof GroupRequest) {
List<EditPart> l = ((GroupRequest) request).getEditParts();
for( EditPart editPart : l ) {
list.add(editPart.getModel());
}
}
return list;
}
protected LayoutManager getLayoutManager() {
if (getHost() instanceof GraphicalEditPart) {
IFigure figure = ((GraphicalEditPart)getHost()).getContentPane();
if (figure != null) return figure.getLayoutManager();
}
return null;
}
protected boolean canShowFeedback() {
LayoutManager layout = getLayoutManager();
if (layout == null) return false;
if (layout instanceof FlowLayout) return true;
if (layout instanceof AlignedFlowLayout) return true;
return false;
}
@Override
protected void showLayoutTargetFeedback(Request request) {
if (!canShowFeedback()) return;
super.showLayoutTargetFeedback(request);
}
@Override
public EditPart getTargetEditPart(Request request) {
// this policy only works for the BPEL Editor itself, not the outline
// TODO: we shouldn't even install this for the outline!! (oops)
if (getHost().getRoot() instanceof GraphicalBPELRootEditPart) {
return super.getTargetEditPart(request);
}
return null;
}
/**
* override to prevent any child policies from being installed
*
* TODO: re-think this.
*/
@Override
protected EditPolicy createChildEditPolicy(EditPart child) {
return null;
}
// https://issues.jboss.org/browse/JBIDE-8694
// isHorizontal() has been deprecated in GEF 3.7
// See also https://bugs.eclipse.org/bugs/show_bug.cgi?id=88884
// @Override - eventually
protected boolean isLayoutHorizontal() {
return this.isHorizontal();
}
@Override
protected boolean isHorizontal() {
LayoutManager layout = getLayoutManager();
if (layout instanceof FlowLayout) return ((FlowLayout)layout).isHorizontal();
if (layout instanceof AlignedFlowLayout) return ((AlignedFlowLayout)layout).isHorizontal();
return false;
}
protected boolean isCollapsed() {
if (getHost() instanceof CollapsableEditPart) {
return ((CollapsableEditPart)getHost()).isCollapsed();
}
return false;
}
protected PolylineConnection createConnection(ConnectionAnchor sourceAnchor, ConnectionAnchor targetAnchor, Color color) {
PolylineConnection connection = new PolylineConnection();
connection.setSourceAnchor(sourceAnchor);
connection.setTargetAnchor(targetAnchor);
connection.setForegroundColor(color);
connection.setBackgroundColor(color);
connection.setConnectionRouter(new ImplicitLinkHandlerConnectionRouter(ModelHelper.isHorizontalLayout(getHost().getModel())));
PolygonDecoration arrow = new PolygonDecoration();
arrow.setTemplate(PolygonDecoration.TRIANGLE_TIP);
arrow.setScale(5,2.5);
arrow.setBackgroundColor(this.arrowColor);
connection.setTargetDecoration(arrow);
getLayer(LayerConstants.CONNECTION_LAYER).add(connection);
return connection;
}
@Override
public void showTargetFeedback(Request request) {
// don't bother if request can't be executed
if (getHost() instanceof BPELEditPart) {
if (!((BPELEditPart)getHost()).canExecuteRequest(request)) {
return;
}
}
super.showTargetFeedback(request);
}
/**
* Does the edit part have children? If so, implicit connection logic will be
* executed. The only edit parts which have children are CompositeActivityEditParts
* (Sequence, While, Flow, RepeatUntil, etc.) and ElseElseIfEditPart (Case, OnMessage, OnAlarm).
*/
protected boolean hasChildren() {
EditPart host = getHost();
if (host instanceof ElseIfEditPart || host instanceof CompositeActivityEditPart || host instanceof ProcessEditPart) {
return true;
}
return false;
}
@Override
public void deactivate() {
// TODO Auto-generated method stub
super.deactivate();
clearConnections();
}
@Override
public int getFeedbackIndexFor(Request request) {
// TODO Auto-generated method stub
return super.getFeedbackIndexFor(request);
}
}