1 /** 2 * Copyright (c) 2007-2010, Gaudenz Alder, David Benson 3 */ 4 package com.mxgraph.swing.view; 5 6 import java.awt.Dimension; 7 import java.awt.Image; 8 import java.awt.Rectangle; 9 import java.awt.Shape; 10 import java.awt.image.ImageObserver; 11 12 import com.mxgraph.canvas.mxGraphics2DCanvas; 13 import com.mxgraph.shape.mxBasicShape; 14 import com.mxgraph.shape.mxIShape; 15 import com.mxgraph.swing.mxGraphComponent; 16 import com.mxgraph.util.mxConstants; 17 import com.mxgraph.util.mxPoint; 18 import com.mxgraph.util.mxUtils; 19 import com.mxgraph.view.mxCellState; 20 21 public class mxInteractiveCanvas extends mxGraphics2DCanvas 22 { 23 /** 24 * 25 */ 26 protected ImageObserver imageObserver = null; 27 28 /** 29 * 30 */ mxInteractiveCanvas()31 public mxInteractiveCanvas() 32 { 33 this(null); 34 } 35 36 /** 37 * 38 */ mxInteractiveCanvas(ImageObserver imageObserver)39 public mxInteractiveCanvas(ImageObserver imageObserver) 40 { 41 setImageObserver(imageObserver); 42 } 43 44 /** 45 * 46 */ setImageObserver(ImageObserver value)47 public void setImageObserver(ImageObserver value) 48 { 49 imageObserver = value; 50 } 51 52 /** 53 * 54 */ getImageObserver()55 public ImageObserver getImageObserver() 56 { 57 return imageObserver; 58 } 59 60 /** 61 * Overrides graphics call to use image observer. 62 */ drawImageImpl(Image image, int x, int y)63 protected void drawImageImpl(Image image, int x, int y) 64 { 65 g.drawImage(image, x, y, imageObserver); 66 } 67 68 /** 69 * Returns the size for the given image. 70 */ getImageSize(Image image)71 protected Dimension getImageSize(Image image) 72 { 73 return new Dimension(image.getWidth(imageObserver), 74 image.getHeight(imageObserver)); 75 } 76 77 /** 78 * 79 */ contains(mxGraphComponent graphComponent, Rectangle rect, mxCellState state)80 public boolean contains(mxGraphComponent graphComponent, Rectangle rect, 81 mxCellState state) 82 { 83 return state != null && state.getX() >= rect.x 84 && state.getY() >= rect.y 85 && state.getX() + state.getWidth() <= rect.x + rect.width 86 && state.getY() + state.getHeight() <= rect.y + rect.height; 87 } 88 89 /** 90 * 91 */ intersects(mxGraphComponent graphComponent, Rectangle rect, mxCellState state)92 public boolean intersects(mxGraphComponent graphComponent, Rectangle rect, 93 mxCellState state) 94 { 95 if (state != null) 96 { 97 // Checks if the label intersects 98 if (state.getLabelBounds() != null 99 && state.getLabelBounds().getRectangle().intersects(rect)) 100 { 101 return true; 102 } 103 104 int pointCount = state.getAbsolutePointCount(); 105 106 // Checks if the segments of the edge intersect 107 if (pointCount > 0) 108 { 109 rect = (Rectangle) rect.clone(); 110 int tolerance = graphComponent.getTolerance(); 111 rect.grow(tolerance, tolerance); 112 113 Shape realShape = null; 114 115 // FIXME: Check if this should be used for all shapes 116 if (mxUtils.getString(state.getStyle(), 117 mxConstants.STYLE_SHAPE, "").equals( 118 mxConstants.SHAPE_ARROW)) 119 { 120 mxIShape shape = getShape(state.getStyle()); 121 122 if (shape instanceof mxBasicShape) 123 { 124 realShape = ((mxBasicShape) shape).createShape(this, 125 state); 126 } 127 } 128 129 if (realShape != null && realShape.intersects(rect)) 130 { 131 return true; 132 } 133 else 134 { 135 mxPoint p0 = state.getAbsolutePoint(0); 136 137 for (int i = 0; i < pointCount; i++) 138 { 139 mxPoint p1 = state.getAbsolutePoint(i); 140 141 if (rect.intersectsLine(p0.getX(), p0.getY(), 142 p1.getX(), p1.getY())) 143 { 144 return true; 145 } 146 147 p0 = p1; 148 } 149 } 150 } 151 else 152 { 153 // Checks if the bounds of the shape intersect 154 return state.getRectangle().intersects(rect); 155 } 156 } 157 158 return false; 159 } 160 161 /** 162 * Returns true if the given point is inside the content area of the given 163 * swimlane. (The content area of swimlanes is transparent to events.) This 164 * implementation does not check if the given state is a swimlane, it is 165 * assumed that the caller has checked this before using this method. 166 */ hitSwimlaneContent(mxGraphComponent graphComponent, mxCellState swimlane, int x, int y)167 public boolean hitSwimlaneContent(mxGraphComponent graphComponent, 168 mxCellState swimlane, int x, int y) 169 { 170 if (swimlane != null) 171 { 172 int start = (int) Math.max(2, Math.round(mxUtils.getInt( 173 swimlane.getStyle(), mxConstants.STYLE_STARTSIZE, 174 mxConstants.DEFAULT_STARTSIZE) 175 * graphComponent.getGraph().getView().getScale())); 176 Rectangle rect = swimlane.getRectangle(); 177 178 if (mxUtils.isTrue(swimlane.getStyle(), 179 mxConstants.STYLE_HORIZONTAL, true)) 180 { 181 rect.y += start; 182 rect.height -= start; 183 } 184 else 185 { 186 rect.x += start; 187 rect.width -= start; 188 } 189 190 return rect.contains(x, y); 191 } 192 193 return false; 194 } 195 196 } 197