/** * $Id: mxInteractiveCanvas.java,v 1.1 2012/11/15 13:26:49 gaudenz Exp $ * Copyright (c) 2007-2010, Gaudenz Alder, David Benson */ package com.mxgraph.swing.view; import java.awt.Dimension; import java.awt.Image; import java.awt.Rectangle; import java.awt.Shape; import java.awt.image.ImageObserver; import com.mxgraph.canvas.mxGraphics2DCanvas; import com.mxgraph.shape.mxBasicShape; import com.mxgraph.shape.mxIShape; import com.mxgraph.swing.mxGraphComponent; import com.mxgraph.util.mxConstants; import com.mxgraph.util.mxPoint; import com.mxgraph.util.mxUtils; import com.mxgraph.view.mxCellState; public class mxInteractiveCanvas extends mxGraphics2DCanvas { /** * */ protected ImageObserver imageObserver = null; /** * */ public mxInteractiveCanvas() { this(null); } /** * */ public mxInteractiveCanvas(ImageObserver imageObserver) { setImageObserver(imageObserver); } /** * */ public void setImageObserver(ImageObserver value) { imageObserver = value; } /** * */ public ImageObserver getImageObserver() { return imageObserver; } /** * Overrides graphics call to use image observer. */ protected void drawImageImpl(Image image, int x, int y) { g.drawImage(image, x, y, imageObserver); } /** * Returns the size for the given image. */ protected Dimension getImageSize(Image image) { return new Dimension(image.getWidth(imageObserver), image.getHeight(imageObserver)); } /** * */ public boolean contains(mxGraphComponent graphComponent, Rectangle rect, mxCellState state) { return state != null && state.getX() >= rect.x && state.getY() >= rect.y && state.getX() + state.getWidth() <= rect.x + rect.width && state.getY() + state.getHeight() <= rect.y + rect.height; } /** * */ public boolean intersects(mxGraphComponent graphComponent, Rectangle rect, mxCellState state) { if (state != null) { // Checks if the label intersects if (state.getLabelBounds() != null && state.getLabelBounds().getRectangle().intersects(rect)) { return true; } int pointCount = state.getAbsolutePointCount(); // Checks if the segments of the edge intersect if (pointCount > 0) { rect = (Rectangle) rect.clone(); int tolerance = graphComponent.getTolerance(); rect.grow(tolerance, tolerance); Shape realShape = null; // FIXME: Check if this should be used for all shapes if (mxUtils.getString(state.getStyle(), mxConstants.STYLE_SHAPE, "").equals( mxConstants.SHAPE_ARROW)) { mxIShape shape = getShape(state.getStyle()); if (shape instanceof mxBasicShape) { realShape = ((mxBasicShape) shape).createShape(this, state); } } if (realShape != null && realShape.intersects(rect)) { return true; } else { mxPoint p0 = state.getAbsolutePoint(0); for (int i = 0; i < pointCount; i++) { mxPoint p1 = state.getAbsolutePoint(i); if (rect.intersectsLine(p0.getX(), p0.getY(), p1.getX(), p1.getY())) { return true; } p0 = p1; } } } else { // Checks if the bounds of the shape intersect return state.getRectangle().intersects(rect); } } return false; } /** * Returns true if the given point is inside the content area of the given * swimlane. (The content area of swimlanes is transparent to events.) This * implementation does not check if the given state is a swimlane, it is * assumed that the caller has checked this before using this method. */ public boolean hitSwimlaneContent(mxGraphComponent graphComponent, mxCellState swimlane, int x, int y) { if (swimlane != null) { int start = (int) Math.max(2, Math.round(mxUtils.getInt( swimlane.getStyle(), mxConstants.STYLE_STARTSIZE, mxConstants.DEFAULT_STARTSIZE) * graphComponent.getGraph().getView().getScale())); Rectangle rect = swimlane.getRectangle(); if (mxUtils.isTrue(swimlane.getStyle(), mxConstants.STYLE_HORIZONTAL, true)) { rect.y += start; rect.height -= start; } else { rect.x += start; rect.width -= start; } return rect.contains(x, y); } return false; } }