1
2
3
4
5
6
7
8
9
10
11
12 package edu.uci.ics.jung.visualization.control;
13
14 import java.awt.Color;
15 import java.awt.Cursor;
16 import java.awt.Graphics;
17 import java.awt.Graphics2D;
18 import java.awt.Point;
19 import java.awt.event.InputEvent;
20 import java.awt.event.MouseEvent;
21 import java.awt.event.MouseListener;
22 import java.awt.event.MouseMotionListener;
23 import java.awt.geom.Point2D;
24 import java.awt.geom.Rectangle2D;
25 import java.util.Collection;
26
27 import javax.swing.JComponent;
28
29 import edu.uci.ics.jung.algorithms.layout.GraphElementAccessor;
30 import edu.uci.ics.jung.algorithms.layout.Layout;
31 import edu.uci.ics.jung.visualization.Layer;
32 import edu.uci.ics.jung.visualization.VisualizationViewer;
33 import edu.uci.ics.jung.visualization.VisualizationServer.Paintable;
34 import edu.uci.ics.jung.visualization.picking.PickedState;
35
36
37
38
39
40
41
42
43
44
45
46 public class PickingGraphMousePlugin<V, E> extends AbstractGraphMousePlugin
47 implements MouseListener, MouseMotionListener {
48
49
50
51
52 protected V vertex;
53
54
55
56
57 protected E edge;
58
59
60
61
62 protected double offsetx;
63
64
65
66
67 protected double offsety;
68
69
70
71
72 protected boolean locked;
73
74
75
76
77
78 protected int addToSelectionModifiers;
79
80
81
82
83 protected Rectangle2D rect = new Rectangle2D.Float();
84
85
86
87
88 protected Paintable lensPaintable;
89
90
91
92
93 protected Color lensColor = Color.cyan;
94
95
96
97
98 public PickingGraphMousePlugin() {
99 this(InputEvent.BUTTON1_MASK, InputEvent.BUTTON1_MASK | InputEvent.SHIFT_MASK);
100 }
101
102
103
104
105
106
107 public PickingGraphMousePlugin(int selectionModifiers, int addToSelectionModifiers) {
108 super(selectionModifiers);
109 this.addToSelectionModifiers = addToSelectionModifiers;
110 this.lensPaintable = new LensPaintable();
111 this.cursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
112 }
113
114
115
116
117 public Color getLensColor() {
118 return lensColor;
119 }
120
121
122
123
124 public void setLensColor(Color lensColor) {
125 this.lensColor = lensColor;
126 }
127
128
129
130
131
132
133
134 class LensPaintable implements Paintable {
135
136 public void paint(Graphics g) {
137 Color oldColor = g.getColor();
138 g.setColor(lensColor);
139 ((Graphics2D)g).draw(rect);
140 g.setColor(oldColor);
141 }
142
143 public boolean useTransform() {
144 return false;
145 }
146 }
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165 @SuppressWarnings("unchecked")
166 public void mousePressed(MouseEvent e) {
167 down = e.getPoint();
168 VisualizationViewer<V,E> vv = (VisualizationViewer)e.getSource();
169 GraphElementAccessor<V,E> pickSupport = vv.getPickSupport();
170 PickedState<V> pickedVertexState = vv.getPickedVertexState();
171 PickedState<E> pickedEdgeState = vv.getPickedEdgeState();
172 if(pickSupport != null && pickedVertexState != null) {
173 Layout<V,E> layout = vv.getGraphLayout();
174 if(e.getModifiers() == modifiers) {
175 rect.setFrameFromDiagonal(down,down);
176
177 Point2D ip = e.getPoint();
178
179 vertex = pickSupport.getVertex(layout, ip.getX(), ip.getY());
180 if(vertex != null) {
181 if(pickedVertexState.isPicked(vertex) == false) {
182 pickedVertexState.clear();
183 pickedVertexState.pick(vertex, true);
184 }
185
186
187 Point2D q = layout.transform(vertex);
188
189 Point2D gp = vv.getRenderContext().getMultiLayerTransformer().inverseTransform(Layer.LAYOUT, ip);
190
191 offsetx = (float) (gp.getX()-q.getX());
192 offsety = (float) (gp.getY()-q.getY());
193 } else if((edge = pickSupport.getEdge(layout, ip.getX(), ip.getY())) != null) {
194 pickedEdgeState.clear();
195 pickedEdgeState.pick(edge, true);
196 } else {
197 vv.addPostRenderPaintable(lensPaintable);
198 pickedEdgeState.clear();
199 pickedVertexState.clear();
200 }
201
202 } else if(e.getModifiers() == addToSelectionModifiers) {
203 vv.addPostRenderPaintable(lensPaintable);
204 rect.setFrameFromDiagonal(down,down);
205 Point2D ip = e.getPoint();
206 vertex = pickSupport.getVertex(layout, ip.getX(), ip.getY());
207 if(vertex != null) {
208 boolean wasThere = pickedVertexState.pick(vertex, !pickedVertexState.isPicked(vertex));
209 if(wasThere) {
210 vertex = null;
211 } else {
212
213
214
215 Point2D q = layout.transform(vertex);
216
217 Point2D gp = vv.getRenderContext().getMultiLayerTransformer().inverseTransform(Layer.LAYOUT, ip);
218
219 offsetx = (float) (gp.getX()-q.getX());
220 offsety = (float) (gp.getY()-q.getY());
221 }
222 } else if((edge = pickSupport.getEdge(layout, ip.getX(), ip.getY())) != null) {
223 pickedEdgeState.pick(edge, !pickedEdgeState.isPicked(edge));
224 }
225 }
226 }
227 if(vertex != null) e.consume();
228 }
229
230
231
232
233
234
235
236 @SuppressWarnings("unchecked")
237 public void mouseReleased(MouseEvent e) {
238 VisualizationViewer<V,E> vv = (VisualizationViewer)e.getSource();
239 if(e.getModifiers() == modifiers) {
240 if(down != null) {
241 Point2D out = e.getPoint();
242
243 if(vertex == null && heyThatsTooClose(down, out, 5) == false) {
244 pickContainedVertices(vv, down, out, true);
245 }
246 }
247 } else if(e.getModifiers() == this.addToSelectionModifiers) {
248 if(down != null) {
249 Point2D out = e.getPoint();
250
251 if(vertex == null && heyThatsTooClose(down,out,5) == false) {
252 pickContainedVertices(vv, down, out, false);
253 }
254 }
255 }
256 down = null;
257 vertex = null;
258 edge = null;
259 rect.setFrame(0,0,0,0);
260 vv.removePostRenderPaintable(lensPaintable);
261 vv.repaint();
262 }
263
264
265
266
267
268
269
270
271 @SuppressWarnings("unchecked")
272 public void mouseDragged(MouseEvent e) {
273 if(locked == false) {
274 VisualizationViewer<V,E> vv = (VisualizationViewer)e.getSource();
275 if(vertex != null) {
276 Point p = e.getPoint();
277 Point2D graphPoint = vv.getRenderContext().getMultiLayerTransformer().inverseTransform(p);
278 Point2D graphDown = vv.getRenderContext().getMultiLayerTransformer().inverseTransform(down);
279 Layout<V,E> layout = vv.getGraphLayout();
280 double dx = graphPoint.getX()-graphDown.getX();
281 double dy = graphPoint.getY()-graphDown.getY();
282 PickedState<V> ps = vv.getPickedVertexState();
283
284 for(V v : ps.getPicked()) {
285 Point2D vp = layout.transform(v);
286 vp.setLocation(vp.getX()+dx, vp.getY()+dy);
287 layout.setLocation(v, vp);
288 }
289 down = p;
290
291 } else {
292 Point2D out = e.getPoint();
293 if(e.getModifiers() == this.addToSelectionModifiers ||
294 e.getModifiers() == modifiers) {
295 rect.setFrameFromDiagonal(down,out);
296 }
297 }
298 if(vertex != null) e.consume();
299 vv.repaint();
300 }
301 }
302
303
304
305
306
307
308
309
310
311
312 private boolean heyThatsTooClose(Point2D p, Point2D q, double min) {
313 return Math.abs(p.getX()-q.getX()) < min &&
314 Math.abs(p.getY()-q.getY()) < min;
315 }
316
317
318
319
320
321
322 protected void pickContainedVertices(VisualizationViewer<V,E> vv, Point2D down, Point2D out, boolean clear) {
323
324 Layout<V,E> layout = vv.getGraphLayout();
325 PickedState<V> pickedVertexState = vv.getPickedVertexState();
326
327 Rectangle2D pickRectangle = new Rectangle2D.Double();
328 pickRectangle.setFrameFromDiagonal(down,out);
329
330 if(pickedVertexState != null) {
331 if(clear) {
332 pickedVertexState.clear();
333 }
334 GraphElementAccessor<V,E> pickSupport = vv.getPickSupport();
335
336 Collection<V> picked = pickSupport.getVertices(layout, pickRectangle);
337 for(V v : picked) {
338 pickedVertexState.pick(v, true);
339 }
340 }
341 }
342
343 public void mouseClicked(MouseEvent e) {
344 }
345
346 public void mouseEntered(MouseEvent e) {
347 JComponent c = (JComponent)e.getSource();
348 c.setCursor(cursor);
349 }
350
351 public void mouseExited(MouseEvent e) {
352 JComponent c = (JComponent)e.getSource();
353 c.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
354 }
355
356 public void mouseMoved(MouseEvent e) {
357 }
358
359
360
361
362 public boolean isLocked() {
363 return locked;
364 }
365
366
367
368
369 public void setLocked(boolean locked) {
370 this.locked = locked;
371 }
372 }