KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > batik > swing > gvt > JGVTComponent


1 /*
2
3    Copyright 2001-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.swing.gvt;
19
20 import java.awt.AlphaComposite JavaDoc;
21 import java.awt.Color JavaDoc;
22 import java.awt.Dimension JavaDoc;
23 import java.awt.EventQueue JavaDoc;
24 import java.awt.Graphics JavaDoc;
25 import java.awt.Graphics2D JavaDoc;
26 import java.awt.Rectangle JavaDoc;
27 import java.awt.RenderingHints JavaDoc;
28 import java.awt.Toolkit JavaDoc;
29 import java.awt.Shape JavaDoc;
30 import java.awt.datatransfer.Clipboard JavaDoc;
31 import java.awt.datatransfer.StringSelection JavaDoc;
32 import java.awt.event.ComponentAdapter JavaDoc;
33 import java.awt.event.ComponentEvent JavaDoc;
34 import java.awt.event.InputEvent JavaDoc;
35 import java.awt.event.KeyEvent JavaDoc;
36 import java.awt.event.KeyListener JavaDoc;
37 import java.awt.event.MouseEvent JavaDoc;
38 import java.awt.event.MouseListener JavaDoc;
39 import java.awt.event.MouseMotionListener JavaDoc;
40 import java.awt.geom.AffineTransform JavaDoc;
41 import java.awt.geom.NoninvertibleTransformException JavaDoc;
42 import java.awt.image.BufferedImage JavaDoc;
43 import java.text.CharacterIterator JavaDoc;
44 import java.util.Collections JavaDoc;
45 import java.util.Iterator JavaDoc;
46 import java.util.LinkedList JavaDoc;
47 import java.util.List JavaDoc;
48
49 import javax.swing.JComponent JavaDoc;
50
51 import org.apache.batik.gvt.GraphicsNode;
52 import org.apache.batik.gvt.event.AWTEventDispatcher;
53 import org.apache.batik.gvt.event.SelectionAdapter;
54 import org.apache.batik.gvt.event.SelectionEvent;
55 import org.apache.batik.gvt.renderer.ConcreteImageRendererFactory;
56 import org.apache.batik.gvt.renderer.ImageRenderer;
57 import org.apache.batik.gvt.renderer.ImageRendererFactory;
58 import org.apache.batik.gvt.text.Mark;
59 import org.apache.batik.util.HaltingThread;
60
61 /**
62  * This class represents a component which can display a GVT tree.
63  *
64  * @author <a HREF="mailto:stephane@hillion.org">Stephane Hillion</a>
65  * @version $Id: JGVTComponent.java,v 1.51 2005/03/27 08:58:36 cam Exp $
66  */

67 public class JGVTComponent extends JComponent JavaDoc {
68
69     /**
70      * The listener.
71      */

72     protected Listener JavaDoc listener;
73
74     /**
75      * The GVT tree renderer.
76      */

77     protected GVTTreeRenderer gvtTreeRenderer;
78
79     /**
80      * The GVT tree root.
81      */

82     protected GraphicsNode gvtRoot;
83
84     /**
85      * The renderer factory.
86      */

87     protected ImageRendererFactory rendererFactory =
88         new ConcreteImageRendererFactory();
89
90     /**
91      * The current renderer.
92      */

93     protected ImageRenderer renderer;
94
95     /**
96      * The GVT tree renderer listeners.
97      */

98     protected List JavaDoc gvtTreeRendererListeners =
99         Collections.synchronizedList(new LinkedList JavaDoc());
100
101     /**
102      * Whether a render was requested.
103      */

104     protected boolean needRender;
105
106     /**
107      * Whether to allow progressive paint.
108      */

109     protected boolean progressivePaint;
110
111     /**
112      * The progressive paint thread.
113      */

114     protected HaltingThread progressivePaintThread;
115
116     /**
117      * The image to paint.
118      */

119     protected BufferedImage JavaDoc image;
120
121     /**
122      * The initial rendering transform.
123      */

124     protected AffineTransform JavaDoc initialTransform = new AffineTransform JavaDoc();
125
126     /**
127      * The transform used for rendering.
128      */

129     protected AffineTransform JavaDoc renderingTransform = new AffineTransform JavaDoc();
130
131     /**
132      * The transform used for painting.
133      */

134     protected AffineTransform JavaDoc paintingTransform;
135
136     /**
137      * The interactor list.
138      */

139     protected List JavaDoc interactors = new LinkedList JavaDoc();
140
141     /**
142      * The current interactor.
143      */

144     protected Interactor interactor;
145
146     /**
147      * The overlays.
148      */

149     protected List JavaDoc overlays = new LinkedList JavaDoc();
150
151     /**
152      * The JGVTComponentListener list.
153      */

154     protected List JavaDoc jgvtListeners = null;
155
156     /**
157      * The event dispatcher.
158      */

159     protected AWTEventDispatcher eventDispatcher;
160
161     /**
162      * The text selection manager.
163      */

164     protected TextSelectionManager textSelectionManager;
165
166     /**
167      * Whether the double buffering is enabled.
168      */

169     protected boolean doubleBufferedRendering;
170
171     /**
172      * Whether the GVT tree should be reactive to mouse and key events.
173      */

174     protected boolean eventsEnabled;
175
176     /**
177      * Whether the text should be selectable if eventEnabled is false,
178      * this flag is ignored.
179      */

180     protected boolean selectableText;
181
182     /**
183      * Whether the JGVTComponent should adhere to 'Unix' text
184      * selection semantics where as soon as text is selected it
185      * is copied to the clipboard. If users want Mac/Windows
186      * behaviour they need to handle selections them selves.
187      */

188     protected boolean useUnixTextSelection = true;
189
190     /**
191      * Whether to suspend interactions.
192      */

193     protected boolean suspendInteractions;
194
195     /**
196      * Whether to unconditionally disable interactions.
197      */

198     protected boolean disableInteractions;
199
200     /**
201      * Creates a new JGVTComponent.
202      */

203     public JGVTComponent() {
204         this(false, false);
205     }
206
207     /**
208      * Creates a new JGVTComponent.
209      * @param eventsEnabled Whether the GVT tree should be reactive
210      * to mouse and key events.
211      * @param selectableText Whether the text should be selectable.
212      * if eventEnabled is false, this flag is ignored.
213      */

214     public JGVTComponent(boolean eventsEnabled, boolean selectableText) {
215         setBackground(Color.white);
216         // setDoubleBuffered(false);
217

218         this.eventsEnabled = eventsEnabled;
219         this.selectableText = selectableText;
220
221         listener = createListener();
222
223         addKeyListener(listener);
224         addMouseListener(listener);
225         addMouseMotionListener(listener);
226
227         addGVTTreeRendererListener(listener);
228
229         addComponentListener(new ComponentAdapter JavaDoc() {
230                 public void componentResized(ComponentEvent JavaDoc e) {
231                     if (updateRenderingTransform())
232                         scheduleGVTRendering();
233                 }
234             });
235
236     }
237
238     /**
239      * Turn off all 'interactor' objects (pan, zoom, etc) if
240      * 'b' is true, turn them on if 'b' is false.
241      */

242     public void setDisableInteractions(boolean b) {
243         disableInteractions = b;
244     }
245
246     /**
247      * Returns true if all 'interactor' objects
248      * (pan, zoom, etc) are disabled.
249      */

250     public boolean getDisableInteractions() {
251         return disableInteractions;
252     }
253
254     /**
255      * If 'b' is true text selections will copied to
256      * the clipboard immediately. If 'b' is false
257      * then nothing will be done when selections are
258      * made (the application is responsable for copying
259      * the selection in response to user actions).
260      */

261     public void setUseUnixTextSelection(boolean b) {
262         useUnixTextSelection = b;
263     }
264
265     /**
266      * Returns true if the canvas will copy selections
267      * to the clipboard when they are completed.
268      */

269     public void getUseUnixTextSelection(boolean b) {
270         useUnixTextSelection = b;
271     }
272
273     /**
274      * Returns the interactor list.
275      */

276     public List JavaDoc getInteractors() {
277         return interactors;
278     }
279
280     /**
281      * Returns the overlay list.
282      */

283     public List JavaDoc getOverlays() {
284         return overlays;
285     }
286
287     /**
288      * Returns the off-screen image, if any.
289      */

290     public BufferedImage JavaDoc getOffScreen() {
291         return image;
292     }
293
294
295     public void addJGVTComponentListener(JGVTComponentListener listener) {
296         if (jgvtListeners == null)
297             jgvtListeners = new LinkedList JavaDoc();
298         jgvtListeners.add(listener);
299     }
300
301     public void removeJGVTComponentListener(JGVTComponentListener listener) {
302         if (jgvtListeners == null) return;
303         jgvtListeners.remove(listener);
304     }
305
306     /**
307      * Resets the rendering transform to its initial value.
308      */

309     public void resetRenderingTransform() {
310         setRenderingTransform(initialTransform);
311     }
312
313     /**
314      * Stops the processing of the current tree.
315      */

316     public void stopProcessing() {
317         if (gvtTreeRenderer != null) {
318             needRender = false;
319             gvtTreeRenderer.halt();
320             haltProgressivePaintThread();
321         }
322     }
323
324     /**
325      * Returns the root of the GVT tree displayed by this component, if any.
326      */

327     public GraphicsNode getGraphicsNode() {
328         return gvtRoot;
329     }
330
331     /**
332      * Sets the GVT tree to display.
333      */

334     public void setGraphicsNode(GraphicsNode gn) {
335         setGraphicsNode(gn, true);
336         initialTransform = new AffineTransform JavaDoc();
337         updateRenderingTransform();
338         setRenderingTransform(initialTransform, true);
339     }
340
341     /**
342      * Sets the GVT tree to display.
343      */

344     protected void setGraphicsNode(GraphicsNode gn, boolean createDispatcher) {
345         gvtRoot = gn;
346         if (gn != null && createDispatcher) {
347             initializeEventHandling();
348         }
349         if (eventDispatcher != null) {
350             eventDispatcher.setRootNode(gn);
351         }
352     }
353
354     /**
355      * Initializes the event handling classes.
356      */

357     protected void initializeEventHandling() {
358         if (eventsEnabled) {
359             eventDispatcher = new AWTEventDispatcher();
360             if (selectableText) {
361                 textSelectionManager = createTextSelectionManager();
362                 textSelectionManager.addSelectionListener
363                     (new UnixTextSelectionListener());
364             }
365         }
366     }
367
368     /**
369      * Creates the TextSelectionManager to be used by this
370      * JGVTComponent. Subclasses may override to provide a
371      * custom subclass.
372      */

373     protected TextSelectionManager createTextSelectionManager() {
374         return new TextSelectionManager(this, eventDispatcher);
375     }
376
377     ////////////////////////////////////////////////////////////////////////
378
// Selection methods
379
////////////////////////////////////////////////////////////////////////
380

381     /**
382      * Returns the current Text selection manager for the Component.
383      * Users can register with this to be notifed of changes in
384      * the text selection.
385      */

386     public TextSelectionManager getTextSelectionManager() {
387         return textSelectionManager;
388     }
389
390     /**
391      * Sets the color of the selection overlay to the specified color.
392      *
393      * @param color the new color of the selection overlay
394      */

395     public void setSelectionOverlayColor(Color JavaDoc color) {
396         if (textSelectionManager != null) {
397             textSelectionManager.setSelectionOverlayColor(color);
398         }
399     }
400
401     /**
402      * Returns the color of the selection overlay.
403      */

404     public Color JavaDoc getSelectionOverlayColor() {
405         if (textSelectionManager != null) {
406             return textSelectionManager.getSelectionOverlayColor();
407         } else {
408             return null;
409         }
410     }
411
412     /**
413      * Sets the color of the outline of the selection overlay to the specified
414      * color.
415      *
416      * @param color the new color of the outline of the selection overlay
417      */

418     public void setSelectionOverlayStrokeColor(Color JavaDoc color) {
419         if (textSelectionManager != null) {
420             textSelectionManager.setSelectionOverlayStrokeColor(color);
421         }
422     }
423
424     /**
425      * Returns the color of the outline of the selection overlay.
426      */

427     public Color JavaDoc getSelectionOverlayStrokeColor() {
428         if (textSelectionManager != null) {
429             return textSelectionManager.getSelectionOverlayStrokeColor();
430         } else {
431             return null;
432         }
433     }
434
435     /**
436      * Sets whether or not the selection overlay will be painted in XOR mode,
437      * depending on the specified parameter.
438      *
439      * @param state true implies the selection overlay will be in XOR mode
440      */

441     public void setSelectionOverlayXORMode(boolean state) {
442         if (textSelectionManager != null) {
443             textSelectionManager.setSelectionOverlayXORMode(state);
444         }
445     }
446
447     /**
448      * Returns true if the selection overlay is painted in XOR mode, false
449      * otherwise.
450      */

451     public boolean isSelectionOverlayXORMode() {
452         if (textSelectionManager != null) {
453             return textSelectionManager.isSelectionOverlayXORMode();
454         } else {
455             return false;
456         }
457     }
458
459     /**
460      * Sets the selection to the specified start and end mark.
461      *
462      * @param start the mark used to define where the selection starts
463      * @param end the mark used to define where the selection ends
464      */

465     public void select(Mark start, Mark end) {
466         if (textSelectionManager != null) {
467             textSelectionManager.setSelection(start, end);
468         }
469     }
470
471     /**
472      * Deselects all.
473      */

474     public void deselectAll() {
475         if (textSelectionManager != null) {
476             textSelectionManager.clearSelection();
477         }
478     }
479
480     ////////////////////////////////////////////////////////////////////////
481
// Painting methods
482
////////////////////////////////////////////////////////////////////////
483

484     /**
485      * Whether to enable the progressive paint.
486      */

487     public void setProgressivePaint(boolean b) {
488         if (progressivePaint != b) {
489             progressivePaint = b;
490             haltProgressivePaintThread();
491         }
492     }
493
494     /**
495      * Tells whether the progressive paint is enabled.
496      */

497     public boolean getProgressivePaint() {
498         return progressivePaint;
499     }
500
501     public Rectangle JavaDoc getRenderRect() {
502         Dimension JavaDoc d = getSize();
503         return new Rectangle JavaDoc(0, 0, d.width, d.height);
504     }
505
506     /**
507      * Repaints immediately the component.
508      */

509     public void immediateRepaint() {
510         if (EventQueue.isDispatchThread()) {
511             Rectangle JavaDoc visRect = getRenderRect();
512             if (doubleBufferedRendering)
513                 repaint(visRect.x, visRect.y,
514                         visRect.width, visRect.height);
515             else
516                 paintImmediately(visRect.x, visRect.y,
517                                  visRect.width, visRect.height);
518         } else {
519             try {
520                 EventQueue.invokeAndWait(new Runnable JavaDoc() {
521                         public void run() {
522                             Rectangle JavaDoc visRect = getRenderRect();
523                             if (doubleBufferedRendering)
524                                 repaint(visRect.x, visRect.y,
525                                         visRect.width, visRect.height);
526                             else
527                                 paintImmediately(visRect.x, visRect.y,
528                                                  visRect.width,visRect.height);
529                         }
530                     });
531             } catch (Exception JavaDoc e) {
532             }
533         }
534     }
535
536     /**
537      * Paints this component.
538      */

539     public void paintComponent(Graphics JavaDoc g) {
540         super.paintComponent(g);
541
542         Graphics2D JavaDoc g2d = (Graphics2D JavaDoc)g;
543
544         Rectangle JavaDoc visRect = getRenderRect();
545         g2d.setComposite(AlphaComposite.SrcOver);
546         g2d.setPaint(getBackground());
547         g2d.fillRect(visRect.x, visRect.y,
548                      visRect.width, visRect.height);
549
550         if (image != null) {
551             if (paintingTransform != null) {
552                 g2d.transform(paintingTransform);
553             }
554             g2d.drawRenderedImage(image, null);
555             g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
556                                  RenderingHints.VALUE_ANTIALIAS_OFF);
557             Iterator JavaDoc it = overlays.iterator();
558             while (it.hasNext()) {
559                 ((Overlay)it.next()).paint(g);
560             }
561         }
562     }
563
564     /**
565      * Sets the painting transform. A null transform is the same as
566      * an identity transform.
567      * The next repaint will use the given transform.
568      */

569     public void setPaintingTransform(AffineTransform JavaDoc at) {
570         paintingTransform = at;
571         immediateRepaint();
572     }
573
574     /**
575      * Returns the current painting transform.
576      */

577     public AffineTransform JavaDoc getPaintingTransform() {
578         return paintingTransform;
579     }
580
581     /**
582      * Sets the rendering transform.
583      * Calling this method causes a rendering to be performed.
584      */

585     public void setRenderingTransform(AffineTransform JavaDoc at) {
586         setRenderingTransform(at, true);
587     }
588
589     public void setRenderingTransform(AffineTransform JavaDoc at,
590                                       boolean performRedraw) {
591         renderingTransform = at;
592         suspendInteractions = true;
593         if (eventDispatcher != null) {
594             try {
595                 eventDispatcher.setBaseTransform
596                     (renderingTransform.createInverse());
597             } catch (NoninvertibleTransformException JavaDoc e) {
598                 handleException(e);
599             }
600         }
601         if (jgvtListeners != null) {
602             Iterator JavaDoc iter = jgvtListeners.iterator();
603             ComponentEvent JavaDoc ce = new ComponentEvent JavaDoc
604                 (this, JGVTComponentListener.COMPONENT_TRANSFORM_CHANGED);
605             while (iter.hasNext()) {
606                 JGVTComponentListener l = (JGVTComponentListener)iter.next();
607                 l.componentTransformChanged(ce);
608             }
609         }
610
611         if (performRedraw)
612             scheduleGVTRendering();
613     }
614
615     /**
616      * Returns the initial transform.
617      */

618     public AffineTransform JavaDoc getInitialTransform() {
619         return initialTransform;
620     }
621
622     /**
623      * Returns the current rendering transform.
624      */

625     public AffineTransform JavaDoc getRenderingTransform() {
626         return renderingTransform;
627     }
628
629     /**
630      * Sets whether this component should use double buffering to render
631      * SVG documents. The change will be effective during the next
632      * rendering.
633      */

634     public void setDoubleBufferedRendering(boolean b) {
635         doubleBufferedRendering = b;
636     }
637
638     /**
639      * Tells whether this component use double buffering to render
640      * SVG documents.
641      */

642     public boolean getDoubleBufferedRendering() {
643         return doubleBufferedRendering;
644     }
645
646     /**
647      * Adds a GVTTreeRendererListener to this component.
648      */

649     public void addGVTTreeRendererListener(GVTTreeRendererListener l) {
650         gvtTreeRendererListeners.add(l);
651     }
652
653     /**
654      * Removes a GVTTreeRendererListener from this component.
655      */

656     public void removeGVTTreeRendererListener(GVTTreeRendererListener l) {
657         gvtTreeRendererListeners.remove(l);
658     }
659
660     /**
661      * Flush any cached image data (preliminary interface,
662      * may be removed or modified in the future).
663      */

664     public void flush() {
665         renderer.flush();
666     }
667
668     /**
669      * Flush a rectangle of cached image data (preliminary interface,
670      * may be removed or modified in the future).
671      */

672     public void flush(Rectangle JavaDoc r) {
673         renderer.flush(r);
674     }
675
676     /**
677      * Creates a new renderer.
678      */

679     protected ImageRenderer createImageRenderer() {
680         return rendererFactory.createStaticImageRenderer();
681     }
682
683     /**
684      * Renders the GVT tree.
685      */

686     protected void renderGVTTree() {
687         Rectangle JavaDoc visRect = getRenderRect();
688         if (gvtRoot == null || visRect.width <= 0 || visRect.height <= 0) {
689             return;
690         }
691
692         // Renderer setup.
693
if (renderer == null || renderer.getTree() != gvtRoot) {
694             renderer = createImageRenderer();
695             renderer.setTree(gvtRoot);
696         }
697
698         // Area of interest computation.
699
AffineTransform JavaDoc inv;
700         try {
701             inv = renderingTransform.createInverse();
702         } catch (NoninvertibleTransformException JavaDoc e) {
703             throw new InternalError JavaDoc(e.getMessage());
704         }
705         Shape JavaDoc s = inv.createTransformedShape(visRect);
706
707         // Rendering thread setup.
708
gvtTreeRenderer = new GVTTreeRenderer(renderer, renderingTransform,
709                                               doubleBufferedRendering, s,
710                                               visRect.width, visRect.height);
711         gvtTreeRenderer.setPriority(Thread.MIN_PRIORITY);
712
713         Iterator JavaDoc it = gvtTreeRendererListeners.iterator();
714         while (it.hasNext()) {
715             gvtTreeRenderer.addGVTTreeRendererListener
716                 ((GVTTreeRendererListener)it.next());
717         }
718
719         // Disable the dispatch during the rendering
720
// to avoid concurrent access to the GVT tree.
721
if (eventDispatcher != null) {
722             eventDispatcher.setEventDispatchEnabled(false);
723         }
724
725         gvtTreeRenderer.start();
726     }
727
728     /**
729      * Computes the initial value of the transform used for rendering.
730      * Return true if a repaint is required, otherwise false.
731      */

732     protected boolean computeRenderingTransform() {
733         initialTransform = new AffineTransform JavaDoc();
734         if (!initialTransform.equals(renderingTransform)) {
735             setRenderingTransform(initialTransform, false);
736             return true;
737         }
738         return false;
739     }
740
741     /**
742      * Updates the value of the transform used for rendering.
743      * Return true if a repaint is required, otherwise false.
744      */

745     protected boolean updateRenderingTransform() {
746         // Do nothing.
747
return false;
748     }
749
750     /**
751      * Handles an exception.
752      */

753     protected void handleException(Exception JavaDoc e) {
754         // Do nothing.
755
}
756
757     /**
758      * Releases the references to the rendering resources,
759      */

760     protected void releaseRenderingReferences() {
761         eventDispatcher = null;
762         if (textSelectionManager != null) {
763             overlays.remove(textSelectionManager.getSelectionOverlay());
764             textSelectionManager = null;
765         }
766         renderer = null;
767         image = null;
768         gvtRoot = null;
769     }
770
771     /**
772      * Schedules a new GVT rendering.
773      */

774     protected void scheduleGVTRendering() {
775         if (gvtTreeRenderer != null) {
776             needRender = true;
777             gvtTreeRenderer.halt();
778         } else {
779             renderGVTTree();
780         }
781     }
782
783     private void haltProgressivePaintThread() {
784         if (progressivePaintThread != null) {
785             progressivePaintThread.halt();
786             progressivePaintThread = null;
787         }
788     }
789
790     /**
791      * Creates an instance of Listener.
792      */

793     protected Listener JavaDoc createListener() {
794         return new Listener JavaDoc();
795     }
796
797     /**
798      * To hide the listener methods.
799      */

800     protected class Listener
801         implements GVTTreeRendererListener,
802                    KeyListener JavaDoc,
803                    MouseListener JavaDoc,
804                    MouseMotionListener JavaDoc {
805         boolean checkClick = false;
806         boolean hadDrag = false;
807         int startX, startY;
808         long startTime;
809         int MAX_DISP = 4*4;
810         long CLICK_TIME = 200;
811
812         /**
813          * Creates a new Listener.
814          */

815         protected Listener() {
816         }
817
818         // GVTTreeRendererListener ///////////////////////////////////////////
819

820         /**
821          * Called when a rendering is in its preparing phase.
822          */

823         public void gvtRenderingPrepare(GVTTreeRendererEvent e) {
824             suspendInteractions = true;
825             if (!progressivePaint && !doubleBufferedRendering) {
826                 image = null;
827             }
828         }
829
830         /**
831          * Called when a rendering started.
832          */

833         public void gvtRenderingStarted(GVTTreeRendererEvent e) {
834             if (progressivePaint && !doubleBufferedRendering) {
835                 image = e.getImage();
836                 progressivePaintThread = new HaltingThread() {
837                     public void run() {
838                         final Thread JavaDoc thisThread = this;
839                         try {
840                             while (!hasBeenHalted()) {
841                                 EventQueue.invokeLater(new Runnable JavaDoc() {
842                                     public void run() {
843                                         if (progressivePaintThread ==
844                                             thisThread) {
845                                             Rectangle JavaDoc vRect = getRenderRect();
846                                             repaint(vRect.x, vRect.y,
847                                                     vRect.width, vRect.height);
848                                         }
849                                     }
850                                 });
851                                 sleep(200);
852                             }
853                         } catch (InterruptedException JavaDoc ie) {
854                         } catch (ThreadDeath JavaDoc td) {
855                             throw td;
856                         } catch (Throwable JavaDoc t) {
857                             t.printStackTrace();
858                         }
859                     }
860                 };
861                 progressivePaintThread.setPriority(Thread.MIN_PRIORITY + 1);
862                 progressivePaintThread.start();
863             }
864             if (!doubleBufferedRendering) {
865                 paintingTransform = null;
866                 suspendInteractions = false;
867             }
868         }
869
870         /**
871          * Called when a rendering was completed.
872          */

873         public void gvtRenderingCompleted(GVTTreeRendererEvent e) {
874             haltProgressivePaintThread();
875
876             if (doubleBufferedRendering) {
877                 paintingTransform = null;
878                 suspendInteractions = false;
879             }
880
881             gvtTreeRenderer = null;
882             if (needRender) {