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.GraphManager Maven / Gradle / Ivy
package org.yaoqiang.graph.view;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.yaoqiang.bpmn.model.elements.choreographyactivities.ChoreographyActivity;
import org.yaoqiang.bpmn.model.elements.choreographyactivities.ChoreographyTask;
import org.yaoqiang.bpmn.model.elements.choreographyactivities.SubChoreography;
import org.yaoqiang.bpmn.model.elements.collaboration.Participant;
import org.yaoqiang.bpmn.model.elements.events.BoundaryEvent;
import org.yaoqiang.graph.model.GraphModel;
import org.yaoqiang.graph.swing.GraphComponent;
import org.yaoqiang.graph.util.GraphUtils;
import org.yaoqiang.util.Constants;
import com.mxgraph.model.mxCell;
import com.mxgraph.model.mxGeometry;
import com.mxgraph.util.mxConstants;
import com.mxgraph.util.mxEvent;
import com.mxgraph.util.mxEventObject;
import com.mxgraph.util.mxEventSource;
import com.mxgraph.util.mxPoint;
import com.mxgraph.util.mxRectangle;
import com.mxgraph.util.mxUndoableEdit;
import com.mxgraph.util.mxUndoableEdit.mxUndoableChange;
/**
* GraphManager
*
* @author Shi Yaoqiang([email protected] )
*/
public class GraphManager extends mxEventSource {
protected GraphComponent graphComponent;
protected Graph graph;
protected GraphModel model;
public GraphManager(GraphComponent graphComponent) {
if (this.graphComponent != null) {
this.graphComponent.getConnectionHandler().removeListener(handler);
this.model.removeListener(handler);
this.graph.removeListener(handler);
}
this.graphComponent = graphComponent;
this.graph = graphComponent.getGraph();
this.model = graphComponent.getGraph().getModel();
if (this.graphComponent != null) {
this.graphComponent.getConnectionHandler().addListener(mxEvent.CONNECT, handler);
this.model.addListener(mxEvent.CHANGE, handler);
this.graph.addListener(mxEvent.FOLD_CELLS, handler);
this.graph.addListener(mxEvent.MOVE_CELLS, handler);
this.graph.addListener(mxEvent.CELLS_ADDED, handler);
this.graph.addListener(mxEvent.CELLS_RESIZED, handler);
}
}
public final mxIEventListener getHandler() {
return handler;
}
protected mxIEventListener handler = new mxIEventListener() {
public void invoke(Object source, mxEventObject evt) {
String eventName = evt.getName();
mxCell cell = (mxCell) graph.getSelectionCell();
if (cell == null) {
Object[] cells = (Object[]) evt.getProperty("cells");
if (cells != null && cells.length > 0) {
cell = (mxCell) cells[0];
}
}
model.beginUpdate();
try {
if (eventName.equals(mxEvent.CONNECT)) {
cell = (mxCell) evt.getProperty("cell");
if (model.isEdge(cell) && model.getStyle(cell).length() == 0) {
String style = GraphUtils.setEdgeStyle(graph, cell);
if (style.equals("messageFlow;elbow=horizontal")) {
GraphUtils.setElementStyles(graph, "elbow", "horizontal", cell);
}
}
} else if (eventName.equals(mxEvent.CHANGE)) {
graphComponent.validateGraph();
} else if (eventName.equals(mxEvent.FOLD_CELLS)) {
Map associations = new HashMap();
for (mxCell a : GraphUtils.getAllAssociations(graph)) {
Object innerCell = null;
if (model.isAnnotation(a.getTarget())) {
innerCell = a.getSource();
if (cell != innerCell && model.isAncestor(cell, innerCell)) {
associations.put(a, (mxCell) a.getTarget());
}
} else {
innerCell = a.getTarget();
if (cell != innerCell && model.isAncestor(cell, innerCell)) {
associations.put(a, (mxCell) a.getSource());
}
}
}
boolean showAnnotation = true;
if (graph.isSubChoreography(cell)) {
showAnnotation = !model.isCollapsedSubProcess(GraphUtils.getChoreographyActivity(graph, cell));
GraphUtils.arrangeChoreography(graph, cell, true);
}
if (model.isSubProcess(cell)) {
showAnnotation = !model.isCollapsedSubProcess(cell);
}
if (graph.isSwimlane(cell)) {
showAnnotation = !graph.isCollapsedSwimlane(cell);
}
for (Entry e : associations.entrySet()) {
model.setVisible(e.getKey(), showAnnotation);
List edges = new ArrayList(Arrays.asList(graph.getConnections(e.getValue())));
edges.remove(e.getKey());
if (edges.isEmpty()) {
model.setVisible(e.getValue(), showAnnotation);
}
}
} else if (eventName.equals(mxEvent.MOVE_CELLS) || eventName.equals(mxEvent.CELLS_ADDED)) {
if (model.isGroupArtifact(cell)) {
graph.orderCells(true, new Object[] { cell });
} else if (cell.getValue() instanceof BoundaryEvent && !cell.getGeometry().isRelative() && graph.getConnections(cell).length == 0) {
arrangeAttachedEvent(cell);
} else if (model.isMessage(cell) && !cell.getGeometry().isRelative() && model.isMessageFlow(model.getParent(cell))) {
arrangeAttachedMessage(cell);
}
if (eventName.equals(mxEvent.CELLS_ADDED)) {
if ((graph.isChoreography(cell) || graph.isSubChoreography(cell)) && model.getChildCount(cell) == 0) {
insertChoreography(cell);
}
}
} else if (eventName.equals(mxEvent.UNDO) || eventName.equals(mxEvent.REDO)) {
Object edit = evt.getProperty("edit");
if (edit != null) {
List changes = ((mxUndoableEdit) edit).getChanges();
graph.setSelectionCells(graph.getSelectionCellsForChanges(changes));
cell = (mxCell) graph.getSelectionCell();
if (graph.isChoreography(cell) || graph.isSubChoreography(cell)) {
GraphUtils.arrangeChoreography(graph, cell, false);
}
}
} else if (eventName.equals(mxEvent.CELLS_RESIZED)) {
Object[] cells = (Object[]) evt.getProperty("cells");
if (cells != null && cells.length > 0 && cells[0] != cell) {
return;
}
if (cell != null && !graph.isImageArtifact(cell) && !graph.isSwimlane(cell)) {
mxGeometry geo = cell.getGeometry();
if (graph.isChoreography(cell) || graph.isSubChoreography(cell)) {
if (geo.getWidth() <= Constants.ACTIVITY_WIDTH) {
geo.setWidth(Constants.ACTIVITY_WIDTH);
}
if (geo.getHeight() <= Constants.ACTIVITY_HEIGHT + Constants.PARTICIPANT_HEIGHT * 2) {
geo.setHeight(Constants.ACTIVITY_HEIGHT + Constants.PARTICIPANT_HEIGHT * 2);
}
model.setGeometry(cell, geo);
GraphUtils.arrangeChoreography(graph, cell, false);
if (graph.isSubChoreography(cell)) {
Object[] selectedCells = new Object[] { GraphUtils.getChoreographyActivity(graph, cell) };
mxRectangle alterBounds = model.getGeometry(selectedCells[0]).getAlternateBounds();
if (model.isCollapsedSubProcess(selectedCells[0])) {
if (alterBounds.getWidth() <= Constants.FOLDED_SUBPROCESS_WIDTH) {
alterBounds.setWidth(Constants.FOLDED_SUBPROCESS_WIDTH + 10);
}
if (alterBounds.getHeight() <= Constants.ACTIVITY_HEIGHT) {
alterBounds.setHeight(Constants.ACTIVITY_HEIGHT * 2);
}
graph.setCellStyles(mxConstants.STYLE_VERTICAL_ALIGN, mxConstants.ALIGN_MIDDLE, selectedCells);
} else {
if (alterBounds.getWidth() > Constants.FOLDED_SUBPROCESS_WIDTH) {
alterBounds.setWidth(Constants.FOLDED_SUBPROCESS_WIDTH - 10);
}
if (alterBounds.getHeight() > Constants.ACTIVITY_HEIGHT) {
alterBounds.setHeight(Constants.ACTIVITY_HEIGHT);
}
graph.setCellStyles(mxConstants.STYLE_VERTICAL_ALIGN, mxConstants.ALIGN_TOP, selectedCells);
}
}
} else {
if (geo.getWidth() <= Constants.ACTIVITY_WIDTH / 2) {
geo.setWidth(Constants.ACTIVITY_WIDTH / 2);
}
if (geo.getHeight() <= Constants.ACTIVITY_HEIGHT / 3) {
geo.setHeight(Constants.ACTIVITY_HEIGHT / 3);
}
mxRectangle alterBounds = geo.getAlternateBounds();
if (model.isSubProcess(cell) && alterBounds != null) {
if (model.isCollapsedSubProcess(cell)) {
if (alterBounds.getWidth() <= Constants.FOLDED_SUBPROCESS_WIDTH) {
alterBounds.setWidth(Constants.FOLDED_SUBPROCESS_WIDTH + 10);
}
if (alterBounds.getHeight() <= Constants.ACTIVITY_HEIGHT) {
alterBounds.setHeight(Constants.ACTIVITY_HEIGHT * 2);
}
graph.setCellStyles(mxConstants.STYLE_VERTICAL_ALIGN, mxConstants.ALIGN_MIDDLE);
} else {
if (alterBounds.getWidth() > Constants.FOLDED_SUBPROCESS_WIDTH) {
alterBounds.setWidth(Constants.FOLDED_SUBPROCESS_WIDTH - 10);
}
if (alterBounds.getHeight() > Constants.ACTIVITY_HEIGHT) {
alterBounds.setHeight(Constants.ACTIVITY_HEIGHT);
}
graph.setCellStyles(mxConstants.STYLE_VERTICAL_ALIGN, mxConstants.ALIGN_TOP);
}
}
model.setGeometry(cell, geo);
}
}
}
graph.refresh();
} finally {
model.endUpdate();
}
}
};
protected void insertChoreography(mxCell cell) {
String call = "";
String name = "";
String id = cell.getId();
ChoreographyActivity activity = null;
List cells = new ArrayList();
if (graph.isCallChoreography(cell)) {
call = ";call=1;strokeWidth=3";
name = "Call \n";
}
if (graph.isChoreography(cell)) {
activity = new ChoreographyTask(name + "Choreography \n Task");
mxCell taskCell = new mxCell(activity, new mxGeometry(0, Constants.PARTICIPANT_HEIGHT, Constants.ACTIVITY_WIDTH,
Constants.ACTIVITY_HEIGHT), "choreographyTask" + call);
id += "_CT";
taskCell.setId(id);
taskCell.setVertex(true);
cells.add(taskCell);
} else {
String value = "Choreography \n Sub-Process";
if (graph.isCallChoreography(cell)) {
value = "Call \n Choreography";
}
mxGeometry geo = new mxGeometry(0, Constants.PARTICIPANT_HEIGHT, Constants.ACTIVITY_WIDTH, Constants.ACTIVITY_HEIGHT);
geo.setAlternateBounds(new mxRectangle(0, 0, 400, 250));
activity = new SubChoreography(value);
mxCell subprocessCell = new mxCell(activity, geo, "choreographySubprocess" + call);
id += "_SC";
subprocessCell.setId(id);
subprocessCell.setVertex(true);
cells.add(subprocessCell);
}
Map participants = model.getAllParticipants();
double ha = 1;
Participant partA = participants.get("Participant A");
String partAId = null;
if (partA == null) {
partA = new Participant("Participant A");
partAId = model.createId(null);
} else {
if (partA.getMultiplicity() != 1) {
ha = 1.75;
}
partAId = partA.getId();
}
activity.setInitiatingParticipantRef(partAId);
double hb = 1;
Participant partB = participants.get("Participant B");
String partBId = null;
if (partB == null) {
partB = new Participant("Participant B");
partBId = model.createId(null);
} else {
if (partB.getMultiplicity() != 1) {
hb = 1.75;
}
partBId = partB.getId();
}
partAId = id + "_part_" + partAId;
partBId = id + "_part_" + partBId;
mxCell participantBCell = new mxCell(partB, new mxGeometry(0, 75, Constants.ACTIVITY_WIDTH, Constants.PARTICIPANT_HEIGHT * hb),
"participantBottom" + call);
participantBCell.setId(partBId);
participantBCell.setVertex(true);
cells.add(participantBCell);
mxCell participantACell = new mxCell(partA, new mxGeometry(0, 0, Constants.ACTIVITY_WIDTH, Constants.PARTICIPANT_HEIGHT * ha),
"participantTop" + call);
participantACell.setId(partAId);
participantACell.setVertex(true);
cells.add(participantACell);
graph.addCells(cells.toArray(), cell);
graph.orderCells(true, new Object[] { participantACell, participantBCell });
GraphUtils.arrangeChoreography(graph, cell, false);
}
protected void arrangeAttachedEvent(mxCell cell) {
Object parent = model.getParent(cell);
if (model.isTask(parent) || (model.isCallActivity(parent) || model.isSubProcess(parent)) && parent != graph.getCurrentRoot()) {
mxCell event = cell;
mxCell subflow = (mxCell) parent;
double eventWidth = event.getGeometry().getWidth();
double xOffset = event.getGeometry().getX();
double yOffset = event.getGeometry().getY();
double height = subflow.getGeometry().getHeight();
double width = subflow.getGeometry().getWidth();
mxGeometry geo = new mxGeometry(0, 0, eventWidth, eventWidth);
mxPoint eventOffset = new mxPoint(-eventWidth / 2, -eventWidth / 2);
if (yOffset + eventWidth == height) { // align subprocess bottom
geo.setY(1);
eventOffset = new mxPoint(xOffset, -eventWidth / 2);
mxGeometry pgeo = new mxGeometry(subflow.getGeometry().getX(), subflow.getGeometry().getY(), width, height - eventWidth / 4);
pgeo.setAlternateBounds(subflow.getGeometry().getAlternateBounds());
model.setGeometry(parent, pgeo);
} else if (xOffset + eventWidth == width) { // align subprocess right
geo.setX(1);
eventOffset = new mxPoint(-eventWidth / 2, yOffset);
mxGeometry pgeo = new mxGeometry(subflow.getGeometry().getX(), subflow.getGeometry().getY(), width - eventWidth / 4, height);
pgeo.setAlternateBounds(subflow.getGeometry().getAlternateBounds());
model.setGeometry(parent, pgeo);
GraphUtils.moveLableToRight(graph, new Object[] { event });
} else if (yOffset == 0) { // align subprocess top
eventOffset = new mxPoint(xOffset, -eventWidth / 2);
GraphUtils.moveLableToTop(graph, new Object[] { event });
} else if (xOffset == 0) { // align subprocess left
eventOffset = new mxPoint(-eventWidth / 2, yOffset);
GraphUtils.moveLableToLeft(graph, new Object[] { event });
} else if (model.isTask(parent) || model.isCallActivity(parent) || model.isSubProcess(parent) && model.isCollapsedSubProcess(parent)
|| model.isSubProcess(parent) && !model.isCollapsedSubProcess(parent) && event.getValue() instanceof BoundaryEvent) {
if (xOffset + eventWidth < width / 2) {
if (yOffset + eventWidth < height / 2) {
if (xOffset < yOffset) { // align left
eventOffset = new mxPoint(-eventWidth / 2, yOffset);
GraphUtils.moveLableToLeft(graph, new Object[] { event });
} else { // align left top
eventOffset = new mxPoint(xOffset, -eventWidth / 2);
GraphUtils.moveLableToTop(graph, new Object[] { event });
}
} else {
if (xOffset < yOffset) { // align left
eventOffset = new mxPoint(-eventWidth / 2, yOffset);
GraphUtils.moveLableToLeft(graph, new Object[] { event });
} else { // align left bottom
geo.setY(1);
eventOffset = new mxPoint(xOffset, -eventWidth / 2);
}
}
} else {
if (yOffset + eventWidth < height / 2) {
if (width - xOffset < yOffset) { // align right
geo.setX(1);
eventOffset = new mxPoint(-eventWidth / 2, yOffset);
GraphUtils.moveLableToRight(graph, new Object[] { event });
} else { // align right top
eventOffset = new mxPoint(xOffset, -eventWidth / 2);
GraphUtils.moveLableToTop(graph, new Object[] { event });
}
} else {
if (width - xOffset < yOffset) { // align right
geo.setX(1);
eventOffset = new mxPoint(-eventWidth / 2, yOffset);
GraphUtils.moveLableToRight(graph, new Object[] { event });
} else { // align right bottom
geo.setY(1);
eventOffset = new mxPoint(xOffset, -eventWidth / 2);
}
}
}
} else {
eventOffset = null;
}
if (eventOffset != null) {
geo.setOffset(eventOffset);
geo.setRelative(true);
model.setGeometry(cell, geo);
}
}
}
protected void arrangeAttachedMessage(mxCell cell) {
cell.setConnectable(false);
double messageWidth = cell.getGeometry().getWidth();
double messageHeight = cell.getGeometry().getHeight();
mxGeometry geo = new mxGeometry(0, 0, messageWidth, messageHeight);
mxPoint messageOffset = new mxPoint(-messageHeight / 2, -messageHeight / 2);
geo.setOffset(messageOffset);
geo.setRelative(true);
model.setGeometry(cell, geo);
}
}