KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > swing > SwingUtilities


1 /*
2  * @(#)SwingUtilities.java 1.134 04/06/15
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7 package javax.swing;
8
9 import com.sun.java.swing.SwingUtilities2;
10 import sun.swing.UIAction;
11
12 import java.applet.*;
13
14 import java.awt.*;
15 import java.awt.event.*;
16
17 import java.util.Vector JavaDoc;
18 import java.util.Hashtable JavaDoc;
19
20 import java.lang.reflect.*;
21
22 import javax.accessibility.*;
23 import javax.swing.event.MenuDragMouseEvent JavaDoc;
24 import javax.swing.plaf.UIResource JavaDoc;
25 import javax.swing.text.View JavaDoc;
26
27 import sun.awt.AppContext;
28
29 /**
30  * A collection of utility methods for Swing.
31  *
32  * @version 1.134 06/15/04
33  * @author unknown
34  */

35 public class SwingUtilities implements SwingConstants JavaDoc
36 {
37     // These states are system-wide, rather than AppContext wide.
38
private static boolean canAccessEventQueue = false;
39     private static boolean eventQueueTested = false;
40
41
42     /**
43      * Return true if <code>a</code> contains <code>b</code>
44      */

45     public static final boolean isRectangleContainingRectangle(Rectangle a,Rectangle b) {
46         if (b.x >= a.x && (b.x + b.width) <= (a.x + a.width) &&
47             b.y >= a.y && (b.y + b.height) <= (a.y + a.height)) {
48             return true;
49         }
50         return false;
51     }
52
53     /**
54      * Return the rectangle (0,0,bounds.width,bounds.height) for the component <code>aComponent</code>
55      */

56     public static Rectangle getLocalBounds(Component aComponent) {
57         Rectangle b = new Rectangle(aComponent.getBounds());
58         b.x = b.y = 0;
59         return b;
60     }
61
62
63     /**
64      * Returns the first <code>Window </code> ancestor of <code>c</code>, or
65      * null if <code>c</code> is not contained inside a <code>Window</code>.
66      *
67      * @param c <code>Component</code> to get <code>Window</code> ancestor
68      * of.
69      * @return the first <code>Window </code> ancestor of <code>c</code>, or
70      * null if <code>c</code> is not contained inside a
71      * <code>Window</code>.
72      */

73     public static Window getWindowAncestor(Component c) {
74         for(Container p = c.getParent(); p != null; p = p.getParent()) {
75             if (p instanceof Window) {
76                 return (Window)p;
77             }
78         }
79         return null;
80     }
81
82     /**
83      * Converts the location <code>x</code> <code>y</code> to the
84      * parents coordinate system, returning the location.
85      */

86     static Point convertScreenLocationToParent(Container parent,int x, int y) {
87         for (Container p = parent; p != null; p = p.getParent()) {
88             if (p instanceof Window) {
89                 Point point = new Point(x, y);
90
91                 SwingUtilities.convertPointFromScreen(point, parent);
92                 return point;
93             }
94         }
95         throw new Error JavaDoc("convertScreenLocationToParent: no window ancestor");
96     }
97
98     /**
99      * Convert a <code>aPoint</code> in <code>source</code> coordinate system to
100      * <code>destination</code> coordinate system.
101      * If <code>source></code>is null,<code>aPoint</code> is assumed to be in <code>destination</code>'s
102      * root component coordinate system.
103      * If <code>destination</code>is null, <code>aPoint</code> will be converted to <code>source</code>'s
104      * root component coordinate system.
105      * If both <code>source</code> and <code>destination</code> are null, return <code>aPoint</code>
106      * without any conversion.
107      */

108     public static Point convertPoint(Component source,Point aPoint,Component destination) {
109         Point p;
110
111         if(source == null && destination == null)
112             return aPoint;
113         if(source == null) {
114             source = getWindowAncestor(destination);
115             if(source == null)
116                 throw new Error JavaDoc("Source component not connected to component tree hierarchy");
117         }
118         p = new Point(aPoint);
119         convertPointToScreen(p,source);
120         if(destination == null) {
121             destination = getWindowAncestor(source);
122             if(destination == null)
123                 throw new Error JavaDoc("Destination component not connected to component tree hierarchy");
124         }
125         convertPointFromScreen(p,destination);
126         return p;
127     }
128
129     /**
130      * Convert the point <code>(x,y)</code> in <code>source</code> coordinate system to
131      * <code>destination</code> coordinate system.
132      * If <code>source></code>is null,<code>(x,y)</code> is assumed to be in <code>destination</code>'s
133      * root component coordinate system.
134      * If <code>destination</code>is null, <code>(x,y)</code> will be converted to <code>source</code>'s
135      * root component coordinate system.
136      * If both <code>source</code> and <code>destination</code> are null, return <code>(x,y)</code>
137      * without any conversion.
138      */

139     public static Point convertPoint(Component source,int x, int y,Component destination) {
140         Point point = new Point(x,y);
141         return convertPoint(source,point,destination);
142     }
143
144     /**
145      * Convert the rectangle <code>aRectangle</code> in <code>source</code> coordinate system to
146      * <code>destination</code> coordinate system.
147      * If <code>source></code>is null,<code>aRectangle</code> is assumed to be in <code>destination</code>'s
148      * root component coordinate system.
149      * If <code>destination</code>is null, <code>aRectangle</code> will be converted to <code>source</code>'s
150      * root component coordinate system.
151      * If both <code>source</code> and <code>destination</code> are null, return <code>aRectangle</code>
152      * without any conversion.
153      */

154     public static Rectangle convertRectangle(Component source,Rectangle aRectangle,Component destination) {
155         Point point = new Point(aRectangle.x,aRectangle.y);
156         point = convertPoint(source,point,destination);
157         return new Rectangle(point.x,point.y,aRectangle.width,aRectangle.height);
158     }
159
160     /**
161      * Convenience method for searching above <code>comp</code> in the
162      * component hierarchy and returns the first object of class <code>c</code> it
163      * finds. Can return null, if a class <code>c</code> cannot be found.
164      */

165     public static Container getAncestorOfClass(Class JavaDoc<?> c, Component comp)
166     {
167         if(comp == null || c == null)
168             return null;
169
170         Container parent = comp.getParent();
171         while(parent != null && !(c.isInstance(parent)))
172             parent = parent.getParent();
173         return parent;
174     }
175
176     /**
177      * Convenience method for searching above <code>comp</code> in the
178      * component hierarchy and returns the first object of <code>name</code> it
179      * finds. Can return null, if <code>name</code> cannot be found.
180      */

181     public static Container getAncestorNamed(String JavaDoc name, Component comp) {
182         if(comp == null || name == null)
183             return null;
184
185         Container parent = comp.getParent();
186         while(parent != null && !(name.equals(parent.getName())))
187             parent = parent.getParent();
188         return parent;
189     }
190
191     /**
192      * Returns the deepest visible descendent Component of <code>parent</code>
193      * that contains the location <code>x</code>, <code>y</code>.
194      * If <code>parent</code> does not contain the specified location,
195      * then <code>null</code> is returned. If <code>parent</code> is not a
196      * container, or none of <code>parent</code>'s visible descendents
197      * contain the specified location, <code>parent</code> is returned.
198      *
199      * @param parent the root component to begin the search
200      * @param x the x target location
201      * @param y the y target location
202      */

203     public static Component getDeepestComponentAt(Component parent, int x, int y) {
204         if (!parent.contains(x, y)) {
205             return null;
206         }
207         if (parent instanceof Container) {
208             Component components[] = ((Container)parent).getComponents();
209             for (int i = 0 ; i < components.length ; i++) {
210                 Component comp = components[i];
211                 if (comp != null && comp.isVisible()) {
212                     Point loc = comp.getLocation();
213                     if (comp instanceof Container) {
214                         comp = getDeepestComponentAt(comp, x - loc.x, y - loc.y);
215                     } else {
216                         comp = comp.getComponentAt(x - loc.x, y - loc.y);
217                     }
218                     if (comp != null && comp.isVisible()) {
219                         return comp;
220                     }
221                 }
222             }
223         }
224         return parent;
225     }
226
227
228     /**
229      * Returns a MouseEvent similar to <code>sourceEvent</code> except that its x
230      * and y members have been converted to <code>destination</code>'s coordinate
231      * system. If <code>source</code> is null, <code>sourceEvent</code> x and y members
232      * are assumed to be into <code>destination</code>'s root component coordinate system.
233      * If <code>destination</code> is <code>null</code>, the
234      * returned MouseEvent will be in <code>source</code>'s coordinate system.
235      * <code>sourceEvent</code> will not be changed. A new event is returned.
236      * the <code>source</code> field of the returned event will be set
237      * to <code>destination</code> if destination is non null
238      * use the translateMouseEvent() method to translate a mouse event from
239      * one component to another without changing the source.
240      */

241     public static MouseEvent JavaDoc convertMouseEvent(Component source,
242                                                MouseEvent JavaDoc sourceEvent,
243                                                Component destination) {
244         Point p = convertPoint(source,new Point(sourceEvent.getX(),
245                                                 sourceEvent.getY()),
246                                destination);
247         Component newSource;
248
249         if(destination != null)
250             newSource = destination;
251         else
252             newSource = source;
253
254     MouseEvent JavaDoc newEvent;
255     if (sourceEvent instanceof MouseWheelEvent) {
256         MouseWheelEvent sourceWheelEvent = (MouseWheelEvent)sourceEvent;
257         newEvent = new MouseWheelEvent(newSource,
258                        sourceWheelEvent.getID(),
259                        sourceWheelEvent.getWhen(),
260                        sourceWheelEvent.getModifiers(),
261                        p.x,p.y,
262                        sourceWheelEvent.getClickCount(),
263                        sourceWheelEvent.isPopupTrigger(),
264                        sourceWheelEvent.getScrollType(),
265                        sourceWheelEvent.getScrollAmount(),
266                        sourceWheelEvent.getWheelRotation());
267     }
268     else if (sourceEvent instanceof MenuDragMouseEvent JavaDoc) {
269         MenuDragMouseEvent JavaDoc sourceMenuDragEvent = (MenuDragMouseEvent JavaDoc)sourceEvent;
270         newEvent = new MenuDragMouseEvent JavaDoc(newSource,
271                           sourceMenuDragEvent.getID(),
272                           sourceMenuDragEvent.getWhen(),
273                           sourceMenuDragEvent.getModifiers(),
274                           p.x,p.y,
275                           sourceMenuDragEvent.getClickCount(),
276                           sourceMenuDragEvent.isPopupTrigger(),
277                           sourceMenuDragEvent.getPath(),
278                           sourceMenuDragEvent.getMenuSelectionManager());
279     }
280     else {
281         newEvent = new MouseEvent JavaDoc(newSource,
282                       sourceEvent.getID(),
283                       sourceEvent.getWhen(),
284                       sourceEvent.getModifiers(),
285                       p.x,p.y,
286                       sourceEvent.getClickCount(),
287                       sourceEvent.isPopupTrigger());
288     }
289     return newEvent;
290     }
291
292
293     /**
294      * Convert a point from a component's coordinate system to
295      * screen coordinates.
296      *
297      * @param p a Point object (converted to the new coordinate system)
298      * @param c a Component object
299      */

300     public static void convertPointToScreen(Point p,Component c) {
301             Rectangle b;
302             int x,y;
303
304             do {
305                 if(c instanceof JComponent JavaDoc) {
306                     x = ((JComponent JavaDoc)c).getX();
307                     y = ((JComponent JavaDoc)c).getY();
308                 } else if(c instanceof java.applet.Applet JavaDoc ||
309                           c instanceof java.awt.Window JavaDoc) {
310                     try {
311                         Point pp = c.getLocationOnScreen();
312                         x = pp.x;
313                         y = pp.y;
314                     } catch (IllegalComponentStateException icse) {
315             x = c.getX();
316             y = c.getY();
317                     }
318                 } else {
319                     x = c.getX();
320                     y = c.getY();
321                 }
322
323                 p.x += x;
324                 p.y += y;
325
326                 if(c instanceof java.awt.Window JavaDoc || c instanceof java.applet.Applet JavaDoc)
327                     break;
328                 c = c.getParent();
329             } while(c != null);
330         }
331
332     /**
333      * Convert a point from a screen coordinates to a component's
334      * coordinate system
335      *
336      * @param p a Point object (converted to the new coordinate system)
337      * @param c a Component object
338      */

339     public static void convertPointFromScreen(Point p,Component c) {
340         Rectangle b;
341         int x,y;
342
343         do {
344             if(c instanceof JComponent JavaDoc) {
345                 x = ((JComponent JavaDoc)c).getX();
346                 y = ((JComponent JavaDoc)c).getY();
347             } else if(c instanceof java.applet.Applet JavaDoc ||
348                        c instanceof java.awt.Window JavaDoc) {
349                 try {
350                     Point pp = c.getLocationOnScreen();
351                     x = pp.x;
352                     y = pp.y;
353                 } catch (IllegalComponentStateException icse) {
354             x = c.getX();
355             y = c.getY();
356                 }
357             } else {
358         x = c.getX();
359         y = c.getY();
360             }
361
362             p.x -= x;
363             p.y -= y;
364
365             if(c instanceof java.awt.Window JavaDoc || c instanceof java.applet.Applet JavaDoc)
366                 break;
367             c = c.getParent();
368         } while(c != null);
369     }
370
371     /**
372      * Returns the first <code>Window </code> ancestor of <code>c</code>, or
373      * null if <code>c</code> is not contained inside a <code>Window</code>.
374      * <p>
375      * Note: This method provides the same functionality as
376      * <code>getWindowAncestor</code>.
377      *
378      * @param c <code>Component</code> to get <code>Window</code> ancestor
379      * of.
380      * @return the first <code>Window </code> ancestor of <code>c</code>, or
381      * null if <code>c</code> is not contained inside a
382      * <code>Window</code>.
383      */

384     public static Window windowForComponent(Component c) {
385         return getWindowAncestor(c);
386     }
387
388     /**
389      * Return <code>true</code> if a component <code>a</code> descends from a component <code>b</code>
390      */

391     public static boolean isDescendingFrom(Component a,Component b) {
392         if(a == b)
393             return true;
394         for(Container p = a.getParent();p!=null;p=p.getParent())
395             if(p == b)
396                 return true;
397         return false;
398     }
399
400
401     /**
402      * Convenience to calculate the intersection of two rectangles
403      * without allocating a new rectangle.
404      * If the two rectangles don't intersect,
405      * then the returned rectangle begins at (0,0)
406      * and has zero width and height.
407      *
408      * @param x the X coordinate of the first rectangle's top-left point
409      * @param y the Y coordinate of the first rectangle's top-left point
410      * @param width the width of the first rectangle
411      * @param height the height of the first rectangle
412      * @param dest the second rectangle
413      *
414      * @return <code>dest</code>, modified to specify the intersection
415      */

416     public static Rectangle computeIntersection(int x,int y,int width,int height,Rectangle dest) {
417         int x1 = (x > dest.x) ? x : dest.x;
418         int x2 = ((x+width) < (dest.x + dest.width)) ? (x+width) : (dest.x + dest.width);
419         int y1 = (y > dest.y) ? y : dest.y;
420         int y2 = ((y + height) < (dest.y + dest.height) ? (y+height) : (dest.y + dest.height));
421
422         dest.x = x1;
423         dest.y = y1;
424         dest.width = x2 - x1;
425         dest.height = y2 - y1;
426
427     // If rectangles don't intersect, return zero'd intersection.
428
if (dest.width < 0 || dest.height < 0) {
429         dest.x = dest.y = dest.width = dest.height = 0;
430     }
431
432         return dest;
433     }
434
435     /**
436      * Convenience method that calculates the union of two rectangles
437      * without allocating a new rectangle.
438      *
439      * @param x the x-coordinate of the first rectangle
440      * @param y the y-coordinate of the first rectangle
441      * @param width the width of the first rectangle
442      * @param height the height of the first rectangle
443      * @param dest the coordinates of the second rectangle; the union
444      * of the two rectangles is returned in this rectangle
445      * @return the <code>dest</code> <code>Rectangle</code>
446      */

447     public static Rectangle computeUnion(int x,int y,int width,int height,Rectangle dest) {
448         int x1 = (x < dest.x) ? x : dest.x;
449         int x2 = ((x+width) > (dest.x + dest.width)) ? (x+width) : (dest.x + dest.width);
450         int y1 = (y < dest.y) ? y : dest.y;
451         int y2 = ((y+height) > (dest.y + dest.height)) ? (y+height) : (dest.y + dest.height);
452
453         dest.x = x1;
454         dest.y = y1;
455         dest.width = (x2 - x1);
456         dest.height= (y2 - y1);
457         return dest;
458     }
459
460     /**
461      * Convenience returning an array of rect representing the regions within
462      * <code>rectA</code> that do not overlap with <code>rectB</code>. If the
463      * two Rects do not overlap, returns an empty array
464      */

465     public static Rectangle[] computeDifference(Rectangle rectA,Rectangle rectB) {
466         if (rectB == null || !rectA.intersects(rectB) || isRectangleContainingRectangle(rectB,rectA)) {
467             return new Rectangle[0];
468         }
469
470         Rectangle t = new Rectangle();
471         Rectangle a=null,b=null,c=null,d=null;
472         Rectangle result[];
473         int rectCount = 0;
474
475         /* rectA contains rectB */
476         if (isRectangleContainingRectangle(rectA,rectB)) {
477             t.x = rectA.x; t.y = rectA.y; t.width = rectB.x - rectA.x; t.height = rectA.height;
478             if(t.width > 0 && t.height > 0) {
479                 a = new Rectangle(t);
480                 rectCount++;
481             }
482
483             t.x = rectB.x; t.y = rectA.y; t.width = rectB.width; t.height = rectB.y - rectA.y;
484             if(t.width > 0 && t.height > 0) {
485                 b = new Rectangle(t);
486                 rectCount++;
487             }
488
489             t.x = rectB.x; t.y = rectB.y + rectB.height; t.width = rectB.width;
490             t.height = rectA.y + rectA.height - (rectB.y + rectB.height);
491             if(t.width > 0 && t.height > 0) {
492                 c = new Rectangle(t);
493                 rectCount++;
494             }
495
496             t.x = rectB.x + rectB.width; t.y = rectA.y; t.width = rectA.x + rectA.width - (rectB.x + rectB.width);
497             t.height = rectA.height;
498             if(t.width > 0 && t.height > 0) {
499                 d = new Rectangle(t);
500                 rectCount++;
501             }
502         } else {
503             /* 1 */
504             if (rectB.x <= rectA.x && rectB.y <= rectA.y) {
505                 if ((rectB.x + rectB.width) > (rectA.x + rectA.width)) {
506
507                     t.x = rectA.x; t.y = rectB.y + rectB.height;
508                     t.width = rectA.width; t.height = rectA.y + rectA.height - (rectB.y + rectB.height);
509                     if(t.width > 0 && t.height > 0) {
510                         a = t;
511                         rectCount++;
512                     }
513                 } else if ((rectB.y + rectB.height) > (rectA.y + rectA.height)) {
514                     t.setBounds((rectB.x + rectB.width), rectA.y,
515                                 (rectA.x + rectA.width) - (rectB.x + rectB.width), rectA.height);
516                     if(t.width > 0 && t.height > 0) {
517                         a = t;
518                         rectCount++;
519                     }
520                 } else {
521                     t.setBounds((rectB.x + rectB.width), rectA.y,
522                                 (rectA.x + rectA.width) - (rectB.x + rectB.width),
523                                 (rectB.y + rectB.height) - rectA.y);
524                     if(t.width > 0 && t.height > 0) {
525                         a = new Rectangle(t);
526                         rectCount++;
527                     }
528
529                     t.setBounds(rectA.x, (rectB.y + rectB.height), rectA.width,
530                                 (rectA.y + rectA.height) - (rectB.y + rectB.height));
531                     if(t.width > 0 && t.height > 0) {
532                         b = new Rectangle(t);
533                         rectCount++;
534                     }
535                 }
536             } else if (rectB.x <= rectA.x && (rectB.y + rectB.height) >= (rectA.y + rectA.height)) {
537                 if ((rectB.x + rectB.width) > (rectA.x + rectA.width)) {
538                     t.setBounds(rectA.x, rectA.y, rectA.width, rectB.y - rectA.y);
539                     if(t.width > 0 && t.height > 0) {
540                         a = t;
541                         rectCount++;
542                     }
543                 } else {
544                     t.setBounds(rectA.x, rectA.y, rectA.width, rectB.y - rectA.y);
545                     if(t.width > 0 && t.height > 0) {
546                         a = new Rectangle(t);
547                         rectCount++;
548                     }
549                     t.setBounds((rectB.x + rectB.width), rectB.y,
550                                 (rectA.x + rectA.width) - (rectB.x + rectB.width),
551                                 (rectA.y + rectA.height) - rectB.y);
552                     if(t.width > 0 && t.height > 0) {
553                         b = new Rectangle(t);
554                         rectCount++;
555                     }
556                 }
557             } else if (rectB.x <= rectA.x) {
558                 if ((rectB.x + rectB.width) >= (rectA.x + rectA.width)) {
559                     t.setBounds(rectA.x, rectA.y, rectA.width, rectB.y - rectA.y);
560                     if(t.width>0 && t.height > 0) {
561                         a = new Rectangle(t);
562                         rectCount++;
563                     }
564
565                     t.setBounds(rectA.x, (rectB.y + rectB.height), rectA.width,
566                                 (rectA.y + rectA.height) - (rectB.y + rectB.height));
567                     if(t.width > 0 && t.height > 0) {
568                         b = new Rectangle(t);
569                         rectCount++;
570                     }
571                 } else {
572                     t.setBounds(rectA.x, rectA.y, rectA.width, rectB.y - rectA.y);
573                     if(t.width > 0 && t.height > 0) {
574                         a = new Rectangle(t);
575                         rectCount++;
576                     }
577
578                     t.setBounds((rectB.x + rectB.width), rectB.y,
579                                 (rectA.x + rectA.width) - (rectB.x + rectB.width),
580                                 rectB.height);
581                     if(t.width > 0 && t.height > 0) {
582                         b = new Rectangle(t);
583                         rectCount++;
584                     }
585
586                     t.setBounds(rectA.x, (rectB.y + rectB.height), rectA.width,
587                                 (rectA.y + rectA.height) - (rectB.y + rectB.height));
588                     if(t.width > 0 && t.height > 0) {
589                         c = new Rectangle(t);
590                         rectCount++;
591                     }
592                 }
593             } else if (rectB.x <= (rectA.x + rectA.width) && (rectB.x + rectB.width) > (rectA.x + rectA.width)) {
594                 if (rectB.y <= rectA.y && (rectB.y + rectB.height) > (rectA.y + rectA.height)) {
595                     t.setBounds(rectA.x, rectA.y, rectB.x - rectA.x, rectA.height);
596                     if(t.width > 0 && t.height > 0) {
597                         a = t;
598                         rectCount++;
599                     }
600                 } else if (rectB.y <= rectA.y) {
601                     t.setBounds(rectA.x, rectA.y, rectB.x - rectA.x,
602                                 (rectB.y + rectB.height) - rectA.y);
603                     if(t.width > 0 && t.height > 0) {
604                         a = new Rectangle(t);
605                         rectCount++;
606                     }
607
608                     t.setBounds(rectA.x, (rectB.y + rectB.height), rectA.width,
609                                 (rectA.y + rectA.height) - (rectB.y + rectB.height));
610                     if(t.width > 0 && t.height > 0) {
611                         b = new Rectangle(t);
612                         rectCount++;
613                     }
614                 } else if ((rectB.y + rectB.height) > (rectA.y + rectA.height)) {
615                     t.setBounds(rectA.x, rectA.y, rectA.width, rectB.y - rectA.y);
616                     if(t.width > 0 && t.height > 0) {
617                         a = new Rectangle(t);
618                         rectCount++;
619                     }
620
621                     t.setBounds(rectA.x, rectB.y, rectB.x - rectA.x,
622                                 (rectA.y + rectA.height) - rectB.y);
623                     if(t.width > 0 && t.height > 0) {
624                         b = new Rectangle(t);
625                         rectCount++;
626                     }
627                 } else {
628                     t.setBounds(rectA.x, rectA.y, rectA.width, rectB.y - rectA.y);
629                     if(t.width > 0 && t.height > 0) {
630                         a = new Rectangle(t);
631                         rectCount++;
632                     }
633
634                     t.setBounds(rectA.x, rectB.y, rectB.x - rectA.x,
635                                 rectB.height);
636                     if(t.width > 0 && t.height > 0) {
637                         b = new Rectangle(t);
638                         rectCount++;
639                     }
640
641                     t.setBounds(rectA.x, (rectB.y + rectB.height), rectA.width,
642                                 (rectA.y + rectA.height) - (rectB.y + rectB.height));
643                     if(t.width > 0 && t.height > 0) {
644                         c = new Rectangle(t);
645                         rectCount++;
646                     }
647                 }
648             } else if (rectB.x >= rectA.x && (rectB.x + rectB.width) <= (rectA.x + rectA.width)) {
649                 if (rectB.y <= rectA.y && (rectB.y + rectB.height) > (rectA.y + rectA.height)) {
650                     t.setBounds(rectA.x, rectA.y, rectB.x - rectA.x, rectA.height);
651                     if(t.width > 0 && t.height > 0) {
652                         a = new Rectangle(t);
653                         rectCount++;
654                     }
655                     t.setBounds((rectB.x + rectB.width), rectA.y,
656                                 (rectA.x + rectA.width) - (rectB.x + rectB.width), rectA.height);
657                     if(t.width > 0 && t.height > 0) {
658                         b = new Rectangle(t);
659                         rectCount++;
660                     }
661                 } else if (rectB.y <= rectA.y) {
662                     t.setBounds(rectA.x, rectA.y, rectB.x - rectA.x, rectA.height);
663                     if(t.width > 0 && t.height > 0) {
664                         a = new Rectangle(t);
665                         rectCount++;
666                     }
667
668                     t.setBounds(rectB.x, (rectB.y + rectB.height),
669                                 rectB.width,
670                                 (rectA.y + rectA.height) - (rectB.y + rectB.height));
671                     if(t.width > 0 && t.height > 0) {
672                         b = new Rectangle(t);
673                         rectCount++;
674                     }
675
676                     t.setBounds((rectB.x + rectB.width), rectA.y,
677                                 (rectA.x + rectA.width) - (rectB.x + rectB.width), rectA.height);
678                     if(t.width > 0 && t.height > 0) {
679                         c = new Rectangle(t);
680                         rectCount++;
681                     }
682                 } else {
683                     t.setBounds(rectA.x, rectA.y, rectB.x - rectA.x, rectA.height);
684                     if(t.width > 0 && t.height > 0) {
685                         a = new Rectangle(t);
686                         rectCount++;
687                     }
688
689                     t.setBounds(rectB.x, rectA.y, rectB.width,
690                                 rectB.y - rectA.y);
691                     if(t.width > 0 && t.height > 0) {
692                         b = new Rectangle(t);
693                         rectCount++;
694                     }
695
696                     t.setBounds((rectB.x + rectB.width), rectA.y,
697                                 (rectA.x + rectA.width) - (rectB.x + rectB.width), rectA.height);
698                     if(t.width > 0 && t.height > 0) {
699                         c = new Rectangle(t);
700                         rectCount++;
701                     }
702                 }
703             }
704         }
705
706         result = new Rectangle[rectCount];
707         rectCount = 0;
708         if(a != null)
709             result[rectCount++] = a;
710         if(b != null)
711             result[rectCount++] = b;
712         if(c != null)
713             result[rectCount++] = c;
714         if(d != null)
715             result[rectCount++] = d;
716         return result;
717     }
718
719     /**
720      * Returns true if the mouse event specifies the left mouse button.
721      *
722      * @param anEvent a MouseEvent object
723      * @return true if the left mouse button was active
724      */

725     public static boolean isLeftMouseButton(MouseEvent JavaDoc anEvent) {
726          return ((anEvent.getModifiers() & InputEvent.BUTTON1_MASK) != 0);
727     }
728
729     /**
730      * Returns true if the mouse event specifies the middle mouse button.
731      *
732      * @param anEvent a MouseEvent object
733      * @return true if the middle mouse button was active
734      */

735     public static boolean isMiddleMouseButton(MouseEvent JavaDoc anEvent) {
736         return ((anEvent.getModifiers() & InputEvent.BUTTON2_MASK) == InputEvent.BUTTON2_MASK);
737     }
738
739     /**
740      * Returns true if the mouse event specifies the right mouse button.
741      *
742      * @param anEvent a MouseEvent object
743      * @return true if the right mouse button was active
744      */

745     public static boolean isRightMouseButton(MouseEvent JavaDoc anEvent) {
746         return ((anEvent.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK);
747     }
748
749     /**
750      * Compute the width of the string using a font with the specified
751      * "metrics" (sizes).
752      *
753      * @param fm a FontMetrics object to compute with
754      * @param str the String to compute
755      * @return an int containing the string width
756      */

757     public static int computeStringWidth(FontMetrics fm,String JavaDoc str) {
758         // You can't assume that a string's width is the sum of its
759
// characters' widths in Java2D -- it may be smaller due to
760
// kerning, etc.
761
return SwingUtilities2.stringWidth(null, fm, str);
762     }
763
764     /**
765      * Compute and return the location of the icons origin, the
766      * location of origin of the text baseline, and a possibly clipped
767      * version of the compound labels string. Locations are computed
768      * relative to the viewR rectangle.
769      * The JComponents orientation (LEADING/TRAILING) will also be taken
770      * into account and translated into LEFT/RIGHT values accordingly.
771      */

772     public static String JavaDoc layoutCompoundLabel(JComponent JavaDoc c,
773                                              FontMetrics fm,
774                                              String JavaDoc text,
775                                              Icon JavaDoc icon,
776                                              int verticalAlignment,
777                                              int horizontalAlignment,
778                                              int verticalTextPosition,
779                                              int horizontalTextPosition,
780                                              Rectangle viewR,
781                                              Rectangle iconR,
782                                              Rectangle textR,
783                                              int textIconGap)
784     {
785         boolean orientationIsLeftToRight = true;
786         int hAlign = horizontalAlignment;
787         int hTextPos = horizontalTextPosition;
788
789         if (c != null) {
790             if (!(c.getComponentOrientation().isLeftToRight())) {
791                 orientationIsLeftToRight = false;
792             }
793         }
794
795         // Translate LEADING/TRAILING values in horizontalAlignment
796
// to LEFT/RIGHT values depending on the components orientation
797
switch (horizontalAlignment) {
798         case LEADING:
799             hAlign = (orientationIsLeftToRight) ? LEFT : RIGHT;
800             break;
801         case TRAILING:
802             hAlign = (orientationIsLeftToRight) ? RIGHT : LEFT;
803             break;
804         }
805
806         // Translate LEADING/TRAILING values in horizontalTextPosition
807
// to LEFT/RIGHT values depending on the components orientation
808
switch (horizontalTextPosition) {
809         case LEADING:
810             hTextPos = (orientationIsLeftToRight) ? LEFT : RIGHT;
811             break;
812         case TRAILING:
813             hTextPos = (orientationIsLeftToRight) ? RIGHT : LEFT;
814             break;
815         }
816
817         return layoutCompoundLabelImpl(c,
818                        fm,
819                        text,
820                        icon,
821                        verticalAlignment,
822                        hAlign,
823                        verticalTextPosition,
824                        hTextPos,
825                        viewR,
826                        iconR,
827                        textR,
828                        textIconGap);
829     }
830
831     /**
832      * Compute and return the location of the icons origin, the
833      * location of origin of the text baseline, and a possibly clipped
834      * version of the compound labels string. Locations are computed
835      * relative to the viewR rectangle.
836      * This layoutCompoundLabel() does not know how to handle LEADING/TRAILING
837      * values in horizontalTextPosition (they will default to RIGHT) and in
838      * horizontalAlignment (they will default to CENTER).
839      * Use the other version of layoutCompoundLabel() instead.
840      */

841     public static String JavaDoc layoutCompoundLabel(
842         FontMetrics fm,
843         String JavaDoc text,
844         Icon JavaDoc icon,
845         int verticalAlignment,
846         int horizontalAlignment,
847         int verticalTextPosition,
848         int horizontalTextPosition,
849         Rectangle viewR,
850         Rectangle iconR,
851         Rectangle textR,
852         int textIconGap)
853     {
854     return layoutCompoundLabelImpl(null, fm, text, icon,
855                        verticalAlignment,
856                        horizontalAlignment,
857                        verticalTextPosition,
858                        horizontalTextPosition,
859                        viewR, iconR, textR, textIconGap);
860     }
861                    
862     /**
863      * Compute and return the location of the icons origin, the
864      * location of origin of the text baseline, and a possibly clipped
865      * version of the compound labels string. Locations are computed
866      * relative to the viewR rectangle.
867      * This layoutCompoundLabel() does not know how to handle LEADING/TRAILING
868      * values in horizontalTextPosition (they will default to RIGHT) and in
869      * horizontalAlignment (they will default to CENTER).
870      * Use the other version of layoutCompoundLabel() instead.
871      */

872     private static String JavaDoc layoutCompoundLabelImpl(
873     JComponent JavaDoc c,
874     FontMetrics fm,
875         String JavaDoc text,
876         Icon JavaDoc icon,
877         int verticalAlignment,
878         int horizontalAlignment,
879         int verticalTextPosition,
880         int horizontalTextPosition,
881         Rectangle viewR,
882         Rectangle iconR,
883         Rectangle textR,
884         int textIconGap)
885     {
886         /* Initialize the icon bounds rectangle iconR.
887          */

888
889         if (icon != null) {
890             iconR.width = icon.getIconWidth();
891             iconR.height = icon.getIconHeight();
892         }
893         else {
894             iconR.width = iconR.height = 0;
895         }
896
897         /* Initialize the text bounds rectangle textR. If a null
898          * or and empty String was specified we substitute "" here
899          * and use 0,0,0,0 for textR.
900          */

901
902         boolean textIsEmpty = (text == null) || text.equals("");
903         int lsb = 0;
904         /* Unless both text and icon are non-null, we effectively ignore
905          * the value of textIconGap.
906          */

907         int gap;
908
909     View JavaDoc v = null;
910         if (textIsEmpty) {
911             textR.width = textR.height = 0;
912             text = "";
913             gap = 0;
914         }
915         else {
916             int availTextWidth;
917             gap = (icon == null) ? 0 : textIconGap;
918
919             if (horizontalTextPosition == CENTER) {
920                 availTextWidth = viewR.width;
921             }
922             else {
923                 availTextWidth = viewR.width - (iconR.width + gap);
924             }
925         v = (c != null) ? (View JavaDoc) c.getClientProperty("html") : null;
926         if (v != null) {
927         textR.width = Math.min(availTextWidth,
928                                        (int) v.getPreferredSpan(View.X_AXIS));
929         textR.height = (int) v.getPreferredSpan(View.Y_AXIS);
930         } else {
931                 textR.width = SwingUtilities2.stringWidth(c, fm, text);
932                 lsb = SwingUtilities2.getLeftSideBearing(c, fm, text);
933                 if (lsb < 0) {
934                     // If lsb is negative, add it to the width and later
935
// adjust the x location. This gives more space than is
936
// actually needed.
937
// This is done like this for two reasons:
938
// 1. If we set the width to the actual bounds all
939
// callers would have to account for negative lsb
940
// (pref size calculations ONLY look at width of
941
// textR)
942
// 2. You can do a drawString at the returned location
943
// and the text won't be clipped.
944
textR.width -= lsb;
945                 }
946                 if (textR.width > availTextWidth) {
947                     text = SwingUtilities2.clipString(c, fm, text,
948                                                       availTextWidth);
949                     textR.width = SwingUtilities2.stringWidth(c, fm, text);
950                 }
951         textR.height = fm.getHeight();
952         }
953         }
954
955
956         /* Compute textR.x,y given the verticalTextPosition and
957          * horizontalTextPosition properties
958          */

959
960         if (verticalTextPosition == TOP) {
961             if (horizontalTextPosition != CENTER) {
962                 textR.y = 0;
963             }
964             else {
965                 textR.y = -(textR.height + gap);
966             }
967         }
968         else if (verticalTextPosition == CENTER) {
969             textR.y = (iconR.height / 2) - (textR.height / 2);
970         }
971         else { // (verticalTextPosition == BOTTOM)
972
if (horizontalTextPosition != CENTER) {
973                 textR.y = iconR.height - textR.height;
974             }
975             else {
976                 textR.y = (iconR.height + gap);
977             }
978         }
979
980         if (horizontalTextPosition == LEFT) {
981             textR.x = -(textR.width + gap);
982         }
983         else if (horizontalTextPosition == CENTER) {
984             textR.x = (iconR.width / 2) - (textR.width / 2);
985         }
986         else { // (horizontalTextPosition == RIGHT)
987
textR.x = (iconR.width + gap);
988         }
989
990         /* labelR is the rectangle that contains iconR and textR.
991          * Move it to its proper position given the labelAlignment
992          * properties.
993          *
994          * To avoid actually allocating a Rectangle, Rectangle.union
995          * has been inlined below.
996          */

997         int labelR_x = Math.min(iconR.x, textR.x);
998         int labelR_width = Math.max(iconR.x + iconR.width,
999                                     textR.x + textR.width) - labelR_x;
1000        int labelR_y = Math.min(iconR.y, textR.y);
1001        int labelR_height = Math.max(iconR.y + iconR.height,
1002                                     textR.y + textR.height) - labelR_y;
1003
1004        int dx, dy;
1005
1006        if (verticalAlignment == TOP) {
1007            dy = viewR.y - labelR_y;
1008        }
1009        else if (verticalAlignment == CENTER) {
1010            dy = (viewR.y + (viewR.height / 2)) - (labelR_y + (labelR_height / 2));
1011        }
1012        else { // (verticalAlignment == BOTTOM)
1013
dy = (viewR.y + viewR.height) - (labelR_y + labelR_height);
1014        }
1015
1016        if (horizontalAlignment == LEFT) {
1017            dx = viewR.x - labelR_x;
1018        }
1019        else if (horizontalAlignment == RIGHT) {
1020            dx = (viewR.x + viewR.width) - (labelR_x + labelR_width);
1021        }
1022        else { // (horizontalAlignment == CENTER)
1023
dx = (viewR.x + (viewR.width / 2)) -
1024                 (labelR_x + (labelR_width / 2));
1025        }
1026
1027        /* Translate textR and glypyR by dx,dy.
1028         */

1029
1030        textR.x += dx;
1031        textR.y += dy;
1032
1033        iconR.x += dx;
1034        iconR.y += dy;
1035
1036        if (lsb < 0) {
1037            // lsb is negative. Shift the x location so that the text is
1038
// visually drawn at the right location.
1039
textR.x -= lsb;
1040        }
1041
1042        return text;
1043    }
1044
1045
1046    /**
1047     * Paints a component <code>c</code> on an arbitrary graphics
1048     * <code>g</code> in the
1049     * specified rectangle, specifying the rectangle's upper left corner
1050     * and size. The component is reparented to a private
1051     * container (whose parent becomes p) which prevents
1052     * <code>c.validate()</code> and <code>c.repaint()</code>
1053     * calls from propagating up the tree. The intermediate
1054     * container has no other effect.
1055     *
1056     * <p>
1057     * The component should either descend from <code>JComponent</code>
1058     * or be another kind of lightweight component.
1059     * A lightweight component is one whose "lightweight" property
1060     * (returned by the <code>Component</code>
1061     * <code>isLightweight</code> method)
1062     * is true. If the Component is not lightweight, bad things map happen:
1063     * crashes, exceptions, painting problems...
1064     * <p>
1065     *
1066     * @param g the <code>Graphics</code> object to draw on
1067     * @param c the <code>Component</code> to draw
1068     * @param p the intermediate <code>Container</code>
1069     * @param x an int specifying the left side of the area draw in, in pixels,
1070     * measured from the left edge of the graphics context
1071     * @param y an int specifying the top of the area to draw in, in pixels
1072     * measured down from the top edge of the graphics context
1073     * @param w an int specifying the width of the area draw in, in pixels
1074     * @param h an int specifying the height of the area draw in, in pixels
1075     *
1076     * @see java.awt.Component#isLightweight
1077     */

1078    public static void paintComponent(Graphics g, Component c, Container p, int x, int y, int w, int h) {
1079        getCellRendererPane(c, p).paintComponent(g, c, p, x, y, w, h,false);
1080    }
1081
1082    /**
1083     * Paints a component <code>c</code> on an arbitrary graphics
1084     * <code>g</code> in the specified rectangle, specifying a Rectangle object.
1085     * The component is reparented to a private
1086     * container (whose parent becomes <code>p</code>) which prevents
1087     * <code>c.validate()</code> and <code>c.repaint()</code>
1088     * calls from propagating up the tree. The intermediate
1089     * container has no other effect.
1090     *
1091     * <p>
1092     * The component should either descend from <code>JComponent</code>
1093     * or be another kind of lightweight component.
1094     * A lightweight component is one whose "lightweight" property
1095     * (returned by the <code>Component</code>
1096     * <code>isLightweight</code> method)
1097     * is true. If the Component is not lightweight, bad things map happen:
1098     * crashes, exceptions, painting problems...
1099     * <p>
1100     *
1101     * @param g the <code>Graphics</code> object to draw on
1102     * @param c the <code>Component</code> to draw
1103     * @param p the intermediate <code>Container</code>
1104     * @param r the <code>Rectangle</code> to draw in
1105     *
1106     * @see java.awt.Component#isLightweight
1107     */

1108    public static void paintComponent(Graphics g, Component c, Container p, Rectangle r) {
1109        paintComponent(g, c, p, r.x, r.y, r.width, r.height);
1110    }
1111
1112
1113    /*
1114     * Ensures that cell renderer <code>c</code> has a
1115     * <code>ComponentShell</code> parent and that
1116     * the shell's parent is p.
1117     */

1118    private static CellRendererPane JavaDoc getCellRendererPane(Component c, Container p) {
1119        Container shell = c.getParent();
1120        if (shell instanceof CellRendererPane JavaDoc) {
1121            if (shell.getParent() != p) {
1122                p.add(shell);
1123            }
1124        } else {
1125            shell = new CellRendererPane JavaDoc();
1126            shell.add(c);
1127            p.add(shell);
1128        }
1129        return (CellRendererPane JavaDoc)shell;
1130    }
1131
1132    /**
1133     * A simple minded look and feel change: ask each node in the tree
1134     * to <code>updateUI()</code> -- that is, to initialize its UI property
1135     * with the current look and feel.
1136     */

1137    public static void updateComponentTreeUI(Component c) {
1138        updateComponentTreeUI0(c);
1139        c.invalidate();
1140        c.validate();
1141        c.repaint();
1142    }
1143
1144    private static void updateComponentTreeUI0(Component c) {
1145        if (c instanceof JComponent JavaDoc) {
1146            ((JComponent JavaDoc) c).updateUI();
1147        }
1148        Component[] children = null;
1149        if (c instanceof JMenu JavaDoc) {
1150            children = ((JMenu JavaDoc)c).getMenuComponents();
1151        }
1152        else if (c instanceof Container) {
1153            children = ((Container)c).getComponents();
1154        }
1155        if (children != null) {
1156            for(int i = 0; i < children.length; i++) {
1157                updateComponentTreeUI0(children[i]);
1158            }
1159        }
1160    }
1161
1162
1163    /**
1164     * Causes <i>doRun.run()</i> to be executed asynchronously on the
1165     * AWT event dispatching thread. This will happen after all
1166     * pending AWT events have been processed. This method should
1167     * be used when an application thread needs to update the GUI.
1168     * In the following example the <code>invokeLater</code> call queues
1169     * the <code>Runnable</code> object <code>doHelloWorld</code>
1170     * on the event dispatching thread and
1171     * then prints a message.
1172     * <pre>
1173     * Runnable doHelloWorld = new Runnable() {
1174     * public void run() {
1175     * System.out.println("Hello World on " + Thread.currentThread());
1176     * }
1177     * };
1178     *
1179     * SwingUtilities.invokeLater(doHelloWorld);
1180     * System.out.println("This might well be displayed before the other message.");
1181     * </pre>
1182     * If invokeLater is called from the event dispatching thread --
1183     * for example, from a JButton's ActionListener -- the <i>doRun.run()</i> will
1184     * still be deferred until all pending events have been processed.
1185     * Note that if the <i>doRun.run()</i> throws an uncaught exception
1186     * the event dispatching thread will unwind (not the current thread).
1187     * <p>
1188     * Additional documentation and examples for this method can be
1189     * found in
1190     * <A HREF="http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html">How to Use Threads</a>,
1191     * in <em>The Java Tutorial</em>.
1192     * <p>
1193     * As of 1.3 this method is just a cover for <code>java.awt.EventQueue.invokeLater()</code>.
1194     *
1195     * @see #invokeAndWait
1196     */

1197    public static void invokeLater(Runnable JavaDoc doRun) {
1198    EventQueue.invokeLater(doRun);
1199    }
1200
1201
1202    /**
1203     * Causes <code>doRun.run()</code> to be executed synchronously on the
1204     * AWT event dispatching thread. This call blocks until
1205     * all pending AWT events have been processed and (then)
1206     * <code>doRun.run()</code> returns. This method should
1207     * be used when an application thread needs to update the GUI.
1208     * It should'nt be called from the <code>EventDispatchThread</code>.
1209     * Here's an example that creates a new application thread
1210     * that uses <code>invokeAndWait</code> to print a string from the event
1211     * dispatching thread and then, when that's finished, print
1212     * a string from the application thread.
1213     * <pre>
1214     * final Runnable doHelloWorld = new Runnable() {
1215     * public void run() {
1216     * System.out.println("Hello World on " + Thread.currentThread());
1217     * }
1218     * };
1219     *
1220     * Thread appThread = new Thread() {
1221     * public void run() {
1222     * try {
1223     * SwingUtilities.invokeAndWait(doHelloWorld);
1224     * }
1225     * catch (Exception e) {
1226     * e.printStackTrace();
1227     * }
1228     * System.out.println("Finished on " + Thread.currentThread());
1229     * }
1230     * };
1231     * appThread.start();
1232     * </pre>
1233     * Note that if the <code>Runnable.run</code> method throws an
1234     * uncaught exception
1235     * (on the event dispatching thread) it's caught and rethrown, as
1236     * an <code>InvocationTargetException</code>, on the caller's thread.
1237     * <p>
1238     * Additional documentation and examples for this method can be
1239     * found in
1240     * <A HREF="http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html">How to Use Threads</a>,
1241     * in <em>The Java Tutorial</em>.
1242     * <p>
1243     * As of 1.3 this method is just a cover for
1244     * <code>java.awt.EventQueue.invokeAndWait()</code>.
1245     *
1246     * @exception InterruptedException if we're interrupted while waiting for
1247     * the event dispatching thread to finish excecuting
1248     * <code>doRun.run()</code>
1249     * @exception InvocationTargetException if an exception is thrown
1250     * while running <code>doRun</code>
1251     *
1252     * @see #invokeLater
1253     */

1254    public static void invokeAndWait(final Runnable JavaDoc doRun)
1255        throws InterruptedException JavaDoc, InvocationTargetException
1256    {
1257    EventQueue.invokeAndWait(doRun);
1258    }
1259
1260    /**
1261     * Returns true if the current thread is an AWT event dispatching thread.
1262     * <p>
1263     * As of 1.3 this method is just a cover for
1264     * <code>java.awt.EventQueue.isDispatchThread()</code>.
1265     *
1266     * @return true if the current thread is an AWT event dispatching thread
1267     */

1268    public static boolean isEventDispatchThread()
1269    {
1270    return EventQueue.isDispatchThread();
1271    }
1272
1273
1274    /*
1275     * --- Accessibility Support ---
1276     *
1277     */

1278
1279    /**
1280     * Get the index of this object in its accessible parent.<p>
1281     *
1282     * Note: as of the Java 2 platform v1.3, it is recommended that developers call
1283     * Component.AccessibleAWTComponent.getAccessibleIndexInParent() instead
1284     * of using this method.
1285     *
1286     * @return -1 of this object does not have an accessible parent.
1287     * Otherwise, the index of the child in its accessible parent.
1288     */

1289    public static int getAccessibleIndexInParent(Component c) {
1290    return c.getAccessibleContext().getAccessibleIndexInParent();
1291    }
1292
1293    /**
1294     * Returns the <code>Accessible</code> child contained at the
1295     * local coordinate <code>Point</code>, if one exists.
1296     * Otherwise returns <code>null</code>.
1297     *
1298     * @return the <code>Accessible</code> at the specified location,
1299     * if it exists; otherwise <code>null</code>
1300     */

1301    public static Accessible getAccessibleAt(Component c, Point p) {
1302        if (c instanceof Container) {
1303        return c.getAccessibleContext().getAccessibleComponent().getAccessibleAt(p);
1304    } else if (c instanceof Accessible) {
1305            Accessible a = (Accessible) c;
1306            if (a != null) {
1307                AccessibleContext ac = a.getAccessibleContext();
1308                if (ac != null) {
1309                    AccessibleComponent acmp;
1310                    Point location;
1311                    int nchildren = ac.getAccessibleChildrenCount();
1312                    for (int i=0; i < nchildren; i++) {
1313                        a = ac.getAccessibleChild(i);
1314                        if ((a != null)) {
1315                            ac = a.getAccessibleContext();
1316                            if (ac != null) {
1317                                acmp = ac.getAccessibleComponent();
1318                                if ((acmp != null) && (acmp.isShowing())) {
1319                                    location = acmp.getLocation();
1320                                    Point np = new Point(p.x-location.x,
1321                                                         p.y-location.y);
1322                                    if (acmp.contains(np)){
1323                                        return a;
1324                                    }
1325                                }
1326                            }
1327                        }
1328                    }
1329                }
1330            }
1331            return (Accessible) c;
1332        }
1333        return null;
1334    }
1335
1336    /**
1337     * Get the state of this object. <p>
1338     *
1339     * Note: as of the Java 2 platform v1.3, it is recommended that developers call
1340     * Component.AccessibleAWTComponent.getAccessibleIndexInParent() instead
1341     * of using this method.
1342     *
1343     * @return an instance of AccessibleStateSet containing the current state
1344     * set of the object
1345     * @see AccessibleState
1346     */

1347    public static AccessibleStateSet getAccessibleStateSet(Component c) {
1348    return c.getAccessibleContext().getAccessibleStateSet();
1349    }
1350
1351    /**
1352     * Returns the number of accessible children in the object. If all
1353     * of the children of this object implement Accessible, than this
1354     * method should return the number of children of this object. <p>
1355     *
1356     * Note: as of the Java 2 platform v1.3, it is recommended that developers call
1357     * Component.AccessibleAWTComponent.getAccessibleIndexInParent() instead
1358     * of using this method.
1359     *
1360     * @return the number of accessible children in the object.
1361     */

1362    public static int getAccessibleChildrenCount(Component c) {
1363    return c.getAccessibleContext().getAccessibleChildrenCount();
1364    }
1365
1366    /**
1367     * Return the nth Accessible child of the object. <p>
1368     *
1369     * Note: as of the Java 2 platform v1.3, it is recommended that developers call
1370     * Component.AccessibleAWTComponent.getAccessibleIndexInParent() instead
1371     * of using this method.
1372     *
1373     * @param i zero-based index of child
1374     * @return the nth Accessible child of the object
1375     */

1376    public static Accessible getAccessibleChild(Component c, int i) {
1377    return c.getAccessibleContext().getAccessibleChild(i);
1378    }
1379
1380    /**
1381     * Return the child <code>Component</code> of the specified
1382     * <code>Component</code> that is the focus owner, if any.
1383     *
1384     * @param c the root of the <code>Component</code> hierarchy to
1385     * search for the focus owner
1386     * @return the focus owner, or <code>null</code> if there is no focus
1387     * owner, or if the focus owner is not <code>comp</code>, or a
1388     * descendant of <code>comp</code>
1389     *
1390     * @see java.awt.KeyboardFocusManager#getFocusOwner
1391     * @deprecated As of 1.4, replaced by
1392     * <code>KeyboardFocusManager.getFocusOwner()</code>.
1393     */

1394    @Deprecated JavaDoc
1395    public static Component findFocusOwner(Component c) {
1396    Component focusOwner = KeyboardFocusManager.
1397        getCurrentKeyboardFocusManager().getFocusOwner();
1398
1399    // verify focusOwner is a descendant of c
1400
for (Component temp = focusOwner; temp != null;
1401         temp = (temp instanceof Window) ? null : temp.getParent())
1402    {
1403        if (temp == c) {
1404        return focusOwner;
1405        }
1406    }
1407
1408    return null;
1409    }
1410
1411    /**
1412     * If c is a JRootPane descendant return its JRootPane ancestor.
1413     * If c is a RootPaneContainer then return its JRootPane.
1414     * @return the JRootPane for Component c or null.
1415     */

1416    public static JRootPane JavaDoc getRootPane(Component c) {
1417        if (c instanceof RootPaneContainer JavaDoc) {
1418            return ((RootPaneContainer JavaDoc)c).getRootPane();
1419        }
1420        for( ; c != null; c = c.getParent()) {
1421            if (c instanceof JRootPane JavaDoc) {
1422                return (JRootPane JavaDoc)c;
1423            }
1424        }
1425        return null;
1426    }
1427
1428
1429    /**
1430     * Returns the root component for the current component tree.
1431     * @return the first ancestor of c that's a Window or the last Applet ancestor
1432     */

1433    public static Component getRoot(Component c) {
1434        Component applet = null;
1435        for(Component p = c; p != null; p = p.getParent()) {
1436            if (p instanceof Window) {
1437                return p;
1438            }
1439            if (p instanceof Applet) {
1440                applet = p;
1441            }
1442        }
1443        return applet;
1444    }
1445
1446    /**
1447     * Process the key bindings for the <code>Component</code> associated with
1448     * <code>event</code>. This method is only useful if
1449     * <code>event.getComponent()</code> does not descend from
1450     * <code>JComponent</code>, or your are not invoking
1451     * <code>super.processKeyEvent</code> from within your
1452     * <code>JComponent</code> subclass. <code>JComponent</code>
1453     * automatically processes bindings from within its
1454     * <code>processKeyEvent</code> method, hence you rarely need
1455     * to directly invoke this method.
1456     *
1457     * @param event KeyEvent used to identify which bindings to process, as
1458     * well as which Component has focus.
1459     * @return true if a binding has found and processed
1460     * @since 1.4
1461     */

1462    public static boolean processKeyBindings(KeyEvent event) {
1463        if (event != null) {
1464            if (event.isConsumed()) {
1465                return false;
1466            }
1467
1468            Component component = event.getComponent();
1469            Component last = component;
1470            boolean pressed = (event.getID() == KeyEvent.KEY_PRESSED);
1471
1472            if (!isValidKeyEventForKeyBindings(event)) {
1473                return false;
1474            }
1475            // Find the first JComponent in the ancestor hierarchy, and
1476
// invoke processKeyBindings on it
1477
while (component != null) {
1478                if (component instanceof JComponent JavaDoc) {
1479                    return ((JComponent JavaDoc)component).processKeyBindings(
1480                                                   event, pressed);
1481                }
1482                last = component;
1483                component = component.getParent();
1484            }
1485            // No JComponents, if Window or Applet parent, process
1486
// WHEN_IN_FOCUSED_WINDOW bindings.
1487
if ((last instanceof Applet) || (last instanceof Window)) {
1488                return JComponent.processKeyBindingsForAllComponents(
1489                                  event, (Container)last, pressed);
1490            }
1491        }
1492        return false;
1493    }
1494
1495    /**
1496     * Returns true if the <code>e</code> is a valid KeyEvent to use in
1497     * processing the key bindings associated with JComponents.
1498     */

1499    static boolean isValidKeyEventForKeyBindings(KeyEvent e) {
1500        if (e.getID() == KeyEvent.KEY_TYPED) {
1501            int mod = e.getModifiers();
1502            if (((mod & ActionEvent.ALT_MASK) != 0) &&
1503                ((mod & ActionEvent.CTRL_MASK) == 0)) {
1504                // filter out typed "alt-?" keys, but not those created
1505
// with AltGr, and not control characters
1506
return false;
1507            }
1508        }
1509        return true;
1510    }
1511
1512    /**
1513     * Invokes <code>actionPerformed</code> on <code>action</code> if
1514     * <code>action</code> is enabled (and non null). The command for the
1515     * ActionEvent is determined by:
1516     * <ol>
1517     * <li>If the action was registered via
1518     * <code>registerKeyboardAction</code>, then the command string
1519     * passed in (null will be used if null was passed in).
1520     * <li>Action value with name Action.ACTION_COMMAND_KEY, unless null.
1521     * <li>String value of the KeyEvent, unless <code>getKeyChar</code>
1522     * returns KeyEvent.CHAR_UNDEFINED..
1523     * </ol>
1524     * This will return true if <code>action</code> is non-null and
1525     * actionPerformed is invoked on it.
1526     *
1527     * @since 1.3
1528     */

1529    public static boolean notifyAction(Action JavaDoc action, KeyStroke JavaDoc ks,
1530                       KeyEvent event, Object JavaDoc sender,
1531                       int modifiers) {
1532    if (action == null) {
1533        return false;
1534    }
1535        if (action instanceof UIAction) {
1536            if (!((UIAction)action).isEnabled(sender)) {
1537                return false;
1538            }
1539        }
1540        else if (!action.isEnabled()) {
1541            return false;
1542        }
1543    Object JavaDoc commandO;
1544    boolean stayNull;
1545
1546    // Get the command object.
1547
commandO = action.getValue(Action.ACTION_COMMAND_KEY);
1548    if (commandO == null && (action instanceof JComponent.ActionStandin JavaDoc)) {
1549        // ActionStandin is used for historical reasons to support
1550
// registerKeyboardAction with a null value.
1551
stayNull = true;
1552    }
1553    else {
1554        stayNull = false;
1555    }
1556
1557    // Convert it to a string.
1558
String JavaDoc command;
1559
1560    if (commandO != null) {
1561        command = commandO.toString();
1562    }
1563    else if (!stayNull && event.getKeyChar() != KeyEvent.CHAR_UNDEFINED) {
1564        command = String.valueOf(event.getKeyChar());
1565    }
1566    else {
1567        // Do null for undefined chars, or if registerKeyboardAction
1568
// was called with a null.
1569
command = null;
1570    }
1571    action.actionPerformed(new ActionEvent(sender,
1572            ActionEvent.ACTION_PERFORMED, command, event.getWhen(),
1573                        modifiers));
1574    return true;
1575    }
1576
1577
1578    /**
1579     * Convenience method to change the UI InputMap for <code>component</code>
1580     * to <code>uiInputMap</code>. If <code>uiInputMap</code> is null,
1581     * this removes any previously installed UI InputMap.
1582     *
1583     * @since 1.3
1584     */

1585    public static void replaceUIInputMap(JComponent JavaDoc component, int type,
1586                     InputMap JavaDoc uiInputMap) {
1587    InputMap JavaDoc map = component.getInputMap(type, (uiInputMap != null));
1588
1589    while (map != null) {
1590        InputMap JavaDoc parent = map.getParent();
1591        if (parent == null || (parent instanceof UIResource JavaDoc)) {
1592        map.setParent(uiInputMap);
1593        return;
1594        }
1595        map = parent;
1596    }
1597    }
1598
1599
1600    /**
1601     * Convenience method to change the UI ActionMap for <code>component</code>
1602     * to <code>uiActionMap</code>. If <code>uiActionMap</code> is null,
1603     * this removes any previously installed UI ActionMap.
1604     *
1605     * @since 1.3
1606     */

1607    public static void replaceUIActionMap(JComponent JavaDoc component,
1608                      ActionMap JavaDoc uiActionMap) {
1609        ActionMap JavaDoc map = component.getActionMap((uiActionMap != null));;
1610
1611    while (map != null) {
1612        ActionMap JavaDoc parent = map.getParent();
1613        if (parent == null || (parent instanceof UIResource JavaDoc)) {
1614        map.setParent(uiActionMap);
1615        return;
1616        }
1617        map = parent;
1618    }
1619    }
1620
1621
1622    /**
1623     * Returns the InputMap provided by the UI for condition
1624     * <code>condition</code> in component <code>component</code>.
1625     * <p>This will return null if the UI has not installed a InputMap
1626     * of the specified type.
1627     *
1628     * @since 1.3
1629     */

1630    public static InputMap JavaDoc getUIInputMap(JComponent JavaDoc component, int condition) {
1631    InputMap JavaDoc map = component.getInputMap(condition, false);
1632    while (map != null) {
1633        InputMap JavaDoc parent = map.getParent();
1634        if (parent instanceof UIResource JavaDoc) {
1635        return parent;
1636        }
1637        map = parent;
1638    }
1639    return null;
1640    }
1641
1642    /**
1643     * Returns the ActionMap provided by the UI
1644     * in component <code>component</code>.
1645     * <p>This will return null if the UI has not installed an ActionMap.
1646     *
1647     * @since 1.3
1648     */

1649    public static ActionMap JavaDoc getUIActionMap(JComponent JavaDoc component) {
1650    ActionMap JavaDoc map = component.getActionMap(false);
1651    while (map != null) {
1652        ActionMap JavaDoc parent = map.getParent();
1653        if (parent instanceof UIResource JavaDoc) {
1654        return parent;
1655        }
1656        map = parent;
1657    }
1658    return null;
1659    }
1660
1661
1662    // Don't use String, as it's not guaranteed to be unique in a Hashtable.
1663
private static final Object JavaDoc sharedOwnerFrameKey =
1664       new StringBuffer JavaDoc("SwingUtilities.sharedOwnerFrame");
1665
1666    static class SharedOwnerFrame extends Frame implements WindowListener {
1667        public void addNotify() {
1668            super.addNotify();
1669            installListeners();
1670        }
1671
1672        /**
1673         * Install window listeners on owned windows to watch for displayability changes
1674         */

1675        void installListeners() {
1676            Window[] windows = getOwnedWindows();
1677            for (int ind = 0; ind < windows.length; ind++){
1678                Window window = windows[ind];
1679                if (window != null) {
1680                    window.removeWindowListener(this);
1681                    window.addWindowListener(this);
1682                }
1683            }
1684        }
1685
1686        /**
1687         * Watches for displayability changes and disposes shared instance if there are no
1688         * displayable children left.
1689         */

1690    public void windowClosed(WindowEvent e) {
1691        synchronized(getTreeLock()) {
1692        Window[] windows = getOwnedWindows();
1693        for (int ind = 0; ind < windows.length; ind++) {
1694            Window window = windows[ind];
1695            if (window != null) {
1696            if (window.isDisplayable()) {
1697                return;
1698            }
1699            window.removeWindowListener(this);
1700            }
1701        }
1702        dispose();
1703        }
1704        }
1705    public void windowOpened(WindowEvent e) {
1706    }
1707    public void windowClosing(WindowEvent e) {
1708    }
1709    public void windowIconified(WindowEvent e) {
1710    }
1711    public void windowDeiconified(WindowEvent e) {
1712    }
1713    public void windowActivated(WindowEvent e) {
1714    }
1715    public void windowDeactivated(WindowEvent e) {
1716    }
1717
1718        public void show() {
1719            // This frame can never be shown
1720
}
1721        public void dispose() {
1722            try {
1723                getToolkit().getSystemEventQueue();
1724                super.dispose();
1725            } catch (Exception JavaDoc e) {
1726                // untrusted code not allowed to dispose
1727
}
1728        }
1729    }
1730
1731    /**
1732     * Returns a toolkit-private, shared, invisible Frame
1733     * to be the owner for JDialogs and JWindows created with
1734     * null owners.
1735     * @exception HeadlessException if GraphicsEnvironment.isHeadless()
1736     * returns true.
1737     * @see java.awt.GraphicsEnvironment#isHeadless
1738     */

1739    static Frame getSharedOwnerFrame() throws HeadlessException {
1740        Frame sharedOwnerFrame =
1741            (Frame)SwingUtilities.appContextGet(sharedOwnerFrameKey);
1742        if (sharedOwnerFrame == null) {
1743            sharedOwnerFrame = new SharedOwnerFrame();
1744            SwingUtilities.appContextPut(sharedOwnerFrameKey,
1745                                         sharedOwnerFrame);
1746        }
1747        return sharedOwnerFrame;
1748    }
1749
1750    /**
1751     * Returns a SharedOwnerFrame's shutdown listener to dispose the SharedOwnerFrame
1752     * if it has no more displayable children.
1753     * @exception HeadlessException if GraphicsEnvironment.isHeadless()
1754     * returns true.
1755     * @see java.awt.GraphicsEnvironment#isHeadless
1756     */

1757    static WindowListener getSharedOwnerFrameShutdownListener() throws HeadlessException {
1758        Frame sharedOwnerFrame = getSharedOwnerFrame();
1759    return (WindowListener)sharedOwnerFrame;
1760    }
1761
1762    /* Don't make these AppContext accessors public or protected --
1763     * since AppContext is in sun.awt in 1.2, we shouldn't expose it
1764     * even indirectly with a public API.
1765     */

1766    // REMIND(aim): phase out use of 4 methods below since they
1767
// are just private covers for AWT methods (?)
1768

1769    static Object JavaDoc appContextGet(Object JavaDoc key) {
1770        return AppContext.getAppContext().get(key);
1771    }
1772
1773    static void appContextPut(Object JavaDoc key, Object JavaDoc value) {
1774        AppContext.getAppContext().put(key, value);
1775    }
1776
1777    static void appContextRemove(Object JavaDoc key) {
1778        AppContext.getAppContext().remove(key);
1779    }
1780
1781
1782    static Class JavaDoc loadSystemClass(String JavaDoc className) throws ClassNotFoundException JavaDoc {
1783    return Class.forName(className, true, Thread.currentThread().
1784                             getContextClassLoader());
1785    }
1786
1787
1788   /*
1789     * Convenience function for determining ComponentOrientation. Helps us
1790     * avoid having Munge directives throughout the code.
1791     */

1792    static boolean isLeftToRight( Component c ) {
1793        return c.getComponentOrientation().isLeftToRight();
1794    }
1795    private SwingUtilities() {
1796        throw new Error JavaDoc("SwingUtilities is just a container for static methods");
1797    }
1798
1799    /**
1800     * Returns true if the Icon <code>icon</code> is an instance of
1801     * ImageIcon, and the image it contains is the same as <code>image</code>.
1802     */

1803    static boolean doesIconReferenceImage(Icon JavaDoc icon, Image image) {
1804    Image iconImage = (icon != null && (icon instanceof ImageIcon JavaDoc)) ?
1805                       ((ImageIcon JavaDoc)icon).getImage() : null;
1806    return (iconImage == image);
1807    }
1808
1809    /**
1810     * Returns index of the first occurrence of <code>mnemonic</code>
1811     * within string <code>text</code>. Matching algorithm is not
1812     * case-sensitive.
1813     *
1814     * @param text The text to search through, may be null
1815     * @param mnemonic The mnemonic to find the character for.
1816     * @return index into the string if exists, otherwise -1
1817     */

1818    static int findDisplayedMnemonicIndex(String JavaDoc text, int mnemonic) {
1819        if (text == null || mnemonic == '\0') {
1820            return -1;
1821        }
1822
1823        char uc = Character.toUpperCase((char)mnemonic);
1824        char lc = Character.toLowerCase((char)mnemonic);
1825
1826        int uci = text.indexOf(uc);
1827        int lci = text.indexOf(lc);
1828
1829        if (uci == -1) {
1830            return lci;
1831        } else if(lci == -1) {
1832            return uci;
1833        } else {
1834            return (lci < uci) ? lci : uci;
1835        }
1836    }
1837
1838    /**
1839     * Stores the position and size of
1840     * the inner painting area of the specified component
1841     * in <code>r</code> and returns <code>r</code>.
1842     * The position and size specify the bounds of the component,
1843     * adjusted so as not to include the border area (the insets).
1844     * This method is useful for classes
1845     * that implement painting code.
1846     *
1847     * @param c the JComponent in question; if null, this method returns null
1848     * @param r the Rectangle instance to be modified;
1849     * may be null
1850     * @return null if the Component is null;
1851     * otherwise, returns the passed-in rectangle (if non-null)
1852     * or a new rectangle specifying position and size information
1853     *
1854     * @since 1.4
1855     */

1856    public static Rectangle calculateInnerArea(JComponent JavaDoc c, Rectangle r) {
1857        if (c == null) {
1858            return null;
1859        }
1860        Rectangle rect = r;
1861        Insets insets = c.getInsets();
1862
1863        if (rect == null) {
1864            rect = new Rectangle();
1865        }
1866
1867        rect.x = insets.left;
1868        rect.y = insets.top;
1869        rect.width = c.getWidth() - insets.left - insets.right;
1870        rect.height = c.getHeight() - insets.top - insets.bottom;
1871
1872        return rect;
1873    }
1874}
1875
Popular Tags