View Javadoc
1   /*
2    * Copyright (c) 2005, The JUNG Authors 
3    *
4    * All rights reserved.
5    *
6    * This software is open-source under the BSD license; see either
7    * "license.txt" or
8    * https://github.com/jrtom/jung/blob/master/LICENSE for a description.
9    *
10   */
11  package edu.uci.ics.jung.visualization.annotations;
12  
13  import java.awt.Color;
14  import java.awt.Cursor;
15  import java.awt.Graphics;
16  import java.awt.Graphics2D;
17  import java.awt.Shape;
18  import java.awt.event.InputEvent;
19  import java.awt.event.MouseEvent;
20  import java.awt.event.MouseListener;
21  import java.awt.event.MouseMotionListener;
22  import java.awt.geom.Point2D;
23  import java.awt.geom.Rectangle2D;
24  import java.awt.geom.RectangularShape;
25  
26  import javax.swing.JComponent;
27  import javax.swing.JOptionPane;
28  
29  import edu.uci.ics.jung.visualization.MultiLayerTransformer;
30  import edu.uci.ics.jung.visualization.RenderContext;
31  import edu.uci.ics.jung.visualization.VisualizationViewer;
32  import edu.uci.ics.jung.visualization.VisualizationServer.Paintable;
33  import edu.uci.ics.jung.visualization.control.AbstractGraphMousePlugin;
34  
35  /** 
36   * AnnotatingGraphMousePlugin can create Shape and Text annotations
37   * in a layer of the graph visualization.
38   * 
39   * @author Tom Nelson
40   */
41  public class AnnotatingGraphMousePlugin<V, E> extends AbstractGraphMousePlugin
42      implements MouseListener, MouseMotionListener {
43  
44      /**
45       * additional modifiers for the action of adding to an existing
46       * selection
47       */
48      protected int additionalModifiers;
49      
50      /**
51       * used to draw a Shape annotation
52       */
53      protected RectangularShape rectangularShape = new Rectangle2D.Float();
54      
55      /**
56       * the Paintable for the Shape annotation
57       */
58      protected Paintable lensPaintable;
59      
60      /**
61       * a Paintable to store all Annotations
62       */
63      protected AnnotationManager annotationManager;
64      
65      /**
66       * color for annotations
67       */
68      protected Color annotationColor = Color.cyan;
69      
70      /**
71       * layer for annotations
72       */
73      protected Annotation.Layer layer = Annotation.Layer.LOWER;
74      
75      protected boolean fill;
76      
77      /**
78       * holds rendering transforms
79       */
80      protected MultiLayerTransformer basicTransformer;
81      
82      /**
83       * holds rendering settings
84       */
85      protected RenderContext<V,E> rc;
86      
87      /**
88       * set to true when the AnnotationPaintable has been
89       * added to the view component
90       */
91      protected boolean added = false;
92      
93      /**
94       * Create an instance with defaults for primary (button 1) and secondary 
95       * (button 1 + shift) selection.
96       * @param rc the RenderContext for which this plugin will be used
97       */
98  	public AnnotatingGraphMousePlugin(RenderContext<V,E> rc) {
99  	    this(rc, InputEvent.BUTTON1_MASK, 
100 	    		InputEvent.BUTTON1_MASK | InputEvent.SHIFT_MASK);
101 	}
102 
103 	/**
104 	 * Create an instance with the specified primary and secondary selection
105 	 * mechanisms.
106      * @param rc the RenderContext for which this plugin will be used
107 	 * @param selectionModifiers for primary selection
108 	 * @param additionalModifiers for additional selection
109 	 */
110     public AnnotatingGraphMousePlugin(RenderContext<V,E> rc,
111     		int selectionModifiers, int additionalModifiers) {
112         super(selectionModifiers);
113         this.rc = rc;
114         this.basicTransformer = rc.getMultiLayerTransformer();
115         this.additionalModifiers = additionalModifiers;
116         this.lensPaintable = new LensPaintable();
117         this.annotationManager = new AnnotationManager(rc);
118         this.cursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
119     }
120     
121     /**
122      * @return Returns the lensColor.
123      */
124     public Color getAnnotationColor() {
125         return annotationColor;
126     }
127 
128     /**
129      * @param lensColor The lensColor to set.
130      */
131     public void setAnnotationColor(Color lensColor) {
132         this.annotationColor = lensColor;
133     }
134 
135     /**
136      * the Paintable that draws a Shape annotation
137      * only while it is being created
138      * 
139      */
140     class LensPaintable implements Paintable {
141 
142         public void paint(Graphics g) {
143             Color oldColor = g.getColor();
144             g.setColor(annotationColor);
145             ((Graphics2D)g).draw(rectangularShape);
146             g.setColor(oldColor);
147         }
148 
149         public boolean useTransform() {
150             return false;
151         }
152     }
153 
154     /**
155      * Sets the location for an Annotation.
156      * Will either pop up a dialog to prompt for text
157      * input for a text annotation, or begin the process
158      * of drawing a Shape annotation
159      * 
160 	 * @param e the event
161 	 */
162     @SuppressWarnings("unchecked")
163     public void mousePressed(MouseEvent e) {
164     	VisualizationViewer<V,E> vv = (VisualizationViewer<V,E>)e.getSource();
165     	down = e.getPoint();
166     	
167 		if(added == false) {
168 			vv.addPreRenderPaintable(annotationManager.getLowerAnnotationPaintable());
169 			vv.addPostRenderPaintable(annotationManager.getUpperAnnotationPaintable());
170 			added = true;
171 		}
172 
173     	
174     	if(e.isPopupTrigger()) {
175     		String annotationString = JOptionPane.showInputDialog(vv,"Annotation:");
176     		if(annotationString != null && annotationString.length() > 0) {
177     			Point2D p = vv.getRenderContext().getMultiLayerTransformer().inverseTransform(down);
178     			Annotation<String> annotation =
179     				new Annotation<String>(annotationString, layer, annotationColor, fill, p);
180     			annotationManager.add(layer, annotation);
181     		}
182     	} else if(e.getModifiers() == additionalModifiers) {
183     		Annotation<?> annotation = annotationManager.getAnnotation(down);
184     		annotationManager.remove(annotation);
185     	} else if(e.getModifiers() == modifiers) {
186     		rectangularShape.setFrameFromDiagonal(down,down);
187     		vv.addPostRenderPaintable(lensPaintable);
188     	}
189     	vv.repaint();
190     }
191 
192     /**
193 	 * Completes the process of adding a Shape annotation
194 	 * and removed the transient paintable
195 	 * 
196 	 */
197     @SuppressWarnings("unchecked")
198     public void mouseReleased(MouseEvent e) {
199         VisualizationViewer<V,E> vv = (VisualizationViewer<V, E>)e.getSource();
200     	if(e.isPopupTrigger()) {
201     		String annotationString = JOptionPane.showInputDialog(vv,"Annotation:");
202     		if(annotationString != null && annotationString.length() > 0) {
203     			Point2D p = vv.getRenderContext().getMultiLayerTransformer().inverseTransform(down);
204     			Annotation<String> annotation =
205     				new Annotation<String>(annotationString, layer, annotationColor, fill, p);
206     			annotationManager.add(layer, annotation);
207     		}
208     	} else if(e.getModifiers() == modifiers) {
209         	if(down != null) {
210         		Point2D out = e.getPoint();
211         		RectangularShape arect = (RectangularShape)rectangularShape.clone();
212         		arect.setFrameFromDiagonal(down,out);
213         		Shape s = vv.getRenderContext().getMultiLayerTransformer().inverseTransform(arect);
214         		Annotation<Shape> annotation =
215         			new Annotation<Shape>(s, layer, annotationColor, fill, out);
216         		annotationManager.add(layer, annotation);
217         	}
218         }
219         down = null;
220         vv.removePostRenderPaintable(lensPaintable);
221         vv.repaint();
222     }
223     
224     /**
225 	 * Draws the transient Paintable that will become
226 	 * a Shape annotation when the mouse button is
227 	 * released
228 	 * 
229 	 */
230     @SuppressWarnings("unchecked")
231     public void mouseDragged(MouseEvent e) {
232         VisualizationViewer<V,E> vv = (VisualizationViewer<V, E>)e.getSource();
233 
234     	Point2D out = e.getPoint();
235     	if(e.getModifiers() == additionalModifiers) {
236             rectangularShape.setFrameFromDiagonal(down,out);
237     		
238     	} else if(e.getModifiers() == modifiers) {
239             rectangularShape.setFrameFromDiagonal(down,out);
240     		
241     	}
242         rectangularShape.setFrameFromDiagonal(down,out);
243         vv.repaint();
244     }
245     
246      public void mouseClicked(MouseEvent e) {
247     }
248 
249     public void mouseEntered(MouseEvent e) {
250         JComponent c = (JComponent)e.getSource();
251         c.setCursor(cursor);
252     }
253 
254     public void mouseExited(MouseEvent e) {
255         JComponent c = (JComponent)e.getSource();
256         c.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
257     }
258 
259     public void mouseMoved(MouseEvent e) {
260     }
261 
262 	/**
263 	 * @return the rect
264 	 */
265 	public RectangularShape getRectangularShape() {
266 		return rectangularShape;
267 	}
268 
269 	/**
270 	 * @param rect the rect to set
271 	 */
272 	public void setRectangularShape(RectangularShape rect) {
273 		this.rectangularShape = rect;
274 	}
275 
276 	/**
277 	 * @return the layer
278 	 */
279 	public Annotation.Layer getLayer() {
280 		return layer;
281 	}
282 
283 	/**
284 	 * @param layer the layer to set
285 	 */
286 	public void setLayer(Annotation.Layer layer) {
287 		this.layer = layer;
288 	}
289 
290 	/**
291 	 * @return the fill
292 	 */
293 	public boolean isFill() {
294 		return fill;
295 	}
296 
297 	/**
298 	 * @param fill the fill to set
299 	 */
300 	public void setFill(boolean fill) {
301 		this.fill = fill;
302 	}
303 
304  }