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

org.yaoqiang.graph.swing.GraphComponent Maven / Gradle / Ivy

There is a newer version: 2.2.18
Show newest version
package org.yaoqiang.graph.swing;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.util.EventObject;

import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
import javax.swing.ToolTipManager;

import org.w3c.dom.Document;
import org.yaoqiang.bpmn.model.elements.activities.Activity;
import org.yaoqiang.bpmn.model.elements.activities.AdHocSubProcess;
import org.yaoqiang.bpmn.model.elements.choreographyactivities.ChoreographyActivity;
import org.yaoqiang.bpmn.model.elements.core.common.FlowNode;
import org.yaoqiang.bpmn.model.elements.core.foundation.BaseElement;
import org.yaoqiang.bpmn.model.elements.events.BoundaryEvent;
import org.yaoqiang.graph.handler.ConnectionHandler;
import org.yaoqiang.graph.handler.GraphHandler;
import org.yaoqiang.graph.model.GraphModel;
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.io.mxCodec;
import com.mxgraph.model.mxICell;
import com.mxgraph.swing.mxGraphComponent;
import com.mxgraph.swing.view.mxICellEditor;
import com.mxgraph.util.mxUtils;
import com.mxgraph.view.mxCellState;

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

	private static final long serialVersionUID = 5582918475032396064L;

	protected Point popupPoint;

	protected Point pasteToPoint;

	protected Object lastViewRoot;

	public GraphComponent(Graph graph) {
		super(graph);
		// Sets switches typically used in an editor
		setPageVisible(true);
		setVerticalPageCount(getGraph().getModel().getPageCount());
		setHorizontalPageCount(getGraph().getModel().getHorizontalPageCount());
		setGridVisible(Constants.SETTINGS.getProperty("showGrid", "1").equals("1"));
		setGridStyle(Integer.parseInt(Constants.SETTINGS.getProperty("gridstyle", "3")));
		setGridColor(mxUtils.parseColor(Constants.SETTINGS.getProperty("gridColor", "#c0c0c0")));
		setToolTips(true);
		setZoomFactor(1.05);
		setTolerance(2);
		setZoomPolicy(mxGraphComponent.ZOOM_POLICY_PAGE);
		setKeepSelectionVisibleOnZoom(true);
		setDragEnabled(false);
		setPreferPageSize(true);
		setEnterStopsCellEditing(true);
		ToolTipManager.sharedInstance().setDismissDelay(Integer.MAX_VALUE);
		getConnectionHandler().setHandleEnabled(true);
		getConnectionHandler().setCreateTarget(true);
		// setTripleBuffered(true);
		// getGraphHandler().setRemoveCellsFromParent(false);

		if (Constants.SETTINGS.getProperty("showRulers", "1").equals("1")) {
			setColumnHeaderView(new Ruler(this, Ruler.ORIENTATION_HORIZONTAL));
			setRowHeaderView(new Ruler(this, Ruler.ORIENTATION_VERTICAL));
		}

		// Loads the defalt stylesheet from an external file
		mxCodec codec = new mxCodec();
		Document doc = mxUtils.loadDocument(GraphComponent.class.getResource(Constants.DEFAULT_STYLE_XML).toString());
		codec.decode(doc.getDocumentElement(), graph.getStylesheet());

		// Sets the background to white
		getViewport().setOpaque(true);
		getViewport().setBackground(Color.WHITE);

		setFocusTraversalKeysEnabled(false);
		addKeyListener(new KeyAdapter() {
			public void keyPressed(KeyEvent e) {
				if (e.getKeyCode() == KeyEvent.VK_ENTER) {
					startEditing();
				} else if (e.getKeyCode() == KeyEvent.VK_TAB) {
					if ((e.getModifiers() & KeyEvent.SHIFT_MASK) != 0) {
						getGraph().selectPreviousCell();
					} else {
						getGraph().selectNextCell();
					}
				}
			}
		});
	}

	public Graph getGraph() {
		return (Graph) graph;
	}

	public Point getPopupPoint() {
		return popupPoint;
	}

	public void setPopupPoint(Point popupPoint) {
		this.popupPoint = popupPoint;
	}

	public Point getPasteToPoint() {
		return pasteToPoint;
	}

	public void setPasteToPoint(Point pasteToPoint) {
		this.pasteToPoint = pasteToPoint;
	}

	public Object getLastViewRoot() {
		return lastViewRoot;
	}

	public void setLastViewRoot(Object lastViewRoot) {
		this.lastViewRoot = lastViewRoot;
	}

	protected ConnectionHandler createConnectionHandler() {
		return new ConnectionHandler(this);
	}

	protected GraphHandler createGraphHandler() {
		return new GraphHandler(this);
	}

	protected mxICellEditor createCellEditor() {
		return new CellEditor(this);
	}

	public Object[] importCells(Object[] cells, double dx, double dy, Object target, Point location) {
		if (cells[0] instanceof mxICell) {
			mxICell dropCell = (mxICell) cells[0];
			Graph graph = getGraph();
			GraphModel model = graph.getModel();

			if ("org".equals(getName()) && !graph.isOrganizationElement(dropCell) || !"org".equals(getName()) && !"GraphEditor".equals(getName())
					&& graph.isOrganizationElement(dropCell)) {
				return null;
			}

			if (target == null) {
				target = graph.getCurrentRoot();
			}

			if (graph.isSwimlane(dropCell)) {
				if (target == null) {
					if (GraphUtils.hasSwimlane(graph, !graph.isVerticalSwimlane(dropCell))) {
						return null;
					}
				} else {
					if (graph.isSwimlane(target)) {
						if (model.isPool(dropCell) || (graph.isVerticalSwimlane(dropCell) && !graph.isVerticalSwimlane(target))
								|| (!graph.isVerticalSwimlane(dropCell) && graph.isVerticalSwimlane(target))) {
							return null;
						}
					} else {
						JOptionPane.showMessageDialog(null, Resources.get("WarningSubProcessCannotContainPool"), "Not Supported", JOptionPane.WARNING_MESSAGE);
						return null;
					}
				}
			} else {
				if (target == null && dropCell.getParent() == null && dropCell.getId() != null && dropCell.isVertex()) {
					if (graph.isChoreography(dropCell) || graph.isSubChoreography(dropCell)) {
						JOptionPane.showMessageDialog(null, Resources.get("WarningCopyPasteNotApplicableForChoreography"), "Not Applicable",
								JOptionPane.WARNING_MESSAGE);
						return null;
					}
					mxICell srcCell = (mxICell) getCellAt((int) dropCell.getGeometry().getX(), (int) dropCell.getGeometry().getY());
					if (getPasteToPoint() != null) {
						srcCell = (mxICell) getCellAt(getPasteToPoint().x, getPasteToPoint().y);
					}

					if (srcCell == null) {
						target = null;
					} else if (dropCell.getId().equals(srcCell.getId())) {
						target = model.getParent(srcCell);
					} else {
						if (model.isSubProcess(srcCell) || graph.isSwimlane(srcCell)) {
							target = srcCell;
						} else {
							target = model.getParent(srcCell);
						}
					}
				}
			}
			if (dropCell.isVertex() && !graph.isOrganizationElement(dropCell)) {
				if (model.isMessage(dropCell)) {
					GraphUtils.setElementStyles(graph, dropCell, "init");
				}
				if (Constants.SETTINGS.getProperty("labelWrap", "0").equals("1")) {
					model.setStyle(dropCell, dropCell.getStyle() + ";whiteSpace=wrap;");
					GraphUtils.setElementStyles(graph, dropCell, "whiteSpace");
				}
			}
			if (dropCell.getValue() instanceof BoundaryEvent) {
				if (target == null || (!model.isTask(target) && !model.isSubProcess(target) && !model.isCallActivity(target))) {
					JOptionPane.showMessageDialog(null, Resources.get("WarningBoundaryEventMustBeAttachedToActivityBoundary"), "Validation Error!",
							JOptionPane.WARNING_MESSAGE);
					return null;
				}
			}
		}
		return graph.moveCells(cells, dx, dy, true, target, location);
	}

	public ImageIcon getFoldingIcon(mxCellState state) {
		if (state != null) {
			// ==============start==============
			if (getGraph().getModel().isCollapsedSubProcess(state.getCell())) {
				return new ImageIcon(GraphComponent.class.getResource("/org/yaoqiang/graph/shape/markers/subprocess.png"));
				// ==============end================
			} else {
				if (isFoldingEnabled() && !graph.getModel().isEdge(state.getCell())) {
					Object cell = state.getCell();
					boolean tmp = graph.isCellCollapsed(cell);

					if (graph.isCellFoldable(cell, !tmp)) {
						return (tmp) ? collapsedIcon : expandedIcon;
					}
				}
			}
		}

		return null;
	}

	public Rectangle getFoldingIconBounds(mxCellState state, ImageIcon icon) {
		if (getGraph().getModel().isCollapsedSubProcess(state.getCell())) {
			FlowNode flowNode = (FlowNode) ((mxICell) state.getCell()).getValue();
			double scale = getGraph().getView().getScale();
			Rectangle iconBounds = state.getRectangle();
			int imgWidth = (int) (32 * scale);
			int imgHeight = (int) (16 * scale);

			String compensationMarker = null;
			String loopMarker = null;

			if (flowNode instanceof Activity) {
				Activity subProcess = (Activity) flowNode;
				compensationMarker = subProcess.isForCompensation() ? "" : null;
				if (subProcess.getLoopCharacteristics() != null) {
					loopMarker = "";
				}
			} else if (flowNode instanceof ChoreographyActivity) {
				ChoreographyActivity subProcess = (ChoreographyActivity) flowNode;
				if (!subProcess.getLoopType().equals("None")) {
					loopMarker = "";
				}
			}

			if (flowNode instanceof AdHocSubProcess) {
				if (loopMarker != null || compensationMarker != null) {
					if (loopMarker != null && compensationMarker != null) {
						iconBounds.setRect(iconBounds.getX() + iconBounds.getWidth() / 2, iconBounds.getY() + iconBounds.getHeight() - imgHeight, imgWidth / 2,
								imgHeight);
					} else {
						iconBounds.setRect(iconBounds.getX() + (2 * iconBounds.getWidth() - imgWidth) / 4, iconBounds.getY() + iconBounds.getHeight()
								- imgHeight, imgWidth / 2, imgHeight);
					}
				} else {
					iconBounds.setRect(iconBounds.getX() + (iconBounds.getWidth() - imgWidth) / 2, iconBounds.getY() + iconBounds.getHeight() - imgHeight,
							imgWidth / 2, imgHeight);
				}
			} else {
				if (loopMarker != null || compensationMarker != null) {
					if (loopMarker != null && compensationMarker != null) {
						iconBounds.setRect(iconBounds.getX() + (2 * iconBounds.getWidth() + imgWidth) / 4, iconBounds.getY() + iconBounds.getHeight()
								- imgHeight, imgWidth / 2, imgHeight);
					} else {
						iconBounds.setRect(iconBounds.getX() + iconBounds.getWidth() / 2, iconBounds.getY() + iconBounds.getHeight() - imgHeight, imgWidth / 2,
								imgHeight);
					}
				} else {
					iconBounds.setRect(iconBounds.getX() + (2 * iconBounds.getWidth() - imgWidth) / 4, iconBounds.getY() + iconBounds.getHeight() - imgHeight,
							imgWidth / 2, imgHeight);
				}
			}
			return iconBounds;
		} else {
			return super.getFoldingIconBounds(state, icon);
		}

	}

	public boolean isGridEnabledEvent(MouseEvent event) {
		boolean enable = Constants.SETTINGS.getProperty("snapToGrid", "0").equals("1");
		return (event != null) ? enable ? !event.isAltDown() : event.isAltDown() : false;
	}

	public boolean isConstrainedEvent(MouseEvent event) {
		return (event != null) ? event.isShiftDown() || getGraph().getModel().isBoundaryEvent(graph.getSelectionCell())
				|| getGraph().getModel().isMessage(graph.getSelectionCell())
				&& getGraph().getModel().isMessageFlow(graph.getModel().getParent(graph.getSelectionCell())) || getGraph().isAutoPool(graph.getSelectionCell())
				|| getGraph().getModel().isRootLane(graph.getSelectionCell()) : false;
	}

	public CellEditor getCellEditor() {
		return (CellEditor) cellEditor;
	}

	public Object getEditingValue(Object cell, EventObject trigger) {
		GraphModel model = getGraph().getModel();
		if (model.isGroupArtifact(cell) || model.isDataStore(cell) || model.isDataObject(cell)) {
			return model.getValue(cell);
		} else if (model.isSequenceFlow(cell)) {
			return ((BaseElement) model.getValue(cell)).get("name").toValue();
		}
		return graph.convertValueToString(cell);
	}

	public void startEditing() {
		Object cell = graph.getSelectionCell();
		if (getGraph().isChoreography(cell) || getGraph().isSubChoreography(cell)) {
			cell = GraphUtils.getChoreographyActivity(getGraph(), cell);
		}
		startEditingAtCell(cell);
	}

	public void paintAuxiliaryLines(Graphics2D g, Rectangle bounds) {
		g.setStroke(new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0f, new float[] { 30.0f, 3.0f, 2.0f, 3.0f }, 0.0f));
		g.setColor(Color.BLACK);
		g.drawLine(bounds.x, 0, bounds.x, graphControl.getHeight());
		g.drawLine(bounds.x + bounds.width / 2, 0, bounds.x + bounds.width / 2, graphControl.getHeight());
		g.drawLine(bounds.x + bounds.width, 0, bounds.x + bounds.width, graphControl.getHeight());
		g.drawLine(0, bounds.y, graphControl.getWidth(), bounds.y);
		g.drawLine(0, bounds.y + bounds.height / 2, graphControl.getWidth(), bounds.y + bounds.height / 2);
		g.drawLine(0, bounds.y + bounds.height, graphControl.getWidth(), bounds.y + bounds.height);
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy