001: /*
002: * $Id: JGraphpadEdgeTool.java,v 1.5 2007/03/25 13:10:02 david Exp $
003: * Copyright (c) 2001-2005, Gaudenz Alder
004: *
005: * All rights reserved.
006: *
007: * See LICENSE file for license details. If you are unable to locate
008: * this file please contact info (at) jgraph (dot) com.
009: */
010: package com.jgraph.pad.tool;
011:
012: import java.awt.Color;
013: import java.awt.Graphics;
014: import java.awt.event.MouseEvent;
015: import java.awt.geom.Point2D;
016: import java.awt.geom.Rectangle2D;
017:
018: import org.jgraph.JGraph;
019: import org.jgraph.graph.DefaultGraphCell;
020: import org.jgraph.graph.EdgeView;
021: import org.jgraph.graph.GraphConstants;
022: import org.jgraph.graph.GraphLayoutCache;
023: import org.jgraph.graph.PortView;
024: import org.jgraph.plaf.GraphUI;
025:
026: /**
027: * Tool that inserts edges based on a prototype.
028: */
029: public class JGraphpadEdgeTool extends JGraphpadVertexTool {
030:
031: /**
032: * Defines the default name for tools of this kind.
033: */
034: public static final String NAME_EDGETOOL = "edgeTool";
035:
036: /**
037: * Initial and current port view.
038: */
039: protected PortView start, current;
040:
041: /**
042: * Constructs a new edge tool for the specified prototype using
043: * {@link #NAME_EDGETOOL}.
044: *
045: * @param prototype
046: * The prototype cell to create new edges with.
047: */
048: public JGraphpadEdgeTool(Object prototype) {
049: this (NAME_EDGETOOL, prototype);
050: }
051:
052: /**
053: * Constructs a new edge tool for the specified name and prototype.
054: * Edgetools must be always active to be able to click on source/target
055: * vertices without triggering a cell move.
056: *
057: * @param name
058: * The name of the tool to be created.
059: * @param prototype
060: * The prototype cell to create new edges with.
061: */
062: public JGraphpadEdgeTool(String name, Object prototype) {
063: super (name, prototype);
064: setAlwaysActive(true);
065: }
066:
067: /**
068: * Returns true if the in any case except the selection cell under the mouse
069: * pointer is an edge. This is used to fetch control when a source/target
070: * selection is made for connecting via a new edge.
071: *
072: * @return Returns false if the selection cell under the mouse is an edge.
073: */
074: public boolean isForceMarqueeEvent(MouseEvent event) {
075: JGraph graph = getGraphForEvent(event);
076: if (graph != null) {
077: Object cell = graph.getSelectionCellAt(event.getPoint());
078: if (graph.getModel().isEdge(cell))
079: return false;
080: }
081: return true;
082: }
083:
084: /**
085: * Extends the parent's implementation to find the port view at the mouse
086: * location and set the startPoint accordingly.
087: *
088: * @param event
089: * The object that describes the event.
090: */
091: public void mousePressed(MouseEvent event) {
092: super .mousePressed(event);
093: JGraph graph = getGraphForEvent(event);
094: if (graph != null) {
095: PortView tmp = graph.getPortViewAt(event.getX(), event
096: .getY());
097: if (graph.getModel().acceptsSource(previewView.getCell(),
098: (tmp != null) ? tmp.getCell() : null)) {
099: start = tmp;
100: if (start != null)
101: startPoint = graph.fromScreen(graph.snap(start
102: .getLocation()));
103: }
104: }
105: }
106:
107: /**
108: * Overrides the parent's implementation to highlight ports which are under
109: * the mousepointer.
110: *
111: * @param event
112: * The object that describes the event.
113: */
114: public void mouseMoved(MouseEvent event) {
115: JGraph graph = getGraphForEvent(event);
116: PortView newPort = graph.getPortViewAt(event.getX(), event
117: .getY());
118: if (this .current != newPort
119: && graph.getModel().acceptsSource(prototype,
120: (newPort != null) ? newPort.getCell() : null)) {
121: Graphics g = graph.getGraphics();
122:
123: // Sets the graphics for xor-painting the highlighted port
124: // and clears the old graphics by repainting
125: Color bg = graph.getBackground();
126: Color fg = graph.getMarqueeColor();
127: g.setColor(fg);
128: g.setXORMode(bg);
129: overlay(graph, g, true);
130:
131: // Updates the state of the tool and repaints
132: this .current = newPort;
133: g.setColor(bg);
134: g.setXORMode(fg);
135: overlay(graph, g, false);
136: }
137: }
138:
139: /**
140: * Overrides the parent's implementation to avoid flickering by checking if
141: * the state of the preview will change.
142: *
143: * @param event
144: * The object that describes the event.
145: */
146: public void mouseDragged(MouseEvent event) {
147: if (startPoint != null) {
148: if (event.getSource() instanceof JGraph) {
149: JGraph graph = (JGraph) event.getSource();
150: PortView newPort = graph.getPortViewAt(event.getX(),
151: event.getY());
152: if (this .current != newPort || newPort == null) {
153: super .mouseDragged(event);
154: }
155: }
156: }
157: }
158:
159: /**
160: * Overrides the parent's implementation to update the preview to connect to
161: * the port under the mouse or use the location of the mouse as a point.
162: *
163: * @param event
164: * The object that describes the event.
165: */
166: protected void processMouseDraggedEvent(MouseEvent event) {
167: super .processMouseDraggedEvent(event);
168: JGraph graph = getGraphForEvent(event);
169: if (graph != null) {
170:
171: // Checks if a port is at the mouse location and updates the
172: // current variable and the current point.
173: PortView tmp = graph.getPortViewAt(event.getX(), event
174: .getY());
175: if (graph.getModel().acceptsSource(previewView.getCell(),
176: (tmp != null) ? tmp.getCell() : null)) {
177: current = tmp;
178: if (current != null)
179: currentPoint = graph
180: .toScreen(current.getLocation());
181: }
182:
183: // Updates the preview to display the start and end point.
184: // This uses the fact that the start and current point are
185: // up-do-date.
186: if (previewView instanceof EdgeView) {
187: EdgeView edge = (EdgeView) previewView;
188: Point2D scaledStart = graph.fromScreen(graph
189: .snap((Point2D) startPoint.clone()));
190: Point2D scaledCurrent = graph.fromScreen(graph
191: .snap((Point2D) currentPoint.clone()));
192:
193: // Sets the points in-place. The update call makes sure
194: // all routing is applied.
195: edge.setPoint(0, scaledStart);
196: edge.setPoint(edge.getPointCount() - 1, scaledCurrent);
197: edge.setSource(start);
198: edge.setTarget(current);
199: edge.update(graph.getGraphLayoutCache());
200: }
201: }
202: }
203:
204: /**
205: * Extends the parent's implementation to reset {@link #start} and
206: * {@link #current}.
207: *
208: * @param event
209: * The object that describes the event.
210: */
211: public void mouseReleased(MouseEvent event) {
212: super .mouseReleased(event);
213: start = null;
214: current = null;
215: }
216:
217: /**
218: * Overrides the parent's implementation to insert the specified edge into
219: * <code>cache</code>.
220: *
221: * @param cache
222: * The cache into which to insert the edge.
223: * @param edge
224: * The edge to be inserted into <code>cache</code>.
225: */
226: protected void execute(JGraph graph, Object edge) {
227: GraphLayoutCache cache = graph.getGraphLayoutCache();
228: // Uses the cached points for the new edge
229: if (previewView instanceof EdgeView) {
230: GraphConstants.setPoints(cache.getModel().getAttributes(
231: edge), ((EdgeView) previewView).getPoints());
232: }
233: Object source = (start != null) ? start.getCell() : null;
234: Object target = (current != null) ? current.getCell() : null;
235: cache.insertEdge(edge, source, target);
236: }
237:
238: /**
239: * Extends the parent's implementation to draw the highlighted port using
240: * {@link #paintPort(JGraph, Graphics)}.
241: *
242: * @param graph
243: * The graph to paint in.
244: * @param g
245: * The graphics to use for paiting.
246: * @param clear
247: * Wether to clear the display.
248: */
249: public void overlay(JGraph graph, Graphics g, boolean clear) {
250: paintPort(graph, g);
251: super .overlay(graph, g, clear);
252: }
253:
254: /**
255: * Paints the {@link #current} port in highlighted state.
256: *
257: * @param graph
258: * The graph to paint the port in.
259: * @param g
260: * The graphics to use for paiting.
261: */
262: protected void paintPort(JGraph graph, Graphics g) {
263: if (current != null && graph != null) {
264: boolean offset = (GraphConstants.getOffset(current
265: .getAllAttributes()) != null);
266: Rectangle2D r = (offset) ? current.getBounds() : current
267: .getParentView().getBounds();
268: r = graph.toScreen((Rectangle2D) r.clone());
269: int s = 3;
270: r.setFrame(r.getX() - s, r.getY() - s,
271: r.getWidth() + 2 * s, r.getHeight() + 2 * s);
272: GraphUI ui = (GraphUI) graph.getUI();
273: ui.paintCell(g, current, r, true);
274: }
275: }
276:
277: }
|