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) {
883                 renderGVTTree();
884                 needRender = false;
885             } else {
886                 image = e.getImage();
887                 immediateRepaint();
888             }
889             if (eventDispatcher != null) {
890                 eventDispatcher.setEventDispatchEnabled(true);
891             }
892         }
893
894         /**
895          * Called when a rendering was cancelled.
896          */

897         public void gvtRenderingCancelled(GVTTreeRendererEvent e) {
898             renderingStopped();
899         }
900
901         /**
902          * Called when a rendering failed.
903          */

904         public void gvtRenderingFailed(GVTTreeRendererEvent e) {
905             renderingStopped();
906         }
907
908         /**
909          * The actual implementation of gvtRenderingCancelled() and
910          * gvtRenderingFailed().
911          */

912         private void renderingStopped() {
913             haltProgressivePaintThread();
914
915             if (doubleBufferedRendering) {
916                 suspendInteractions = false;
917             }
918
919             gvtTreeRenderer = null;
920             if (needRender) {
921                 renderGVTTree();
922                 needRender = false;
923             } else {
924                 immediateRepaint();
925             }
926
927             if (eventDispatcher != null) {
928                 eventDispatcher.setEventDispatchEnabled(true);
929             }
930         }
931
932         // KeyListener //////////////////////////////////////////////////////
933

934         /**
935          * Invoked when a key has been typed.
936          * This event occurs when a key press is followed by a key release.
937          */

938         public void keyTyped(KeyEvent JavaDoc e) {
939             selectInteractor(e);
940             if (interactor != null) {
941                 interactor.keyTyped(e);
942                 deselectInteractor();
943             } else if (eventDispatcher != null) {
944                 dispatchKeyTyped(e);
945             }
946         }
947
948         /**
949          * Dispatches the event to the GVT tree.
950          */

951         protected void dispatchKeyTyped(KeyEvent JavaDoc e) {
952             eventDispatcher.keyTyped(e);
953         }
954
955         /**
956          * Invoked when a key has been pressed.
957          */

958         public void keyPressed(KeyEvent JavaDoc e) {
959             selectInteractor(e);
960             if (interactor != null) {
961                 interactor.keyPressed(e);
962                 deselectInteractor();
963             } else if (eventDispatcher != null) {
964                 dispatchKeyPressed(e);
965             }
966         }
967
968         /**
969          * Dispatches the event to the GVT tree.
970          */

971         protected void dispatchKeyPressed(KeyEvent JavaDoc e) {
972             eventDispatcher.keyPressed(e);
973         }
974
975         /**
976          * Invoked when a key has been released.
977          */

978         public void keyReleased(KeyEvent JavaDoc e) {
979             selectInteractor(e);
980             if (interactor != null) {
981                 interactor.keyReleased(e);
982                 deselectInteractor();
983             } else if (eventDispatcher != null) {
984                 dispatchKeyReleased(e);
985             }
986         }
987
988         /**
989          * Dispatches the event to the GVT tree.
990          */

991         protected void dispatchKeyReleased(KeyEvent JavaDoc e) {
992             eventDispatcher.keyReleased(e);
993         }
994
995         // MouseListener ////////////////////////////////////////////////////
996

997         /**
998          * Invoked when the mouse has been clicked on a component.
999          */

1000        public void mouseClicked(MouseEvent JavaDoc e) {
1001            selectInteractor(e);
1002            if (interactor != null) {
1003                interactor.mouseClicked(e);
1004                deselectInteractor();
1005            } else if (eventDispatcher != null) {
1006                dispatchMouseClicked(e);
1007            }
1008        }
1009
1010        /**
1011         * Dispatches the event to the GVT tree.
1012         */

1013        protected void dispatchMouseClicked(MouseEvent JavaDoc e) {
1014            eventDispatcher.mouseClicked(e);
1015        }
1016
1017        /**
1018         * Invoked when a mouse button has been pressed on a component.
1019         */

1020        public void mousePressed(MouseEvent JavaDoc e) {
1021            startX = e.getX();
1022            startY = e.getY();
1023            startTime = System.currentTimeMillis();
1024            checkClick = true;
1025
1026            selectInteractor(e);
1027            if (interactor != null) {
1028                interactor.mousePressed(e);
1029                deselectInteractor();
1030            } else if (eventDispatcher != null) {
1031                dispatchMousePressed(e);
1032            }
1033        }
1034
1035        /**
1036         * Dispatches the event to the GVT tree.
1037         */

1038        protected void dispatchMousePressed(MouseEvent JavaDoc e) {
1039            eventDispatcher.mousePressed(e);
1040        }
1041
1042        /**
1043         * Invoked when a mouse button has been released on a component.
1044         */

1045        public void mouseReleased(java.awt.event.MouseEvent JavaDoc e) {
1046            if ((checkClick) && hadDrag) {
1047                int dx = startX-e.getX();
1048                int dy = startY-e.getY();
1049                long cTime = System.currentTimeMillis();
1050                if ((dx*dx+dy*dy < MAX_DISP) &&
1051                    (cTime-startTime) < CLICK_TIME) {
1052                    // our drag was short! dispatch a CLICK event.
1053
//
1054
MouseEvent JavaDoc click = new MouseEvent JavaDoc
1055                        (e.getComponent(),
1056                         MouseEvent.MOUSE_CLICKED,
1057                         e.getWhen(),
1058                         e.getModifiers(), // modifiers
1059
e.getX(),
1060                         e.getY(),
1061                         e.getClickCount(),
1062                         e.isPopupTrigger());
1063                            
1064                    mouseClicked(click);
1065                }
1066            }
1067            checkClick = false;
1068            hadDrag = false;
1069
1070            selectInteractor(e);
1071            if (interactor != null) {
1072                interactor.mouseReleased(e);
1073                deselectInteractor();
1074            } else if (eventDispatcher != null) {
1075                dispatchMouseReleased(e);
1076            }
1077        }
1078
1079        /**
1080         * Dispatches the event to the GVT tree.
1081         */

1082        protected void dispatchMouseReleased(MouseEvent JavaDoc e) {
1083            eventDispatcher.mouseReleased(e);
1084        }
1085
1086        /**
1087         * Invoked when the mouse enters a component.
1088         */

1089        public void mouseEntered(MouseEvent JavaDoc e) {
1090            // requestFocus(); // This would grab focus every time mouse enters!
1091
selectInteractor(e);
1092            if (interactor != null) {
1093                interactor.mouseEntered(e);
1094                deselectInteractor();
1095            } else if (eventDispatcher != null) {
1096                dispatchMouseEntered(e);
1097            }
1098        }
1099
1100        /**
1101         * Dispatches the event to the GVT tree.
1102         */

1103        protected void dispatchMouseEntered(MouseEvent JavaDoc e) {
1104            eventDispatcher.mouseEntered(e);
1105        }
1106
1107        /**
1108         * Invoked when the mouse exits a component.
1109         */

1110        public void mouseExited(MouseEvent JavaDoc e) {
1111            selectInteractor(e);
1112            if (interactor != null) {
1113                interactor.mouseExited(e);
1114                deselectInteractor();
1115            } else if (eventDispatcher != null) {
1116                dispatchMouseExited(e);
1117            }
1118        }
1119
1120        /**
1121         * Dispatches the event to the GVT tree.
1122         */

1123        protected void dispatchMouseExited(MouseEvent JavaDoc e) {
1124            eventDispatcher.mouseExited(e);
1125        }
1126
1127        // MouseMotionListener //////////////////////////////////////////////
1128

1129        /**
1130         * Invoked when a mouse button is pressed on a component and then
1131         * dragged. Mouse drag events will continue to be delivered to
1132         * the component where the first originated until the mouse button is
1133         * released (regardless of whether the mouse position is within the
1134         * bounds of the component).
1135         */

1136        public void mouseDragged(MouseEvent JavaDoc e) {
1137            hadDrag = true;
1138            int dx = startX-e.getX();
1139            int dy = startY-e.getY();
1140            if (dx*dx+dy*dy > MAX_DISP)
1141                checkClick = false;
1142
1143            selectInteractor(e);
1144            if (interactor != null) {
1145                interactor.mouseDragged(e);
1146                deselectInteractor();
1147            } else if (eventDispatcher != null) {
1148                dispatchMouseDragged(e);
1149            }
1150        }
1151
1152        /**
1153         * Dispatches the event to the GVT tree.
1154         */

1155        protected void dispatchMouseDragged(MouseEvent JavaDoc e) {
1156            eventDispatcher.mouseDragged(e);
1157        }
1158
1159        /**
1160         * Invoked when the mouse button has been moved on a component
1161         * (with no buttons no down).
1162         */

1163        public void mouseMoved(MouseEvent JavaDoc e) {
1164            selectInteractor(e);
1165            if (interactor != null) {
1166                interactor.mouseMoved(e);
1167                deselectInteractor();
1168            } else if (eventDispatcher != null) {
1169                dispatchMouseMoved(e);
1170            }
1171        }
1172
1173        /**
1174         * Dispatches the event to the GVT tree.
1175         */

1176        protected void dispatchMouseMoved(MouseEvent JavaDoc e) {
1177            eventDispatcher.mouseMoved(e);
1178        }
1179
1180        /**
1181         * Selects an interactor, given an input event.
1182         */

1183        protected void selectInteractor(InputEvent JavaDoc ie) {
1184            if (!disableInteractions &&
1185                !suspendInteractions &&
1186                interactor == null &&
1187                gvtRoot != null) {
1188                Iterator JavaDoc it = interactors.iterator();
1189                while (it.hasNext()) {
1190                    Interactor i = (Interactor)it.next();
1191                    if (i.startInteraction(ie)) {
1192                        interactor = i;
1193                        break;
1194                    }
1195                }
1196            }
1197        }
1198
1199        /**
1200         * Deselects an interactor, if the interaction has finished.
1201         */

1202        protected void deselectInteractor() {
1203            if (interactor.endInteraction()) {
1204                interactor = null;
1205            }
1206        }
1207    }
1208
1209    protected class UnixTextSelectionListener
1210        extends SelectionAdapter {
1211        
1212        public void selectionDone(SelectionEvent evt) {
1213            if (!useUnixTextSelection) return;
1214
1215            Object JavaDoc o = evt.getSelection();
1216            if (!(o instanceof CharacterIterator JavaDoc))
1217                return;
1218            CharacterIterator JavaDoc iter = (CharacterIterator JavaDoc) o;
1219
1220            // first see if we can access the clipboard
1221
SecurityManager JavaDoc securityManager;
1222            securityManager = System.getSecurityManager();
1223            if (securityManager != null) {
1224                try {
1225                    securityManager.checkSystemClipboardAccess();
1226                } catch (SecurityException JavaDoc e) {
1227                    return; // Can't access clipboard.
1228
}
1229            }
1230
1231            int sz = iter.getEndIndex()-iter.getBeginIndex();
1232            if (sz == 0) return;
1233
1234            char[] cbuff = new char[sz];
1235            cbuff[0] = iter.first();
1236            for (int i=1; i<cbuff.length;++i) {
1237                cbuff[i] = iter.next();
1238            }
1239            final String JavaDoc strSel = new String JavaDoc(cbuff);
1240            // HACK: getSystemClipboard sometimes deadlocks on
1241
// linux when called from the AWT Thread. The Thread
1242
// creation prevents that.
1243
new Thread JavaDoc() {
1244                public void run() {
1245                    Clipboard JavaDoc cb;
1246                    cb = Toolkit.getDefaultToolkit().getSystemClipboard();
1247                    StringSelection JavaDoc sel;
1248                    sel = new StringSelection JavaDoc(strSel);
1249                    cb.setContents(sel, sel);
1250                }
1251            }.start();
1252        }
1253    }
1254
1255
1256}
1257
Popular Tags