KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > batik > gvt > ShapeNode


1 /*
2
3    Copyright 2000-2003 The Apache Software Foundation
4
5    Licensed under the Apache License, Version 2.0 (the "License");
6    you may not use this file except in compliance with the License.
7    You may obtain a copy of the License at
8
9        http://www.apache.org/licenses/LICENSE-2.0
10
11    Unless required by applicable law or agreed to in writing, software
12    distributed under the License is distributed on an "AS IS" BASIS,
13    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14    See the License for the specific language governing permissions and
15    limitations under the License.
16
17  */

18 package org.apache.batik.gvt;
19
20 import java.awt.Graphics2D JavaDoc;
21 import java.awt.Shape JavaDoc;
22 import java.awt.geom.Point2D JavaDoc;
23 import java.awt.geom.Rectangle2D JavaDoc;
24
25 import org.apache.batik.util.HaltingThread;
26
27 /**
28  * A graphics node that represents a shape.
29  *
30  * @author <a HREF="mailto:Thierry.Kormann@sophia.inria.fr">Thierry Kormann</a>
31  * @version $Id: ShapeNode.java,v 1.32 2005/03/27 08:58:34 cam Exp $
32  */

33 public class ShapeNode extends AbstractGraphicsNode {
34
35     /**
36      * The shape that describes this <tt>ShapeNode</tt>.
37      */

38     protected Shape JavaDoc shape;
39
40     /**
41      * The shape painter used to paint the shape of this shape node.
42      */

43     protected ShapePainter shapePainter;
44
45     /**
46      * Internal Cache: Primitive bounds
47      */

48     private Rectangle2D JavaDoc primitiveBounds;
49
50     /**
51      * Internal Cache: Geometry bounds
52      */

53     private Rectangle2D JavaDoc geometryBounds;
54
55     /**
56      * Internal Cache: Sensitive bounds
57      */

58     private Rectangle2D JavaDoc sensitiveBounds;
59
60     /**
61      * Internal Cache: The painted area.
62      */

63     private Shape JavaDoc paintedArea;
64
65     /**
66      * Internal Cache: The sensitive area.
67      */

68     private Shape JavaDoc sensitiveArea;
69
70     /**
71      * Constructs a new empty <tt>ShapeNode</tt>.
72      */

73     public ShapeNode() {}
74
75     //
76
// Properties methods
77
//
78

79     /**
80      * Sets the shape of this <tt>ShapeNode</tt>.
81      *
82      * @param newShape the new shape of this shape node
83      */

84     public void setShape(Shape JavaDoc newShape) {
85         fireGraphicsNodeChangeStarted();
86         invalidateGeometryCache();
87         this.shape = newShape;
88         if(this.shapePainter != null){
89             if (newShape != null) {
90                 this.shapePainter.setShape(newShape);
91             } else {
92                 this.shapePainter = null;
93             }
94         }
95         fireGraphicsNodeChangeCompleted();
96     }
97
98     /**
99      * Returns the shape of this <tt>ShapeNode</tt>.
100      */

101     public Shape JavaDoc getShape() {
102         return shape;
103     }
104
105     /**
106      * Sets the <tt>ShapePainter</tt> used by this shape node to render its
107      * shape.
108      *
109      * @param newShapePainter the new ShapePainter to use
110      */

111     public void setShapePainter(ShapePainter newShapePainter) {
112         if (shape == null) // Doesn't matter if we don't have a shape.
113
return;
114         fireGraphicsNodeChangeStarted();
115         invalidateGeometryCache();
116         this.shapePainter = newShapePainter;
117         if(shapePainter != null && shape != this.shapePainter.getShape()){
118             shapePainter.setShape(shape);
119         }
120         fireGraphicsNodeChangeCompleted();
121     }
122
123     /**
124      * Returns the <tt>ShapePainter</tt> used by this shape node to render its
125      * shape.
126      */

127     public ShapePainter getShapePainter() {
128         return shapePainter;
129     }
130
131     //
132
// Drawing methods
133
//
134

135     /**
136      * Paints this node.
137      *
138      * @param g2d the Graphics2D to use
139      */

140     public void paint(Graphics2D JavaDoc g2d) {
141         if (isVisible)
142             super.paint(g2d);
143     }
144
145     /**
146      * Paints this node without applying Filter, Mask, Composite, and clip.
147      *
148      * @param g2d the Graphics2D to use
149      */

150     public void primitivePaint(Graphics2D JavaDoc g2d) {
151         if (shapePainter != null) {
152             shapePainter.paint(g2d);
153         }
154     }
155
156     //
157
// Geometric methods
158
//
159

160     /**
161      * Invalidates this <tt>ShapeNode</tt>. This node and all its ancestors have
162      * been informed that all its cached values related to its bounds must be
163      * recomputed.
164      */

165     protected void invalidateGeometryCache() {
166         super.invalidateGeometryCache();
167         primitiveBounds = null;
168         geometryBounds = null;
169         sensitiveBounds = null;
170         paintedArea = null;
171         sensitiveArea = null;
172     }
173
174     public void setPointerEventType(int pointerEventType) {
175         super.setPointerEventType(pointerEventType);
176         sensitiveBounds = null;
177         sensitiveArea = null;
178     }
179     /**
180      * Returns true if the specified Point2D is inside the boundary of this
181      * node, false otherwise.
182      *
183      * @param p the specified Point2D in the user space
184      */

185     public boolean contains(Point2D JavaDoc p) {
186         switch(pointerEventType) {
187         case VISIBLE_PAINTED:
188         case VISIBLE_FILL:
189         case VISIBLE_STROKE:
190         case VISIBLE:
191             if (!isVisible) return false;
192             // Fall Through
193
case PAINTED:
194         case FILL:
195         case STROKE:
196         case ALL: {
197             Rectangle2D JavaDoc b = getSensitiveBounds();
198             if (b == null || !b.contains(p))
199                 return false;
200
201             return inSensitiveArea(p);
202         }
203         case NONE:
204         default:
205             return false;
206         }
207     }
208
209     /**
210      * Returns true if the interior of this node intersects the interior of a
211      * specified Rectangle2D, false otherwise.
212      *
213      * @param r the specified Rectangle2D in the user node space
214      */

215     public boolean intersects(Rectangle2D JavaDoc r) {
216         Rectangle2D JavaDoc b = getBounds();
217         if (b != null) {
218             return (b.intersects(r) &&
219                     paintedArea != null &&
220                     paintedArea.intersects(r));
221         }
222         return false;
223     }
224
225     /**
226      * Returns the bounds of the area covered by this node's primitive paint.
227      */

228     public Rectangle2D JavaDoc getPrimitiveBounds() {
229         if (!isVisible) return null;
230         if (shape == null) return null;
231         if (primitiveBounds != null)
232             return primitiveBounds;
233
234         if (shapePainter == null)
235             primitiveBounds = shape.getBounds2D();
236         else
237             primitiveBounds = shapePainter.getPaintedBounds2D();
238         
239         // Check If we should halt early.
240
if (HaltingThread.hasBeenHalted()) {
241             // The Thread has been halted.
242
// Invalidate any cached values and proceed (this
243
// sets primitiveBounds to null).
244
invalidateGeometryCache();
245         }
246         return primitiveBounds;
247     }
248
249     public boolean inSensitiveArea(Point2D JavaDoc pt) {
250         if (shapePainter == null)
251             return false;
252
253         // <!> NOT REALLY NICE CODE BUT NO OTHER WAY
254
ShapePainter strokeShapePainter = null;
255         ShapePainter fillShapePainter = null;
256         if (shapePainter instanceof StrokeShapePainter) {
257             strokeShapePainter = shapePainter;
258         } else if (shapePainter instanceof FillShapePainter) {
259             fillShapePainter = shapePainter;
260         } else if (shapePainter instanceof CompositeShapePainter) {
261             CompositeShapePainter cp = (CompositeShapePainter)shapePainter;
262
263             for (int i=0; i < cp.getShapePainterCount(); ++i) {
264                 ShapePainter sp = cp.getShapePainter(i);
265                 if (sp instanceof StrokeShapePainter) {
266                     strokeShapePainter = sp;
267                 } else if (sp instanceof FillShapePainter) {
268                     fillShapePainter = sp;
269                 }
270             }
271         } else {
272             return false; // Don't know what we have...
273
}
274
275         switch(pointerEventType) {
276         case VISIBLE_PAINTED:
277         case PAINTED:
278             return shapePainter.inPaintedArea(pt);
279         case VISIBLE:
280         case ALL:
281             return shapePainter.inSensitiveArea(pt);
282         case VISIBLE_FILL:
283         case FILL:
284             if (fillShapePainter != null)
285                 return fillShapePainter.inSensitiveArea(pt);
286             break;
287         case VISIBLE_STROKE:
288         case STROKE:
289             if (strokeShapePainter != null)
290                 return strokeShapePainter.inSensitiveArea(pt);
291             break;
292         case NONE:
293         default:
294             // nothing to tdo
295
}
296         return false;
297     }
298
299     /**
300      * Returns the bounds of the sensitive area covered by this node,
301      * This includes the stroked area but does not include the effects
302      * of clipping, masking or filtering.
303      */

304     public Rectangle2D JavaDoc getSensitiveBounds() {
305         if (sensitiveBounds != null)
306             return sensitiveBounds;
307
308         if (shapePainter == null)
309             return null;
310
311         // <!> NOT REALLY NICE CODE BUT NO OTHER WAY
312
ShapePainter strokeShapePainter = null;
313         ShapePainter fillShapePainter = null;
314         if (shapePainter instanceof StrokeShapePainter) {
315             strokeShapePainter = shapePainter;
316         } else if (shapePainter instanceof FillShapePainter) {
317             fillShapePainter = shapePainter;
318         } else if (shapePainter instanceof CompositeShapePainter) {
319             CompositeShapePainter cp = (CompositeShapePainter)shapePainter;
320
321             for (int i=0; i < cp.getShapePainterCount(); ++i) {
322                 ShapePainter sp = cp.getShapePainter(i);
323                 if (sp instanceof StrokeShapePainter) {
324                     strokeShapePainter = sp;
325                 } else if (sp instanceof FillShapePainter) {
326                     fillShapePainter = sp;
327                 }
328             }
329         } else return null; // Don't know what we have...
330

331
332         switch(pointerEventType) {
333         case VISIBLE_PAINTED:
334         case PAINTED:
335             sensitiveBounds = shapePainter.getPaintedBounds2D();
336             break;
337         case VISIBLE_FILL:
338         case FILL:
339             if (fillShapePainter != null) {
340                 sensitiveBounds = fillShapePainter.getSensitiveBounds2D();
341             }
342             break;
343         case VISIBLE_STROKE:
344         case STROKE:
345             if (strokeShapePainter != null) {
346                 sensitiveBounds = strokeShapePainter.getSensitiveBounds2D();
347             }
348             break;
349         case VISIBLE:
350         case ALL:
351             sensitiveBounds = shapePainter.getSensitiveBounds2D();
352             break;
353         case NONE:
354         default:
355             // nothing to tdo
356
}
357         return sensitiveBounds;
358     }
359
360     /**
361      * Returns the shape that represents the sensitive area of this graphics
362      * node.
363      */

364     public Shape JavaDoc getSensitiveArea() {
365         if (sensitiveArea != null)
366             return sensitiveArea;
367         if (shapePainter == null)
368             return null;
369
370         // <!> NOT REALLY NICE CODE BUT NO OTHER WAY
371
ShapePainter strokeShapePainter = null;
372         ShapePainter fillShapePainter = null;
373         if (shapePainter instanceof StrokeShapePainter) {
374             strokeShapePainter = shapePainter;
375         } else if (shapePainter instanceof FillShapePainter) {
376             fillShapePainter = shapePainter;
377         } else if (shapePainter instanceof CompositeShapePainter) {
378             CompositeShapePainter cp = (CompositeShapePainter)shapePainter;
379
380             for (int i=0; i < cp.getShapePainterCount(); ++i) {
381                 ShapePainter sp = cp.getShapePainter(i);
382                 if (sp instanceof StrokeShapePainter) {
383                     strokeShapePainter = sp;
384                 } else if (sp instanceof FillShapePainter) {
385                     fillShapePainter = sp;
386                 }
387             }
388         } else return null; // Don't know what we have...
389

390
391         switch(pointerEventType) {
392         case VISIBLE_PAINTED:
393         case PAINTED:
394             sensitiveArea = shapePainter.getPaintedArea();
395             break;
396         case VISIBLE_FILL:
397         case FILL:
398             if (fillShapePainter != null) {
399                 sensitiveArea = fillShapePainter.getSensitiveArea();
400             }
401             break;
402         case VISIBLE_STROKE:
403         case STROKE:
404             if (strokeShapePainter != null) {
405                 sensitiveArea = strokeShapePainter.getSensitiveArea();
406             }
407             break;
408         case VISIBLE:
409         case ALL:
410             sensitiveArea = shapePainter.getSensitiveArea();
411             break;
412         case NONE:
413         default:
414             // nothing to tdo
415
}
416         return sensitiveArea;
417     }
418
419     /**
420      * Returns the bounds of the area covered by this node, without
421      * taking any of its rendering attribute into account. That is,
422      * exclusive of any clipping, masking, filtering or stroking, for
423      * example.
424      */

425     public Rectangle2D JavaDoc getGeometryBounds(){
426         if (geometryBounds == null) {
427             if (shape == null) {
428                 return null;
429             }
430             geometryBounds = normalizeRectangle(shape.getBounds2D());
431         }
432         return geometryBounds;
433     }
434
435     /**
436      * Returns the outline of this node.
437      */

438     public Shape JavaDoc getOutline() {
439         return shape;
440     }
441 }
442
Popular Tags