
org.yaoqiang.graph.handler.YGraphHandler Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of yaoqiang-bpmn-editor Show documentation
Show all versions of yaoqiang-bpmn-editor Show documentation
an Open Source BPMN 2.0 Modeler
package org.yaoqiang.graph.handler;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.TransferHandler;
import org.yaoqiang.graph.swing.YGraphComponent;
import org.yaoqiang.graph.util.Constants;
import org.yaoqiang.graph.view.YGraph;
import com.mxgraph.model.mxCell;
import com.mxgraph.model.mxGeometry;
import com.mxgraph.model.mxIGraphModel;
import com.mxgraph.swing.mxGraphComponent;
import com.mxgraph.swing.mxGraphComponent.mxGraphControl;
import com.mxgraph.swing.handler.mxCellMarker;
import com.mxgraph.swing.handler.mxGraphHandler;
import com.mxgraph.swing.handler.mxGraphTransferHandler;
import com.mxgraph.swing.util.mxSwingConstants;
import com.mxgraph.util.mxPoint;
import com.mxgraph.util.mxUtils;
import com.mxgraph.view.mxCellState;
import com.mxgraph.view.mxGraph;
/**
* YGraphHandler
*
* @author Shi Yaoqiang([email protected])
*/
public class YGraphHandler extends mxGraphHandler {
public YGraphHandler(mxGraphComponent graphComponent) {
super(graphComponent);
}
public YGraphComponent getGraphComponent() {
return (YGraphComponent) graphComponent;
}
protected mxCellMarker createMarker()
{
mxCellMarker marker = new mxCellMarker(graphComponent, Color.BLUE)
{
/**
*
*/
private static final long serialVersionUID = -8451338653189373347L;
/**
*
*/
public boolean isEnabled()
{
return graphComponent.getGraph().isDropEnabled();
}
/**
*
*/
public Object getCell(MouseEvent e)
{
mxIGraphModel model = graphComponent.getGraph().getModel();
TransferHandler th = graphComponent.getTransferHandler();
boolean isLocal = th instanceof mxGraphTransferHandler
&& ((mxGraphTransferHandler) th).isLocalDrag();
YGraph graph = getGraphComponent().getGraph();
Object cell = super.getCell(e);
Object[] cells = (isLocal) ? graph.getSelectionCells()
: dragCells;
cell = graph.getDropTarget(cells, e.getPoint(), cell);
// Checks if parent is dropped into child
Object parent = cell;
while (parent != null)
{
if (mxUtils.contains(cells, parent))
{
return null;
}
parent = model.getParent(parent);
}
boolean clone = graphComponent.isCloneEvent(e) && cloneEnabled;
if (isLocal && cell != null && cells.length > 0 && !clone
&& graph.getModel().getParent(cells[0]) == cell)
{
cell = null;
}
// ==============start==============
if (graph.getSelectionCells().length > 0) {
Object selectedCell = graph.getSelectionCells()[0];
if (graph.isAttachedEvent(selectedCell)) {
cell = graph.getModel().getParent(selectedCell);
}
}
// ==============end================
return cell;
}
};
// Swimlane content area will not be transparent drop targets
marker.setSwimlaneContentEnabled(true);
return marker;
}
protected Cursor getCursor(MouseEvent e)
{
Cursor cursor = null;
if (isMoveEnabled())
{
Object cell = graphComponent.getCellAt(e.getX(), e.getY(), false);
if (cell != null)
{
if (graphComponent.isFoldingEnabled()
&& graphComponent.hitFoldingIcon(cell, e.getX(),
e.getY()))
{
cursor = FOLD_CURSOR;
}
else if (graphComponent.getGraph().isCellMovable(cell))
{
// ==============start==============
if (graphComponent.getGraph().getModel().isEdge(cell)) {
cursor = new Cursor(Cursor.HAND_CURSOR);
} else {
cursor = MOVE_CURSOR;
}
// ==============end================
}
}
}
return cursor;
}
public void mousePressed(MouseEvent e)
{
if (graphComponent.isEnabled() && isEnabled() && !e.isConsumed()
&& !graphComponent.isForceMarqueeEvent(e))
{
cell = graphComponent.getCellAt(e.getX(), e.getY(), false);
// ==============start==============
YGraph graph = getGraphComponent().getGraph();
if (graph.isChoreographyTask(cell) || graph.isChoreographySubprocess(cell) || graph.isChoreographyParticipant(cell)) {
cell = graph.getModel().getParent(cell);
}
// ==============end================
initialCell = cell;
if (cell != null)
{
if (isSelectEnabled()
&& !graphComponent.getGraph().isCellSelected(cell))
{
graphComponent.selectCellForEvent(cell, e);
cell = null;
}
// Starts move if the cell under the mouse is movable and/or any
// cells of the selection are movable
if (isMoveEnabled() && !e.isPopupTrigger())
{
start(e);
e.consume();
}
}
else if (e.isPopupTrigger())
{
graphComponent.getGraph().clearSelection();
}
}
}
public void mouseDragged(MouseEvent e)
{
// LATER: Check scrollborder, use scroll-increments, do not
// scroll when over ruler dragging from library
graphComponent.getGraphControl().scrollRectToVisible(
new Rectangle(e.getPoint()));
if (!e.isConsumed())
{
gridEnabledEvent = graphComponent.isGridEnabledEvent(e);
constrainedEvent = graphComponent.isConstrainedEvent(e);
YGraph graph = getGraphComponent().getGraph();
if (constrainedEvent && first != null)
{
int x = e.getX();
int y = e.getY();
// ==============start==============
mxCell cell = (mxCell) graph.getSelectionCell();
if (graph.isAttachedEvent(cell)) {
mxCell parent = (mxCell) graph.getModel().getParent(cell);
Rectangle rect = graph.getView().getState(parent).getRectangle();
Rectangle eventRect = graph.getView().getState(cell).getRectangle();
if (Math.abs(e.getX() - first.x) > Math.abs(e.getY() - first.y)) {
if (first.y - eventRect.getHeight() / 2 <= rect.getY() || first.y + eventRect.getHeight() / 2 >= (rect.getY() + rect.getHeight())) {
if (x > (rect.getX() + rect.getWidth())) {
x = (int) ((rect.getX() + rect.getWidth()));
} else if (x < rect.getX()) {
x = (int) (rect.getX());
}
y = first.y;
} else {
x = first.x;
y = first.y;
}
} else {
if (first.x - eventRect.getWidth() / 2 <= rect.getX() || first.x + eventRect.getWidth() / 2 >= (rect.getX() + rect.getWidth())) {
if (y > (rect.getY() + rect.getHeight())) {
y = (int) ((rect.getY() + rect.getHeight()));
} else if (y < rect.getY()) {
y = (int) (rect.getY());
}
x = first.x;
} else {
x = first.x;
y = first.y;
}
}
} else if (graph.isMessage(cell)) {
mxCell parent = (mxCell) graph.getModel().getParent(cell);
if (graph.isMessageFlow(parent)) {
mxCellState state = graph.getView().getState(parent);
double scale = graph.getView().getScale();
List points = new ArrayList(state.getAbsolutePoints());
mxPoint[] p = points.toArray(new mxPoint[points.size()]);
Rectangle rect = state.getRectangle();
if (x > (rect.getX() + rect.getWidth())) {
x = (int) ((rect.getX() + rect.getWidth()));
} else if (x < rect.getX()) {
x = (int) (rect.getX());
} else {
y = (int) p[1].getY();
}
if (y > (rect.getY() + rect.getHeight())) {
y = (int) ((rect.getY() + rect.getHeight()));
} else if (y < rect.getY()) {
y = (int) (rect.getY());
}
if (Math.abs(x - p[0].getX()) < 5 * scale) {
if (p[0].getY() > p[1].getY()) {
if (y < p[1].getY()) {
y = (int) p[1].getY();
}
} else {
if (y > p[1].getY()) {
y = (int) p[1].getY();
}
}
} else if (Math.abs(x - p[2].getX()) < 5 * scale) {
if (p[p.length - 1].getY() > p[p.length - 2].getY()) {
if (y < p[p.length - 2].getY()) {
y = (int) p[p.length - 2].getY();
}
} else if ((int) p[p.length - 1].getY() == (int) p[p.length - 2].getY()) {
y = (int) p[p.length - 2].getY();
} else if (p[p.length - 1].getY() < p[p.length - 2].getY()) {
if (y > p[p.length - 2].getY()) {
y = (int) p[p.length - 2].getY();
}
} else if (y > p[p.length - 1].getY()) {
y = (int) p[p.length - 2].getY();
}
}
if ((int) p[0].getX() == (int) p[p.length - 1].getX()) {
x = first.x;
}
}
} else if (graph.isPool(cell)) {
if (graph.isVerticalSwimlane(cell)) {
y = first.y;
} else {
x = first.x;
}
} else {
if (Math.abs(e.getX() - first.x) > Math.abs(e.getY() - first.y)) {
y = first.y;
} else {
x = first.x;
}
}
// ==============end================
e = new MouseEvent(e.getComponent(), e.getID(), e.getWhen(),
e.getModifiers(), x, y, e.getClickCount(),
e.isPopupTrigger(), e.getButton());
}
if (isVisible() && isMarkerEnabled())
{
marker.process(e);
}
if (first != null)
{
if (movePreview.isActive())
{
double dx = e.getX() - first.x;
double dy = e.getY() - first.y;
if (graphComponent.isGridEnabledEvent(e))
{
dx = graph.snap(dx);
dy = graph.snap(dy);
}
boolean clone = isCloneEnabled()
&& graphComponent.isCloneEvent(e);
movePreview.update(e, dx, dy, clone);
e.consume();
}
else if (cellBounds != null)
{
double dx = e.getX() - first.x;
double dy = e.getY() - first.y;
if (previewBounds != null)
{
setPreviewBounds(new Rectangle(getPreviewLocation(e,
gridEnabledEvent), previewBounds.getSize()));
}
if (!isVisible() && graphComponent.isSignificant(dx, dy))
{
if (imagePreview && dragImage == null
&& !graphComponent.isDragEnabled())
{
updateDragImage(cells);
}
setVisible(true);
}
e.consume();
}
}
}
}
public void mouseReleased(MouseEvent e)
{
if (graphComponent.isEnabled() && isEnabled() && !e.isConsumed())
{
YGraph graph = getGraphComponent().getGraph();
double dx = 0;
double dy = 0;
if (first != null && (cellBounds != null || movePreview.isActive()))
{
double scale = graph.getView().getScale();
mxPoint trans = graph.getView().getTranslate();
// TODO: Simplify math below, this was copy pasted from
// getPreviewLocation with the rounding removed
dx = e.getX() - first.x;
dy = e.getY() - first.y;
if (cellBounds != null && bbox != null)
{
double dxg = ((cellBounds.getX() + dx) / scale)
- trans.getX();
double dyg = ((cellBounds.getY() + dy) / scale)
- trans.getY();
if (gridEnabledEvent)
{
dxg = graph.snap(dxg);
dyg = graph.snap(dyg);
}
double x = ((dxg + trans.getX()) * scale) + (bbox.getX())
- (cellBounds.getX());
double y = ((dyg + trans.getY()) * scale) + (bbox.getY())
- (cellBounds.getY());
dx = Math.round((x - bbox.getX()) / scale);
dy = Math.round((y - bbox.getY()) / scale);
}
}
if (first == null
|| !graphComponent.isSignificant(e.getX() - first.x,
e.getY() - first.y))
{
// Delayed handling of selection
if (cell != null && !e.isPopupTrigger() && isSelectEnabled()
&& (first != null || !isMoveEnabled()))
{
graphComponent.selectCellForEvent(cell, e);
}
// Delayed folding for cell that was initially under the mouse
if (graphComponent.isFoldingEnabled()
&& graphComponent.hitFoldingIcon(initialCell, e.getX(),
e.getY()))
{
fold(initialCell);
}
else
{
// Handles selection if no cell was initially under the mouse
Object tmp = graphComponent.getCellAt(e.getX(), e.getY(),
graphComponent.isSwimlaneSelectionEnabled());
if (cell == null && first == null)
{
if (tmp == null)
{
if (!graphComponent.isToggleEvent(e))
{
graph.clearSelection();
}
}
else if (graph.isSwimlane(tmp)
&& graphComponent.getCanvas()
.hitSwimlaneContent(graphComponent,
graph.getView().getState(tmp),
e.getX(), e.getY()))
{
graphComponent.selectCellForEvent(tmp, e);
}
}
if (graphComponent.isFoldingEnabled()
&& graphComponent.hitFoldingIcon(tmp, e.getX(),
e.getY()))
{
fold(tmp);
e.consume();
}
}
}
else if (movePreview.isActive())
{
if (graphComponent.isConstrainedEvent(e))
{
if (Math.abs(dx) > Math.abs(dy))
{
dy = 0;
}
else
{
dx = 0;
}
}
mxCellState markedState = marker.getMarkedState();
Object target = (markedState != null) ? markedState.getCell()
: null;
// FIXME: Cell is null if selection was carried out, need other variable
//trace("cell", cell);
if (target == null
&& isRemoveCellsFromParent()
&& shouldRemoveCellFromParent(graph.getModel()
.getParent(initialCell), cells, e))
{
target = graph.getDefaultParent();
}
boolean clone = isCloneEnabled()
&& graphComponent.isCloneEvent(e);
Object[] result = movePreview.stop(true, e, dx, dy, clone,
target);
if (cells != result)
{
graph.setSelectionCells(result);
}
e.consume();
}
else if (isVisible())
{
// ==============start==============
if (constrainedEvent) {
mxCell cell = (mxCell) graph.getSelectionCell();
if (graph.isAttachedEvent(cell)) {
mxCell parent = (mxCell) graph.getModel().getParent(cell);
Rectangle rect = graph.getView().getState(parent).getRectangle();
mxGeometry geo = cell.getGeometry();
mxPoint eventOffset = geo.getOffset();
if (Math.abs(dx) > Math.abs(dy)) {
if (first.x + dx > rect.getX() + rect.getWidth()) {
dx = rect.getX() + rect.getWidth() - first.x;
} else if (first.x + dx < rect.getX()) {
dx = rect.getX() - first.x;
}
dy = 0;
if (eventOffset.getY() < -parent.getGeometry().getHeight() / 2) { // align subprocess
// top
geo.setY(0);
eventOffset.setY(-geo.getWidth() / 2);
} else if (geo.getY() == 0) {
} else { // align subprocess bottom
geo.setY(1);
eventOffset.setY(-geo.getWidth() / 2);
}
} else {
if (first.y + dy > rect.getY() + rect.getHeight()) {
dy = rect.getY() + rect.getHeight() - first.y;
} else if (first.y + dy < rect.getY()) {
dy = rect.getY() - first.y;
}
dx = 0;
if (eventOffset.getX() > 0) { // align subprocess right
geo.setX(1);
eventOffset.setX(-geo.getWidth() / 2);
} else if (geo.getX() == 1) {
} else { // align subprocess left
geo.setX(0);
eventOffset.setX(-geo.getWidth() / 2);
}
}
geo.setOffset(eventOffset);
graph.getModel().setGeometry(cell, geo);
} else if (graph.isMessage(cell)) {
mxCell parent = (mxCell) graph.getModel().getParent(cell);
if (graph.isMessageFlow(parent)) {
mxCellState state = graph.getView().getState(parent);
double scale = graph.getView().getScale();
List points = new ArrayList(state.getAbsolutePoints());
mxPoint[] p = points.toArray(new mxPoint[points.size()]);
Rectangle rect = graph.getView().getState(parent).getRectangle();
if (first.x + dx > rect.getX() + rect.getWidth()) {
dx = rect.getX() + rect.getWidth() - first.x;
} else if (first.x + dx < rect.getX()) {
dx = rect.getX() - first.x;
} else {
dy = (int) p[1].getY() - first.y;
}
if (first.y + dy > rect.getY() + rect.getHeight()) {
dy = rect.getY() + rect.getHeight() - first.y;
} else if (first.y + dy < rect.getY()) {
dy = rect.getY() - first.y;
}
if (Math.abs(first.x + dx - p[0].getX()) < 5 * scale) {
if (p[0].getY() > p[1].getY()) {
if (first.y + dy < p[1].getY()) {
dy = p[1].getY() - first.y;
}
} else {
if (first.y + dy > p[1].getY()) {
dy = p[1].getY() - first.y;
}
}
} else if (Math.abs(first.x + dx - p[2].getX()) < 5 * scale) {
if (p[p.length - 1].getY() > p[p.length - 2].getY()) {
if (first.y + dy < p[p.length - 2].getY()) {
dy = p[p.length - 2].getY() - first.y;
}
} else if ((int) p[p.length - 1].getY() == (int) p[p.length - 2].getY()) {
dy = p[p.length - 2].getY() - first.y;
} else if (p[p.length - 1].getY() < p[p.length - 2].getY()) {
if (first.y + dy > p[p.length - 2].getY()) {
dy = p[p.length - 2].getY() - first.y;
}
} else if (first.y + dy > p[p.length - 1].getY()) {
dy = (int) p[p.length - 2].getY() - first.y;
}
}
if ((int) p[0].getX() == (int) p[p.length - 1].getX()) {
dx = 0;
}
}
} else if (graph.isPool(cell)) {
if (graph.isVerticalSwimlane(cell)) {
dy = 0;
} else {
dx = 0;
}
}
else {
if (Math.abs(dx) > Math.abs(dy)) {
dy = 0;
} else {
dx = 0;
}
}
}
// ==============end================
mxCellState targetState = marker.getValidState();
Object target = (targetState != null) ? targetState.getCell()
: null;
if (graph.isSplitEnabled()
&& graph.isSplitTarget(target, cells))
{
graph.splitEdge(target, cells, dx, dy);
}
else
{
moveCells(cells, dx, dy, target, e);
}
e.consume();
}
}
reset();
}
public void paint(Graphics g)
{
if (isVisible() && previewBounds != null)
{
if (dragImage != null)
{
// LATER: Clipping with mxUtils doesnt fix the problem
// of the drawImage being painted over the scrollbars
Graphics2D tmp = (Graphics2D) g.create();
if (graphComponent.getPreviewAlpha() < 1)
{
tmp.setComposite(AlphaComposite.getInstance(
AlphaComposite.SRC_OVER,
graphComponent.getPreviewAlpha()));
}
tmp.drawImage(dragImage.getImage(), previewBounds.x,
previewBounds.y, dragImage.getIconWidth(),
dragImage.getIconHeight(), null);
// ==============start==============
if (cells == null || cells != null && cells.length == 1) {
if (Constants.SETTINGS.getProperty("showAuxiliary", "0").equals("1")) {
getGraphComponent().paintAuxiliaryLines(tmp, previewBounds);
}
}
// ==============end================
tmp.dispose();
}
else if (!imagePreview)
{
mxSwingConstants.PREVIEW_BORDER.paintBorder(graphComponent, g,
previewBounds.x, previewBounds.y, previewBounds.width,
previewBounds.height);
}
}
}
protected Point getPreviewLocation(MouseEvent e, boolean gridEnabled)
{
int x = 0;
int y = 0;
if (first != null && cellBounds != null)
{
mxGraph graph = graphComponent.getGraph();
double scale = graph.getView().getScale();
mxPoint trans = graph.getView().getTranslate();
// LATER: Drag image _size_ depends on the initial position and may sometimes
// not align with the grid when dragging. This is because the rounding of the width
// and height at the initial position may be different than that at the current
// position as the left and bottom side of the shape must align to the grid lines.
// Only fix is a full repaint of the drag cells at each new mouse location.
double dx = e.getX() - first.x;
double dy = e.getY() - first.y;
double dxg = ((cellBounds.getX() + dx) / scale) - trans.getX();
double dyg = ((cellBounds.getY() + dy) / scale) - trans.getY();
if (gridEnabled)
{
dxg = graph.snap(dxg);
dyg = graph.snap(dyg);
}
// ==============start==============
x = (int) Math.round((dxg + trans.getX()) * scale);
y = (int) Math.round((dyg + trans.getY()) * scale);
// ==============end================
}
return new Point(x, y);
}
public void setPreviewBounds(Rectangle bounds)
{
if ((bounds == null && previewBounds != null)
|| (bounds != null && previewBounds == null)
|| (bounds != null && previewBounds != null && !bounds
.equals(previewBounds)))
{
Rectangle dirty = null;
if (isVisible())
{
dirty = previewBounds;
if (dirty != null)
{
dirty.add(bounds);
}
else
{
dirty = bounds;
}
}
previewBounds = bounds;
if (dirty != null)
{
graphComponent.getGraphControl().repaint(dirty.x - 1,
dirty.y - 1, dirty.width + 2, dirty.height + 2);
}
// ==============start==============
if (previewBounds != null) {
repaintAuxiliaryArea(previewBounds);
}
// ==============end================
}
}
public void reset()
{
super.reset();
// ==============start==============
if (previewBounds != null) {
repaintAuxiliaryArea(previewBounds);
}
// ==============end================
}
protected void repaintAuxiliaryArea(Rectangle bounds) {
if (Constants.SETTINGS.getProperty("showAuxiliary", "0").equals("1")) {
mxGraphControl graphControl = graphComponent.getGraphControl();
graphControl.repaint(bounds.x - 1, 0, bounds.width + 2, graphControl.getHeight());
graphControl.repaint(0, bounds.y - 1, graphControl.getWidth(), bounds.height + 2);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy