All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.yaoqiang.graph.handler.ConnectionHandler Maven / Gradle / Ivy

package org.yaoqiang.graph.handler;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.AbstractAction;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import javax.swing.JRootPane;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;

import org.yaoqiang.bpmn.model.elements.activities.AdHocSubProcess;
import org.yaoqiang.bpmn.model.elements.activities.BusinessRuleTask;
import org.yaoqiang.bpmn.model.elements.activities.CallActivity;
import org.yaoqiang.bpmn.model.elements.activities.ReceiveTask;
import org.yaoqiang.bpmn.model.elements.activities.ScriptTask;
import org.yaoqiang.bpmn.model.elements.activities.SendTask;
import org.yaoqiang.bpmn.model.elements.activities.ServiceTask;
import org.yaoqiang.bpmn.model.elements.activities.SubProcess;
import org.yaoqiang.bpmn.model.elements.activities.Task;
import org.yaoqiang.bpmn.model.elements.activities.Transaction;
import org.yaoqiang.bpmn.model.elements.events.EndEvent;
import org.yaoqiang.bpmn.model.elements.events.IntermediateCatchEvent;
import org.yaoqiang.bpmn.model.elements.events.IntermediateThrowEvent;
import org.yaoqiang.bpmn.model.elements.gateways.ComplexGateway;
import org.yaoqiang.bpmn.model.elements.gateways.EventBasedGateway;
import org.yaoqiang.bpmn.model.elements.gateways.ExclusiveGateway;
import org.yaoqiang.bpmn.model.elements.gateways.InclusiveGateway;
import org.yaoqiang.bpmn.model.elements.gateways.ParallelGateway;
import org.yaoqiang.bpmn.model.elements.humaninteraction.ManualTask;
import org.yaoqiang.bpmn.model.elements.humaninteraction.UserTask;
import org.yaoqiang.graph.model.GraphModel;
import org.yaoqiang.graph.swing.GraphComponent;
import org.yaoqiang.graph.util.GraphUtils;
import org.yaoqiang.graph.view.Graph;
import org.yaoqiang.util.Constants;
import org.yaoqiang.util.Resources;

import com.mxgraph.model.mxCell;
import com.mxgraph.model.mxGeometry;
import com.mxgraph.swing.mxGraphComponent;
import com.mxgraph.swing.handler.mxConnectionHandler;
import com.mxgraph.util.mxEvent;
import com.mxgraph.util.mxEventObject;
import com.mxgraph.util.mxPoint;
import com.mxgraph.util.mxRectangle;
import com.mxgraph.view.mxCellState;
import com.mxgraph.view.mxGraph;

/**
 * ConnectionHandler
 * 
 * @author Shi Yaoqiang([email protected])
 */
public class ConnectionHandler extends mxConnectionHandler {

	public boolean create = true;

	public ConnectionHandler(mxGraphComponent graphComponent) {
		super(graphComponent);
	}

	public GraphComponent getGraphComponent() {
		return (GraphComponent) graphComponent;
	}

	public boolean isCreateTarget() {
		Graph graph = getGraphComponent().getGraph();
		GraphModel model = graph.getModel();
		if (model.isEdge(source.getCell()) || model.isEndEvent(source.getCell()) || graph.isSwimlane(source.getCell())
				|| model.isEventSubProcess(source.getCell()) || model.isParticipant(source.getCell()) || model.isChoreographyTask(source.getCell())
				|| model.isChoreographySubprocess(source.getCell()) || model.isConversationNode(source.getCell())) {
			return false;
		}
		return true;
	}

	public void mouseMoved(MouseEvent e) {
		mouseDragged(e);

		if (isHighlighting() && !marker.hasValidState()) {
			source = null;
		}

		if (!isHighlighting() && source != null) {
			int imgWidth = handleSize;
			int imgHeight = handleSize;

			if (connectIcon != null) {
				imgWidth = connectIcon.getIconWidth();
				imgHeight = connectIcon.getIconHeight();
			}

			int x = (int) source.getCenterX() - imgWidth / 2;
			int y = (int) source.getCenterY() - imgHeight / 2;

			if (graphComponent.getGraph().isSwimlane(source.getCell())) {
				mxRectangle size = graphComponent.getGraph().getStartSize(source.getCell());

				if (size.getWidth() > 0) {
					x = (int) (source.getX() + size.getWidth() / 2 - imgWidth / 2);
				} else {
					y = (int) (source.getY() + size.getHeight() / 2 - imgHeight / 2);
				}
			} else if (getGraphComponent().getGraph().getModel().isExpandedSubProcess(source.getCell())) {
				x = (int) (source.getX() + source.getWidth() - 12);
			}

			setBounds(new Rectangle(x, y, imgWidth, imgHeight));
		} else {
			setBounds(null);
		}

		if (source != null && (bounds == null || bounds.contains(e.getPoint()))) {
			// ==============start==============
			graphComponent.getGraphControl().setCursor(GraphUtils.getConnectCursor(graphComponent));
			// ==============end================
			e.consume();
		}
	}

	public void mouseReleased(MouseEvent e) {
		if (isActive()) {
			if (error != null) {
				if (error.length() > 0) {
					// ==============start==============
					JOptionPane.showMessageDialog(graphComponent, error, "Validation Error!", JOptionPane.WARNING_MESSAGE);
					// ==============end================
				}
			} else if (first != null) {
				mxGraph graph = graphComponent.getGraph();
				double dx = first.getX() - e.getX();
				double dy = first.getY() - e.getY();

				if (connectPreview.isActive() && (marker.hasValidState() || isCreateTarget() || graph.isAllowDanglingEdges())) {
					graph.getModel().beginUpdate();

					try {
						Object dropTarget = null;
						Object vertex = source.getCell();

						if (!marker.hasValidState() && isCreateTarget()) {
							vertex = createTargetVertex(e, source.getCell());
							dropTarget = graph.getDropTarget(new Object[] { vertex }, e.getPoint(), graphComponent.getCellAt(e.getX(), e.getY()));

							if (vertex != null) {
								// Disables edges as drop targets if the target cell was created
								if (dropTarget == null || !graph.getModel().isEdge(dropTarget)) {
									mxCellState pstate = graph.getView().getState(dropTarget);

									if (pstate != null) {
										mxGeometry geo = graph.getModel().getGeometry(vertex);

										mxPoint origin = pstate.getOrigin();
										geo.setX(geo.getX() - origin.getX());
										geo.setY(geo.getY() - origin.getY());
									}
								} else {
									dropTarget = graph.getDefaultParent();
								}

								graph.addCells(new Object[] { vertex }, dropTarget);

								// FIXME: Here we pre-create the state for the vertex to be
								// inserted in order to invoke update in the connectPreview.
								// This means we have a cell state which should be created
								// after the model.update, so this should be fixed.
								mxCellState targetState = graph.getView().getState(vertex, true);
								connectPreview.update(e, targetState, e.getX(), e.getY());
							} else {
								graphComponent.refresh();
							}
						}

						if (vertex != null) {
							Object cell = connectPreview.stop(graphComponent.isSignificant(dx, dy), e);

							if (cell != null) {
								if (vertex != source.getCell()) {
									graph.setSelectionCell(vertex);
									graphComponent.startEditing();
								} else {
									graph.setSelectionCell(cell);
								}
								eventSource.fireEvent(new mxEventObject(mxEvent.CONNECT, "cell", cell, "event", e, "target", dropTarget));
							}

							e.consume();
						}
					} finally {
						graph.getModel().endUpdate();
					}
				}
			}
		}

		reset();
	}

	public Object createTargetVertex(MouseEvent e, Object source) {
		Graph graph = getGraphComponent().getGraph();
		GraphModel model = graph.getModel();
		graph.refresh();
		connectPreview.update(e, null, e.getX(), e.getY());
		final mxCell[] target = new mxCell[1];
		target[0] = new mxCell();
		target[0].setVertex(true);
		target[0].setStyle("task");

		final int width = Integer.parseInt(Constants.SETTINGS.getProperty("style_task_width", "85"));
		final int height = Integer.parseInt(Constants.SETTINGS.getProperty("style_task_height", "55"));
		final mxGeometry geo = new mxGeometry(0, 0, width, height);
		target[0].setGeometry(geo);

		final int gateWaySize = Integer.parseInt(Constants.SETTINGS.getProperty("style_gateway_size", "42"));
		final mxGeometry gateWayGeo = new mxGeometry(0, 0, gateWaySize, gateWaySize);

		final int subprocessWidth = Integer.parseInt(Constants.SETTINGS.getProperty("style_subprocess_width", "400"));
		final int subprocessHeight = Integer.parseInt(Constants.SETTINGS.getProperty("style_subprocess_height", "250"));
		final mxGeometry subprocessGeo = new mxGeometry(0, 0, 85, 55);
		subprocessGeo.setAlternateBounds(new mxRectangle(0, 0, subprocessWidth, subprocessHeight));

		final JDialog dialog = new JDialog() {
			private static final long serialVersionUID = 2189389368898372086L;

			protected JRootPane createRootPane() {
				KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
				JRootPane rootPane = new JRootPane();
				rootPane.registerKeyboardAction(new ActionListener() {
					public void actionPerformed(ActionEvent actionEvent) {
						create = false;
						dispose();
					}
				}, stroke, JComponent.WHEN_IN_FOCUSED_WINDOW);
				return rootPane;
			}
		};
		dialog.setModal(true);
		dialog.setUndecorated(true);
		if (Constants.JAVA_VERSION >= 1.6) {
			dialog.setLocation(e.getLocationOnScreen());
		} else {
			dialog.setLocation(SwingUtilities.convertPoint(e.getComponent(), e.getPoint(), null));
		}
		JMenuBar menuBar = new JMenuBar();
		menuBar.setBorderPainted(false);
		JMenu menu = menuBar.add(new JMenu(Resources.get("task")));
		menu.add(new AbstractAction(Resources.get("task")) {
			private static final long serialVersionUID = -1611245355110855186L;

			public void actionPerformed(ActionEvent e) {
				target[0].setValue(new Task(Resources.get("task")));
				create = true;
				dialog.dispose();
			}
		});
		menu.add(new AbstractAction(Resources.get("sendTask")) {
			private static final long serialVersionUID = -3844960188265669082L;

			public void actionPerformed(ActionEvent e) {
				target[0].setValue(new SendTask(Resources.get("sendTask")));
				create = true;
				dialog.dispose();

			}
		});
		menu.add(new AbstractAction(Resources.get("receiveTask")) {
			private static final long serialVersionUID = 1691280172715903327L;

			public void actionPerformed(ActionEvent e) {
				target[0].setValue(new ReceiveTask(Resources.get("receiveTask")));
				create = true;
				dialog.dispose();

			}
		});
		menu.add(new AbstractAction(Resources.get("serviceTask")) {
			private static final long serialVersionUID = -8211002550564218740L;

			public void actionPerformed(ActionEvent e) {
				target[0].setValue(new ServiceTask(Resources.get("serviceTask")));
				create = true;
				dialog.dispose();

			}
		});
		menu.add(new AbstractAction(Resources.get("userTask")) {
			private static final long serialVersionUID = 392290782993080476L;

			public void actionPerformed(ActionEvent e) {
				target[0].setValue(new UserTask(Resources.get("userTask")));
				create = true;
				dialog.dispose();

			}
		});
		menu.add(new AbstractAction(Resources.get("manualTask")) {
			private static final long serialVersionUID = -7275303335441020154L;

			public void actionPerformed(ActionEvent e) {
				target[0].setValue(new ManualTask(Resources.get("manualTask")));
				create = true;
				dialog.dispose();

			}
		});
		menu.add(new AbstractAction(Resources.get("scriptTask")) {
			private static final long serialVersionUID = -1666035613396497829L;

			public void actionPerformed(ActionEvent e) {
				target[0].setValue(new ScriptTask(Resources.get("scriptTask")));
				create = true;
				dialog.dispose();

			}
		});
		menu.add(new AbstractAction(Resources.get("businessRuleTask")) {
			private static final long serialVersionUID = -3208987886595389014L;

			public void actionPerformed(ActionEvent e) {
				target[0].setValue(new BusinessRuleTask(Resources.get("businessRuleTask")));
				create = true;
				dialog.dispose();

			}
		});
		menu = menuBar.add(new JMenu(Resources.get("subprocess")));
		menu.add(new AbstractAction(Resources.get("subprocess")) {
			private static final long serialVersionUID = -1611245355110855186L;

			public void actionPerformed(ActionEvent e) {
				target[0].setValue(new SubProcess(Resources.get("subprocess")));
				target[0].setGeometry(subprocessGeo);
				target[0].setStyle("subprocess;verticalAlign=middle");
				create = true;
				dialog.dispose();

			}
		});
		menu.add(new AbstractAction(Resources.get("tranSubProcess")) {
			private static final long serialVersionUID = 1691280172715903327L;

			public void actionPerformed(ActionEvent e) {
				target[0].setValue(new Transaction(Resources.get("tranSubProcess")));
				target[0].setGeometry(subprocessGeo);
				target[0].setStyle("subprocess;verticalAlign=middle");
				create = true;
				dialog.dispose();

			}
		});
		menu.add(new AbstractAction(Resources.get("adHocSubProcess")) {
			private static final long serialVersionUID = -8211002550564218740L;

			public void actionPerformed(ActionEvent e) {
				target[0].setValue(new AdHocSubProcess(Resources.get("adHocSubProcess")));
				target[0].setGeometry(subprocessGeo);
				target[0].setStyle("subprocess;verticalAlign=middle");
				create = true;
				dialog.dispose();

			}
		});
		menu = menuBar.add(new JMenu(Resources.get("CallActivity")));
		menu.add(new AbstractAction(Resources.get("callActivity")) {
			private static final long serialVersionUID = -1611245355110855186L;

			public void actionPerformed(ActionEvent e) {
				target[0].setValue(new CallActivity(Resources.get("CallActivity"), "globalTask"));
				target[0].setStyle("callTask");
				create = true;
				dialog.dispose();

			}
		});
		menu.add(new AbstractAction(Resources.get("callUser")) {
			private static final long serialVersionUID = -3844960188265669082L;

			public void actionPerformed(ActionEvent e) {
				target[0].setValue(new CallActivity(Resources.get("CallActivity"), "globalUserTask"));
				target[0].setStyle("callTask");
				create = true;
				dialog.dispose();

			}
		});
		menu.add(new AbstractAction(Resources.get("callManual")) {
			private static final long serialVersionUID = 1691280172715903327L;

			public void actionPerformed(ActionEvent e) {
				target[0].setValue(new CallActivity(Resources.get("CallActivity"), "globalManualTask"));
				target[0].setStyle("callTask");
				create = true;
				dialog.dispose();

			}
		});
		menu.add(new AbstractAction(Resources.get("callScript")) {
			private static final long serialVersionUID = -8211002550564218740L;

			public void actionPerformed(ActionEvent e) {
				target[0].setValue(new CallActivity(Resources.get("CallActivity"), "globalScriptTask"));
				target[0].setStyle("callTask");
				create = true;
				dialog.dispose();

			}
		});
		menu.add(new AbstractAction(Resources.get("callBusinessRule")) {
			private static final long serialVersionUID = 392290782993080476L;

			public void actionPerformed(ActionEvent e) {
				target[0].setValue(new CallActivity(Resources.get("CallActivity"), "globalBusinessRuleTask"));
				target[0].setStyle("callTask");
				create = true;
				dialog.dispose();

			}
		});
		menu.add(new AbstractAction(Resources.get("callProcess")) {
			private static final long serialVersionUID = -7275303335441020154L;

			public void actionPerformed(ActionEvent e) {
				target[0].setValue(new CallActivity(Resources.get("CallActivity"), "callProcess"));
				target[0].setStyle("callProcess");
				create = true;
				dialog.dispose();

			}
		});
		menu = menuBar.add(new JMenu(Resources.get("gateway")));
		menu.add(new AbstractAction(Resources.get("exclusiveGateway")) {
			private static final long serialVersionUID = -1611245355110855186L;

			public void actionPerformed(ActionEvent e) {
				target[0].setValue(new ExclusiveGateway(Resources.get("exclusiveGateway")));
				target[0].setGeometry(gateWayGeo);
				target[0].setStyle("exclusiveGateway");
				create = true;
				dialog.dispose();

			}
		});
		menu.add(new AbstractAction(Resources.get("exclusiveGatewayWithIndicator")) {
			private static final long serialVersionUID = -3844960188265669082L;

			public void actionPerformed(ActionEvent e) {
				target[0].setValue(new ExclusiveGateway(Resources.get("exclusiveGateway")));
				target[0].setGeometry(gateWayGeo);
				target[0].setStyle("exclusiveGatewayWithIndicator");
				create = true;
				dialog.dispose();

			}
		});
		menu.add(new AbstractAction(Resources.get("parallelGateway")) {
			private static final long serialVersionUID = 1691280172715903327L;

			public void actionPerformed(ActionEvent e) {
				target[0].setValue(new ParallelGateway(Resources.get("parallelGateway")));
				target[0].setGeometry(gateWayGeo);
				target[0].setStyle("gateway");
				create = true;
				dialog.dispose();

			}
		});
		menu.add(new AbstractAction(Resources.get("inclusiveGateway")) {
			private static final long serialVersionUID = -8211002550564218740L;

			public void actionPerformed(ActionEvent e) {
				target[0].setValue(new InclusiveGateway(Resources.get("inclusiveGateway")));
				target[0].setGeometry(gateWayGeo);
				target[0].setStyle("gateway");
				create = true;
				dialog.dispose();

			}
		});
		menu.add(new AbstractAction(Resources.get("complexGateway")) {
			private static final long serialVersionUID = 392290782993080476L;

			public void actionPerformed(ActionEvent e) {
				target[0].setValue(new ComplexGateway(Resources.get("complexGateway")));
				target[0].setGeometry(gateWayGeo);
				target[0].setStyle("gateway");
				create = true;
				dialog.dispose();

			}
		});
		menu.add(new AbstractAction(Resources.get("eventGateway")) {
			private static final long serialVersionUID = -7275303335441020154L;

			public void actionPerformed(ActionEvent e) {
				target[0].setValue(new EventBasedGateway(Resources.get("eventGateway")));
				target[0].setGeometry(gateWayGeo);
				target[0].setStyle("gateway");
				create = true;
				dialog.dispose();

			}
		});
		menu = menuBar.add(new JMenu(Resources.get("event")));
		menu.add(new AbstractAction(Resources.get("intermediateThrowEvent")) {
			private static final long serialVersionUID = 8410063499332903660L;

			public void actionPerformed(ActionEvent e) {
				String size = Constants.SETTINGS.getProperty("style_intermediateThrowEvent_size", "32");
				mxGeometry geo = new mxGeometry(0, 0, Integer.parseInt(size), Integer.parseInt(size));
				target[0].setValue(new IntermediateThrowEvent(Resources.get("intermediateThrowEvent")));
				target[0].setGeometry(geo);
				target[0].setStyle("intermediateEvent");
				create = true;
				dialog.dispose();

			}
		});
		menu.add(new AbstractAction(Resources.get("intermediateCatchEvent")) {
			private static final long serialVersionUID = 8608648819131423456L;

			public void actionPerformed(ActionEvent e) {
				String size = Constants.SETTINGS.getProperty("style_intermediateCatchEvent_size", "32");
				mxGeometry geo = new mxGeometry(0, 0, Integer.parseInt(size), Integer.parseInt(size));
				target[0].setValue(new IntermediateCatchEvent(Resources.get("intermediateCatchEvent")));
				target[0].setGeometry(geo);
				target[0].setStyle("intermediateEvent");
				create = true;
				dialog.dispose();

			}
		});
		menu.add(new AbstractAction(Resources.get("endEvent")) {
			private static final long serialVersionUID = -581622438562374357L;

			public void actionPerformed(ActionEvent e) {
				String size = Constants.SETTINGS.getProperty("style_endEvent_size", "32");
				mxGeometry geo = new mxGeometry(0, 0, Integer.parseInt(size), Integer.parseInt(size));
				target[0].setValue(new EndEvent(Resources.get("endEvent")));
				target[0].setGeometry(geo);
				target[0].setStyle("endEvent");
				create = true;
				dialog.dispose();

			}
		});
		menu = menuBar.add(new JMenu(new AbstractAction("", new ImageIcon(ConnectionHandler.class.getResource("/org/yaoqiang/images/close.png"))) {
			private static final long serialVersionUID = -1878271033938524199L;

			public void actionPerformed(ActionEvent e) {
			}
		}));
		menu.addMouseListener(new MouseAdapter() {
			public void mousePressed(MouseEvent e) {
				create = false;
				dialog.dispose();
			}
		});
		dialog.add(menuBar);
		dialog.pack();
		dialog.setVisible(true);
		if (!create) {
			return null;
		}
		if (target.length == 1) {
			Object clone = graph.cloneCells(target)[0];
			if (Constants.SETTINGS.getProperty("labelWrap", "0").equals("1")) {
				model.setStyle(clone, model.getStyle(clone) + ";whiteSpace=wrap;");
				GraphUtils.setElementStyles(graph, clone, "whiteSpace");
			}
			mxGeometry newGeo = model.getGeometry(clone);

			if (newGeo != null) {
				mxPoint point = graphComponent.getPointForEvent(e);
				newGeo.setX(graph.snap(point.getX() - newGeo.getWidth() / 2));
				newGeo.setY(graph.snap(point.getY() - newGeo.getHeight() / 2));
			}
			return clone;
		}

		return null;
	}

	public void paint(Graphics g) {
		if (bounds != null) {
			if (connectIcon != null) {
				g.drawImage(connectIcon.getImage(), bounds.x, bounds.y, bounds.width, bounds.height, null);
			} else if (handleEnabled) {
				// ==============start==============
				g.setColor(Color.BLACK);
				g.draw3DRect(bounds.x, bounds.y, bounds.width - 1, bounds.height - 1, true);
				g.setColor(Color.BLUE);
				g.fill3DRect(bounds.x + 1, bounds.y + 1, bounds.width - 2, bounds.height - 2, true);
				// ==============end================
			}
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy