Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.yaoqiang.graph.view.Graph Maven / Gradle / Ivy
package org.yaoqiang.graph.view;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.swing.JOptionPane;
import org.w3c.dom.Element;
import org.yaoqiang.bpmn.model.BPMNModelUtils;
import org.yaoqiang.bpmn.model.elements.XMLElement;
import org.yaoqiang.bpmn.model.elements.activities.SubProcess;
import org.yaoqiang.bpmn.model.elements.artifacts.Association;
import org.yaoqiang.bpmn.model.elements.artifacts.Group;
import org.yaoqiang.bpmn.model.elements.artifacts.TextAnnotation;
import org.yaoqiang.bpmn.model.elements.collaboration.Participant;
import org.yaoqiang.bpmn.model.elements.core.common.FlowNode;
import org.yaoqiang.bpmn.model.elements.core.foundation.BaseElement;
import org.yaoqiang.bpmn.model.elements.core.infrastructure.Definitions;
import org.yaoqiang.bpmn.model.elements.data.DataAssociation;
import org.yaoqiang.bpmn.model.elements.data.DataInput;
import org.yaoqiang.bpmn.model.elements.data.DataObject;
import org.yaoqiang.bpmn.model.elements.data.DataObjectReference;
import org.yaoqiang.bpmn.model.elements.data.DataOutput;
import org.yaoqiang.bpmn.model.elements.data.DataStoreReference;
import org.yaoqiang.bpmn.model.elements.data.ItemAwareElement;
import org.yaoqiang.graph.model.GraphModel;
import org.yaoqiang.graph.util.GraphUtils;
import org.yaoqiang.graph.util.TooltipBuilder;
import org.yaoqiang.util.Constants;
import org.yaoqiang.util.Resources;
import com.mxgraph.model.mxCell;
import com.mxgraph.model.mxGeometry;
import com.mxgraph.model.mxGraphModel;
import com.mxgraph.model.mxICell;
import com.mxgraph.util.mxConstants;
import com.mxgraph.util.mxEvent;
import com.mxgraph.util.mxEventObject;
import com.mxgraph.util.mxPoint;
import com.mxgraph.util.mxRectangle;
import com.mxgraph.util.mxUtils;
import com.mxgraph.view.mxCellState;
import com.mxgraph.view.mxGraph;
/**
* Graph
*
* @author Shi Yaoqiang([email protected] )
*/
public class Graph extends mxGraph {
protected Map bpmnElementMap = new HashMap();
protected Map externalDefinitions = new HashMap();
protected TooltipBuilder tooltipBuilder;
public Graph(mxGraphModel model) {
super(model, null);
setVertexLabelsMovable(true);
setResetViewOnRootChange(false);
setDisconnectOnMove(false);
setAllowDanglingEdges(false);
setResetEdgesOnConnect(false);
setMultigraph(false);
setConnectableEdges(Constants.SETTINGS.getProperty("connectableEdge", "0").equals("1"));
setCellsDisconnectable(false);
setKeepEdgesInForeground(true);
setGridSize(Integer.parseInt(Constants.SETTINGS.getProperty("gridSize", "5")));
this.tooltipBuilder = new TooltipBuilder();
}
public final Definitions getBpmnModel() {
return getModel().getBpmnModel();
}
public Map getBpmnElementMap() {
return bpmnElementMap;
}
public void clearBpmnModel() {
getBpmnModel().clear();
externalDefinitions.clear();
bpmnElementMap.clear();
getBpmnModel().setName("");
}
public final void setBpmnElementMap(Map bpmnElementMap) {
this.bpmnElementMap = bpmnElementMap;
}
public Map getExternalDefinitions() {
return externalDefinitions;
}
public GraphModel getModel() {
return (GraphModel) model;
}
public GraphView getView() {
return (GraphView) view;
}
protected GraphView createGraphView() {
return new GraphView(this);
}
public String getToolTipForCell(Object cell) {
return tooltipBuilder.getTooltip(this, (mxCell) cell);
}
public String convertValueToString(Object cell) {
if (cell instanceof mxCell) {
Object value = ((mxCell) cell).getValue();
String name = null;
if (value instanceof Element) {
Element elt = (Element) value;
if (isOrganizationElement(cell)) {
name = elt.getAttribute("cn");
if (isOrganization(cell) || isOrganizationRoot(cell)) {
name = elt.getAttribute("o");
} else if (isOrganizationalUnit(cell)) {
name = elt.getAttribute("ou");
}
} else {
name = elt.getAttribute("value");
}
return name;
} else if (value instanceof BaseElement) {
if (value instanceof TextAnnotation) {
return ((BaseElement) value).get("text").toValue();
} else if (value instanceof Group) {
return BPMNModelUtils.getCategoryValueString(getBpmnModel(), ((Group) value).getCategoryValueRef());
} else if (value instanceof Association || value instanceof DataAssociation) {
return "";
} else if (value instanceof DataStoreReference) {
String dsRef = ((DataStoreReference) value).getDataStoreRef();
if (dsRef.length() == 0) {
return "";
} else {
return getBpmnModel().getDataStore(dsRef).getName();
}
} else if (value instanceof ItemAwareElement) {
String dataState = null;
if (value instanceof DataObjectReference) {
DataObject obj = ((DataObjectReference) value).getRefDataObject();
if (obj == null) {
return "";
} else {
name = obj.getName();
dataState = obj.getDataState();
}
} else if (value instanceof DataInput || value instanceof DataOutput) {
name = ((BaseElement) value).get("name").toValue();
dataState = ((ItemAwareElement) value).getDataState();
}
if (dataState == null || dataState.length() == 0) {
return name;
} else {
return name + "\n[" + dataState + "]";
}
}
return ((BaseElement) value).get("name").toValue();
}
}
return super.convertValueToString(cell);
}
public void cellLabelChanged(Object cell, Object newValue, boolean autoSize) {
if (cell instanceof mxCell && newValue != null) {
Object value = ((mxCell) cell).getValue();
if (value instanceof Element) {
String label = newValue.toString();
Element elt = (Element) value;
// Clones the value for correct undo/redo
elt = (Element) elt.cloneNode(true);
String attrName = "value";
if (isOrganizationElement(cell)) {
attrName = "cn";
if (isOrganization(cell) || isOrganizationRoot(cell)) {
attrName = "o";
} else if (isOrganizationalUnit(cell)) {
attrName = "ou";
}
}
elt.setAttribute(attrName, label);
newValue = elt;
} else if (value instanceof BaseElement && newValue instanceof String) {
String label = newValue.toString();
BaseElement baseElement = (BaseElement) ((BaseElement) value).clone();
if (value instanceof TextAnnotation) {
baseElement.set("text", label);
} else if (value instanceof ItemAwareElement) {
int index = label.lastIndexOf("\n[");
if (index > 0) {
String name = label.substring(0, index);
String state = label.substring(index + 2, label.length() - 1);
baseElement.set("name", name);
((ItemAwareElement) baseElement).setDataState(state);
} else {
baseElement.set("name", label);
((ItemAwareElement) baseElement).setDataState("");
}
} else {
baseElement.set("name", label);
}
newValue = baseElement;
}
if (newValue.toString().length() == 0 && getModel().isLinkEvent(cell)) {
JOptionPane.showMessageDialog(null, Resources.get("WarningLinkEventMustHaveAName"), "Validation Error!", JOptionPane.WARNING_MESSAGE);
return;
}
if (!(value instanceof BaseElement) && value.equals(newValue)) {
return;
}
model.beginUpdate();
if (getModel().isChoreographyParticipant(cell)) {
int index = ((mxCell) cell).getId().indexOf("_part_");
String partId = ((mxCell) cell).getId().substring(index + 6);
String actId = ((mxCell) cell).getId().substring(0, index);
int option = JOptionPane.YES_OPTION;
Map participants = getAllParticipants();
if (participants.get(newValue) == null && getModel().hasParticipantRef((mxCell) cell, partId)) {
option = JOptionPane.showConfirmDialog(null, Resources.get("InfoYesToRenameSelectedParticipantOrNoToCreateNewParticipant"),
Resources.get("InfoRenameOrCreate"), JOptionPane.YES_NO_OPTION);
if (option == JOptionPane.NO_OPTION) {
String newPartId = getModel().createId(cell);
mxCell newCell = (mxCell) model.cloneCells(new Object[] { cell }, false)[0];
newCell.setValue(new Participant(newValue.toString()));
newCell.setId(actId + "_part_" + newPartId);
newCell.setParent(null);
Object parent = ((mxCell) cell).getParent();
removeCells(new Object[] { cell });
addCell(newCell, parent);
if (this.isAdditionalChoreographyParticipant(newCell)) {
orderCells(false, new Object[] { newCell });
} else {
orderCells(true, new Object[] { newCell });
}
cell = newCell;
} else {
Map participantCells = getModel().getAllChoreographyParticipants();
for (Entry part : participantCells.entrySet()) {
if (part.getKey().endsWith(partId)) {
model.setValue(part.getValue(), newValue);
}
}
}
} else if (participants.get(newValue) != null) {
String newPartId = participants.get(newValue);
mxCell newCell = (mxCell) model.cloneCells(new Object[] { cell }, false)[0];
newCell.setId(actId + "_part_" + newPartId);
if (getModel().getCell(newCell.getId()) != null) {
JOptionPane.showMessageDialog(null, Resources.get("WarningSubChoreographyMustNotInvolveDuplicatedParticipants"), "Validation Error!",
JOptionPane.WARNING_MESSAGE);
return;
}
newCell.setParent(null);
newCell.setValue(newValue);
removeCells(new Object[] { cell });
addCell(newCell, ((mxCell) cell).getParent());
if (this.isAdditionalChoreographyParticipant(newCell)) {
orderCells(false, new Object[] { newCell });
} else {
orderCells(true, new Object[] { newCell });
}
cell = newCell;
} else if (!getModel().hasParticipantRef((mxCell) cell, partId)) {
model.setValue(cell, newValue);
}
} else {
model.setValue(cell, newValue);
}
model.endUpdate();
}
if (newValue != null) {
fireEvent(new mxEventObject(mxEvent.LABEL_CHANGED, "cells", new Object[] { cell }));
}
}
public boolean isLaneMovable(Object cell) {
if (getModel().isLane(cell) && model.getChildCount(model.getParent(cell)) > 1) {
return true;
}
return false;
}
public boolean isLabelMovable(Object cell) {
return !isCellLocked(cell)
&& ((model.isEdge(cell) && isEdgeLabelsMovable()) || ((getModel().isGateway(cell) || getModel().isEvent(cell) || getModel().isDataObject(cell)
|| getModel().isDataInput(cell) || getModel().isDataOutput(cell) || getModel().isDataStore(cell) || getModel().isConversationNode(cell)
|| getModel().isMessage(cell) || isImageArtifact(cell)) && isVertexLabelsMovable()));
}
public boolean isCellSelectable(Object cell) {
return isCellsSelectable() && !getModel().isChoreographyTask(cell) && !getModel().isChoreographySubprocess(cell)
&& !getModel().isChoreographyParticipant(cell) && !isOrganizationName(cell);
}
public boolean isCellCollapsed(Object cell) {
return isCollapsedSwimlane(cell) || model.isCollapsed(cell);
}
public boolean isCellEditable(Object cell) {
if (getModel().isAssociation(cell) || getModel().isDataAssociation(cell) || isOrganizationName(cell)) {
return false;
}
return true;
}
public boolean isCellResizable(Object cell) {
if (((mxCell) cell).getStyle() != null
&& (getModel().isLane(cell) && hasChildLane(cell) || isAutoPool(cell) && hasChildLane(cell) || getModel().isDataObject(cell)
|| getModel().isDataInput(cell) || getModel().isDataOutput(cell) || getModel().isDataStore(cell) || getModel().isMessage(cell)
|| getModel().isChoreographyTask(cell) || getModel().isChoreographySubprocess(cell) || getModel().isChoreographyParticipant(cell)
|| getModel().isConversationNode(cell) || getModel().isEvent(cell) || getModel().isGateway(cell) || isOrganizationName(cell) || isOrganizationElement(cell))) {
return false;
}
return super.isCellResizable(cell);
}
public boolean isCellFoldable(Object cell, boolean collapse) {
return (!getModel().isCallActivity(cell) && !isSubChoreography(cell) && !isChoreography(cell) && !getModel().isTask(cell))
&& !getModel().isMessageFlow(cell) && model.getChildCount(cell) > 0 || getModel().isSubProcess(cell)
|| getModel().isChoreographySubprocess(cell) || isSwimlane(cell);
}
public boolean isCellMovable(Object cell) {
if (getModel().isLane(cell) && model.getChildCount(cell) > 1 || getModel().isChoreographyTask(cell) || getModel().isChoreographySubprocess(cell)
|| getModel().isChoreographyParticipant(cell) || isOrganizationName(cell)) {
return false;
}
return super.isCellMovable(cell) || getModel().isBoundaryEvent(cell) || getModel().isMessage(cell);
}
public boolean isValidDropTarget(Object cell, Object[] cells) {
if (cells == null) {
cells = getSelectionCells();
}
if (hasChildNonLane(cell) && isSwimlane(cells[0]) && model.getParent(cells[0]) != cell) {
return false;
}
if (hasChildLane(cell) && !isSwimlane(cells[0])) {
return false;
}
if (getModel().isSubProcess(cell) && isSwimlane(cells[0])) {
return false;
}
if (model.isCollapsed(cell) && isSwimlane(cell)) {
return false;
}
if (isSwimlane(cell) && getModel().isPool(cells[0])) {
return false;
}
if (getModel().isChoreographyTask(cell) || getModel().isCollapsedSubProcess(cell) && getModel().isChoreographySubprocess(cell)) {
return false;
}
if ((getModel().isTask(cell) || getModel().isCallActivity(cell) || getModel().isCollapsedSubProcess(cell))
&& (getConnections(cells[0]).length > 0 || getModel().isLinkEvent(cells[0]) || getModel().isThrowEvent(cells[0]))) {
return false;
}
if ((getModel().isTask(cell) || getModel().isCallActivity(cell))
&& (model.getChildCount(cell) > 3 || !getModel().isIntermediateEvent(cells[0]) || cells.length > 1)) {
return false;
}
if (getModel().isCollapsedSubProcess(cell)
&& (!getModel().isEvent(cells[0]) || getModel().isStartEvent(cells[0]) && !getModel().isNoneEvent(cells[0]) || getModel()
.isThrowEvent(cells[0]) && !getModel().isEndEvent(cells[0]) && !getModel().isNoneEvent(cells[0]))) {
return false;
}
if (getModel().isReceiveTask(cell) && getModel().isIntermediateEvent(cells[0])) {
Object[] edges = getIncomingEdges(cell);
if (edges.length > 0 && getModel().isEventGateway(model.getTerminal(edges[0], true))) {
return false;
}
}
if (getModel().isBoundaryEvent(cells[0]) && model.getParent(cells[0]) != cell) {
return false;
}
if (getModel().isGroupArtifact(cells[0]) && !getModel().isSubProcess(cell) && !isSubChoreography(cell)) {
return false;
}
if (getModel().isAnnotation(cells[0]) || (isChoreography(cells[0]) || isSubChoreography(cells[0]))
&& (!getModel().isChoreographySubprocess(cell) || getModel().isChoreographySubprocess(cell) && model.isAncestor(cells[0], cell))) {
return false;
}
if (!getModel().isChoreographyParticipant(cells[0]) && !getModel().isChoreographySubprocess(cells[0]) && !getModel().isChoreographyTask(cells[0])
&& (isChoreography(cell) || isSubChoreography(cell))) {
return false;
}
if (!getModel().isGroupArtifact(cells[0]) && !getModel().isEvent(cells[0]) && !getModel().isGateway(cells[0]) && !getModel().isMessage(cells[0])
&& !isChoreography(cells[0]) && !isSubChoreography(cells[0]) && getModel().isChoreographySubprocess(cell)) {
return false;
}
if (cells != null) {
for (int i = 0; i < cells.length; i++) {
if (isSubChoreography(cells[i]) && getModel().isChoreographySubprocess(cell) && model.isAncestor(cells[i], cell))
return false;
if (getModel().isSubProcess(cells[i]) && getModel().isSubProcess(cell) && model.isAncestor(cells[i], cell))
return false;
if (isSwimlane(cells[i]) && isSwimlane(cell) && model.isAncestor(cells[i], cell))
return false;
}
}
if (!isPlane(cell) && getModel().isConversationNode(cells[0])) {
return false;
}
if (!getModel().isMessageFlow(cell) && !isPlane(cell) && !getModel().isChoreographySubprocess(cell) && getModel().isMessage(cells[0])) {
return false;
}
if (getModel().isMessageFlow(cell) && model.getChildCount(cell) > 0) {
return false;
}
return cell != null
&& cells != null
&& cell != cells[0]
&& ((isSplitEnabled() && isSplitTarget(cell, cells)) || getModel().isMessageFlow(cell) && getModel().isMessage(cells[0]) || (!model
.isEdge(cell) && (isSwimlane(cell) || getModel().isTask(cell) && getModel().isIntermediateEvent(cells[0])
|| getModel().isCallActivity(cell) && getModel().isIntermediateEvent(cells[0]) || getModel().isSubProcess(cell)
|| getModel().isChoreographySubprocess(cell) || (model.getChildCount(cell) > 0 && !isCellCollapsed(cell)))));
}
public boolean isSplitTarget(Object target, Object[] cells) {
if (getModel().isMessageFlow(target) || isCompensationAssociation(target) || getModel().isDataAssociation(target) || getModel().isAssociation(target)) {
return false;
}
if (cells == null || cells.length != 1 || getModel().isArtifact(cells[0]) || isSwimlane(cells[0]) || getModel().isStartEvent(cells[0])
|| getModel().isEndEvent(cells[0]) || getModel().isDataObject(cells[0]) || getModel().isDataInput(cells[0])
|| getModel().isDataOutput(cells[0]) || getModel().isDataStore(cells[0])) {
return false;
}
return super.isSplitTarget(target, cells);
}
public Object splitEdge(Object edge, Object[] cells, double dx, double dy) {
if (getModel().isMessage(cells[0])) {
return null;
}
if (getModel().isSubProcess(cells[0])) {
mxGeometry geo = ((mxICell) cells[0]).getGeometry();
geo.setAlternateBounds(new mxRectangle(0, 0, Constants.ACTIVITY_WIDTH, Constants.ACTIVITY_HEIGHT));
model.setGeometry(cells[0], geo);
foldCells(true, false, new Object[] { cells[0] });
}
Object parent = model.getParent(edge);
Object source = model.getTerminal(edge, true);
Object target = model.getTerminal(edge, false);
model.beginUpdate();
try {
cellsMoved(cells, dx, dy, false, false);
cellsAdded(cells, parent, model.getChildCount(parent), null, null, true);
Object leftEdge = cloneCells(new Object[] { edge })[0];
Object rightEdge = cloneCells(new Object[] { edge })[0];
cellsAdded(new Object[] { leftEdge }, parent, model.getChildCount(parent), source, cells[0], false);
cellsAdded(new Object[] { rightEdge }, parent, model.getChildCount(parent), cells[0], target, false);
removeCells(new Object[] { edge }, true);
fireEvent(new mxEventObject(mxEvent.SPLIT_EDGE, "edge", edge, "cells", cells, "dx", dx, "dy", dy));
} finally {
model.endUpdate();
}
return edge;
}
public mxRectangle getBoundsForGroup(Object group, Object[] children, double border) {
mxRectangle result = getBoundingBoxFromGeometry(children);
if (result != null) {
if (isSwimlane(group)) {
mxRectangle size = getStartSize(group);
result.setX(result.getX() - size.getWidth());
result.setY(result.getY() - size.getHeight());
result.setWidth(result.getWidth() + size.getWidth());
result.setHeight(result.getHeight() + size.getHeight());
} else if (getModel().isSubProcess(group)) {
if (result.getWidth() <= Constants.FOLDED_SUBPROCESS_WIDTH) {
result.setWidth(Constants.FOLDED_SUBPROCESS_WIDTH);
}
if (result.getHeight() <= Constants.FOLDED_SUBPROCESS_HEIGHT) {
result.setHeight(Constants.FOLDED_SUBPROCESS_HEIGHT);
}
}
// Adds the border
result.setX(result.getX() - border);
result.setY(result.getY() - border);
result.setWidth(result.getWidth() + 2 * border);
result.setHeight(result.getHeight() + 2 * border);
}
return result;
}
public Object groupCells(Object group, double border, Object[] cells) {
if (cells == null) {
cells = mxUtils.sortCells(getSelectionCells(), true);
}
cells = getCellsForGroup(cells);
if (group == null) {
group = createGroupCell(cells);
}
mxRectangle bounds = getBoundsForGroup(group, cells, border);
if (cells.length > 0 && bounds != null) {
// Uses parent of group or previous parent of first child
Object parent = model.getParent(group);
if (parent == null) {
parent = model.getParent(cells[0]);
}
model.beginUpdate();
try {
// Checks if the group has a geometry and
// creates one if one does not exist
if (getCellGeometry(group) == null) {
model.setGeometry(group, new mxGeometry());
}
// Adds the children into the group and moves
int index = model.getChildCount(group);
cellsAdded(cells, group, index, null, null, false);
cellsMoved(cells, -bounds.getX(), -bounds.getY(), false, true);
// Adds the group into the parent and resizes
index = model.getChildCount(parent);
cellsAdded(new Object[] { group }, parent, index, null, null, false, false);
cellsResized(new Object[] { group }, new mxRectangle[] { bounds });
// ==============start==============
for (Object cell : cells) {
if (model.isVertex(cell)) {
List edges = Arrays.asList(getConnections(cell));
for (Object edge : edges) {
String id = ((mxCell) edge).getId();
Object source = model.getTerminal(edge, true);
Object target = model.getTerminal(edge, false);
if (!Arrays.asList(cells).contains(source)) {
model.setTerminal(edge, group, false);
Object value = model.getValue(target);
if (value instanceof FlowNode) {
((FlowNode) value).removeIncoming(id);
}
} else if (!Arrays.asList(cells).contains(target)) {
model.setTerminal(edge, group, true);
Object value = model.getValue(source);
if (value instanceof FlowNode) {
((FlowNode) value).removeOutgoing(id);
}
}
}
}
}
// ==============end================
fireEvent(new mxEventObject(mxEvent.GROUP_CELLS, "group", group, "cells", cells, "border", border));
} finally {
model.endUpdate();
}
}
return group;
}
public Object[] getCellsForGroup(Object[] cells) {
List result = new ArrayList(cells.length);
if (cells.length > 0) {
Object parent = model.getParent(cells[0]);
result.add(cells[0]);
// Filters selection cells with the same parent
for (int i = 1; i < cells.length; i++) {
if (model.getParent(cells[i]) == parent) {
result.add(cells[i]);
}
}
}
Set tmp = new HashSet();
for (Object cell : result) {
if (model.isEdge(cell)) {
if (!result.contains(model.getTerminal(cell, true)) || !result.contains(model.getTerminal(cell, false))) {
tmp.add(cell);
}
}
}
result.removeAll(tmp);
Set addEdges = new HashSet();
for (Object cell : result) {
if (model.isVertex(cell)) {
List edges = Arrays.asList(getConnections(cell));
for (Object edge : edges) {
Object source = model.getTerminal(edge, true);
Object target = model.getTerminal(edge, false);
if (result.contains(source) && result.contains(target) && !result.contains(edge)) {
addEdges.add(edge);
}
}
}
}
result.addAll(addEdges);
return result.toArray();
}
public Object createGroupCell(Object[] cells) {
mxGeometry geo = new mxGeometry();
geo.setAlternateBounds(new mxRectangle(0, 0, 85, 55));
mxCell group = new mxCell(new SubProcess(Resources.get("subprocess")), geo, "subprocess");
group.setVertex(true);
return group;
}
public Object[] foldCells(boolean collapse, boolean recurse, Object[] cells) {
if (cells == null) {
cells = getFoldableCells(getSelectionCells(), collapse);
if (cells == null || cells.length < 1)
return null;
}
model.beginUpdate();
try {
if (getModel().isSubProcess(cells[0]) || getModel().isChoreographySubprocess(cells[0])) {
Object[] selectedCells = cells;
if (getModel().isCollapsedSubProcess(cells[0])) {
if (isSubChoreography(cells[0])) {
selectedCells = new Object[] { GraphUtils.getChoreographyActivity(this, cells[0]) };
}
setCellStyles(mxConstants.STYLE_VERTICAL_ALIGN, mxConstants.ALIGN_TOP, selectedCells);
if (getAttechedEventCount(cells[0]) > 0) {
mxCell subflow = (mxCell) cells[0];
for (Object eventCell : getAttechedEvents(subflow)) {
mxGeometry eventGeo = (mxGeometry) model.getGeometry(eventCell).clone();
mxRectangle alterBounds = eventGeo.getAlternateBounds();
if (alterBounds != null) {
alterBounds.setX(eventGeo.getOffset().getX());
alterBounds.setY(eventGeo.getOffset().getY());
mxPoint offset = new mxPoint(alterBounds.getHeight(), alterBounds.getWidth());
eventGeo.setOffset(offset);
model.setGeometry(eventCell, eventGeo);
}
}
}
} else {
if (isSubChoreography(cells[0])) {
selectedCells = new Object[] { GraphUtils.getChoreographyActivity(this, cells[0]) };
}
setCellStyles(mxConstants.STYLE_VERTICAL_ALIGN, mxConstants.ALIGN_MIDDLE, selectedCells);
if (getAttechedEventCount(cells[0]) > 0) {
mxCell subflow = (mxCell) cells[0];
mxGeometry geo = subflow.getGeometry();
mxRectangle rect = geo.getAlternateBounds();
if (rect != null && (rect.getHeight() <= 65 || rect.getWidth() <= 95)) {
rect.setHeight(65);
rect.setWidth(95);
geo.setAlternateBounds(rect);
model.setGeometry(subflow, geo);
}
for (Object eventCell : getAttechedEvents(subflow)) {
mxGeometry eventGeo = (mxGeometry) model.getGeometry(eventCell).clone();
Point offset = null;
mxRectangle alterBounds = eventGeo.getAlternateBounds();
if (alterBounds == null) {
alterBounds = new mxRectangle();
alterBounds.setHeight(eventGeo.getOffset().getX());
alterBounds.setWidth(eventGeo.getOffset().getY());
if (eventGeo.getX() == 1 || eventGeo.getY() == 0 && eventGeo.getOffset().getX() < 0) {
alterBounds.setX(eventGeo.getOffset().getX());
alterBounds.setY(10);
} else if (eventGeo.getY() == 1 || eventGeo.getX() == 0 && eventGeo.getOffset().getY() < 0) {
alterBounds.setX(50);
alterBounds.setY(eventGeo.getOffset().getY());
}
offset = alterBounds.getPoint();
eventGeo.setAlternateBounds(alterBounds);
} else {
alterBounds.setWidth(eventGeo.getOffset().getY());
alterBounds.setHeight(eventGeo.getOffset().getX());
offset = eventGeo.getAlternateBounds().getPoint();
}
eventGeo.setOffset(new mxPoint(offset));
model.setGeometry(eventCell, eventGeo);
}
}
}
} else if (isSwimlane(cells[0])) {
boolean horizontal = true;
toggleCellStyles(mxConstants.STYLE_HORIZONTAL, horizontal, cells);
mxGeometry geo = model.getGeometry(cells[0]);
mxRectangle rect = geo.getAlternateBounds();
if (rect == null) {
if (isVerticalSwimlane(cells[0])) {
rect = new mxRectangle(geo.getX(), geo.getY(), collapse ? Constants.SWIMLANE_SIZE / 3 : getMinSwimlaneSize(cells[0]), geo.getHeight());
geo.setAlternateBounds(rect);
model.setGeometry(cells[0], geo);
} else {
rect = new mxRectangle(geo.getX(), geo.getY(), geo.getWidth(), collapse ? Constants.SWIMLANE_SIZE / 3 : getMinSwimlaneSize(cells[0]));
geo.setAlternateBounds(rect);
model.setGeometry(cells[0], geo);
}
}
}
cellsFolded(cells, collapse, recurse);
fireEvent(new mxEventObject(mxEvent.FOLD_CELLS, "cells", cells, "collapse", collapse, "recurse", recurse));
} finally {
model.endUpdate();
}
return cells;
}
public void cellsFolded(Object[] cells, boolean collapse, boolean recurse) {
if (cells != null && cells.length > 0) {
model.beginUpdate();
try {
for (int i = 0; i < cells.length; i++) {
if (collapse != isCellCollapsed(cells[i])) {
// ==============start==============
if (!getModel().isSubProcess(cells[i]) && !getModel().isChoreographySubprocess(cells[i])) {
model.setCollapsed(cells[i], collapse);
}
// ==============end================
swapBounds(cells[i], collapse);
if (isExtendParent(cells[i])) {
extendParent(cells[i]);
}
// ==============start==============
if (getModel().isExpandedSubProcess(cells[i])) {
for (Object cell : this.getChildVertices(cells[i])) {
if (isExtendParent(cell)) {
extendParent(cell);
constrainChild(cell);
}
}
}
// ==============end================
if (recurse) {
Object[] children = mxGraphModel.getChildren(model, cells[i]);
cellsFolded(children, collapse, recurse);
}
}
}
fireEvent(new mxEventObject(mxEvent.CELLS_FOLDED, "cells", cells, "collapse", collapse, "recurse", recurse));
} finally {
model.endUpdate();
}
}
}
public void cellsRemoved(Object[] cells) {
if (cells != null && cells.length > 0) {
model.beginUpdate();
try {
for (int i = 0; i < cells.length; i++) {
Collection cellSet = new HashSet();
cellSet.addAll(Arrays.asList(cells));
Object[] edges = getConnections(cells[i]);
// removes edges which are not in cells
for (int j = 0; j < edges.length; j++) {
if (!cellSet.contains(edges[j])) {
removeCells(new Object[] { edges[j] }, true);
}
}
// merge edges
if (edges.length == 2 && getModel().isSequenceFlow(edges[0]) && getModel().isSequenceFlow(edges[1])) {
Object source = null;
Object target = null;
Object edge = null;
Object parent = null;
if (model.getTerminal(edges[0], false) == cells[i] && model.getTerminal(edges[1], true) == cells[i]) {
source = model.getTerminal(edges[0], true);
target = model.getTerminal(edges[1], false);
parent = model.getParent(edges[0]);
edge = cloneCells(new Object[] { edges[0] })[0];
} else if (model.getTerminal(edges[0], true) == cells[i] && model.getTerminal(edges[1], false) == cells[i]) {
source = model.getTerminal(edges[1], true);
target = model.getTerminal(edges[0], false);
parent = model.getParent(edges[1]);
edge = cloneCells(new Object[] { edges[1] })[0];
}
if (edge != null && cells.length == 3) {
cellsAdded(new Object[] { edge }, parent, model.getChildCount(parent), source, target, false);
}
}
model.remove(cells[i]);
}
fireEvent(new mxEventObject(mxEvent.CELLS_REMOVED, "cells", cells));
} finally {
model.endUpdate();
}
}
}
public Object[] moveCells(Object[] cells, double dx, double dy, boolean clone, Object target, Point location) {
// ==============start==============
Object previous_parent = null;
if (clone && cells.length == 1 && (getModel().isBoundaryEvent(cells[0]) || getModel().isAttachedMessage(cells[0]))) {
return null;
}
for (int i = 0; i < cells.length; i++) {
if (clone && model.getChildCount(cells[i]) > 0 && (isChoreography(cells[i]) || isSubChoreography(cells[i]))) {
JOptionPane.showMessageDialog(null, Resources.get("WarningCopyPasteNotApplicableForChoreography"), "Not Applicable",
JOptionPane.WARNING_MESSAGE);
return null;
}
Object[] edges = getConnections(cells[i]);
Set movedEdges = new HashSet(Arrays.asList(edges));
Set movedCells = new HashSet(Arrays.asList(cells));
for (Object movedCell : cells) {
if (getAttechedEventCount(movedCell) > 0) {
for (Object event : getAttechedEvents(movedCell)) {
movedEdges.addAll(new HashSet(Arrays.asList(getConnections(event))));
movedCells.add(event);
}
}
}
if (!getModel().isBoundaryEvent(cells[i]) && !movedEdges.isEmpty()) {
Object moveTarget = target == null ? getDefaultParent() : target;
while (getModel().isLane(moveTarget)) {
moveTarget = getParentCell((mxCell) moveTarget);
}
for (Object edge : movedEdges) {
Object src = model.getTerminal(edge, true);
Object srcParent = getParentCell((mxCell) src);
while (getModel().isLane(srcParent)) {
srcParent = getParentCell((mxCell) srcParent);
}
Object tgt = model.getTerminal(edge, false);
Object tgtParent = getParentCell((mxCell) tgt);
while (getModel().isLane(tgtParent)) {
tgtParent = getParentCell((mxCell) tgtParent);
}
if (getModel().isSequenceFlow(edge)) {
if ((!movedCells.contains(src) || !movedCells.contains(tgt)) && (srcParent != moveTarget || tgtParent != moveTarget)) {
JOptionPane.showMessageDialog(null, Resources.get("WarningInvalidOperation"), "Validation Error!", JOptionPane.WARNING_MESSAGE);
return null;
}
} else if (getModel().isMessageFlow(edge)) {
if (movedCells.contains(src) && (srcParent != moveTarget) || movedCells.contains(tgt) && (tgtParent != moveTarget)) {
return null;
}
}
}
}
Object parent = model.getParent(cells[i]);
if (previous_parent == null) {
previous_parent = parent;
} else if (previous_parent != parent) {
return null;
}
if (getModel().isEventSubProcess(target)) {
if (getModel().isStartEvent(cells[i])) {
if (hasStartEvent(target) && model.getParent(cells[i]) != target) {
JOptionPane.showMessageDialog(null, Resources.get("WarningEventSubProcessMustHaveOneAndOnlyOneStartEvent"), "Validation Error!",
JOptionPane.WARNING_MESSAGE);
return null;
}
}
}
if (getModel().isStartEvent(cells[i]) && getModel().isEventSubProcess(model.getParent(cells[i])) && model.getParent(cells[i]) != target) {
JOptionPane.showMessageDialog(null, Resources.get("WarningEventSubProcessMustHaveOneAndOnlyOneStartEvent"), "Validation Error!",
JOptionPane.WARNING_MESSAGE);
return null;
}
if (hasElementNotAllowedInChoreography()) {
if (isChoreography(cells[i]) || isSubChoreography(cells[i])) {
JOptionPane.showMessageDialog(null, Resources.get("WarningOnlyEventGatewayArtifactAndPoolAreAllowedInChoreography"), "Validation Error!",
JOptionPane.WARNING_MESSAGE);
return null;
}
}
if (hasElementNotAllowedInConversation()) {
if (getModel().isConversationNode(cells[i])) {
JOptionPane.showMessageDialog(null, Resources.get("WarningOnlyParticipantsAreAllowedInConversation"), "Validation Error!",
JOptionPane.WARNING_MESSAGE);
return null;
}
}
if (hasChoreography()) {
if (isElementNotAllowedInChoreography(cells[i]) && !isSwimlane(target) && !getModel().isSubProcess(target) || isSwimlane(cells[i])
&& isSwimlane(target)) {
JOptionPane.showMessageDialog(null, Resources.get("WarningOnlyEventGatewayArtifactAndPoolAreAllowedInChoreography"), "Validation Error!",
JOptionPane.WARNING_MESSAGE);
return null;
}
}
if (hasConversation()) {
if (isElementNotAllowedInConversation(cells[i]) && !isSwimlane(target) && !getModel().isSubProcess(target) || isSwimlane(cells[i])
&& isSwimlane(target)) {
JOptionPane.showMessageDialog(null, Resources.get("WarningOnlyParticipantsAreAllowedInConversation"), "Validation Error!",
JOptionPane.WARNING_MESSAGE);
return null;
}
}
if (getModel().isCancelEndEvent(cells[i]) && !getModel().isTransactionSubProcess(target)) {
JOptionPane.showMessageDialog(null, Resources.get("WarningCancelEndEventCanOnlyBeUsedWithinTranSubProcess"), "Validation Error!",
JOptionPane.WARNING_MESSAGE);
return null;
}
if (getModel().isAdhocSubProcess(target)) {
if (getModel().isStartEvent(cells[i])) {
JOptionPane.showMessageDialog(null, Resources.get("WarningStartEventMustNotBeUsedInAdHocSubProcess"), "Validation Error!",
JOptionPane.WARNING_MESSAGE);
return null;
}
if (getModel().isEndEvent(cells[i])) {
JOptionPane.showMessageDialog(null, Resources.get("WarningEndEventMustNotBeUsedInAdHocSubProcess"), "Validation Error!",
JOptionPane.WARNING_MESSAGE);
return null;
}
}
if (getModel().isSubProcess(target)) {
if (getModel().isDataInput(cells[i]) || getModel().isDataOutput(cells[i])) {
JOptionPane.showMessageDialog(null, Resources.get("WarningSubProcessMustNotDefineDataInputsOutputsDirectly"), "Validation Error!",
JOptionPane.WARNING_MESSAGE);
return null;
}
}
previous_parent = model.getParent(cells[i]);
if (isSwimlane(cells[i])) {
if (target == null || isPlane(target)) {
if (getModel().isLane(cells[i])) {
return null;
}
((mxCell) cells[i]).setConnectable(true);
} else if (isSwimlane(target)) {
if ((isVerticalSwimlane(cells[i]) && !isVerticalSwimlane(target)) || (!isVerticalSwimlane(cells[i]) && isVerticalSwimlane(target))) {
return null;
}
((mxCell) cells[i]).setConnectable(false);
}
} else {
if (clone && model.isEdge(cells[i])) {
mxCell flow = (mxCell) cells[i];
List cellList = Arrays.asList(cells);
if (!cellList.contains(flow.getSource()) || !cellList.contains(flow.getTarget())) {
return null;
}
}
if (getModel().isBoundaryEvent(cells[i]) && target != model.getParent(cells[i])) {
target = model.getParent(cells[i]);
}
if ((getModel().isTask(target) || getModel().isCallActivity(target) && target != getCurrentRoot() || getModel().isCollapsedSubProcess(target))
&& getModel().isEvent(cells[i]) && !getModel().isBoundaryEvent(cells[i])) {
if (getAttechedEventCount(target) < 4) {
mxCell subflow = (mxCell) target;
mxGeometry geo = subflow.getGeometry();
if (geo.getWidth() <= Constants.ACTIVITY_WIDTH) {
geo.grow(5);
getModel().setGeometry(target, geo);
}
}
}
}
}
// ==============end================
if (cells != null && (dx != 0 || dy != 0 || clone || target != null)) {
model.beginUpdate();
try {
if (clone) {
cells = cloneCells(cells, isCloneInvalidEdges());
if (target == null) {
target = getDefaultParent();
}
}
cellsMoved(cells, dx, dy, !clone && isDisconnectOnMove() && isAllowDanglingEdges(), target == null);
if (target != null) {
// ==============start==============
boolean changeParent = false;
Set parents = new HashSet(Arrays.asList(cells));
parents.add(target);
for (Object cell : cells) {
if (!parents.contains(model.getParent(cell))) {
changeParent = true;
break;
}
}
if (changeParent) {
Integer index = model.getChildCount(target);
cellsAdded(cells, target, index, null, null, true);
} else {
for (Object cell : cells) {
if (isExtendParentsOnAdd() && isExtendParent(cell)) {
extendParent(cell);
}
constrainChild(cell);
}
}
// ==============end================
}
fireEvent(new mxEventObject(mxEvent.MOVE_CELLS, "cells", cells, "dx", dx, "dy", dy, "clone", clone, "target", target, "location", location));
} finally {
model.endUpdate();
}
}
return cells;
}
public Object[] alignCells(String align, Object[] cells, Object param) {
if (cells == null) {
cells = getSelectionCells();
}
if (cells != null && cells.length > 1) {
Object parent = model.getParent(cells[0]);
// Finds the required coordinate for the alignment
if (param == null) {
for (int i = 0; i < cells.length; i++) {
mxGeometry geo = getCellGeometry(cells[i]);
if (geo != null && !model.isEdge(cells[i]) && model.getParent(cells[i]) == parent && !getModel().isBoundaryEvent(cells[i])
&& !getModel().isAttachedMessage(cells[i]) && !getModel().isChoreographyTask(cells[i])
&& !getModel().isChoreographySubprocess(cells[i]) && !getModel().isChoreographyParticipant(cells[i])) {
if (param == null) {
if (align == null || align.equals(mxConstants.ALIGN_LEFT)) {
param = geo.getX();
} else if (align.equals(mxConstants.ALIGN_CENTER)) {
param = geo.getX() + geo.getWidth() / 2;
break;
} else if (align.equals(mxConstants.ALIGN_RIGHT)) {
param = geo.getX() + geo.getWidth();
} else if (align.equals(mxConstants.ALIGN_TOP)) {
param = geo.getY();
} else if (align.equals(mxConstants.ALIGN_MIDDLE)) {
param = geo.getY() + geo.getHeight() / 2;
break;
} else if (align.equals(mxConstants.ALIGN_BOTTOM)) {
param = geo.getY() + geo.getHeight();
}
} else {
double tmp = Double.parseDouble(String.valueOf(param));
if (align == null || align.equals(mxConstants.ALIGN_LEFT)) {
param = Math.min(tmp, geo.getX());
} else if (align.equals(mxConstants.ALIGN_RIGHT)) {
param = Math.max(tmp, geo.getX() + geo.getWidth());
} else if (align.equals(mxConstants.ALIGN_TOP)) {
param = Math.min(tmp, geo.getY());
} else if (align.equals(mxConstants.ALIGN_BOTTOM)) {
param = Math.max(tmp, geo.getY() + geo.getHeight());
}
}
}
}
}
// Aligns the cells to the coordinate
model.beginUpdate();
try {
double tmp = Double.parseDouble(String.valueOf(param));
for (int i = 0; i < cells.length; i++) {
mxGeometry geo = getCellGeometry(cells[i]);
if (geo != null && !model.isEdge(cells[i]) && model.getParent(cells[i]) == parent && !getModel().isBoundaryEvent(cells[i])
&& !getModel().isAttachedMessage(cells[i]) && !getModel().isChoreographyTask(cells[i])
&& !getModel().isChoreographySubprocess(cells[i]) && !getModel().isChoreographyParticipant(cells[i])) {
geo = (mxGeometry) geo.clone();
if (align == null || align.equals(mxConstants.ALIGN_LEFT)) {
geo.setX(tmp);
} else if (align.equals(mxConstants.ALIGN_CENTER)) {
geo.setX(tmp - geo.getWidth() / 2);
} else if (align.equals(mxConstants.ALIGN_RIGHT)) {
geo.setX(tmp - geo.getWidth());
} else if (align.equals(mxConstants.ALIGN_TOP)) {
geo.setY(tmp);
} else if (align.equals(mxConstants.ALIGN_MIDDLE)) {
geo.setY(tmp - geo.getHeight() / 2);
} else if (align.equals(mxConstants.ALIGN_BOTTOM)) {
geo.setY(tmp - geo.getHeight());
}
model.setGeometry(cells[i], geo);
if (isResetEdgesOnMove()) {
resetEdges(new Object[] { cells[i] });
}
}
}
fireEvent(new mxEventObject(mxEvent.ALIGN_CELLS, "cells", cells, "align", align));
} finally {
model.endUpdate();
}
}
return cells;
}
public List findTreeRoots(Object parent, boolean isolate, boolean invert) {
List roots = new ArrayList();
if (parent != null) {
int childCount = model.getChildCount(parent);
Object best = null;
int maxDiff = 0;
for (int i = 0; i < childCount; i++) {
Object cell = model.getChildAt(parent, i);
if (model.isVertex(cell) && isCellVisible(cell)) {
Object[] conns = getConnections(cell, (isolate) ? parent : null);
int fanOut = 0;
int fanIn = 0;
for (int j = 0; j < conns.length; j++) {
Object src = view.getVisibleTerminal(conns[j], true);
if (src == cell) {
fanOut++;
} else {
fanIn++;
}
}
if ((invert && fanOut == 0 && fanIn > 0) || (!invert && fanIn == 0 && fanOut > 0)) {
roots.add(0, cell);
}
int diff = (invert) ? fanIn - fanOut : fanOut - fanIn;
if (diff > maxDiff) {
maxDiff = diff;
best = cell;
}
roots.addAll(Arrays.asList(getAttechedEvents(cell)));
}
}
if (roots.isEmpty() && best != null) {
roots.add(best);
}
}
return roots;
}
public Object[] getSelectionCells() {
List cells = new ArrayList();
for (Object cell : Arrays.asList(selectionModel.getCells())) {
if (model.isVertex(cell)) {
cells.add(0, cell);
} else {
cells.add(cell);
}
}
return cells.toArray();
}
public boolean isCellConvertable(Object cell) {
return !hasDataAssociationConnections(cell)
&& (getModel().isIntermediateCatchEvent(cell) || getModel().isIntermediateThrowEvent(cell) || getModel().isTask(cell) || getModel().isGateway(
cell));
}
public Object[] moveCells(String dir, boolean slow) {
double step = 5;
if (slow) {
step = 1;
}
Object[] cells = getSelectionCells();
if (cells != null && cells.length > 0) {
model.beginUpdate();
try {
for (Object cell : cells) {
if (isCellMovable(cell) && !getModel().isBoundaryEvent(cell) && !isSwimlane(cell)) {
mxGeometry geo = getCellGeometry(cell);
if (geo != null) {
geo = (mxGeometry) geo.clone();
if (model.isVertex(cell)) {
if ("up".equals(dir)) {
geo.translate(0, -1 * step);
} else if ("down".equals(dir)) {
geo.translate(0, 1 * step);
} else if ("right".equals(dir)) {
geo.translate(1 * step, 0);
} else if ("left".equals(dir)) {
geo.translate(-1 * step, 0);
}
} else if (model.isEdge(cell)) {
List points = geo.getPoints();
if (points != null) {
for (mxPoint p : points) {
if ("up".equals(dir)) {
p.setY(p.getY() - 1 * step);
} else if ("down".equals(dir)) {
p.setY(p.getY() + 1 * step);
} else if ("right".equals(dir)) {
p.setX(p.getX() + 1 * step);
} else if ("left".equals(dir)) {
p.setX(p.getX() - 1 * step);
}
}
}
}
model.setGeometry(cell, geo);
}
}
}
fireEvent(new mxEventObject(mxEvent.ALIGN_CELLS, "cells", cells, "align", dir));
} finally {
model.endUpdate();
}
}
return cells;
}
public Object[] sameCells(String type) {
Object[] cells = getSelectionCells();
if (cells != null && cells.length > 1) {
mxGeometry geo = getCellGeometry(cells[0]);
if (!getModel().isTask(cells[0]) && !getModel().isCallActivity(cells[0]) && !getModel().isCollapsedSubProcess(cells[0]) && !isSwimlane(cells[0])
&& !isOrganizationElement(cells[0])) {
geo = getCellGeometry(cells[1]);
}
double width = geo.getWidth();
double height = geo.getHeight();
boolean isSwimlane = isSwimlane(cells[0]) && (hasChildNonLane(cells[0]) || isEmptySwimlane(cells[0]));
boolean isVerticalSwimlane = isVerticalSwimlane(cells[0]);
model.beginUpdate();
try {
for (Object cell : cells) {
geo = getCellGeometry(cell);
if (geo != null) {
geo = (mxGeometry) geo.clone();
if (isSwimlane && isSwimlane(cell) && (hasChildNonLane(cell) || isEmptySwimlane(cell))
&& isVerticalSwimlane == isVerticalSwimlane(cell)) {
if (isVerticalSwimlane) {
geo.setWidth(width);
} else {
geo.setHeight(height);
}
} else if (getModel().isTask(cell) || getModel().isCallActivity(cell) || getModel().isSubProcess(cell) || isSwimlane(cell)
|| isOrganizationElement(cell)) {
if (type == null || type.length() == 0) {
geo.setWidth(width);
geo.setHeight(height);
} else if (type.equals(Constants.HEIGHT)) {
geo.setHeight(height);
} else if (type.equals(Constants.WIDTH)) {
geo.setWidth(width);
}
}
model.setGeometry(cell, geo);
}
}
fireEvent(new mxEventObject(mxEvent.ALIGN_CELLS, "cells", cells, "align", type));
} finally {
model.endUpdate();
}
}
return cells;
}
public Object[] distributeCells(String type) {
Object[] cells = getSelectionCells();
if (cells != null && cells.length > 2) {
Object parent = null;
mxGeometry geo = null;
List cells4align = new ArrayList();
for (Object cell : cells) {
if (!model.isEdge(cell) && (parent == null || model.getParent(cell) == parent) && !getModel().isBoundaryEvent(cell)
&& !getModel().isAttachedMessage(cell) && !getModel().isChoreographyTask(cell) && !getModel().isChoreographySubprocess(cell)
&& !getModel().isChoreographyParticipant(cell)) {
if (parent == null) {
parent = model.getParent(cell);
}
cells4align.add(cell);
}
}
if (type.equals(mxConstants.ALIGN_CENTER)) {
Collections.sort(cells4align, new Comparator() {
public int compare(Object o1, Object o2) {
mxGeometry geo1 = ((mxCell) o1).getGeometry();
mxGeometry geo2 = ((mxCell) o2).getGeometry();
return (int) (geo1.getCenterX() - geo2.getCenterX());
}
});
double offset = ((mxCell) cells4align.get(0)).getGeometry().getCenterX();
double space = (((mxCell) cells4align.get(cells4align.size() - 1)).getGeometry().getCenterX() - offset) / (cells4align.size() - 1);
model.beginUpdate();
try {
for (Object cell : cells4align) {
geo = (mxGeometry) getCellGeometry(cell).clone();
geo.setX(offset - geo.getWidth() / 2);
model.setGeometry(cell, geo);
offset += space;
}
fireEvent(new mxEventObject(mxEvent.ALIGN_CELLS, "cells", cells, "distribute", type));
} finally {
model.endUpdate();
}
} else {
Collections.sort(cells4align, new Comparator() {
public int compare(Object o1, Object o2) {
mxGeometry geo1 = ((mxCell) o1).getGeometry();
mxGeometry geo2 = ((mxCell) o2).getGeometry();
return (int) (geo1.getCenterY() - geo2.getCenterY());
}
});
double offset = ((mxCell) cells4align.get(0)).getGeometry().getCenterY();
double space = (((mxCell) cells4align.get(cells4align.size() - 1)).getGeometry().getCenterY() - offset) / (cells4align.size() - 1);
model.beginUpdate();
try {
for (Object cell : cells4align) {
geo = (mxGeometry) getCellGeometry(cell).clone();
geo.setY(offset - geo.getHeight() / 2);
model.setGeometry(cell, geo);
offset += space;
}
fireEvent(new mxEventObject(mxEvent.ALIGN_CELLS, "cells", cells, "distribute", type));
} finally {
model.endUpdate();
}
}
}
return cells;
}
public void resetSelection() {
Object cell = selectionModel.getCell();
selectionModel.clear();
selectionModel.setCell(cell);
}
public String getCellValue(String id) {
Object value = model.getValue(getModel().getCell(id));
return value == null ? "" : value.toString();
}
public String adjustEdgeStyle(Object edge) {
Object source = model.getTerminal(edge, true);
Object target = model.getTerminal(edge, false);
return adjustEdgeStyle(source, target, edge);
}
public String adjustEdgeStyle(Object source, Object target, Object edge) {
String style = null;
if (!getModel().hasSameParentPool(source, target) && !getModel().isConversationNode(source) && !getModel().isConversationNode(target)
|| getModel().isPool(source) || getModel().isPool(target)) {
if (getModel().isChoreographyParticipant(source)) {
style = "messageFlow;startArrow=none";
} else if (getModel().isChoreographyParticipant(target)) {
style = "messageFlow;endArrow=none";
} else {
if (isVerticalSwimlane(getModel().getParentPool(source)) || isVerticalSwimlane(getModel().getParentPool(target))) {
style = "messageFlow;elbow=horizontal";
} else {
style = "messageFlow";
}
}
}
if (getModel().isItemAwareElement(source) || getModel().isItemAwareElement(target)) {
if (model.isEdge(source) || model.isEdge(target)) {
style = "association";
} else {
style = "dataAssociation";
}
}
if (getModel().isBoundaryEvent(source) && getModel().isCompensationIntermediateEvent(source)) {
style = "compensationAssociation";
}
if (getModel().isConversationNode(source) || getModel().isConversationNode(target)) {
style = "conversationLink";
}
if (getModel().isAnnotation(source) || getModel().isAnnotation(target) || isImageArtifact(source) || isImageArtifact(target)
|| getModel().isMessage(source) || getModel().isMessage(target)) {
style = "association";
}
if (isOrganizationElement(source) || isOrganizationElement(target)) {
style = "organizationFlow";
}
if (style == null) {
style = "defaultEdge";
}
return style;
}
public double getMinSwimlaneSize(Object cell) {
double size = Constants.SWIMLANE_SIZE;
if (isVerticalSwimlane(cell)) {
for (Object child : mxGraphModel.getChildVertices(model, cell)) {
mxGeometry geo = model.getGeometry(child);
if (size < geo.getX() + geo.getWidth()) {
size = geo.getX() + geo.getWidth();
}
}
} else {
for (Object child : mxGraphModel.getChildVertices(model, cell)) {
mxGeometry geo = model.getGeometry(child);
if (size < geo.getY() + geo.getHeight()) {
size = geo.getY() + geo.getHeight();
}
}
}
return size;
}
public String validateEdge(Object edge, Object source, Object target) {
return GraphUtils.validateEdge(this, edge, source, target);
}
public String validateCell(Object cell, Hashtable context) {
return GraphUtils.validateCell(this, cell);
}
// public void enterGroup(Object cell) {
// if (cell == null) {
// cell = getSelectionCell();
// }
//
// if (cell != null && isValidRoot(cell)) {
// view.setCurrentRoot(cell);
// clearSelection();
// }
// }
public boolean isValidRoot(Object cell) {
return (cell != null && (getModel().isSubProcess(cell) || isPlane(cell)));
}
public boolean isPlane(Object cell) {
if (cell != null) {
if (model.getParent(cell) == model.getRoot() || cell == view.getCurrentRoot() && !getModel().isSubProcess(cell)) {
return true;
}
}
return false;
}
public boolean isVerticalSwimlane(Object cell) {
if (isSwimlane(cell)) {
return model.getStyle(cell).startsWith("vertical");
}
return false;
}
public boolean isInCollapsedSwimlane(Object cell) {
if (isPlane(cell)) {
return false;
}
if (!isSwimlane(cell)) {
cell = model.getParent(cell);
while (!isSwimlane(cell) && !isPlane(cell)) {
cell = model.getParent(cell);
}
}
if (isSwimlane(cell)) {
while (isSwimlane(cell)) {
if (isCollapsedSwimlane(cell)) {
return true;
} else {
cell = model.getParent(cell);
}
}
return false;
} else {
return false;
}
}
public boolean isCollapsedSwimlane(Object cell) {
mxCellState state = view.getState(cell);
Map style = (state != null) ? state.getStyle() : getCellStyle(cell);
if (style != null && !model.isEdge(cell)) {
if (mxUtils.isTrue(style, mxConstants.STYLE_HORIZONTAL, false)) {
return !isVerticalSwimlane(cell);
} else {
return isVerticalSwimlane(cell);
}
}
return false;
}
public boolean isAutoPool(Object cell) {
if (getModel().isPool(cell)) {
mxCellState state = view.getState(cell);
Map style = (state != null) ? state.getStyle() : getCellStyle(cell);
if (style != null && !model.isEdge(cell)) {
return mxUtils.isTrue(style, Constants.STYLE_AUTO, true);
}
}
return false;
}
public boolean isManualPool(Object cell) {
if (getModel().isPool(cell)) {
mxCellState state = view.getState(cell);
Map style = (state != null) ? state.getStyle() : getCellStyle(cell);
if (style != null && !model.isEdge(cell)) {
return !mxUtils.isTrue(style, Constants.STYLE_AUTO, true);
}
}
return false;
}
public boolean isLaneByStyle(Object cell) {
if (isSwimlane(cell)) {
return mxUtils.isTrue(view.getState(cell).getStyle(), Constants.SWIMLANE_STYLE_LANE, false);
}
return false;
}
public boolean isInitiatingMessage(Object cell) {
if (getModel().isMessage(cell)) {
if (mxUtils.isTrue(view.getState(cell).getStyle(), Constants.STYLE_INIT, false)) {
return true;
}
}
return false;
}
public boolean isImageArtifact(Object cell) {
if (cell != null) {
if (model.getParent(cell) != model.getRoot()) {
mxCellState state = view.getState(cell);
Map style = (state != null) ? state.getStyle() : getCellStyle(cell);
if (style != null && !model.isEdge(cell)) {
String shape = mxUtils.getString(style, mxConstants.STYLE_SHAPE, "");
String type = mxUtils.getString(style, Constants.STYLE_TYPE, "");
return shape.equals(mxConstants.SHAPE_IMAGE) && type.equals(mxConstants.SHAPE_IMAGE);
}
}
}
return false;
}
public boolean isOrganizationFlow(Object cell) {
if (cell != null) {
if (model.getParent(cell) != model.getRoot()) {
String style = model.getStyle(cell);
if (style != null && model.isEdge(cell)) {
return style.startsWith(Constants.EDGE_TYPE_ORGANIZATION_FLOW);
}
}
}
return false;
}
public boolean isCompensationAssociation(Object cell) {
if (cell != null) {
if (model.getParent(cell) != model.getRoot()) {
String style = model.getStyle(cell);
if (style != null && model.isEdge(cell)) {
return style.startsWith(Constants.EDGE_TYPE_COMPENSATION_ASSOCIATION);
}
}
}
return false;
}
public boolean isLinkEvent(Object cell, boolean source) {
if (getModel().isIntermediateEvent(cell)) {
if (source) {
return source == mxUtils.isTrue(getCellStyle(cell), Constants.STYLE_SOURCE, false);
} else {
return source == mxUtils.isTrue(getCellStyle(cell), Constants.STYLE_SOURCE, true);
}
}
return false;
}
public boolean isCallChoreography(Object cell) {
if (isChoreography(cell) || isSubChoreography(cell)) {
return mxUtils.isTrue(getCellStyle(cell), Constants.STYLE_CALL);
}
return false;
}
public boolean isChoreography(Object cell) {
if (cell != null) {
if (model.getParent(cell) != model.getRoot()) {
mxCellState state = view.getState(cell);
Map style = (state != null) ? state.getStyle() : getCellStyle(cell);
if (style != null && !model.isEdge(cell)) {
String shape = mxUtils.getString(style, mxConstants.STYLE_SHAPE, "");
String type = mxUtils.getString(style, Constants.STYLE_TYPE, "");
return shape.equals(Constants.SHAPE_ACTIVITY) && type.equals(Constants.ACTIVITY_STYLE_CHOREOGRAPHY);
}
}
}
return false;
}
public boolean isSubChoreography(Object cell) {
if (cell != null) {
if (model.getParent(cell) != model.getRoot()) {
mxCellState state = view.getState(cell);
Map style = (state != null) ? state.getStyle() : getCellStyle(cell);
if (style != null && !model.isEdge(cell)) {
String shape = mxUtils.getString(style, mxConstants.STYLE_SHAPE, "");
String type = mxUtils.getString(style, Constants.STYLE_TYPE, "");
return shape.equals(Constants.SHAPE_ACTIVITY) && type.equals(Constants.ACTIVITY_STYLE_SUBCHOREOGRAPHY);
}
}
}
return false;
}
public boolean isTopChoreographyParticipant(Object cell) {
if (getModel().isChoreographyParticipant(cell)) {
String position = mxUtils.getString(getCellStyle(cell), Constants.STYLE_POSITION, "top");
if (position.equals(mxConstants.ALIGN_TOP)) {
return true;
}
}
return false;
}
public boolean isBottomChoreographyParticipant(Object cell) {
if (getModel().isChoreographyParticipant(cell)) {
String position = mxUtils.getString(getCellStyle(cell), Constants.STYLE_POSITION, "top");
if (position.equals(mxConstants.ALIGN_BOTTOM)) {
return true;
}
}
return false;
}
public boolean isAdditionalChoreographyParticipant(Object cell) {
if (getModel().isChoreographyParticipant(cell)) {
if (!mxUtils.isTrue(getCellStyle(cell), Constants.STYLE_BORDER, true)) {
return true;
}
}
return false;
}
public boolean isEmptySwimlane(Object cell) {
return isEmptyPool(cell) || isEmptyLane(cell);
}
public boolean isEmptyPool(Object cell) {
if (getModel().isPool(cell)) {
int count = model.getChildCount(cell);
if (count == 0) {
return true;
}
return false;
}
return false;
}
public boolean isEmptyLane(Object cell) {
if (getModel().isLane(cell)) {
int count = model.getChildCount(cell);
if (count == 0) {
return true;
}
return false;
}
return false;
}
public boolean hasChildLane(Object cell) {
if (isSwimlane(cell)) {
int count = model.getChildCount(cell);
if (count == 0) {
return false;
} else {
for (int i = 0; i < count; i++) {
Object child = model.getChildAt(cell, i);
if (isSwimlane(child)) {
return true;
}
}
}
return false;
}
return false;
}
public boolean hasChildNonLane(Object cell) {
if (isSwimlane(cell)) {
int count = model.getChildCount(cell);
if (count == 0) {
return false;
} else {
for (int i = 0; i < count; i++) {
Object child = model.getChildAt(cell, i);
if (!isSwimlane(child) && !model.isEdge(child)) {
return true;
}
}
}
return false;
}
return false;
}
public boolean isInCollapsedSubProcess(Object cell) {
if (isPlane(cell)) {
return false;
}
if (!getModel().isSubProcess(cell)) {
cell = model.getParent(cell);
while (!getModel().isSubProcess(cell) && !isPlane(cell)) {
cell = model.getParent(cell);
}
}
if (getModel().isSubProcess(cell)) {
while (getModel().isSubProcess(cell)) {
if (getModel().isCollapsedSubProcess(cell)) {
return true;
} else {
cell = model.getParent(cell);
}
}
return false;
} else {
return false;
}
}
public boolean isElementNotAllowedInChoreography(Object cell) {
if (!isSwimlane(cell) && !getModel().isMessage(cell) && !getModel().isEvent(cell) && !getModel().isGateway(cell) && !getModel().isArtifact(cell)
&& !getModel().isSequenceFlow(cell) && !getModel().isMessageFlow(cell) && !isChoreography(cell) && !isSubChoreography(cell)
&& !getModel().isChoreographySubprocess(cell)) {
return true;
}
return false;
}
public boolean isElementNotAllowedInConversation(Object cell) {
if (!isSwimlane(cell) && !getModel().isMessage(cell) && !getModel().isArtifact(cell) && !getModel().isMessageFlow(cell)
&& !getModel().isConversationLink(cell) && !getModel().isConversationNode(cell)) {
return true;
}
return false;
}
public boolean isFragments(Object cell) {
if (cell != null) {
return model.getStyle(cell).startsWith("pattern=") || model.getStyle(cell).startsWith("fragment=");
}
return false;
}
public boolean isOrganizationElement(Object cell) {
if (isOrganizationRoot(cell) || isOrganization(cell) || isOrganizationalUnit(cell) || isOrganizationalGroup(cell) || isOrganizationalRole(cell)
|| isOrganizationalPerson(cell)) {
return true;
}
return false;
}
public boolean isOrganizationName(Object cell) {
if (cell != null) {
if (model.getParent(cell) != model.getRoot()) {
String style = model.getStyle(cell);
if (style != null && !model.isEdge(cell)) {
return style.startsWith(Constants.STYLE_ORGANIZATION_NAME);
}
}
}
return false;
}
public boolean isOrganizationRoot(Object cell) {
if (cell != null) {
if (model.getParent(cell) != model.getRoot()) {
String style = model.getStyle(cell);
if (style != null && !model.isEdge(cell)) {
return style.startsWith(Constants.STYLE_ORGANIZATIONAL_ROOT);
}
}
}
return false;
}
public boolean isOrganization(Object cell) {
if (cell != null) {
if (model.getParent(cell) != model.getRoot()) {
String style = model.getStyle(cell);
if (style != null && !model.isEdge(cell)) {
return style.equals(Constants.STYLE_ORGANIZATION) || style.startsWith(Constants.STYLE_ORGANIZATION + ";");
}
}
}
return false;
}
public boolean isOrganizationalUnit(Object cell) {
if (cell != null) {
if (model.getParent(cell) != model.getRoot()) {
String style = model.getStyle(cell);
if (style != null && !model.isEdge(cell)) {
return style.startsWith(Constants.STYLE_ORGANIZATIONAL_UNIT);
}
}
}
return false;
}
public boolean isOrganizationalGroup(Object cell) {
if (cell != null) {
if (model.getParent(cell) != model.getRoot()) {
String style = model.getStyle(cell);
if (style != null && !model.isEdge(cell)) {
return style.startsWith(Constants.STYLE_ORGANIZATIONAL_GROUP);
}
}
}
return false;
}
public boolean isOrganizationalRole(Object cell) {
if (cell != null) {
if (model.getParent(cell) != model.getRoot()) {
String style = model.getStyle(cell);
if (style != null && !model.isEdge(cell)) {
return style.startsWith(Constants.STYLE_ORGANIZATIONAL_ROLE);
}
}
}
return false;
}
public boolean isOrganizationalPerson(Object cell) {
if (cell != null) {
if (model.getParent(cell) != model.getRoot()) {
String style = model.getStyle(cell);
if (style != null && !model.isEdge(cell)) {
return style.startsWith(Constants.STYLE_ORGANIZATIONAL_PERSON);
}
}
}
return false;
}
public boolean hasPool() {
Object[] cells = mxGraphModel.getChildVertices(model, this.getDefaultParent());
if (cells == null) {
return false;
}
for (Object cell : cells) {
if (getModel().isPool(cell)) {
return true;
}
}
return false;
}
public boolean hasChoreography() {
Object[] cells = mxGraphModel.getChildVertices(model, this.getDefaultParent());
if (cells == null) {
return false;
}
for (Object cell : cells) {
if (isChoreography(cell) || isSubChoreography(cell)) {
return true;
}
}
return false;
}
public boolean hasConversation() {
Object[] cells = mxGraphModel.getChildVertices(model, this.getDefaultParent());
if (cells == null) {
return false;
}
for (Object cell : cells) {
if (getModel().isConversationNode(cell)) {
return true;
}
}
return false;
}
public boolean hasElementNotAllowedInChoreography() {
if (getCurrentRoot() != null && isElementNotAllowedInChoreography(getCurrentRoot())) {
return true;
}
Object[] cells = mxGraphModel.getChildVertices(model, getDefaultParent());
if (cells == null) {
return false;
}
for (Object cell : cells) {
if (isElementNotAllowedInChoreography(cell)) {
return true;
}
}
return false;
}
public boolean hasElementNotAllowedInConversation() {
if (getCurrentRoot() != null && isElementNotAllowedInConversation(getCurrentRoot())) {
return true;
}
Object[] cells = mxGraphModel.getChildVertices(model, getDefaultParent());
if (cells == null) {
return false;
}
for (Object cell : cells) {
if (isElementNotAllowedInConversation(cell)) {
return true;
}
}
return false;
}
public boolean hasDataAssociationConnections(Object cell) {
Object[] connections = getConnections(cell);
for (Object conn : connections) {
if (getModel().isDataAssociation(conn)) {
return true;
}
}
return false;
}
public boolean canBeAssembled() {
List cells = new ArrayList(Arrays.asList(getSelectionCells()));
Object cell = getSelectionCell();
if (cells.isEmpty()) {
return false;
}
if (cells.size() == 1 && (model.isEdge(cell) || !getModel().isTask(cell))) {
return false;
}
Set delEdges = new HashSet();
for (Object c : cells) {
if (model.isEdge(c)) {
if (!cells.contains(model.getTerminal(c, true)) || !cells.contains(model.getTerminal(c, false))) {
delEdges.add(c);
}
}
}
cells.removeAll(delEdges);
if (cells.isEmpty() || (cells.size() == 1 && !getModel().isTask(cell))) {
return false;
}
for (Object c : cells) {
if (isSwimlane(c) || getModel().isConversationNode(c) || getModel().isDataOutput(c) || getModel().isDataInput(c)) {
return false;
}
}
return true;
}
public List getArtifacts() {
List artifacts = new ArrayList();
Object[] cells = mxGraphModel.getChildren(model, this.getDefaultParent());
if (cells == null) {
return artifacts;
}
for (Object cell : cells) {
if (getModel().isArtifact(cell)) {
artifacts.add(cell);
}
}
return artifacts;
}
public Object getParentSwimlane(Object cell) {
Object parent = null;
if (cell != null) {
if (isSwimlane(cell)) {
return cell;
}
if (model.getParent(cell) != model.getRoot()) {
parent = model.getParent(cell);
while (parent != null && !isSwimlane(parent)) {
parent = model.getParent(cell);
cell = parent;
}
}
}
return parent;
}
public mxCell getParentCell(mxCell cell) {
mxCell parent = (mxCell) cell.getParent();
if (getModel().isBoundaryEvent(cell) || getModel().isAttachedMessage(cell) || getModel().isChoreographyTask(cell)
|| getModel().isChoreographySubprocess(cell) || getModel().isChoreographyParticipant(cell)) {
parent = (mxCell) parent.getParent();
}
return parent;
}
public List getAllPools() {
List pools = new ArrayList();
Object[] cells = mxGraphModel.getChildVertices(model, this.getDefaultParent());
if (cells == null) {
return pools;
}
for (Object cell : cells) {
if (getModel().isPool(cell)) {
pools.add(cell);
}
}
return pools;
}
public List getAllLanesAndSubprocesses() {
List parents = new ArrayList();
List vertices = new ArrayList();
List callActivities = new ArrayList();
Object parent = getCurrentRoot() == null ? getDefaultParent() : getCurrentRoot();
vertices.add(parent);
GraphUtils.getAllVerticesInOrder(this, parent, vertices, callActivities);
for (Object cell : vertices) {
if (hasChildNonLane(cell) || isPlane(cell) || getModel().isPool(cell)) {
parents.add(cell);
} else if (getModel().isExpandedSubProcess(cell)) {
parents.add(0, cell);
}
}
return parents;
}
public Map getAllParticipants() {
Map participants = new HashMap();
for (mxCell cell : getModel().getAllChoreographyParticipants().values()) {
if (getModel().isChoreographyParticipant(cell)) {
mxCell participant = cell;
int index = participant.getId().indexOf("_part_");
if (index != -1) {
participants.put(cell.getValue().toString(), cell.getId().substring(index + 6));
}
}
}
return participants;
}
public Map getAllAdditionalChoreographyParticipants() {
Map participants = new HashMap();
Object[] cells = getModel().getCells().values().toArray();
for (Object cell : cells) {
if (this.isAdditionalChoreographyParticipant(cell)) {
participants.put(((mxCell) cell).getId(), (mxCell) cell);
}
}
return participants;
}
public Map getAllChoreographyParticipants(Object activity) {
Map participants = new HashMap();
Object[] cells = mxGraphModel.getChildVertices(model, activity);
for (Object cell : cells) {
if (getModel().isChoreographyParticipant(cell)) {
participants.put(((mxCell) cell).getId(), (mxCell) cell);
}
}
return participants;
}
public Object getAttechedMessage(Object cell) {
if (cell == null || !getModel().isMessageFlow(cell) || model.getChildCount(cell) != 1) {
return null;
}
return model.getChildAt(cell, 0);
}
public Object[] getAttechedEvents(Object cell) {
if (cell == null) {
return null;
}
int childCount = model.getChildCount(cell);
List result = new ArrayList(childCount);
if (getModel().isSubProcess(cell) || getModel().isCallActivity(cell) || getModel().isTask(cell)) {
for (int i = 0; i < childCount; i++) {
Object child = model.getChildAt(cell, i);
if (getModel().isBoundaryEvent(child)) {
result.add(child);
}
}
}
return result.toArray();
}
public int getAttechedEventCount(Object cell) {
if (getModel().isSubProcess(cell)) {
Object[] events = getAttechedEvents(cell);
if (events == null) {
return 0;
} else {
return events.length;
}
} else if (getModel().isCallActivity(cell) || getModel().isTask(cell)) {
return model.getChildCount(cell);
}
return 0;
}
public boolean hasStartEvent(Object cell) {
Object[] cells = mxGraphModel.getChildVertices(model, cell);
for (int i = 0; i < cells.length; i++) {
if (getModel().isStartEvent(cells[i])) {
return true;
}
}
return false;
}
public boolean hasEndEvent(Object cell) {
Object[] cells = mxGraphModel.getChildVertices(model, cell);
for (int i = 0; i < cells.length; i++) {
if (getModel().isEndEvent(cells[i])) {
return true;
}
}
return false;
}
public Object[] getLinkEvent(Object cell, boolean source, String name) {
Object[] cells = mxGraphModel.getChildVertices(model, cell);
List links = new ArrayList();
for (int i = 0; i < cells.length; i++) {
if (isLinkEvent(cells[i], source)) {
if (name == null || ((mxCell) cells[i]).getValue().equals(name)) {
links.add(cells[i]);
}
}
}
return links.toArray();
}
public void selectProcess(String direction) {
Object cell = getSelectionCell();
Set selectedCells = new HashSet();
Set outgoingCells = GraphUtils.getOutgoingCells(this, cell, null, model.getParent(cell));
Set incomingCells = GraphUtils.getIncomingCells(this, cell, null, model.getParent(cell));
if ("entrire".equals(direction)) {
selectedCells.addAll(incomingCells);
selectedCells.addAll(outgoingCells);
} else {
mxGeometry geo = model.getGeometry(cell);
if ("right".equals(direction) || "bottom".equals(direction)) {
selectedCells.addAll(outgoingCells);
for (Object c : outgoingCells) {
if (model.isVertex(c)) {
mxGeometry g = model.getGeometry(c);
if (g.getCenterX() < geo.getCenterX() && "right".equals(direction)) {
selectedCells.remove(c);
selectedCells.removeAll(Arrays.asList(getConnections(c, model.getParent(cell))));
} else if (g.getCenterY() < geo.getCenterY() && "bottom".equals(direction)) {
selectedCells.remove(c);
selectedCells.removeAll(Arrays.asList(getConnections(c, model.getParent(cell))));
}
}
}
} else if ("left".equals(direction) || "top".equals(direction)) {
selectedCells.addAll(incomingCells);
for (Object c : incomingCells) {
if (model.isVertex(c)) {
mxGeometry g = model.getGeometry(c);
if (g.getCenterX() > geo.getCenterX() && "left".equals(direction)) {
selectedCells.remove(c);
selectedCells.removeAll(Arrays.asList(getConnections(c, model.getParent(cell))));
} else if (g.getCenterY() > geo.getCenterY() && "top".equals(direction)) {
selectedCells.remove(c);
selectedCells.removeAll(Arrays.asList(getConnections(c, model.getParent(cell))));
}
}
}
}
}
setSelectionCells(selectedCells);
}
public static void main(String[] args) {
System.out.println("BPMN 2.0 Graph version \"" + VERSION + "\"");
}
}