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