KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2
3    Copyright 1999-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
19 package org.apache.batik.gvt;
20
21 import java.awt.Shape JavaDoc;
22 import java.awt.Rectangle JavaDoc;
23 import java.awt.geom.AffineTransform JavaDoc;
24 import java.awt.geom.Rectangle2D JavaDoc;
25 import java.lang.ref.WeakReference JavaDoc;
26 import java.util.HashMap JavaDoc;
27 import java.util.Iterator JavaDoc;
28 import java.util.LinkedList JavaDoc;
29 import java.util.List JavaDoc;
30 import java.util.Map JavaDoc;
31 import java.util.Set JavaDoc;
32
33 import org.apache.batik.gvt.event.GraphicsNodeChangeAdapter;
34 import org.apache.batik.gvt.event.GraphicsNodeChangeEvent;
35 import org.apache.batik.ext.awt.image.renderable.Filter;
36 /**
37  * This class tracks the changes on a GVT tree
38  *
39  * @author <a HREF="mailto:Thomas.DeWeeese@Kodak.com">Thomas DeWeese</a>
40  * @version $Id: UpdateTracker.java,v 1.24 2005/03/27 08:58:34 cam Exp $
41  */

42 public class UpdateTracker extends GraphicsNodeChangeAdapter {
43
44     Map JavaDoc dirtyNodes = null;
45     Map JavaDoc fromBounds = new HashMap JavaDoc();
46     protected static Rectangle2D JavaDoc NULL_RECT = new Rectangle JavaDoc();
47
48     public UpdateTracker(){
49     }
50     
51     /**
52      * Tells whether the GVT tree has changed.
53      */

54     public boolean hasChanged() {
55         return (dirtyNodes != null);
56     }
57
58     /**
59      * Returns the list of dirty areas on GVT.
60      */

61     public List JavaDoc getDirtyAreas() {
62         if (dirtyNodes == null)
63             return null;
64
65         List JavaDoc ret = new LinkedList JavaDoc();
66         Set JavaDoc keys = dirtyNodes.keySet();
67         Iterator JavaDoc i = keys.iterator();
68         while (i.hasNext()) {
69             WeakReference JavaDoc gnWRef = (WeakReference JavaDoc)i.next();
70             GraphicsNode gn = (GraphicsNode)gnWRef.get();
71             // GraphicsNode srcGN = gn;
72

73             // if the weak ref has been cleared then this node is no
74
// longer part of the GVT tree (and the change should be
75
// reflected in some ancestor that should also be in the
76
// dirty list).
77
if (gn == null) continue;
78
79             AffineTransform JavaDoc oat;
80             oat = (AffineTransform JavaDoc)dirtyNodes.get(gnWRef);
81             if (oat != null){
82                 oat = new AffineTransform JavaDoc(oat);
83             }
84             
85             Rectangle2D JavaDoc srcORgn = (Rectangle2D JavaDoc)fromBounds.remove(gnWRef);
86
87             Rectangle2D JavaDoc srcNRgn = null;
88             AffineTransform JavaDoc nat = null;
89             if (!(srcORgn instanceof ChngSrcRect)) {
90                 // For change srcs don't use the new bounds of parent node.
91
srcNRgn = gn.getBounds();
92                 nat = gn.getTransform();
93                 if (nat != null)
94                     nat = new AffineTransform JavaDoc(nat);
95             }
96
97
98             // System.out.println("Rgns: " + srcORgn + " - " + srcNRgn);
99
// System.out.println("ATs: " + oat + " - " + nat);
100
do {
101                 // f.invalidateCache(oRng);
102
// f.invalidateCache(nRng);
103

104                 // f = gn.getEnableBackgroundGraphicsNodeRable(false);
105
// (need to push rgn through filter chain if any...)
106
// f.invalidateCache(oRng);
107
// f.invalidateCache(nRng);
108

109                 gn = gn.getParent();
110                 if (gn == null)
111                     break; // We reached the top of the tree
112

113                 Filter f= gn.getFilter();
114                 if ( f != null) {
115                     srcNRgn = f.getBounds2D();
116                     nat = null;
117                 }
118
119                 // Get the parent's current Affine
120
AffineTransform JavaDoc at = gn.getTransform();
121                 // Get the parent's Affine last time we rendered.
122
gnWRef = gn.getWeakReference();
123                 AffineTransform JavaDoc poat = (AffineTransform JavaDoc)dirtyNodes.get(gnWRef);
124                 if (poat == null) poat = at;
125                 if (poat != null) {
126                     if (oat != null)
127                         oat.preConcatenate(poat);
128                     else
129                         oat = new AffineTransform JavaDoc(poat);
130                 }
131
132                 if (at != null){
133                     if (nat != null)
134                         nat.preConcatenate(at);
135                     else
136                         nat = new AffineTransform JavaDoc(at);
137                 }
138             } while (true);
139
140             if (gn == null) {
141                 // We made it to the root graphics node so add them.
142
// System.out.println
143
// ("Adding: " + oat + " - " + nat + "\n" +
144
// srcORgn + "\n" + srcNRgn + "\n");
145
// <!>
146
Shape JavaDoc oRgn = srcORgn;
147                 if ((oRgn != null) && (oRgn != NULL_RECT)) {
148                     if (oat != null)
149                         oRgn = oat.createTransformedShape(srcORgn);
150                     // System.err.println("GN: " + srcGN);
151
// System.err.println("Src: " + oRgn.getBounds2D());
152
ret.add(oRgn);
153                 }
154                 
155                 if (srcNRgn != null) {
156                     Shape JavaDoc nRgn = srcNRgn;
157                     if (nat != null)
158                         nRgn = nat.createTransformedShape(srcNRgn);
159                     if (nRgn != null)
160                         ret.add(nRgn);
161                 }
162             }
163         }
164         return ret;
165     }
166
167     /**
168      * This returns the dirty region for gn in the coordinate system
169      * given by <code>at</at>.
170      * @param gn Node tree to return dirty region for.
171      * @param at Affine transform to coordinate space to accumulate
172      * dirty regions in.
173      */

174     public Rectangle2D JavaDoc getNodeDirtyRegion(GraphicsNode gn,
175                                           AffineTransform JavaDoc at) {
176         WeakReference JavaDoc gnWRef = gn.getWeakReference();
177         AffineTransform JavaDoc nat = (AffineTransform JavaDoc)dirtyNodes.get(gnWRef);
178         if (nat == null) nat = gn.getTransform();
179         if (nat != null) {
180             at = new AffineTransform JavaDoc(at);
181             at.concatenate(nat);
182         }
183
184         Rectangle2D JavaDoc ret = null;
185         if (gn instanceof CompositeGraphicsNode) {
186             CompositeGraphicsNode cgn = (CompositeGraphicsNode)gn;
187             Iterator JavaDoc iter = cgn.iterator();
188
189             while (iter.hasNext()) {
190                 GraphicsNode childGN = (GraphicsNode)iter.next();
191                 Rectangle2D JavaDoc r2d = getNodeDirtyRegion(childGN, at);
192                 if (r2d != null) {
193                     if ((ret == null) || (ret == NULL_RECT)) ret = r2d;
194                     else ret = ret.createUnion(r2d);
195                 }
196             }
197         } else {
198             ret = (Rectangle2D JavaDoc)fromBounds.remove(gnWRef);
199             if (ret == null)
200                 ret = gn.getBounds();
201             else if (ret == NULL_RECT)
202                 ret = null;
203             if (ret != null)
204                 ret = at.createTransformedShape(ret).getBounds2D();
205         }
206         return ret;
207     }
208
209     public Rectangle2D JavaDoc getNodeDirtyRegion(GraphicsNode gn) {
210         return getNodeDirtyRegion(gn, new AffineTransform JavaDoc());
211     }
212
213     /**
214      * Recieves notification of a change to a GraphicsNode.
215      * @param gnce The event object describing the GraphicsNode change.
216      */

217     public void changeStarted(GraphicsNodeChangeEvent gnce) {
218         // System.out.println("A node has changed for: " + this);
219
GraphicsNode gn = gnce.getGraphicsNode();
220         WeakReference JavaDoc gnWRef = gn.getWeakReference();
221
222         boolean doPut = false;
223         if (dirtyNodes == null) {
224             dirtyNodes = new HashMap JavaDoc();
225             doPut = true;
226         } else if (!dirtyNodes.containsKey(gnWRef))
227             doPut = true;
228
229         if (doPut) {
230             AffineTransform JavaDoc at = gn.getTransform();
231             if (at != null) at = (AffineTransform JavaDoc)at.clone();
232             else at = new AffineTransform JavaDoc();
233             dirtyNodes.put(gnWRef, at);
234         }
235
236         GraphicsNode chngSrc = gnce.getChangeSrc();
237         Rectangle2D JavaDoc rgn = null;
238         if (chngSrc != null) {
239             // A child node is moving in the tree so assign it's dirty
240
// regions to this node before it moves.
241
Rectangle2D JavaDoc drgn = getNodeDirtyRegion(chngSrc);
242             if (drgn != null)
243                 rgn = new ChngSrcRect(drgn);
244         } else {
245             // Otherwise just use gn's current region.
246
rgn = gn.getBounds();
247         }
248         // Add this dirty region to any existing dirty region.
249
Rectangle2D JavaDoc r2d = (Rectangle2D JavaDoc)fromBounds.remove(gnWRef);
250         if (rgn != null) {
251             if ((r2d != null) && (r2d != NULL_RECT)) {
252                 // System.err.println("GN: " + gn);
253
// System.err.println("R2d: " + r2d);
254
// System.err.println("Rgn: " + rgn);
255
r2d = r2d.createUnion(rgn);
256                 // System.err.println("Union: " + r2d);
257
}
258             else r2d = rgn;
259         }
260
261         // if ((gn instanceof CompositeGraphicsNode) &&
262
// (r2d.getWidth() > 200)) {
263
// new Exception("Adding Large: " + gn).printStackTrace();
264
// }
265

266         // Store the bounds for the future.
267
if (r2d == null)
268             r2d = NULL_RECT;
269         fromBounds.put(gnWRef, r2d);
270     }
271
272     class ChngSrcRect extends Rectangle2D.Float JavaDoc {
273         ChngSrcRect(Rectangle2D JavaDoc r2d) {
274             super((float)r2d.getX(), (float)r2d.getY(),
275                   (float)r2d.getWidth(), (float)r2d.getHeight());
276         }
277     }
278
279     /**
280      * Clears the tracker.
281      */

282     public void clear() {
283         dirtyNodes = null;
284     }
285 }
286
Popular Tags