View Javadoc

1   /*
2    * Copyright (c) 2005, the JUNG Project and the Regents of the University of
3    * California All rights reserved.
4    *
5    * This software is open-source under the BSD license; see either "license.txt"
6    * or http://jung.sourceforge.net/license.txt for a description.
7    *
8    * 
9    */
10  package edu.uci.ics.jung.visualization.annotations;
11  
12  import java.awt.Component;
13  import java.awt.Dimension;
14  import java.awt.Shape;
15  import java.awt.geom.AffineTransform;
16  import java.awt.geom.Point2D;
17  import java.awt.geom.Rectangle2D;
18  import java.util.Collection;
19  import java.util.HashSet;
20  import java.util.Set;
21  
22  import edu.uci.ics.jung.visualization.Layer;
23  import edu.uci.ics.jung.visualization.RenderContext;
24  import edu.uci.ics.jung.visualization.transform.AffineTransformer;
25  import edu.uci.ics.jung.visualization.transform.LensTransformer;
26  import edu.uci.ics.jung.visualization.transform.MutableTransformer;
27  
28  /**
29   * handles the selection of annotations, and the support for the
30   * tools to draw them at specific layers.
31   * 
32   * @author Tom Nelson - tomnelson@dev.java.net
33   *
34   */
35  public class AnnotationManager {
36  	
37      protected AnnotationRenderer annotationRenderer = new AnnotationRenderer();
38  	protected AnnotationPaintable lowerAnnotationPaintable;
39  	protected AnnotationPaintable upperAnnotationPaintable;
40  	
41  	protected RenderContext<?,?> rc;
42  	protected AffineTransformer transformer;
43  
44  	public AnnotationManager(RenderContext<?,?> rc) {
45  		this.rc = rc;
46  		this.lowerAnnotationPaintable = new AnnotationPaintable(rc, annotationRenderer);
47  		this.upperAnnotationPaintable = new AnnotationPaintable(rc, annotationRenderer);
48  		
49  		MutableTransformer mt = rc.getMultiLayerTransformer().getTransformer(Layer.LAYOUT);
50  		if(mt instanceof AffineTransformer) {
51  			transformer = (AffineTransformer)mt;
52  		} else if(mt instanceof LensTransformer) {
53  			transformer = (AffineTransformer)((LensTransformer)mt).getDelegate();
54  		}
55  
56  	}
57  	
58  	public AnnotationPaintable getAnnotationPaintable(Annotation.Layer layer) {
59  		if(layer == Annotation.Layer.LOWER) {
60  			return this.lowerAnnotationPaintable;
61  		}
62  		if(layer == Annotation.Layer.UPPER) {
63  			return this.upperAnnotationPaintable;
64  		}
65  		return null;
66  	}
67  	
68  	public void add(Annotation.Layer layer, Annotation<?> annotation) {
69  		if(layer == Annotation.Layer.LOWER) {
70  			this.lowerAnnotationPaintable.add(annotation);
71  		}
72  		if(layer == Annotation.Layer.UPPER) {
73  			this.upperAnnotationPaintable.add(annotation);
74  		}
75  	}
76  	
77  	public void remove(Annotation<?> annotation) {
78  		this.lowerAnnotationPaintable.remove(annotation);
79  		this.upperAnnotationPaintable.remove(annotation);
80  	}
81  	
82  	protected AnnotationPaintable getLowerAnnotationPaintable() {
83  		return lowerAnnotationPaintable;
84  	}
85  	
86  	protected AnnotationPaintable getUpperAnnotationPaintable() {
87  		return upperAnnotationPaintable;
88  	}
89  	
90  	@SuppressWarnings("unchecked")
91      public Annotation getAnnotation(Point2D p) {
92  		Set<Annotation> annotations = new HashSet<Annotation>(lowerAnnotationPaintable.getAnnotations());
93  		annotations.addAll(upperAnnotationPaintable.getAnnotations());
94  		return getAnnotation(p, annotations);
95  	}
96  	
97  	@SuppressWarnings("unchecked")
98      public Annotation getAnnotation(Point2D p, Collection<Annotation> annotations) {
99  		double closestDistance = Double.MAX_VALUE;
100 		Annotation closestAnnotation = null;
101 		for(Annotation annotation : annotations) {
102 			Object ann = annotation.getAnnotation();
103 			if(ann instanceof Shape) {
104 				Point2D ip = rc.getMultiLayerTransformer().inverseTransform(p);
105 				Shape shape = (Shape)ann;
106 				if(shape.contains(ip)) {
107 					
108 					Rectangle2D shapeBounds = shape.getBounds2D();
109 					Point2D shapeCenter = new Point2D.Double(shapeBounds.getCenterX(), shapeBounds.getCenterY());
110 					double distanceSq = shapeCenter.distanceSq(ip);
111 					if(distanceSq < closestDistance) {
112 						closestDistance = distanceSq;
113 						closestAnnotation = annotation;
114 					}
115 				}
116 			} else if(ann instanceof String) {
117 				
118 				Point2D ip = rc.getMultiLayerTransformer().inverseTransform(Layer.VIEW, p);
119 				Point2D ap = annotation.getLocation();
120 				String label = (String)ann;
121 				Component component = prepareRenderer(rc, annotationRenderer, label);
122 				
123 				AffineTransform base = new AffineTransform(transformer.getTransform());
124 				double rotation = transformer.getRotation();
125 				// unrotate the annotation
126 				AffineTransform unrotate =
127 					AffineTransform.getRotateInstance(-rotation, ap.getX(), ap.getY());
128 				base.concatenate(unrotate);
129 				
130 				Dimension d = component.getPreferredSize();
131 				Rectangle2D componentBounds = new Rectangle2D.Double(ap.getX(), ap.getY(), d.width, d.height);
132 				
133 				Shape componentBoundsShape = base.createTransformedShape(componentBounds);
134 				Point2D componentCenter = new Point2D.Double(componentBoundsShape.getBounds().getCenterX(),
135 						componentBoundsShape.getBounds().getCenterY());
136 				if(componentBoundsShape.contains(ip)) {
137 					double distanceSq = componentCenter.distanceSq(ip);
138 					if(distanceSq < closestDistance) {
139 						closestDistance = distanceSq;
140 						closestAnnotation = annotation;
141 					}
142 				}
143 				
144 			}
145 		}
146 		return closestAnnotation;
147 	}
148 	
149 	public Component prepareRenderer(RenderContext<?,?> rc, AnnotationRenderer annotationRenderer, Object value) {
150 		return annotationRenderer.getAnnotationRendererComponent(rc.getScreenDevice(), value);
151 	}
152 
153 
154 	
155 	
156 
157 }