/******************************************************************************* | |
* 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; | |
import java.util.ArrayList; | |
import java.util.Collections; | |
import java.util.List; | |
import org.eclipse.bpel.common.ui.markers.IModelMarkerConstants; | |
import org.eclipse.bpel.model.Activity; | |
import org.eclipse.bpel.model.Link; | |
import org.eclipse.bpel.model.Source; | |
import org.eclipse.bpel.model.Sources; | |
import org.eclipse.bpel.model.Target; | |
import org.eclipse.bpel.model.Targets; | |
import org.eclipse.bpel.ui.BPELUIPlugin; | |
import org.eclipse.bpel.ui.GraphicalBPELRootEditPart; | |
import org.eclipse.bpel.ui.IBPELUIConstants; | |
import org.eclipse.bpel.ui.IHoverHelper; | |
import org.eclipse.bpel.ui.adapters.IMarkerHolder; | |
import org.eclipse.bpel.ui.editparts.borders.DrawerBorder; | |
import org.eclipse.bpel.ui.editparts.policies.BPELGraphicalEditPolicy; | |
import org.eclipse.bpel.ui.extensions.BPELUIRegistry; | |
import org.eclipse.bpel.ui.figures.CenteredConnectionAnchor; | |
import org.eclipse.bpel.ui.util.BPELUtil; | |
import org.eclipse.bpel.ui.util.ModelHelper; | |
import org.eclipse.core.resources.IMarker; | |
import org.eclipse.core.runtime.CoreException; | |
import org.eclipse.draw2d.ConnectionAnchor; | |
import org.eclipse.draw2d.IFigure; | |
import org.eclipse.draw2d.Label; | |
import org.eclipse.draw2d.MouseEvent; | |
import org.eclipse.draw2d.MouseMotionListener; | |
import org.eclipse.draw2d.geometry.Dimension; | |
import org.eclipse.draw2d.geometry.Point; | |
import org.eclipse.draw2d.geometry.Rectangle; | |
import org.eclipse.gef.ConnectionEditPart; | |
import org.eclipse.gef.EditPart; | |
import org.eclipse.gef.EditPolicy; | |
import org.eclipse.gef.GraphicalEditPart; | |
import org.eclipse.gef.NodeEditPart; | |
import org.eclipse.gef.Request; | |
/** | |
* ActivityEditPart is the graphical GEF edit part representing a BPEL Activity. | |
* It implements NodeEditPart because activities can be the source and the target of | |
* connections in the graph. These connections include flow links as well as implicit | |
* control flow connections, often determined by the node's parent. | |
*/ | |
public abstract class ActivityEditPart extends BPELEditPart implements NodeEditPart { | |
private MouseMotionListener mouseMotionListener; | |
/** | |
* Brand new shiny ActivityEditPart. | |
*/ | |
public ActivityEditPart() { | |
super(); | |
} | |
@Override | |
protected void addAllAdapters() { | |
super.addAllAdapters(); | |
Sources sources = getActivity().getSources(); | |
if (sources != null) { | |
adapter.addToObject(sources); | |
for(Source source : sources.getChildren()) { | |
adapter.addToObject(source); | |
} | |
// | |
// for (Iterator it = sources.getChildren().iterator(); it.hasNext(); ) { | |
// Source source = (Source)it.next(); | |
// // also include the link, if there is one (since we indirectly | |
// // control the activation of the LinkEditPart) | |
// if (source.getLink() != null) adapter.addToObject(source.getLink()); | |
// | |
// // Okay--the real problem here, is that the Activity might be | |
// // referred to by a Source object, but the Activity is not going | |
// // to find out about the creation of a new Sources that references | |
// // it. Therefore, our model listeners don't know what to do! | |
// | |
// // TODO: temporarily hacked around in FlowEditPart.FlowContentAdapter. | |
// | |
// // TODO: also include any parent flows, and the Links object of | |
// // any parent flows that have one. ! | |
// // TODO: in future, use a global listener to handle refreshing the | |
// // correct source editpart. | |
// } | |
} | |
Targets targets = getActivity().getTargets(); | |
if (targets != null) { | |
adapter.addToObject(targets); | |
for( Target target : targets.getChildren()) { | |
adapter.addToObject(target); | |
} | |
} | |
} | |
/** | |
* Install the BPELGraphicalEditPolicy as GRAPHICAL_NODE_ROLE. This policy allows | |
* the graphical creation of flow links between activities. | |
*/ | |
@Override | |
protected void createEditPolicies() { | |
super.createEditPolicies(); | |
installEditPolicy(EditPolicy.GRAPHICAL_NODE_ROLE, new BPELGraphicalEditPolicy()); | |
} | |
/** | |
* The model is the source of the following connections: | |
* - Any flow links that the model is the source of | |
* - Any other connections that the model's parent determines the model is the source of | |
*/ | |
@Override | |
protected List<Link> getModelSourceConnections() { | |
Sources sources = getActivity().getSources(); | |
if (sources == null) { | |
return Collections.emptyList(); | |
} | |
List<Link> result = new ArrayList<Link>(); | |
for(Source source : sources.getChildren()) { | |
if (source.getLink() != null) { | |
result.add(source.getLink()); | |
} | |
} | |
return result; | |
} | |
/** | |
* The model is the target of the following connections: | |
* - Any flow links that the model is the target of | |
* - Any other connections that the model's parent determines the model is the target of | |
*/ | |
@Override | |
protected List<Link> getModelTargetConnections() { | |
Targets targets = getActivity().getTargets(); | |
if (targets == null) { | |
return Collections.emptyList(); | |
} | |
List<Link> result = new ArrayList<Link>(); | |
for(Target target : targets.getChildren()) { | |
if (target.getLink() != null) { | |
result.add(target.getLink()); | |
} | |
} | |
return result; | |
} | |
/** | |
* Returns the connection anchor of a source connection which | |
* is at the given point. | |
* | |
* @return ConnectionAnchor. | |
*/ | |
public ConnectionAnchor getSourceConnectionAnchor(Request request) { | |
// TODO: Translate point to figure, call other method | |
return getSourceConnectionAnchor((ConnectionEditPart)null); | |
} | |
/** | |
* Returns the connection anchor of a target connection which | |
* is at the given point. | |
* | |
* @return ConnectionAnchor. | |
*/ | |
public ConnectionAnchor getTargetConnectionAnchor(Request request) { | |
// TODO: Translate point to figure, call other method | |
return getTargetConnectionAnchor((ConnectionEditPart)null); | |
} | |
/** | |
* Because ActivityEditPart implements NodeEditPart, there may be connections | |
* to or from this node that are affected by model changes. Refresh the | |
* connections now. | |
* | |
* If the model change involves the addition of an ActivityExtension, add an adapter | |
* to that extension. | |
*/ | |
@Override | |
protected void handleModelChanged() { | |
super.handleModelChanged(); | |
refreshSourceConnections(); | |
refreshTargetConnections(); | |
} | |
/** | |
* Convenience method to get the model as a BPEL Activity | |
* @return the model as a BPEL activity | |
*/ | |
public Activity getActivity() { | |
return (Activity) getModel(); | |
} | |
/** | |
* Override so we can set the constraint for every XY placed object | |
*/ | |
@Override | |
public void refreshVisuals() { | |
Rectangle r = null; | |
if (this.getParent() instanceof FlowEditPart) { | |
EditPart root = getRoot(); | |
if (root instanceof GraphicalBPELRootEditPart) { | |
Point p = ModelHelper.getLocation(getActivity()); | |
if (p.x == Integer.MIN_VALUE) { | |
// HACK: We don't know its position, pretend it's at 0, 0. This should only | |
// be necessary during brief edge-case situations (like during startup before | |
// we've done auto-layout on flows without metadata).. | |
p = new Point(0, 0); | |
} | |
Dimension s = new Dimension(-1, -1); | |
r = new Rectangle(p, s); | |
} | |
} | |
if (r != null) { | |
((GraphicalEditPart) getParent()).setLayoutConstraint(this, getFigure(), r); | |
} | |
super.refreshVisuals(); | |
} | |
public ConnectionAnchor getTargetConnectionAnchorForTargetChild(ConnectionEditPart connEditPart) { | |
return null; | |
} | |
protected void refreshDrawerHoverHelp() { | |
IHoverHelper helper = null; | |
try { | |
helper = BPELUIRegistry.getInstance().getHoverHelper(); | |
if (helper == null) { | |
return ; | |
} | |
} catch (CoreException ce) { | |
getFigure().setToolTip(null); | |
BPELUIPlugin.log(ce); | |
return ; | |
} | |
// Get the marker and pass it to the hover helper | |
ArrayList<IMarker> listOfMarkers = new ArrayList<IMarker>(); | |
IMarkerHolder holder = BPELUtil.adapt(getActivity(), IMarkerHolder.class); | |
for (IMarker m : holder.getMarkers(getActivity()) ) { | |
// if we can't see it, then we will not look at it | |
if (m.getAttribute(IModelMarkerConstants.DECORATION_MARKER_VISIBLE_ATTR, true) == false) { | |
continue; | |
} | |
String where = m.getAttribute(IModelMarkerConstants.DECORATION_GRAPHICAL_MARKER_ANCHOR_POINT_ATTR,EMPTY_STRING); | |
if (mouseLocation == 1) { | |
// Top drawer | |
if (where.equals( IBPELUIConstants.MARKER_ANCHORPOINT_DRAWER_TOP )) { | |
listOfMarkers.add(m); | |
} | |
} else { | |
// bottom drawer | |
if (where.equals( IBPELUIConstants.MARKER_ANCHORPOINT_DRAWER_BOTTOM )) { | |
listOfMarkers.add(m); | |
} | |
} | |
} | |
if (listOfMarkers.size() == 0) { | |
return; | |
} | |
String text = null; | |
if (listOfMarkers.size() == 1) { | |
text = helper.getHoverHelp( listOfMarkers.get(0) ); | |
} else { | |
StringBuilder sb = new StringBuilder(); | |
sb.append("There are ").append(listOfMarkers.size()).append(" issues here:\n"); | |
for(IMarker m : listOfMarkers) { | |
String t = helper.getHoverHelp (m) ; | |
sb.append("o ").append(t).append("\n"); | |
} | |
text = sb.toString(); | |
} | |
if (text == null || text.length() < 1) { | |
getFigure().setToolTip(null); | |
} else { | |
getFigure().setToolTip(new Label(text)); | |
} | |
} | |
protected MouseMotionListener getMouseMotionListener() { | |
if (mouseMotionListener == null) { | |
this.mouseMotionListener = new MouseMotionListener() { | |
public void mouseDragged(MouseEvent me) { | |
} | |
public void mouseEntered(MouseEvent me) { | |
} | |
public void mouseExited(MouseEvent me) { | |
} | |
public void mouseHover(MouseEvent me) { | |
} | |
public void mouseMoved(MouseEvent me) { | |
DrawerBorder border = getDrawerBorder(); | |
if (border == null) return; | |
int inTop = border.isPointInTopDrawer(me.x, me.y) ? 1 : 0; | |
int inBottom = border.isPointInBottomDrawer(me.x, me.y) ? 2 : 0; | |
// If mouse stayed in the same place it was in last time, do nothing | |
int newLocation = inTop | inBottom; | |
if (newLocation == mouseLocation) return; | |
mouseLocation = newLocation; | |
refreshHoverHelp(); | |
} | |
}; | |
} | |
return mouseMotionListener; | |
} | |
protected abstract DrawerBorder getDrawerBorder(); | |
/** | |
* Override the refreshHoverHelp method from BPELEditPart. This method | |
* will refresh either the regular hover help, or the drawer hover help | |
* if that is what is currently being displayed. | |
*/ | |
@Override | |
public void refreshHoverHelp() { | |
switch (mouseLocation) { | |
case 1: | |
refreshDrawerHoverHelp(); | |
return; | |
case 2: | |
refreshDrawerHoverHelp(); | |
return; | |
} | |
super.refreshHoverHelp(); | |
} | |
public IFigure getMainActivityFigure() { | |
return getFigure(); | |
} | |
public ConnectionAnchor getSourceConnectionAnchor(ConnectionEditPart connEditPart) { | |
// Provide default anchor for Links. | |
if (connEditPart == null || connEditPart instanceof LinkEditPart) { | |
if(ModelHelper.isHorizontalLayout(getModel())){ | |
return new CenteredConnectionAnchor(getMainActivityFigure(), CenteredConnectionAnchor.RIGHT_INNER, 0); | |
}else | |
return new CenteredConnectionAnchor(getMainActivityFigure(), CenteredConnectionAnchor.BOTTOM, 0); | |
} | |
return null; | |
} | |
public ConnectionAnchor getTargetConnectionAnchor(ConnectionEditPart connEditPart) { | |
// Provide default anchor for Links. | |
if (connEditPart == null || connEditPart instanceof LinkEditPart) { | |
if(ModelHelper.isHorizontalLayout(getModel())){ | |
return new CenteredConnectionAnchor(getMainActivityFigure(), CenteredConnectionAnchor.LEFT_INNER, 0); | |
}else | |
return new CenteredConnectionAnchor(getMainActivityFigure(), CenteredConnectionAnchor.TOP, 0); | |
} | |
return null; | |
} | |
} |