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