View Javadoc

1   /*
2    * Copyright (c) 2003, 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   package edu.uci.ics.jung.visualization.transform;
10  
11  import java.awt.Component;
12  import java.awt.Dimension;
13  import java.awt.Shape;
14  import java.awt.event.ComponentAdapter;
15  import java.awt.event.ComponentEvent;
16  import java.awt.geom.AffineTransform;
17  import java.awt.geom.Ellipse2D;
18  import java.awt.geom.Point2D;
19  import java.awt.geom.Rectangle2D;
20  import java.awt.geom.RectangularShape;
21  
22  /**
23   * LensTransformer wraps a MutableAffineTransformer and modifies
24   * the transform and inverseTransform methods so that they create a
25   * projection of the graph points within an elliptical lens.
26   * 
27   * LensTransformer uses an
28   * affine transform to cause translation, scaling, rotation, and shearing
29   * while applying a possibly non-affine filter in its transform and
30   * inverseTransform methods.
31   * 
32   * @author Tom Nelson
33   *
34   *
35   */
36  public abstract class LensTransformer extends MutableTransformerDecorator implements MutableTransformer {
37  
38      /**
39       * the area affected by the transform
40       */
41      protected RectangularShape lensShape = new Ellipse2D.Float();
42      
43      protected float magnification = 0.7f;
44      
45      /**
46       * create an instance with a possibly shared transform
47       * @param component
48       * @param delegate
49       */
50      public LensTransformer(Component component, MutableTransformer delegate) {
51      		super(delegate);
52          setComponent(component);
53          component.addComponentListener(new ComponentListenerImpl());
54     }
55      
56      /**
57       * set values from the passed component.
58       * declared private so it can't be overridden
59       * @param component
60       */
61      private void setComponent(Component component) {
62          Dimension d = component.getSize();
63          if(d.width <= 0 || d.height <= 0) {
64              d = component.getPreferredSize();
65          }
66          float ewidth = d.width/1.5f;
67          float eheight = d.height/1.5f;
68          lensShape.setFrame(d.width/2-ewidth/2, d.height/2-eheight/2, ewidth, eheight);
69      }
70      
71      /**
72       * @return Returns the magnification.
73       */
74      public float getMagnification() {
75          return magnification;
76      }
77      /**
78       * @param magnification The magnification to set.
79       */
80      public void setMagnification(float magnification) {
81          this.magnification = magnification;
82      }
83      /**
84       * @return Returns the viewCenter.
85       */
86      public Point2D getViewCenter() {
87          return new Point2D.Double(lensShape.getCenterX(), lensShape.getCenterY());
88      }
89      /**
90       * @param viewCenter The viewCenter to set.
91       */
92      public void setViewCenter(Point2D viewCenter) {
93          double width = lensShape.getWidth();
94          double height = lensShape.getHeight();
95          lensShape.setFrame(viewCenter.getX()-width/2,
96                  viewCenter.getY()-height/2,
97                  width, height);
98      }
99  
100     /**
101      * @return Returns the viewRadius.
102      */
103     public double getViewRadius() {
104         return lensShape.getHeight()/2;
105     }
106     /**
107      * @param viewRadius The viewRadius to set.
108      */
109     public void setViewRadius(double viewRadius) {
110         double x = lensShape.getCenterX();
111         double y = lensShape.getCenterY();
112         double viewRatio = getRatio();
113         lensShape.setFrame(x-viewRadius/viewRatio,
114                 y-viewRadius,
115                 2*viewRadius/viewRatio,
116                 2*viewRadius);
117     }
118     
119     /**
120      * @return Returns the ratio.
121      */
122     public double getRatio() {
123         return lensShape.getHeight()/lensShape.getWidth();
124     }
125     
126     public void setLensShape(RectangularShape ellipse) {
127         this.lensShape = ellipse;
128     }
129     public RectangularShape getLensShape() {
130         return lensShape;
131     }
132     public void setToIdentity() {
133         this.delegate.setToIdentity();
134     }
135 
136     /**
137      * react to size changes on a component
138      */
139     protected class ComponentListenerImpl extends ComponentAdapter {
140         public void componentResized(ComponentEvent e) {
141             setComponent(e.getComponent());
142          }
143     }
144     
145     /**
146      * override base class transform to project the fisheye effect
147      */
148     public abstract Point2D transform(Point2D graphPoint);
149     
150     /**
151      * override base class to un-project the fisheye effect
152      */
153     public abstract Point2D inverseTransform(Point2D viewPoint);
154     
155     public double getDistanceFromCenter(Point2D p) {
156     	
157         double dx = lensShape.getCenterX()-p.getX();
158         double dy = lensShape.getCenterY()-p.getY();
159         dx *= getRatio();
160         return Math.sqrt(dx*dx + dy*dy);
161     }
162     
163     /**
164      * return the supplied shape, translated to the coordinates
165      * that result from calling transform on its center
166      */
167     public Shape transform(Shape shape) {
168     	Rectangle2D bounds = shape.getBounds2D();
169     	Point2D center = new Point2D.Double(bounds.getCenterX(),bounds.getCenterY());
170     	Point2D newCenter = transform(center);
171     	double dx = newCenter.getX()-center.getX();
172     	double dy = newCenter.getY()-center.getY();
173     	AffineTransform at = AffineTransform.getTranslateInstance(dx,dy);
174     	return at.createTransformedShape(shape);
175     }
176     
177     /**
178      * return the supplied shape, translated to the coordinates
179      * that result from calling inverseTransform on its center
180      */
181     public Shape inverseTransform(Shape shape) {
182     	Rectangle2D bounds = shape.getBounds2D();
183     	Point2D center = new Point2D.Double(bounds.getCenterX(),bounds.getCenterY());
184     	Point2D newCenter = inverseTransform(center);
185     	double dx = newCenter.getX()-center.getX();
186     	double dy = newCenter.getY()-center.getY();
187     	AffineTransform at = AffineTransform.getTranslateInstance(dx,dy);
188     	return at.createTransformedShape(shape);
189     }
190 
191 }