View Javadoc

1   /*
2    * Copyright (c) 2005, the JUNG Project and the Regents of the University 
3    * of California
4    * All rights reserved.
5    *
6    * This software is open-source under the BSD license; see either
7    * "license.txt" or
8    * http://jung.sourceforge.net/license.txt 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 default settings
95  	 */
96  	public AnnotatingGraphMousePlugin(RenderContext<V,E> rc) {
97  	    this(rc, InputEvent.BUTTON1_MASK, 
98  	    		InputEvent.BUTTON1_MASK | InputEvent.SHIFT_MASK);
99  	}
100 
101 	/**
102 	 * create an instance with overides
103 	 * @param selectionModifiers for primary selection
104 	 * @param additionalModifiers for additional selection
105 	 */
106     public AnnotatingGraphMousePlugin(RenderContext<V,E> rc,
107     		int selectionModifiers, int additionalModifiers) {
108         super(selectionModifiers);
109         this.rc = rc;
110         this.basicTransformer = rc.getMultiLayerTransformer();
111         this.additionalModifiers = additionalModifiers;
112         this.lensPaintable = new LensPaintable();
113 //        this.annotationPaintable = new AnnotationPaintable(rc);
114         this.annotationManager = new AnnotationManager(rc);
115         this.cursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
116     }
117     
118     /**
119      * @return Returns the lensColor.
120      */
121     public Color getAnnotationColor() {
122         return annotationColor;
123     }
124 
125     /**
126      * @param lensColor The lensColor to set.
127      */
128     public void setAnnotationColor(Color lensColor) {
129         this.annotationColor = lensColor;
130     }
131 
132     /**
133      * the Paintable that draws a Shape annotation
134      * only while it is being created
135      * 
136      */
137     class LensPaintable implements Paintable {
138 
139         public void paint(Graphics g) {
140             Color oldColor = g.getColor();
141             g.setColor(annotationColor);
142             ((Graphics2D)g).draw(rectangularShape);
143             g.setColor(oldColor);
144         }
145 
146         public boolean useTransform() {
147             return false;
148         }
149     }
150 
151     /**
152      * Sets the location for an Annotation.
153      * Will either pop up a dialog to prompt for text
154      * input for a text annotation, or begin the process
155      * of drawing a Shape annotation
156      * 
157 	 * @param e the event
158 	 */
159     @SuppressWarnings("unchecked")
160     public void mousePressed(MouseEvent e) {
161     	VisualizationViewer<V,E> vv = (VisualizationViewer)e.getSource();
162     	down = e.getPoint();
163     	
164 		if(added == false) {
165 			vv.addPreRenderPaintable(annotationManager.getLowerAnnotationPaintable());
166 			vv.addPostRenderPaintable(annotationManager.getUpperAnnotationPaintable());
167 			added = true;
168 		}
169 
170     	
171     	if(e.isPopupTrigger()) {
172     		String annotationString = JOptionPane.showInputDialog(vv,"Annotation:");
173     		if(annotationString != null && annotationString.length() > 0) {
174     			Point2D p = vv.getRenderContext().getMultiLayerTransformer().inverseTransform(down);
175     			Annotation<String> annotation =
176     				new Annotation<String>(annotationString, layer, annotationColor, fill, p);
177     			annotationManager.add(layer, annotation);
178     		}
179     	} else if(e.getModifiers() == additionalModifiers) {
180     		Annotation annotation = annotationManager.getAnnotation(down);
181     		annotationManager.remove(annotation);
182     	} else if(e.getModifiers() == modifiers) {
183     		rectangularShape.setFrameFromDiagonal(down,down);
184     		vv.addPostRenderPaintable(lensPaintable);
185     	}
186     	vv.repaint();
187     }
188 
189     /**
190 	 * Completes the process of adding a Shape annotation
191 	 * and removed the transient paintable
192 	 * 
193 	 */
194     @SuppressWarnings("unchecked")
195     public void mouseReleased(MouseEvent e) {
196         VisualizationViewer<V,E> vv = (VisualizationViewer)e.getSource();
197     	if(e.isPopupTrigger()) {
198     		String annotationString = JOptionPane.showInputDialog(vv,"Annotation:");
199     		if(annotationString != null && annotationString.length() > 0) {
200     			Point2D p = vv.getRenderContext().getMultiLayerTransformer().inverseTransform(down);
201     			Annotation<String> annotation =
202     				new Annotation<String>(annotationString, layer, annotationColor, fill, p);
203     			annotationManager.add(layer, annotation);
204     		}
205     	} else if(e.getModifiers() == modifiers) {
206         	if(down != null) {
207         		Point2D out = e.getPoint();
208         		RectangularShape arect = (RectangularShape)rectangularShape.clone();
209         		arect.setFrameFromDiagonal(down,out);
210         		Shape s = vv.getRenderContext().getMultiLayerTransformer().inverseTransform(arect);
211         		Annotation<Shape> annotation =
212         			new Annotation<Shape>(s, layer, annotationColor, fill, out);
213         		annotationManager.add(layer, annotation);
214         	}
215         }
216         down = null;
217         vv.removePostRenderPaintable(lensPaintable);
218         vv.repaint();
219     }
220     
221     /**
222 	 * Draws the transient Paintable that will become
223 	 * a Shape annotation when the mouse button is
224 	 * released
225 	 * 
226 	 */
227     @SuppressWarnings("unchecked")
228     public void mouseDragged(MouseEvent e) {
229         VisualizationViewer<V,E> vv = (VisualizationViewer)e.getSource();
230 
231     	Point2D out = e.getPoint();
232     	if(e.getModifiers() == additionalModifiers) {
233             rectangularShape.setFrameFromDiagonal(down,out);
234     		
235     	} else if(e.getModifiers() == modifiers) {
236             rectangularShape.setFrameFromDiagonal(down,out);
237     		
238     	}
239         rectangularShape.setFrameFromDiagonal(down,out);
240         vv.repaint();
241     }
242     
243      public void mouseClicked(MouseEvent e) {
244     }
245 
246     public void mouseEntered(MouseEvent e) {
247         JComponent c = (JComponent)e.getSource();
248         c.setCursor(cursor);
249     }
250 
251     public void mouseExited(MouseEvent e) {
252         JComponent c = (JComponent)e.getSource();
253         c.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
254     }
255 
256     public void mouseMoved(MouseEvent e) {
257     }
258 
259 	/**
260 	 * @return the rect
261 	 */
262 	public RectangularShape getRectangularShape() {
263 		return rectangularShape;
264 	}
265 
266 	/**
267 	 * @param rect the rect to set
268 	 */
269 	public void setRectangularShape(RectangularShape rect) {
270 		this.rectangularShape = rect;
271 	}
272 
273 	/**
274 	 * @return the layer
275 	 */
276 	public Annotation.Layer getLayer() {
277 		return layer;
278 	}
279 
280 	/**
281 	 * @param layer the layer to set
282 	 */
283 	public void setLayer(Annotation.Layer layer) {
284 		this.layer = layer;
285 	}
286 
287 	/**
288 	 * @return the fill
289 	 */
290 	public boolean isFill() {
291 		return fill;
292 	}
293 
294 	/**
295 	 * @param fill the fill to set
296 	 */
297 	public void setFill(boolean fill) {
298 		this.fill = fill;
299 	}
300 
301  }