/*
* Copyright (c) 2005, the JUNG Project and the Regents of the University of
* California All rights reserved.
*
* This software is open-source under the BSD license; see either "license.txt"
* or http://jung.sourceforge.net/license.txt for a description.
*
*
*/
package edu.uci.ics.jung.visualization.annotations;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import edu.uci.ics.jung.visualization.Layer;
import edu.uci.ics.jung.visualization.RenderContext;
import edu.uci.ics.jung.visualization.transform.AffineTransformer;
import edu.uci.ics.jung.visualization.transform.LensTransformer;
import edu.uci.ics.jung.visualization.transform.MutableTransformer;
/**
* handles the selection of annotations, and the support for the
* tools to draw them at specific layers.
*
* @author Tom Nelson - tomnelson@dev.java.net
*
*/
public class AnnotationManager {
protected AnnotationRenderer annotationRenderer = new AnnotationRenderer();
protected AnnotationPaintable lowerAnnotationPaintable;
protected AnnotationPaintable upperAnnotationPaintable;
protected RenderContext<?,?> rc;
protected AffineTransformer transformer;
public AnnotationManager(RenderContext<?,?> rc) {
this.rc = rc;
this.lowerAnnotationPaintable = new AnnotationPaintable(rc, annotationRenderer);
this.upperAnnotationPaintable = new AnnotationPaintable(rc, annotationRenderer);
MutableTransformer mt = rc.getMultiLayerTransformer().getTransformer(Layer.LAYOUT);
if(mt instanceof AffineTransformer) {
transformer = (AffineTransformer)mt;
} else if(mt instanceof LensTransformer) {
transformer = (AffineTransformer)((LensTransformer)mt).getDelegate();
}
}
public AnnotationPaintable getAnnotationPaintable(Annotation.Layer layer) {
if(layer == Annotation.Layer.LOWER) {
return this.lowerAnnotationPaintable;
}
if(layer == Annotation.Layer.UPPER) {
return this.upperAnnotationPaintable;
}
return null;
}
public void add(Annotation.Layer layer, Annotation<?> annotation) {
if(layer == Annotation.Layer.LOWER) {
this.lowerAnnotationPaintable.add(annotation);
}
if(layer == Annotation.Layer.UPPER) {
this.upperAnnotationPaintable.add(annotation);
}
}
public void remove(Annotation<?> annotation) {
this.lowerAnnotationPaintable.remove(annotation);
this.upperAnnotationPaintable.remove(annotation);
}
protected AnnotationPaintable getLowerAnnotationPaintable() {
return lowerAnnotationPaintable;
}
protected AnnotationPaintable getUpperAnnotationPaintable() {
return upperAnnotationPaintable;
}
@SuppressWarnings("unchecked")
public Annotation getAnnotation(Point2D p) {
Set<Annotation> annotations = new HashSet<Annotation>(lowerAnnotationPaintable.getAnnotations());
annotations.addAll(upperAnnotationPaintable.getAnnotations());
return getAnnotation(p, annotations);
}
@SuppressWarnings("unchecked")
public Annotation getAnnotation(Point2D p, Collection<Annotation> annotations) {
double closestDistance = Double.MAX_VALUE;
Annotation closestAnnotation = null;
for(Annotation annotation : annotations) {
Object ann = annotation.getAnnotation();
if(ann instanceof Shape) {
Point2D ip = rc.getMultiLayerTransformer().inverseTransform(p);
Shape shape = (Shape)ann;
if(shape.contains(ip)) {
Rectangle2D shapeBounds = shape.getBounds2D();
Point2D shapeCenter = new Point2D.Double(shapeBounds.getCenterX(), shapeBounds.getCenterY());
double distanceSq = shapeCenter.distanceSq(ip);
if(distanceSq < closestDistance) {
closestDistance = distanceSq;
closestAnnotation = annotation;
}
}
} else if(ann instanceof String) {
Point2D ip = rc.getMultiLayerTransformer().inverseTransform(Layer.VIEW, p);
Point2D ap = annotation.getLocation();
String label = (String)ann;
Component component = prepareRenderer(rc, annotationRenderer, label);
AffineTransform base = new AffineTransform(transformer.getTransform());
double rotation = transformer.getRotation();
// unrotate the annotation
AffineTransform unrotate =
AffineTransform.getRotateInstance(-rotation, ap.getX(), ap.getY());
base.concatenate(unrotate);
Dimension d = component.getPreferredSize();
Rectangle2D componentBounds = new Rectangle2D.Double(ap.getX(), ap.getY(), d.width, d.height);
Shape componentBoundsShape = base.createTransformedShape(componentBounds);
Point2D componentCenter = new Point2D.Double(componentBoundsShape.getBounds().getCenterX(),
componentBoundsShape.getBounds().getCenterY());
if(componentBoundsShape.contains(ip)) {
double distanceSq = componentCenter.distanceSq(ip);
if(distanceSq < closestDistance) {
closestDistance = distanceSq;
closestAnnotation = annotation;
}
}
}
}
return closestAnnotation;
}
public Component prepareRenderer(RenderContext<?,?> rc, AnnotationRenderer annotationRenderer, Object value) {
return annotationRenderer.getAnnotationRendererComponent(rc.getScreenDevice(), value);
}
}