KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > thoughtriver > open > vectorvisuals > VVDisplay


1 /*
2  * VVDisplay.java
3  *
4  * Created on 23 May 2005, 15:55
5  */

6
7 package com.thoughtriver.open.vectorvisuals;
8
9 import java.awt.*;
10 import java.awt.geom.*;
11
12 import com.thoughtriver.open.vectorvisuals.task.*;
13 import com.thoughtriver.open.vectorvisuals.ui.*;
14
15 /**
16  * A <CODE>VVDisplay</CODE> represents a single controllable vector world in
17  * the Vector Visuals system. It maintains information about the user's view of
18  * the world, such as the scale and translation of the view, as well as a
19  * reference to the <CODE>VVViewPane</CODE> used to render the world, the
20  * <CODE>TaskManager</CODE> that handles all of the animation tasks for the
21  * world, and the root <CODE>VisualObject</CODE> within which all other
22  * objects are embedded.
23  *
24  * @author Brandon Franklin
25  * @version $Date: 2006/11/25 09:18:36 $
26  */

27 public class VVDisplay {
28
29     /**
30      * The <CODE>VVViewPane</CODE> component that will actually render the
31      * world
32      */

33     private final VVViewPane viewPane;
34
35     /**
36      * The manager instance that handles all of the tasks for this display
37      * instance
38      */

39     private final TaskManager taskManager;
40
41     /** The root <CODE>VisualObject</CODE> in which all others are contained */
42     private final VisualObject rootObj;
43
44     /** The translation of this panel's view into the vector world */
45     private Point2D translation = null;
46
47     /** The scale of this panel's view into the vector world */
48     private double scale;
49
50     /**
51      * The theta value of the rotation of this panel's view into the vector
52      * world
53      */

54     private double rotation;
55
56     /**
57      * Creates a new instance of <CODE>VVDisplay</CODE>, configured to render
58      * upon the supplied <CODE>VVViewPane</CODE>, and to use the supplied
59      * <CODE>VisualObject</CODE> as the root of the object tree.
60      *
61      * @param viewPane the <CODE>VVViewPane</CODE> that will be used to render
62      * the vector world
63      * @param rootObj the <CODE>VisualObject</CODE> to use as the root of the
64      * object tree
65      */

66     public VVDisplay(final VVViewPane viewPane, final VisualObject rootObj) {
67
68         this.rootObj = rootObj;
69         rootObj.setDisplay(this);
70
71         taskManager = new TaskManager(this);
72         translation = new Point2D.Double(0, 0);
73         scale = 1.0;
74         rotation = 0.0;
75
76         if (viewPane instanceof Component) {
77             this.viewPane = viewPane;
78             viewPane.setVVDisplay(this);
79         }
80         else {
81             throw new IllegalArgumentException JavaDoc("All VVViewPane implementations must extend Component");
82         }
83         viewPane.setFocusable(true);
84     }
85
86     /**
87      * Creates a new instance of <CODE>VVDisplay</CODE>, configured to render
88      * upon the supplied <CODE>VVViewPane</CODE>.
89      *
90      * @param viewPane the <CODE>VVViewPane</CODE> that will be used to render
91      * the vector world
92      */

93     public VVDisplay(final VVViewPane viewPane) {
94         this(viewPane, new VisualContainerObject());
95     }
96
97     /**
98      * Returns a reference to the <CODE>VVViewPane</CODE> used to render the
99      * vector world. The datatype view of the returned object is <CODE>Component</CODE>
100      * for convenience, as often this method is used to add the panel into a
101      * <CODE>Component</CODE> hierarchy.
102      *
103      * @return a reference to the <CODE>VVViewPane</CODE> used to render the
104      * vector world
105      */

106     public Component getViewPane() {
107         return (Component) viewPane;
108     }
109
110     /**
111      * Returns a reference to the <CODE>VisualObject</CODE> used to contain
112      * all of the contents of this panel.
113      *
114      * @return a reference to the <CODE>VisualObject</CODE> used to contain
115      * all of the contents of this panel
116      */

117     public VisualObject getRootObject() {
118         return rootObj;
119     }
120
121     /**
122      * Returns the <CODE>TaskManager</CODE> that handles all of the tasks for
123      * this display instance.
124      *
125      * @return the <CODE>TaskManager</CODE> that handles all of the tasks for
126      * this display instance
127      */

128     public TaskManager getTaskManager() {
129         return taskManager;
130     }
131
132     /**
133      * Sets the scale of view into the vector world that this panel is to
134      * display.
135      *
136      * @param scale the scaling factor of the view
137      */

138     public synchronized void setWorldViewScale(final double scale) {
139
140         // Reject excessively small scales
141
if (scale < 0.001) {
142             return;
143         }
144
145         // Find the world point at the center of the window
146
int centerX = viewPane.getWidth() / 2;
147         int centerY = viewPane.getHeight() / 2;
148         Point2D oldCenter = getWorldPointUnderPixel(centerX, centerY);
149
150         // Set the new scale
151
this.scale = scale;
152
153         // Find what the new world point in the center of the window would be
154
Point2D newCenter = getWorldPointUnderPixel(centerX, centerY);
155
156         // Calculate the difference
157
double xDiff = newCenter.getX() - oldCenter.getX();
158         double yDiff = newCenter.getY() - oldCenter.getY();
159
160         // Translate the view to maintain the center point
161
Point2D translation = getWorldViewTranslation();
162         setWorldViewTranslation(translation.getX() + (xDiff * scale), translation.getY()
163                 + (yDiff * scale));
164
165         viewPane.repaint();
166     }
167
168     /**
169      * Returns the scale of the view into the vector world that this panel is
170      *
171      * @return the scaling factor of the view
172      */

173     public synchronized double getWorldViewScale() {
174         return scale;
175     }
176
177     /**
178      * Translates (moves) the view into the vector world that this panel is
179      * displaying.
180      *
181      * @param offset the offset by which to translate the view
182      */

183     public synchronized void setWorldViewTranslation(final Point2D offset) {
184         translation = offset;
185
186         viewPane.repaint();
187     }
188
189     /**
190      * Translates (moves) the view into the vector world that this panel is
191      * displaying.
192      *
193      * @param x the distance along the X axis to translate the view
194      * @param y the distance along the Y axis to translate the view
195      */

196     public synchronized void setWorldViewTranslation(final double x, final double y) {
197         setWorldViewTranslation(new Point2D.Double(x, y));
198     }
199
200     /**
201      * Returns the offset into the vector world that this panel is displaying.
202      *
203      * @return the offset into the vector world that this panel is displaying
204      */

205     public synchronized Point2D getWorldViewTranslation() {
206         return translation;
207     }
208
209     /**
210      * Adjusts the view into the vector world so that the center of the supplied
211      * object is the center of the view.
212      *
213      * @param obj the object on which the view should be centered
214      */

215     public synchronized void centerViewOn(final VisualObject obj) {
216
217         // Find the world point at the center of the window
218
int centerX = viewPane.getWidth() / 2;
219         int centerY = viewPane.getHeight() / 2;
220         Point2D oldCenter = getWorldPointUnderPixel(centerX, centerY);
221
222         // Examine the object's position and size
223
Rectangle2D objBounds = obj.getShape().getBounds2D();
224         AffineTransform objTransform = obj.getTransformRelativeTo(null);
225
226         // Adjust the transform so it includes the object's center
227
objTransform.translate(objBounds.getCenterX(), objBounds.getCenterY());
228
229         // Calculate the difference
230
double xDiff = objTransform.getTranslateX() - oldCenter.getX();
231         double yDiff = objTransform.getTranslateY() - oldCenter.getY();
232
233         // Adjust the view using the difference
234
Point2D translation = getWorldViewTranslation();
235         setWorldViewTranslation(translation.getX()
236                 - (xDiff * getWorldViewScale()), translation.getY()
237                 - (yDiff * getWorldViewScale()));
238
239     }
240
241     /**
242      * Returns the composite transform for the view into the vector world that
243      * this panel is displaying. This <CODE>AffineTransform</CODE> object will
244      * be built from the translation, scale, and rotation values currently
245      * active on this instance.
246      *
247      * @return the composite transform for the view into the vector world that
248      * this panel is displaying
249      */

250     public synchronized AffineTransform getCompositeTransform() {
251
252         AffineTransform compositeTransform = AffineTransform.getTranslateInstance(getWorldViewTranslation().getX(), getWorldViewTranslation().getY());
253
254         compositeTransform.concatenate(AffineTransform.getScaleInstance(scale, scale));
255
256         compositeTransform.concatenate(AffineTransform.getRotateInstance(rotation));
257
258         return compositeTransform;
259     }
260
261     /**
262      * Adds a <CODE>VVMouseListener</CODE> that will respond to events on this
263      * <CODE>VVPanel</CODE> instance. The listener will be analyzed to see
264      * what interfaces it implements, and will be attached to all of the
265      * appropriate event sources automatically.
266      *
267      * @param listener a <CODE>VVMouseListener</CODE> that will respond to
268      * events on this <CODE>VVPanel</CODE> instance
269      */

270     public void addVVMouseListener(final VVMouseListener listener) {
271         viewPane.addMouseListener(listener);
272         viewPane.addMouseWheelListener(listener);
273         viewPane.addMouseMotionListener(listener);
274     }
275
276     /**
277      * Removes a <CODE>VVMouseListener</CODE> from responding to events on
278      * this <CODE>VVPanel</CODE> instance. The listener will be analyzed to
279      * see what interfaces it implements, and will be removed from all of the
280      * appropriate event sources automatically.
281      *
282      * @param listener the <CODE>VVMouseListener</CODE> to remove
283      */

284     public void removeVVMouseListener(final VVMouseListener listener) {
285         viewPane.removeMouseListener(listener);
286         viewPane.removeMouseWheelListener(listener);
287         viewPane.removeMouseMotionListener(listener);
288     }
289
290     /**
291      * Returns the <CODE>VisualObject</CODE>, if any, that is currently being
292      * displayed at the provided pixel coordinates on this panel. This method is
293      * used by the <CODE>VVMouseListener</CODE> to allow the selection of
294      * objects by clicking on them.
295      *
296      * @param x the X coordinate of interest
297      * @param y the Y coordinate of interest
298      * @return the <CODE>VisualObject</CODE>, if any, that is currently being
299      * displayed at the provided pixel coordinates, or null if there is
300      * no object at that location
301      */

302     public synchronized VisualObject getVisualObjectAt(final int x, final int y) {
303
304         Point2D point = getWorldPointUnderPixel(x, y);
305         if (point == null) {
306             return null;
307         }
308
309         return rootObj.getVisualObjectAt(point);
310     }
311
312     /**
313      * Returns the absolute point in vector space that currently lies under the
314      * provided pixel coordinate on the <CODE>VVPanel</CODE>.
315      *
316      * @param x the X coordinate of interest
317      * @param y the Y coordinate of interest
318      * @return the absolute point in vector space that currently lies under the
319      * provided pixel coordinate
320      */

321     public synchronized Point2D getWorldPointUnderPixel(final int x, final int y) {
322         Point2D point = new Point2D.Double(x, y);
323         try {
324             point = getCompositeTransform().createInverse().transform(point, point);
325         }
326         catch (NoninvertibleTransformException e) {
327             return null;
328         }
329
330         return point;
331     }
332
333     /**
334      * Causes the <CODE>VVPanel</CODE> to render itself. In the Vector Visuals
335      * system, this method is called quite frequently in order to facilitate
336      * animations.
337      *
338      * @param g the <CODE>Graphics</CODE> context of the panel
339      */

340     public synchronized void paint(final Graphics g) {
341
342         Graphics2D g2d = (Graphics2D) g.create();
343         g2d.setColor(viewPane.getBackground());
344         g2d.fillRect(0, 0, viewPane.getWidth(), viewPane.getHeight());
345
346         AffineTransform transform = g2d.getTransform();
347         transform.concatenate(getCompositeTransform());
348         g2d.setTransform(transform);
349
350         g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED);
351         g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
352         g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);
353         rootObj.render(g2d);
354
355         g2d.dispose();
356     }
357
358     /**
359      * Adds the supplied <CODE>VisualObject</CODE> for rendering in the vector
360      * world.
361      *
362      * @param vo the new <CODE>VisualObject</CODE> to be rendered
363      */

364     public void addObject(final VisualObject vo) {
365         rootObj.add(vo);
366         viewPane.repaint();
367     }
368
369     /**
370      * Removes the supplied <CODE>VisualObject</CODE> from rendering in the
371      * vector world.
372      *
373      * @param vo the <CODE>VisualObject</CODE> to be removed
374      */

375     public void removeObject(final VisualObject vo) {
376         rootObj.remove(vo);
377         viewPane.repaint();
378     }
379
380 }
381
Popular Tags