1 /*
   2  * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package javax.swing;
  26 
  27 import sun.reflect.misc.ReflectUtil;
  28 import sun.swing.SwingUtilities2;
  29 import sun.swing.UIAction;
  30 
  31 import java.applet.*;
  32 
  33 import java.awt.*;
  34 import java.awt.event.*;
  35 import java.awt.dnd.DropTarget;
  36 
  37 import java.lang.reflect.*;
  38 
  39 import javax.accessibility.*;
  40 import javax.swing.event.MenuDragMouseEvent;
  41 import javax.swing.plaf.UIResource;
  42 import javax.swing.text.View;
  43 import java.security.AccessController;
  44 import sun.security.action.GetPropertyAction;
  45 
  46 import sun.awt.AppContext;
  47 
  48 /**
  49  * A collection of utility methods for Swing.
  50  *
  51  * @author unknown
  52  */
  53 public class SwingUtilities implements SwingConstants
  54 {
  55     // These states are system-wide, rather than AppContext wide.
  56     private static boolean canAccessEventQueue = false;
  57     private static boolean eventQueueTested = false;
  58 
  59     /**
  60      * Indicates if we should change the drop target when a
  61      * {@code TransferHandler} is set.
  62      */
  63     private static boolean suppressDropSupport;
  64 
  65     /**
  66      * Indiciates if we've checked the system property for suppressing
  67      * drop support.
  68      */
  69     private static boolean checkedSuppressDropSupport;
  70 
  71 
  72     /**
  73      * Returns true if <code>setTransferHandler</code> should change the
  74      * <code>DropTarget</code>.
  75      */
  76     private static boolean getSuppressDropTarget() {
  77         if (!checkedSuppressDropSupport) {
  78             suppressDropSupport = Boolean.valueOf(
  79                 AccessController.doPrivileged(
  80                     new GetPropertyAction("suppressSwingDropSupport")));
  81             checkedSuppressDropSupport = true;
  82         }
  83         return suppressDropSupport;
  84     }
  85 
  86     /**
  87      * Installs a {@code DropTarget} on the component as necessary for a
  88      * {@code TransferHandler} change.
  89      */
  90     static void installSwingDropTargetAsNecessary(Component c,
  91                                                          TransferHandler t) {
  92 
  93         if (!getSuppressDropTarget()) {
  94             DropTarget dropHandler = c.getDropTarget();
  95             if ((dropHandler == null) || (dropHandler instanceof UIResource)) {
  96                 if (t == null) {
  97                     c.setDropTarget(null);
  98                 } else if (!GraphicsEnvironment.isHeadless()) {
  99                     c.setDropTarget(new TransferHandler.SwingDropTarget(c));
 100                 }
 101             }
 102         }
 103     }
 104 
 105     /**
 106      * Return true if <code>a</code> contains <code>b</code>
 107      */
 108     public static final boolean isRectangleContainingRectangle(Rectangle a,Rectangle b) {
 109         return b.x >= a.x && (b.x + b.width) <= (a.x + a.width) &&
 110                 b.y >= a.y && (b.y + b.height) <= (a.y + a.height);
 111     }
 112 
 113     /**
 114      * Return the rectangle (0,0,bounds.width,bounds.height) for the component <code>aComponent</code>
 115      */
 116     public static Rectangle getLocalBounds(Component aComponent) {
 117         Rectangle b = new Rectangle(aComponent.getBounds());
 118         b.x = b.y = 0;
 119         return b;
 120     }
 121 
 122 
 123     /**
 124      * Returns the first <code>Window </code> ancestor of <code>c</code>, or
 125      * {@code null} if <code>c</code> is not contained inside a <code>Window</code>.
 126      *
 127      * @param c <code>Component</code> to get <code>Window</code> ancestor
 128      *        of.
 129      * @return the first <code>Window </code> ancestor of <code>c</code>, or
 130      *         {@code null} if <code>c</code> is not contained inside a
 131      *         <code>Window</code>.
 132      * @since 1.3
 133      */
 134     public static Window getWindowAncestor(Component c) {
 135         for(Container p = c.getParent(); p != null; p = p.getParent()) {
 136             if (p instanceof Window) {
 137                 return (Window)p;
 138             }
 139         }
 140         return null;
 141     }
 142 
 143     /**
 144      * Converts the location <code>x</code> <code>y</code> to the
 145      * parents coordinate system, returning the location.
 146      */
 147     static Point convertScreenLocationToParent(Container parent,int x, int y) {
 148         for (Container p = parent; p != null; p = p.getParent()) {
 149             if (p instanceof Window) {
 150                 Point point = new Point(x, y);
 151 
 152                 SwingUtilities.convertPointFromScreen(point, parent);
 153                 return point;
 154             }
 155         }
 156         throw new Error("convertScreenLocationToParent: no window ancestor");
 157     }
 158 
 159     /**
 160      * Convert a <code>aPoint</code> in <code>source</code> coordinate system to
 161      * <code>destination</code> coordinate system.
 162      * If <code>source</code> is {@code null}, <code>aPoint</code> is assumed to be in <code>destination</code>'s
 163      * root component coordinate system.
 164      * If <code>destination</code> is {@code null}, <code>aPoint</code> will be converted to <code>source</code>'s
 165      * root component coordinate system.
 166      * If both <code>source</code> and <code>destination</code> are {@code null}, return <code>aPoint</code>
 167      * without any conversion.
 168      */
 169     public static Point convertPoint(Component source,Point aPoint,Component destination) {
 170         Point p;
 171 
 172         if(source == null && destination == null)
 173             return aPoint;
 174         if(source == null) {
 175             source = getWindowAncestor(destination);
 176             if(source == null)
 177                 throw new Error("Source component not connected to component tree hierarchy");
 178         }
 179         p = new Point(aPoint);
 180         convertPointToScreen(p,source);
 181         if(destination == null) {
 182             destination = getWindowAncestor(source);
 183             if(destination == null)
 184                 throw new Error("Destination component not connected to component tree hierarchy");
 185         }
 186         convertPointFromScreen(p,destination);
 187         return p;
 188     }
 189 
 190     /**
 191      * Convert the point <code>(x,y)</code> in <code>source</code> coordinate system to
 192      * <code>destination</code> coordinate system.
 193      * If <code>source</code> is {@code null}, <code>(x,y)</code> is assumed to be in <code>destination</code>'s
 194      * root component coordinate system.
 195      * If <code>destination</code> is {@code null}, <code>(x,y)</code> will be converted to <code>source</code>'s
 196      * root component coordinate system.
 197      * If both <code>source</code> and <code>destination</code> are {@code null}, return <code>(x,y)</code>
 198      * without any conversion.
 199      */
 200     public static Point convertPoint(Component source,int x, int y,Component destination) {
 201         Point point = new Point(x,y);
 202         return convertPoint(source,point,destination);
 203     }
 204 
 205     /**
 206      * Convert the rectangle <code>aRectangle</code> in <code>source</code> coordinate system to
 207      * <code>destination</code> coordinate system.
 208      * If <code>source</code> is {@code null}, <code>aRectangle</code> is assumed to be in <code>destination</code>'s
 209      * root component coordinate system.
 210      * If <code>destination</code> is {@code null}, <code>aRectangle</code> will be converted to <code>source</code>'s
 211      * root component coordinate system.
 212      * If both <code>source</code> and <code>destination</code> are {@code null}, return <code>aRectangle</code>
 213      * without any conversion.
 214      */
 215     public static Rectangle convertRectangle(Component source,Rectangle aRectangle,Component destination) {
 216         Point point = new Point(aRectangle.x,aRectangle.y);
 217         point =  convertPoint(source,point,destination);
 218         return new Rectangle(point.x,point.y,aRectangle.width,aRectangle.height);
 219     }
 220 
 221     /**
 222      * Convenience method for searching above <code>comp</code> in the
 223      * component hierarchy and returns the first object of class <code>c</code> it
 224      * finds. Can return {@code null}, if a class <code>c</code> cannot be found.
 225      */
 226     public static Container getAncestorOfClass(Class<?> c, Component comp)
 227     {
 228         if(comp == null || c == null)
 229             return null;
 230 
 231         Container parent = comp.getParent();
 232         while(parent != null && !(c.isInstance(parent)))
 233             parent = parent.getParent();
 234         return parent;
 235     }
 236 
 237     /**
 238      * Convenience method for searching above <code>comp</code> in the
 239      * component hierarchy and returns the first object of <code>name</code> it
 240      * finds. Can return {@code null}, if <code>name</code> cannot be found.
 241      */
 242     public static Container getAncestorNamed(String name, Component comp) {
 243         if(comp == null || name == null)
 244             return null;
 245 
 246         Container parent = comp.getParent();
 247         while(parent != null && !(name.equals(parent.getName())))
 248             parent = parent.getParent();
 249         return parent;
 250     }
 251 
 252     /**
 253      * Returns the deepest visible descendent Component of <code>parent</code>
 254      * that contains the location <code>x</code>, <code>y</code>.
 255      * If <code>parent</code> does not contain the specified location,
 256      * then <code>null</code> is returned.  If <code>parent</code> is not a
 257      * container, or none of <code>parent</code>'s visible descendents
 258      * contain the specified location, <code>parent</code> is returned.
 259      *
 260      * @param parent the root component to begin the search
 261      * @param x the x target location
 262      * @param y the y target location
 263      */
 264     public static Component getDeepestComponentAt(Component parent, int x, int y) {
 265         if (!parent.contains(x, y)) {
 266             return null;
 267         }
 268         if (parent instanceof Container) {
 269             Component components[] = ((Container)parent).getComponents();
 270             for (Component comp : components) {
 271                 if (comp != null && comp.isVisible()) {
 272                     Point loc = comp.getLocation();
 273                     if (comp instanceof Container) {
 274                         comp = getDeepestComponentAt(comp, x - loc.x, y - loc.y);
 275                     } else {
 276                         comp = comp.getComponentAt(x - loc.x, y - loc.y);
 277                     }
 278                     if (comp != null && comp.isVisible()) {
 279                         return comp;
 280                     }
 281                 }
 282             }
 283         }
 284         return parent;
 285     }
 286 
 287 
 288     /**
 289      * Returns a MouseEvent similar to <code>sourceEvent</code> except that its x
 290      * and y members have been converted to <code>destination</code>'s coordinate
 291      * system.  If <code>source</code> is {@code null}, <code>sourceEvent</code> x and y members
 292      * are assumed to be into <code>destination</code>'s root component coordinate system.
 293      * If <code>destination</code> is <code>null</code>, the
 294      * returned MouseEvent will be in <code>source</code>'s coordinate system.
 295      * <code>sourceEvent</code> will not be changed. A new event is returned.
 296      * the <code>source</code> field of the returned event will be set
 297      * to <code>destination</code> if destination is non-{@code null}
 298      * use the translateMouseEvent() method to translate a mouse event from
 299      * one component to another without changing the source.
 300      */
 301     public static MouseEvent convertMouseEvent(Component source,
 302                                                MouseEvent sourceEvent,
 303                                                Component destination) {
 304         Point p = convertPoint(source,new Point(sourceEvent.getX(),
 305                                                 sourceEvent.getY()),
 306                                destination);
 307         Component newSource;
 308 
 309         if(destination != null)
 310             newSource = destination;
 311         else
 312             newSource = source;
 313 
 314         MouseEvent newEvent;
 315         if (sourceEvent instanceof MouseWheelEvent) {
 316             MouseWheelEvent sourceWheelEvent = (MouseWheelEvent)sourceEvent;
 317             newEvent = new MouseWheelEvent(newSource,
 318                                            sourceWheelEvent.getID(),
 319                                            sourceWheelEvent.getWhen(),
 320                                            sourceWheelEvent.getModifiers()
 321                                                    | sourceWheelEvent.getModifiersEx(),
 322                                            p.x,p.y,
 323                                            sourceWheelEvent.getXOnScreen(),
 324                                            sourceWheelEvent.getYOnScreen(),
 325                                            sourceWheelEvent.getClickCount(),
 326                                            sourceWheelEvent.isPopupTrigger(),
 327                                            sourceWheelEvent.getScrollType(),
 328                                            sourceWheelEvent.getScrollAmount(),
 329                                            sourceWheelEvent.getWheelRotation());
 330         }
 331         else if (sourceEvent instanceof MenuDragMouseEvent) {
 332             MenuDragMouseEvent sourceMenuDragEvent = (MenuDragMouseEvent)sourceEvent;
 333             newEvent = new MenuDragMouseEvent(newSource,
 334                                               sourceMenuDragEvent.getID(),
 335                                               sourceMenuDragEvent.getWhen(),
 336                                               sourceMenuDragEvent.getModifiers()
 337                                                       | sourceMenuDragEvent.getModifiersEx(),
 338                                               p.x,p.y,
 339                                               sourceMenuDragEvent.getXOnScreen(),
 340                                               sourceMenuDragEvent.getYOnScreen(),
 341                                               sourceMenuDragEvent.getClickCount(),
 342                                               sourceMenuDragEvent.isPopupTrigger(),
 343                                               sourceMenuDragEvent.getPath(),
 344                                               sourceMenuDragEvent.getMenuSelectionManager());
 345         }
 346         else {
 347             newEvent = new MouseEvent(newSource,
 348                                       sourceEvent.getID(),
 349                                       sourceEvent.getWhen(),
 350                                       sourceEvent.getModifiers()
 351                                               | sourceEvent.getModifiersEx(),
 352                                       p.x,p.y,
 353                                       sourceEvent.getXOnScreen(),
 354                                       sourceEvent.getYOnScreen(),
 355                                       sourceEvent.getClickCount(),
 356                                       sourceEvent.isPopupTrigger(),
 357                                       sourceEvent.getButton());
 358         }
 359         return newEvent;
 360     }
 361 
 362 
 363     /**
 364      * Convert a point from a component's coordinate system to
 365      * screen coordinates.
 366      *
 367      * @param p  a Point object (converted to the new coordinate system)
 368      * @param c  a Component object
 369      */
 370     public static void convertPointToScreen(Point p,Component c) {
 371             Rectangle b;
 372             int x,y;
 373 
 374             do {
 375                 if(c instanceof JComponent) {
 376                     x = c.getX();
 377                     y = c.getY();
 378                 } else if(c instanceof java.applet.Applet ||
 379                           c instanceof java.awt.Window) {
 380                     try {
 381                         Point pp = c.getLocationOnScreen();
 382                         x = pp.x;
 383                         y = pp.y;
 384                     } catch (IllegalComponentStateException icse) {
 385                         x = c.getX();
 386                         y = c.getY();
 387                     }
 388                 } else {
 389                     x = c.getX();
 390                     y = c.getY();
 391                 }
 392 
 393                 p.x += x;
 394                 p.y += y;
 395 
 396                 if(c instanceof java.awt.Window || c instanceof java.applet.Applet)
 397                     break;
 398                 c = c.getParent();
 399             } while(c != null);
 400         }
 401 
 402     /**
 403      * Convert a point from a screen coordinates to a component's
 404      * coordinate system
 405      *
 406      * @param p  a Point object (converted to the new coordinate system)
 407      * @param c  a Component object
 408      */
 409     public static void convertPointFromScreen(Point p,Component c) {
 410         Rectangle b;
 411         int x,y;
 412 
 413         do {
 414             if(c instanceof JComponent) {
 415                 x = c.getX();
 416                 y = c.getY();
 417             }  else if(c instanceof java.applet.Applet ||
 418                        c instanceof java.awt.Window) {
 419                 try {
 420                     Point pp = c.getLocationOnScreen();
 421                     x = pp.x;
 422                     y = pp.y;
 423                 } catch (IllegalComponentStateException icse) {
 424                     x = c.getX();
 425                     y = c.getY();
 426                 }
 427             } else {
 428                 x = c.getX();
 429                 y = c.getY();
 430             }
 431 
 432             p.x -= x;
 433             p.y -= y;
 434 
 435             if(c instanceof java.awt.Window || c instanceof java.applet.Applet)
 436                 break;
 437             c = c.getParent();
 438         } while(c != null);
 439     }
 440 
 441     /**
 442      * Returns the first <code>Window </code> ancestor of <code>c</code>, or
 443      * {@code null} if <code>c</code> is not contained inside a <code>Window</code>.
 444      * <p>
 445      * Note: This method provides the same functionality as
 446      * <code>getWindowAncestor</code>.
 447      *
 448      * @param c <code>Component</code> to get <code>Window</code> ancestor
 449      *        of.
 450      * @return the first <code>Window </code> ancestor of <code>c</code>, or
 451      *         {@code null} if <code>c</code> is not contained inside a
 452      *         <code>Window</code>.
 453      */
 454     public static Window windowForComponent(Component c) {
 455         return getWindowAncestor(c);
 456     }
 457 
 458     /**
 459      * Return <code>true</code> if a component <code>a</code> descends from a component <code>b</code>
 460      */
 461     public static boolean isDescendingFrom(Component a,Component b) {
 462         if(a == b)
 463             return true;
 464         for(Container p = a.getParent();p!=null;p=p.getParent())
 465             if(p == b)
 466                 return true;
 467         return false;
 468     }
 469 
 470 
 471     /**
 472      * Convenience to calculate the intersection of two rectangles
 473      * without allocating a new rectangle.
 474      * If the two rectangles don't intersect,
 475      * then the returned rectangle begins at (0,0)
 476      * and has zero width and height.
 477      *
 478      * @param x       the X coordinate of the first rectangle's top-left point
 479      * @param y       the Y coordinate of the first rectangle's top-left point
 480      * @param width   the width of the first rectangle
 481      * @param height  the height of the first rectangle
 482      * @param dest    the second rectangle
 483      *
 484      * @return <code>dest</code>, modified to specify the intersection
 485      */
 486     public static Rectangle computeIntersection(int x,int y,int width,int height,Rectangle dest) {
 487         int x1 = (x > dest.x) ? x : dest.x;
 488         int x2 = ((x+width) < (dest.x + dest.width)) ? (x+width) : (dest.x + dest.width);
 489         int y1 = (y > dest.y) ? y : dest.y;
 490         int y2 = ((y + height) < (dest.y + dest.height) ? (y+height) : (dest.y + dest.height));
 491 
 492         dest.x = x1;
 493         dest.y = y1;
 494         dest.width = x2 - x1;
 495         dest.height = y2 - y1;
 496 
 497         // If rectangles don't intersect, return zero'd intersection.
 498         if (dest.width < 0 || dest.height < 0) {
 499             dest.x = dest.y = dest.width = dest.height = 0;
 500         }
 501 
 502         return dest;
 503     }
 504 
 505     /**
 506      * Convenience method that calculates the union of two rectangles
 507      * without allocating a new rectangle.
 508      *
 509      * @param x the x-coordinate of the first rectangle
 510      * @param y the y-coordinate of the first rectangle
 511      * @param width the width of the first rectangle
 512      * @param height the height of the first rectangle
 513      * @param dest  the coordinates of the second rectangle; the union
 514      *    of the two rectangles is returned in this rectangle
 515      * @return the <code>dest</code> <code>Rectangle</code>
 516      */
 517     public static Rectangle computeUnion(int x,int y,int width,int height,Rectangle dest) {
 518         int x1 = (x < dest.x) ? x : dest.x;
 519         int x2 = ((x+width) > (dest.x + dest.width)) ? (x+width) : (dest.x + dest.width);
 520         int y1 = (y < dest.y) ? y : dest.y;
 521         int y2 = ((y+height) > (dest.y + dest.height)) ? (y+height) : (dest.y + dest.height);
 522 
 523         dest.x = x1;
 524         dest.y = y1;
 525         dest.width = (x2 - x1);
 526         dest.height= (y2 - y1);
 527         return dest;
 528     }
 529 
 530     /**
 531      * Convenience returning an array of rect representing the regions within
 532      * <code>rectA</code> that do not overlap with <code>rectB</code>. If the
 533      * two Rects do not overlap, returns an empty array
 534      */
 535     public static Rectangle[] computeDifference(Rectangle rectA,Rectangle rectB) {
 536         if (rectB == null || !rectA.intersects(rectB) || isRectangleContainingRectangle(rectB,rectA)) {
 537             return new Rectangle[0];
 538         }
 539 
 540         Rectangle t = new Rectangle();
 541         Rectangle a=null,b=null,c=null,d=null;
 542         Rectangle result[];
 543         int rectCount = 0;
 544 
 545         /* rectA contains rectB */
 546         if (isRectangleContainingRectangle(rectA,rectB)) {
 547             t.x = rectA.x; t.y = rectA.y; t.width = rectB.x - rectA.x; t.height = rectA.height;
 548             if(t.width > 0 && t.height > 0) {
 549                 a = new Rectangle(t);
 550                 rectCount++;
 551             }
 552 
 553             t.x = rectB.x; t.y = rectA.y; t.width = rectB.width; t.height = rectB.y - rectA.y;
 554             if(t.width > 0 && t.height > 0) {
 555                 b = new Rectangle(t);
 556                 rectCount++;
 557             }
 558 
 559             t.x = rectB.x; t.y = rectB.y + rectB.height; t.width = rectB.width;
 560             t.height = rectA.y + rectA.height - (rectB.y + rectB.height);
 561             if(t.width > 0 && t.height > 0) {
 562                 c = new Rectangle(t);
 563                 rectCount++;
 564             }
 565 
 566             t.x = rectB.x + rectB.width; t.y = rectA.y; t.width = rectA.x + rectA.width - (rectB.x + rectB.width);
 567             t.height = rectA.height;
 568             if(t.width > 0 && t.height > 0) {
 569                 d = new Rectangle(t);
 570                 rectCount++;
 571             }
 572         } else {
 573             /* 1 */
 574             if (rectB.x <= rectA.x && rectB.y <= rectA.y) {
 575                 if ((rectB.x + rectB.width) > (rectA.x + rectA.width)) {
 576 
 577                     t.x = rectA.x; t.y = rectB.y + rectB.height;
 578                     t.width = rectA.width; t.height = rectA.y + rectA.height - (rectB.y + rectB.height);
 579                     if(t.width > 0 && t.height > 0) {
 580                         a = t;
 581                         rectCount++;
 582                     }
 583                 } else if ((rectB.y + rectB.height) > (rectA.y + rectA.height)) {
 584                     t.setBounds((rectB.x + rectB.width), rectA.y,
 585                                 (rectA.x + rectA.width) - (rectB.x + rectB.width), rectA.height);
 586                     if(t.width > 0 && t.height > 0) {
 587                         a = t;
 588                         rectCount++;
 589                     }
 590                 } else {
 591                     t.setBounds((rectB.x + rectB.width), rectA.y,
 592                                 (rectA.x + rectA.width) - (rectB.x + rectB.width),
 593                                 (rectB.y + rectB.height) - rectA.y);
 594                     if(t.width > 0 && t.height > 0) {
 595                         a = new Rectangle(t);
 596                         rectCount++;
 597                     }
 598 
 599                     t.setBounds(rectA.x, (rectB.y + rectB.height), rectA.width,
 600                                 (rectA.y + rectA.height) - (rectB.y + rectB.height));
 601                     if(t.width > 0 && t.height > 0) {
 602                         b = new Rectangle(t);
 603                         rectCount++;
 604                     }
 605                 }
 606             } else if (rectB.x <= rectA.x && (rectB.y + rectB.height) >= (rectA.y + rectA.height)) {
 607                 if ((rectB.x + rectB.width) > (rectA.x + rectA.width)) {
 608                     t.setBounds(rectA.x, rectA.y, rectA.width, rectB.y - rectA.y);
 609                     if(t.width > 0 && t.height > 0) {
 610                         a = t;
 611                         rectCount++;
 612                     }
 613                 } else {
 614                     t.setBounds(rectA.x, rectA.y, rectA.width, rectB.y - rectA.y);
 615                     if(t.width > 0 && t.height > 0) {
 616                         a = new Rectangle(t);
 617                         rectCount++;
 618                     }
 619                     t.setBounds((rectB.x + rectB.width), rectB.y,
 620                                 (rectA.x + rectA.width) - (rectB.x + rectB.width),
 621                                 (rectA.y + rectA.height) - rectB.y);
 622                     if(t.width > 0 && t.height > 0) {
 623                         b = new Rectangle(t);
 624                         rectCount++;
 625                     }
 626                 }
 627             } else if (rectB.x <= rectA.x) {
 628                 if ((rectB.x + rectB.width) >= (rectA.x + rectA.width)) {
 629                     t.setBounds(rectA.x, rectA.y, rectA.width, rectB.y - rectA.y);
 630                     if(t.width>0 && t.height > 0) {
 631                         a = new Rectangle(t);
 632                         rectCount++;
 633                     }
 634 
 635                     t.setBounds(rectA.x, (rectB.y + rectB.height), rectA.width,
 636                                 (rectA.y + rectA.height) - (rectB.y + rectB.height));
 637                     if(t.width > 0 && t.height > 0) {
 638                         b = new Rectangle(t);
 639                         rectCount++;
 640                     }
 641                 } else {
 642                     t.setBounds(rectA.x, rectA.y, rectA.width, rectB.y - rectA.y);
 643                     if(t.width > 0 && t.height > 0) {
 644                         a = new Rectangle(t);
 645                         rectCount++;
 646                     }
 647 
 648                     t.setBounds((rectB.x + rectB.width), rectB.y,
 649                                 (rectA.x + rectA.width) - (rectB.x + rectB.width),
 650                                 rectB.height);
 651                     if(t.width > 0 && t.height > 0) {
 652                         b = new Rectangle(t);
 653                         rectCount++;
 654                     }
 655 
 656                     t.setBounds(rectA.x, (rectB.y + rectB.height), rectA.width,
 657                                 (rectA.y + rectA.height) - (rectB.y + rectB.height));
 658                     if(t.width > 0 && t.height > 0) {
 659                         c = new Rectangle(t);
 660                         rectCount++;
 661                     }
 662                 }
 663             } else if (rectB.x <= (rectA.x + rectA.width) && (rectB.x + rectB.width) > (rectA.x + rectA.width)) {
 664                 if (rectB.y <= rectA.y && (rectB.y + rectB.height) > (rectA.y + rectA.height)) {
 665                     t.setBounds(rectA.x, rectA.y, rectB.x - rectA.x, rectA.height);
 666                     if(t.width > 0 && t.height > 0) {
 667                         a = t;
 668                         rectCount++;
 669                     }
 670                 } else if (rectB.y <= rectA.y) {
 671                     t.setBounds(rectA.x, rectA.y, rectB.x - rectA.x,
 672                                 (rectB.y + rectB.height) - rectA.y);
 673                     if(t.width > 0 && t.height > 0) {
 674                         a = new Rectangle(t);
 675                         rectCount++;
 676                     }
 677 
 678                     t.setBounds(rectA.x, (rectB.y + rectB.height), rectA.width,
 679                                 (rectA.y + rectA.height) - (rectB.y + rectB.height));
 680                     if(t.width > 0 && t.height > 0) {
 681                         b = new Rectangle(t);
 682                         rectCount++;
 683                     }
 684                 } else if ((rectB.y + rectB.height) > (rectA.y + rectA.height)) {
 685                     t.setBounds(rectA.x, rectA.y, rectA.width, rectB.y - rectA.y);
 686                     if(t.width > 0 && t.height > 0) {
 687                         a = new Rectangle(t);
 688                         rectCount++;
 689                     }
 690 
 691                     t.setBounds(rectA.x, rectB.y, rectB.x - rectA.x,
 692                                 (rectA.y + rectA.height) - rectB.y);
 693                     if(t.width > 0 && t.height > 0) {
 694                         b = new Rectangle(t);
 695                         rectCount++;
 696                     }
 697                 } else {
 698                     t.setBounds(rectA.x, rectA.y, rectA.width, rectB.y - rectA.y);
 699                     if(t.width > 0 && t.height > 0) {
 700                         a = new Rectangle(t);
 701                         rectCount++;
 702                     }
 703 
 704                     t.setBounds(rectA.x, rectB.y, rectB.x - rectA.x,
 705                                 rectB.height);
 706                     if(t.width > 0 && t.height > 0) {
 707                         b = new Rectangle(t);
 708                         rectCount++;
 709                     }
 710 
 711                     t.setBounds(rectA.x, (rectB.y + rectB.height), rectA.width,
 712                                 (rectA.y + rectA.height) - (rectB.y + rectB.height));
 713                     if(t.width > 0 && t.height > 0) {
 714                         c = new Rectangle(t);
 715                         rectCount++;
 716                     }
 717                 }
 718             } else if (rectB.x >= rectA.x && (rectB.x + rectB.width) <= (rectA.x + rectA.width)) {
 719                 if (rectB.y <= rectA.y && (rectB.y + rectB.height) > (rectA.y + rectA.height)) {
 720                     t.setBounds(rectA.x, rectA.y, rectB.x - rectA.x, rectA.height);
 721                     if(t.width > 0 && t.height > 0) {
 722                         a = new Rectangle(t);
 723                         rectCount++;
 724                     }
 725                     t.setBounds((rectB.x + rectB.width), rectA.y,
 726                                 (rectA.x + rectA.width) - (rectB.x + rectB.width), rectA.height);
 727                     if(t.width > 0 && t.height > 0) {
 728                         b = new Rectangle(t);
 729                         rectCount++;
 730                     }
 731                 } else if (rectB.y <= rectA.y) {
 732                     t.setBounds(rectA.x, rectA.y, rectB.x - rectA.x, rectA.height);
 733                     if(t.width > 0 && t.height > 0) {
 734                         a = new Rectangle(t);
 735                         rectCount++;
 736                     }
 737 
 738                     t.setBounds(rectB.x, (rectB.y + rectB.height),
 739                                 rectB.width,
 740                                 (rectA.y + rectA.height) - (rectB.y + rectB.height));
 741                     if(t.width > 0 && t.height > 0) {
 742                         b = new Rectangle(t);
 743                         rectCount++;
 744                     }
 745 
 746                     t.setBounds((rectB.x + rectB.width), rectA.y,
 747                                 (rectA.x + rectA.width) - (rectB.x + rectB.width), rectA.height);
 748                     if(t.width > 0 && t.height > 0) {
 749                         c = new Rectangle(t);
 750                         rectCount++;
 751                     }
 752                 } else {
 753                     t.setBounds(rectA.x, rectA.y, rectB.x - rectA.x, rectA.height);
 754                     if(t.width > 0 && t.height > 0) {
 755                         a = new Rectangle(t);
 756                         rectCount++;
 757                     }
 758 
 759                     t.setBounds(rectB.x, rectA.y, rectB.width,
 760                                 rectB.y - rectA.y);
 761                     if(t.width > 0 && t.height > 0) {
 762                         b = new Rectangle(t);
 763                         rectCount++;
 764                     }
 765 
 766                     t.setBounds((rectB.x + rectB.width), rectA.y,
 767                                 (rectA.x + rectA.width) - (rectB.x + rectB.width), rectA.height);
 768                     if(t.width > 0 && t.height > 0) {
 769                         c = new Rectangle(t);
 770                         rectCount++;
 771                     }
 772                 }
 773             }
 774         }
 775 
 776         result = new Rectangle[rectCount];
 777         rectCount = 0;
 778         if(a != null)
 779             result[rectCount++] = a;
 780         if(b != null)
 781             result[rectCount++] = b;
 782         if(c != null)
 783             result[rectCount++] = c;
 784         if(d != null)
 785             result[rectCount++] = d;
 786         return result;
 787     }
 788 
 789     /**
 790      * Returns true if the mouse event specifies the left mouse button.
 791      *
 792      * @param anEvent  a MouseEvent object
 793      * @return true if the left mouse button was active
 794      */
 795     public static boolean isLeftMouseButton(MouseEvent anEvent) {
 796          return ((anEvent.getModifiersEx() & InputEvent.BUTTON1_DOWN_MASK) != 0 ||
 797                  anEvent.getButton() == MouseEvent.BUTTON1);
 798     }
 799 
 800     /**
 801      * Returns true if the mouse event specifies the middle mouse button.
 802      *
 803      * @param anEvent  a MouseEvent object
 804      * @return true if the middle mouse button was active
 805      */
 806     public static boolean isMiddleMouseButton(MouseEvent anEvent) {
 807         return ((anEvent.getModifiersEx() & InputEvent.BUTTON2_DOWN_MASK) != 0 ||
 808                 anEvent.getButton() == MouseEvent.BUTTON2);
 809     }
 810 
 811     /**
 812      * Returns true if the mouse event specifies the right mouse button.
 813      *
 814      * @param anEvent  a MouseEvent object
 815      * @return true if the right mouse button was active
 816      */
 817     public static boolean isRightMouseButton(MouseEvent anEvent) {
 818         return ((anEvent.getModifiersEx() & InputEvent.BUTTON3_DOWN_MASK) != 0 ||
 819                 anEvent.getButton() == MouseEvent.BUTTON3);
 820     }
 821 
 822     /**
 823      * Compute the width of the string using a font with the specified
 824      * "metrics" (sizes).
 825      *
 826      * @param fm   a FontMetrics object to compute with
 827      * @param str  the String to compute
 828      * @return an int containing the string width
 829      */
 830     public static int computeStringWidth(FontMetrics fm,String str) {
 831         // You can't assume that a string's width is the sum of its
 832         // characters' widths in Java2D -- it may be smaller due to
 833         // kerning, etc.
 834         return SwingUtilities2.stringWidth(null, fm, str);
 835     }
 836 
 837     /**
 838      * Compute and return the location of the icons origin, the
 839      * location of origin of the text baseline, and a possibly clipped
 840      * version of the compound labels string.  Locations are computed
 841      * relative to the viewR rectangle.
 842      * The JComponents orientation (LEADING/TRAILING) will also be taken
 843      * into account and translated into LEFT/RIGHT values accordingly.
 844      */
 845     public static String layoutCompoundLabel(JComponent c,
 846                                              FontMetrics fm,
 847                                              String text,
 848                                              Icon icon,
 849                                              int verticalAlignment,
 850                                              int horizontalAlignment,
 851                                              int verticalTextPosition,
 852                                              int horizontalTextPosition,
 853                                              Rectangle viewR,
 854                                              Rectangle iconR,
 855                                              Rectangle textR,
 856                                              int textIconGap)
 857     {
 858         boolean orientationIsLeftToRight = true;
 859         int     hAlign = horizontalAlignment;
 860         int     hTextPos = horizontalTextPosition;
 861 
 862         if (c != null) {
 863             if (!(c.getComponentOrientation().isLeftToRight())) {
 864                 orientationIsLeftToRight = false;
 865             }
 866         }
 867 
 868         // Translate LEADING/TRAILING values in horizontalAlignment
 869         // to LEFT/RIGHT values depending on the components orientation
 870         switch (horizontalAlignment) {
 871         case LEADING:
 872             hAlign = (orientationIsLeftToRight) ? LEFT : RIGHT;
 873             break;
 874         case TRAILING:
 875             hAlign = (orientationIsLeftToRight) ? RIGHT : LEFT;
 876             break;
 877         }
 878 
 879         // Translate LEADING/TRAILING values in horizontalTextPosition
 880         // to LEFT/RIGHT values depending on the components orientation
 881         switch (horizontalTextPosition) {
 882         case LEADING:
 883             hTextPos = (orientationIsLeftToRight) ? LEFT : RIGHT;
 884             break;
 885         case TRAILING:
 886             hTextPos = (orientationIsLeftToRight) ? RIGHT : LEFT;
 887             break;
 888         }
 889 
 890         return layoutCompoundLabelImpl(c,
 891                                        fm,
 892                                        text,
 893                                        icon,
 894                                        verticalAlignment,
 895                                        hAlign,
 896                                        verticalTextPosition,
 897                                        hTextPos,
 898                                        viewR,
 899                                        iconR,
 900                                        textR,
 901                                        textIconGap);
 902     }
 903 
 904     /**
 905      * Compute and return the location of the icons origin, the
 906      * location of origin of the text baseline, and a possibly clipped
 907      * version of the compound labels string.  Locations are computed
 908      * relative to the viewR rectangle.
 909      * This layoutCompoundLabel() does not know how to handle LEADING/TRAILING
 910      * values in horizontalTextPosition (they will default to RIGHT) and in
 911      * horizontalAlignment (they will default to CENTER).
 912      * Use the other version of layoutCompoundLabel() instead.
 913      */
 914     public static String layoutCompoundLabel(
 915         FontMetrics fm,
 916         String text,
 917         Icon icon,
 918         int verticalAlignment,
 919         int horizontalAlignment,
 920         int verticalTextPosition,
 921         int horizontalTextPosition,
 922         Rectangle viewR,
 923         Rectangle iconR,
 924         Rectangle textR,
 925         int textIconGap)
 926     {
 927         return layoutCompoundLabelImpl(null, fm, text, icon,
 928                                        verticalAlignment,
 929                                        horizontalAlignment,
 930                                        verticalTextPosition,
 931                                        horizontalTextPosition,
 932                                        viewR, iconR, textR, textIconGap);
 933     }
 934 
 935     /**
 936      * Compute and return the location of the icons origin, the
 937      * location of origin of the text baseline, and a possibly clipped
 938      * version of the compound labels string.  Locations are computed
 939      * relative to the viewR rectangle.
 940      * This layoutCompoundLabel() does not know how to handle LEADING/TRAILING
 941      * values in horizontalTextPosition (they will default to RIGHT) and in
 942      * horizontalAlignment (they will default to CENTER).
 943      * Use the other version of layoutCompoundLabel() instead.
 944      */
 945     private static String layoutCompoundLabelImpl(
 946         JComponent c,
 947         FontMetrics fm,
 948         String text,
 949         Icon icon,
 950         int verticalAlignment,
 951         int horizontalAlignment,
 952         int verticalTextPosition,
 953         int horizontalTextPosition,
 954         Rectangle viewR,
 955         Rectangle iconR,
 956         Rectangle textR,
 957         int textIconGap)
 958     {
 959         /* Initialize the icon bounds rectangle iconR.
 960          */
 961 
 962         if (icon != null) {
 963             iconR.width = icon.getIconWidth();
 964             iconR.height = icon.getIconHeight();
 965         }
 966         else {
 967             iconR.width = iconR.height = 0;
 968         }
 969 
 970         /* Initialize the text bounds rectangle textR.  If a null
 971          * or and empty String was specified we substitute "" here
 972          * and use 0,0,0,0 for textR.
 973          */
 974 
 975         boolean textIsEmpty = (text == null) || text.equals("");
 976         int lsb = 0;
 977         int rsb = 0;
 978         /* Unless both text and icon are non-null, we effectively ignore
 979          * the value of textIconGap.
 980          */
 981         int gap;
 982 
 983         View v;
 984         if (textIsEmpty) {
 985             textR.width = textR.height = 0;
 986             text = "";
 987             gap = 0;
 988         }
 989         else {
 990             int availTextWidth;
 991             gap = (icon == null) ? 0 : textIconGap;
 992 
 993             if (horizontalTextPosition == CENTER) {
 994                 availTextWidth = viewR.width;
 995             }
 996             else {
 997                 availTextWidth = viewR.width - (iconR.width + gap);
 998             }
 999             v = (c != null) ? (View) c.getClientProperty("html") : null;
1000             if (v != null) {
1001                 textR.width = Math.min(availTextWidth,
1002                                        (int) v.getPreferredSpan(View.X_AXIS));
1003                 textR.height = (int) v.getPreferredSpan(View.Y_AXIS);
1004             } else {
1005                 textR.width = SwingUtilities2.stringWidth(c, fm, text);
1006                 lsb = SwingUtilities2.getLeftSideBearing(c, fm, text);
1007                 if (lsb < 0) {
1008                     // If lsb is negative, add it to the width and later
1009                     // adjust the x location. This gives more space than is
1010                     // actually needed.
1011                     // This is done like this for two reasons:
1012                     // 1. If we set the width to the actual bounds all
1013                     //    callers would have to account for negative lsb
1014                     //    (pref size calculations ONLY look at width of
1015                     //    textR)
1016                     // 2. You can do a drawString at the returned location
1017                     //    and the text won't be clipped.
1018                     textR.width -= lsb;
1019                 }
1020                 if (textR.width > availTextWidth) {
1021                     text = SwingUtilities2.clipString(c, fm, text,
1022                                                       availTextWidth);
1023                     textR.width = SwingUtilities2.stringWidth(c, fm, text);
1024                 }
1025                 textR.height = fm.getHeight();
1026             }
1027         }
1028 
1029 
1030         /* Compute textR.x,y given the verticalTextPosition and
1031          * horizontalTextPosition properties
1032          */
1033 
1034         if (verticalTextPosition == TOP) {
1035             if (horizontalTextPosition != CENTER) {
1036                 textR.y = 0;
1037             }
1038             else {
1039                 textR.y = -(textR.height + gap);
1040             }
1041         }
1042         else if (verticalTextPosition == CENTER) {
1043             textR.y = (iconR.height / 2) - (textR.height / 2);
1044         }
1045         else { // (verticalTextPosition == BOTTOM)
1046             if (horizontalTextPosition != CENTER) {
1047                 textR.y = iconR.height - textR.height;
1048             }
1049             else {
1050                 textR.y = (iconR.height + gap);
1051             }
1052         }
1053 
1054         if (horizontalTextPosition == LEFT) {
1055             textR.x = -(textR.width + gap);
1056         }
1057         else if (horizontalTextPosition == CENTER) {
1058             textR.x = (iconR.width / 2) - (textR.width / 2);
1059         }
1060         else { // (horizontalTextPosition == RIGHT)
1061             textR.x = (iconR.width + gap);
1062         }
1063 
1064         // WARNING: DefaultTreeCellEditor uses a shortened version of
1065         // this algorithm to position it's Icon. If you change how this
1066         // is calculated, be sure and update DefaultTreeCellEditor too.
1067 
1068         /* labelR is the rectangle that contains iconR and textR.
1069          * Move it to its proper position given the labelAlignment
1070          * properties.
1071          *
1072          * To avoid actually allocating a Rectangle, Rectangle.union
1073          * has been inlined below.
1074          */
1075         int labelR_x = Math.min(iconR.x, textR.x);
1076         int labelR_width = Math.max(iconR.x + iconR.width,
1077                                     textR.x + textR.width) - labelR_x;
1078         int labelR_y = Math.min(iconR.y, textR.y);
1079         int labelR_height = Math.max(iconR.y + iconR.height,
1080                                      textR.y + textR.height) - labelR_y;
1081 
1082         int dx, dy;
1083 
1084         if (verticalAlignment == TOP) {
1085             dy = viewR.y - labelR_y;
1086         }
1087         else if (verticalAlignment == CENTER) {
1088             dy = (viewR.y + (viewR.height / 2)) - (labelR_y + (labelR_height / 2));
1089         }
1090         else { // (verticalAlignment == BOTTOM)
1091             dy = (viewR.y + viewR.height) - (labelR_y + labelR_height);
1092         }
1093 
1094         if (horizontalAlignment == LEFT) {
1095             dx = viewR.x - labelR_x;
1096         }
1097         else if (horizontalAlignment == RIGHT) {
1098             dx = (viewR.x + viewR.width) - (labelR_x + labelR_width);
1099         }
1100         else { // (horizontalAlignment == CENTER)
1101             dx = (viewR.x + (viewR.width / 2)) -
1102                  (labelR_x + (labelR_width / 2));
1103         }
1104 
1105         /* Translate textR and glypyR by dx,dy.
1106          */
1107 
1108         textR.x += dx;
1109         textR.y += dy;
1110 
1111         iconR.x += dx;
1112         iconR.y += dy;
1113 
1114         if (lsb < 0) {
1115             // lsb is negative. Shift the x location so that the text is
1116             // visually drawn at the right location.
1117             textR.x -= lsb;
1118 
1119             textR.width += lsb;
1120         }
1121         if (rsb > 0) {
1122             textR.width -= rsb;
1123         }
1124 
1125         return text;
1126     }
1127 
1128 
1129     /**
1130      * Paints a component to the specified <code>Graphics</code>.
1131      * This method is primarily useful to render
1132      * <code>Component</code>s that don't exist as part of the visible
1133      * containment hierarchy, but are used for rendering.  For
1134      * example, if you are doing your own rendering and want to render
1135      * some text (or even HTML), you could make use of
1136      * <code>JLabel</code>'s text rendering support and have it paint
1137      * directly by way of this method, without adding the label to the
1138      * visible containment hierarchy.
1139      * <p>
1140      * This method makes use of <code>CellRendererPane</code> to handle
1141      * the actual painting, and is only recommended if you use one
1142      * component for rendering.  If you make use of multiple components
1143      * to handle the rendering, as <code>JTable</code> does, use
1144      * <code>CellRendererPane</code> directly.  Otherwise, as described
1145      * below, you could end up with a <code>CellRendererPane</code>
1146      * per <code>Component</code>.
1147      * <p>
1148      * If <code>c</code>'s parent is not a <code>CellRendererPane</code>,
1149      * a new <code>CellRendererPane</code> is created, <code>c</code> is
1150      * added to it, and the <code>CellRendererPane</code> is added to
1151      * <code>p</code>.  If <code>c</code>'s parent is a
1152      * <code>CellRendererPane</code> and the <code>CellRendererPane</code>s
1153      * parent is not <code>p</code>, it is added to <code>p</code>.
1154      * <p>
1155      * The component should either descend from <code>JComponent</code>
1156      * or be another kind of lightweight component.
1157      * A lightweight component is one whose "lightweight" property
1158      * (returned by the <code>Component</code>
1159      * <code>isLightweight</code> method)
1160      * is true. If the Component is not lightweight, bad things map happen:
1161      * crashes, exceptions, painting problems...
1162      *
1163      * @param g  the <code>Graphics</code> object to draw on
1164      * @param c  the <code>Component</code> to draw
1165      * @param p  the intermediate <code>Container</code>
1166      * @param x  an int specifying the left side of the area draw in, in pixels,
1167      *           measured from the left edge of the graphics context
1168      * @param y  an int specifying the top of the area to draw in, in pixels
1169      *           measured down from the top edge of the graphics context
1170      * @param w  an int specifying the width of the area draw in, in pixels
1171      * @param h  an int specifying the height of the area draw in, in pixels
1172      *
1173      * @see CellRendererPane
1174      * @see java.awt.Component#isLightweight
1175      */
1176     public static void paintComponent(Graphics g, Component c, Container p, int x, int y, int w, int h) {
1177         getCellRendererPane(c, p).paintComponent(g, c, p, x, y, w, h,false);
1178     }
1179 
1180     /**
1181      * Paints a component to the specified <code>Graphics</code>.  This
1182      * is a cover method for
1183      * {@link #paintComponent(Graphics,Component,Container,int,int,int,int)}.
1184      * Refer to it for more information.
1185      *
1186      * @param g  the <code>Graphics</code> object to draw on
1187      * @param c  the <code>Component</code> to draw
1188      * @param p  the intermediate <code>Container</code>
1189      * @param r  the <code>Rectangle</code> to draw in
1190      *
1191      * @see #paintComponent(Graphics,Component,Container,int,int,int,int)
1192      * @see CellRendererPane
1193      */
1194     public static void paintComponent(Graphics g, Component c, Container p, Rectangle r) {
1195         paintComponent(g, c, p, r.x, r.y, r.width, r.height);
1196     }
1197 
1198 
1199     /*
1200      * Ensures that cell renderer <code>c</code> has a
1201      * <code>ComponentShell</code> parent and that
1202      * the shell's parent is p.
1203      */
1204     private static CellRendererPane getCellRendererPane(Component c, Container p) {
1205         Container shell = c.getParent();
1206         if (shell instanceof CellRendererPane) {
1207             if (shell.getParent() != p) {
1208                 p.add(shell);
1209             }
1210         } else {
1211             shell = new CellRendererPane();
1212             shell.add(c);
1213             p.add(shell);
1214         }
1215         return (CellRendererPane)shell;
1216     }
1217 
1218     /**
1219      * A simple minded look and feel change: ask each node in the tree
1220      * to <code>updateUI()</code> -- that is, to initialize its UI property
1221      * with the current look and feel.
1222      */
1223     public static void updateComponentTreeUI(Component c) {
1224         updateComponentTreeUI0(c);
1225         c.invalidate();
1226         c.validate();
1227         c.repaint();
1228     }
1229 
1230     private static void updateComponentTreeUI0(Component c) {
1231         if (c instanceof JComponent) {
1232             JComponent jc = (JComponent) c;
1233             jc.updateUI();
1234             JPopupMenu jpm =jc.getComponentPopupMenu();
1235             if(jpm != null) {
1236                 updateComponentTreeUI(jpm);
1237             }
1238         }
1239         Component[] children = null;
1240         if (c instanceof JMenu) {
1241             children = ((JMenu)c).getMenuComponents();
1242         }
1243         else if (c instanceof Container) {
1244             children = ((Container)c).getComponents();
1245         }
1246         if (children != null) {
1247             for (Component child : children) {
1248                 updateComponentTreeUI0(child);
1249             }
1250         }
1251     }
1252 
1253 
1254     /**
1255      * Causes <i>doRun.run()</i> to be executed asynchronously on the
1256      * AWT event dispatching thread.  This will happen after all
1257      * pending AWT events have been processed.  This method should
1258      * be used when an application thread needs to update the GUI.
1259      * In the following example the <code>invokeLater</code> call queues
1260      * the <code>Runnable</code> object <code>doHelloWorld</code>
1261      * on the event dispatching thread and
1262      * then prints a message.
1263      * <pre>
1264      * Runnable doHelloWorld = new Runnable() {
1265      *     public void run() {
1266      *         System.out.println("Hello World on " + Thread.currentThread());
1267      *     }
1268      * };
1269      *
1270      * SwingUtilities.invokeLater(doHelloWorld);
1271      * System.out.println("This might well be displayed before the other message.");
1272      * </pre>
1273      * If invokeLater is called from the event dispatching thread --
1274      * for example, from a JButton's ActionListener -- the <i>doRun.run()</i> will
1275      * still be deferred until all pending events have been processed.
1276      * Note that if the <i>doRun.run()</i> throws an uncaught exception
1277      * the event dispatching thread will unwind (not the current thread).
1278      * <p>
1279      * Additional documentation and examples for this method can be
1280      * found in
1281      * <A HREF="http://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html">Concurrency in Swing</a>.
1282      * <p>
1283      * As of 1.3 this method is just a cover for <code>java.awt.EventQueue.invokeLater()</code>.
1284      * <p>
1285      * Unlike the rest of Swing, this method can be invoked from any thread.
1286      *
1287      * @see #invokeAndWait
1288      */
1289     public static void invokeLater(Runnable doRun) {
1290         EventQueue.invokeLater(doRun);
1291     }
1292 
1293 
1294     /**
1295      * Causes <code>doRun.run()</code> to be executed synchronously on the
1296      * AWT event dispatching thread.  This call blocks until
1297      * all pending AWT events have been processed and (then)
1298      * <code>doRun.run()</code> returns. This method should
1299      * be used when an application thread needs to update the GUI.
1300      * It shouldn't be called from the event dispatching thread.
1301      * Here's an example that creates a new application thread
1302      * that uses <code>invokeAndWait</code> to print a string from the event
1303      * dispatching thread and then, when that's finished, print
1304      * a string from the application thread.
1305      * <pre>
1306      * final Runnable doHelloWorld = new Runnable() {
1307      *     public void run() {
1308      *         System.out.println("Hello World on " + Thread.currentThread());
1309      *     }
1310      * };
1311      *
1312      * Thread appThread = new Thread() {
1313      *     public void run() {
1314      *         try {
1315      *             SwingUtilities.invokeAndWait(doHelloWorld);
1316      *         }
1317      *         catch (Exception e) {
1318      *             e.printStackTrace();
1319      *         }
1320      *         System.out.println("Finished on " + Thread.currentThread());
1321      *     }
1322      * };
1323      * appThread.start();
1324      * </pre>
1325      * Note that if the <code>Runnable.run</code> method throws an
1326      * uncaught exception
1327      * (on the event dispatching thread) it's caught and rethrown, as
1328      * an <code>InvocationTargetException</code>, on the caller's thread.
1329      * <p>
1330      * Additional documentation and examples for this method can be
1331      * found in
1332      * <A HREF="http://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html">Concurrency in Swing</a>.
1333      * <p>
1334      * As of 1.3 this method is just a cover for
1335      * <code>java.awt.EventQueue.invokeAndWait()</code>.
1336      *
1337      * @exception  InterruptedException if we're interrupted while waiting for
1338      *             the event dispatching thread to finish executing
1339      *             <code>doRun.run()</code>
1340      * @exception  InvocationTargetException  if an exception is thrown
1341      *             while running <code>doRun</code>
1342      *
1343      * @see #invokeLater
1344      */
1345     public static void invokeAndWait(final Runnable doRun)
1346         throws InterruptedException, InvocationTargetException
1347     {
1348         EventQueue.invokeAndWait(doRun);
1349     }
1350 
1351     /**
1352      * Returns true if the current thread is an AWT event dispatching thread.
1353      * <p>
1354      * As of 1.3 this method is just a cover for
1355      * <code>java.awt.EventQueue.isDispatchThread()</code>.
1356      *
1357      * @return true if the current thread is an AWT event dispatching thread
1358      */
1359     public static boolean isEventDispatchThread()
1360     {
1361         return EventQueue.isDispatchThread();
1362     }
1363 
1364 
1365     /*
1366      * --- Accessibility Support ---
1367      *
1368      */
1369 
1370     /**
1371      * Get the index of this object in its accessible parent.<p>
1372      *
1373      * Note: as of the Java 2 platform v1.3, it is recommended that developers call
1374      * Component.AccessibleAWTComponent.getAccessibleIndexInParent() instead
1375      * of using this method.
1376      *
1377      * @return -1 of this object does not have an accessible parent.
1378      * Otherwise, the index of the child in its accessible parent.
1379      */
1380     public static int getAccessibleIndexInParent(Component c) {
1381         return c.getAccessibleContext().getAccessibleIndexInParent();
1382     }
1383 
1384     /**
1385      * Returns the <code>Accessible</code> child contained at the
1386      * local coordinate <code>Point</code>, if one exists.
1387      * Otherwise returns <code>null</code>.
1388      *
1389      * @return the <code>Accessible</code> at the specified location,
1390      *    if it exists; otherwise <code>null</code>
1391      */
1392     public static Accessible getAccessibleAt(Component c, Point p) {
1393         if (c instanceof Container) {
1394             return c.getAccessibleContext().getAccessibleComponent().getAccessibleAt(p);
1395         } else if (c instanceof Accessible) {
1396             Accessible a = (Accessible) c;
1397             if (a != null) {
1398                 AccessibleContext ac = a.getAccessibleContext();
1399                 if (ac != null) {
1400                     AccessibleComponent acmp;
1401                     Point location;
1402                     int nchildren = ac.getAccessibleChildrenCount();
1403                     for (int i=0; i < nchildren; i++) {
1404                         a = ac.getAccessibleChild(i);
1405                         if ((a != null)) {
1406                             ac = a.getAccessibleContext();
1407                             if (ac != null) {
1408                                 acmp = ac.getAccessibleComponent();
1409                                 if ((acmp != null) && (acmp.isShowing())) {
1410                                     location = acmp.getLocation();
1411                                     Point np = new Point(p.x-location.x,
1412                                                          p.y-location.y);
1413                                     if (acmp.contains(np)){
1414                                         return a;
1415                                     }
1416                                 }
1417                             }
1418                         }
1419                     }
1420                 }
1421             }
1422             return (Accessible) c;
1423         }
1424         return null;
1425     }
1426 
1427     /**
1428      * Get the state of this object. <p>
1429      *
1430      * Note: as of the Java 2 platform v1.3, it is recommended that developers call
1431      * Component.AccessibleAWTComponent.getAccessibleIndexInParent() instead
1432      * of using this method.
1433      *
1434      * @return an instance of AccessibleStateSet containing the current state
1435      * set of the object
1436      * @see AccessibleState
1437      */
1438     public static AccessibleStateSet getAccessibleStateSet(Component c) {
1439         return c.getAccessibleContext().getAccessibleStateSet();
1440     }
1441 
1442     /**
1443      * Returns the number of accessible children in the object.  If all
1444      * of the children of this object implement Accessible, than this
1445      * method should return the number of children of this object. <p>
1446      *
1447      * Note: as of the Java 2 platform v1.3, it is recommended that developers call
1448      * Component.AccessibleAWTComponent.getAccessibleIndexInParent() instead
1449      * of using this method.
1450      *
1451      * @return the number of accessible children in the object.
1452      */
1453     public static int getAccessibleChildrenCount(Component c) {
1454         return c.getAccessibleContext().getAccessibleChildrenCount();
1455     }
1456 
1457     /**
1458      * Return the nth Accessible child of the object. <p>
1459      *
1460      * Note: as of the Java 2 platform v1.3, it is recommended that developers call
1461      * Component.AccessibleAWTComponent.getAccessibleIndexInParent() instead
1462      * of using this method.
1463      *
1464      * @param i zero-based index of child
1465      * @return the nth Accessible child of the object
1466      */
1467     public static Accessible getAccessibleChild(Component c, int i) {
1468         return c.getAccessibleContext().getAccessibleChild(i);
1469     }
1470 
1471     /**
1472      * Return the child <code>Component</code> of the specified
1473      * <code>Component</code> that is the focus owner, if any.
1474      *
1475      * @param c the root of the <code>Component</code> hierarchy to
1476      *        search for the focus owner
1477      * @return the focus owner, or <code>null</code> if there is no focus
1478      *         owner, or if the focus owner is not <code>comp</code>, or a
1479      *         descendant of <code>comp</code>
1480      *
1481      * @see java.awt.KeyboardFocusManager#getFocusOwner
1482      * @deprecated As of 1.4, replaced by
1483      *   <code>KeyboardFocusManager.getFocusOwner()</code>.
1484      */
1485     @Deprecated
1486     public static Component findFocusOwner(Component c) {
1487         Component focusOwner = KeyboardFocusManager.
1488             getCurrentKeyboardFocusManager().getFocusOwner();
1489 
1490         // verify focusOwner is a descendant of c
1491         for (Component temp = focusOwner; temp != null;
1492              temp = (temp instanceof Window) ? null : temp.getParent())
1493         {
1494             if (temp == c) {
1495                 return focusOwner;
1496             }
1497         }
1498 
1499         return null;
1500     }
1501 
1502     /**
1503      * If c is a JRootPane descendant return its JRootPane ancestor.
1504      * If c is a RootPaneContainer then return its JRootPane.
1505      * @return the JRootPane for Component c or {@code null}.
1506      */
1507     public static JRootPane getRootPane(Component c) {
1508         if (c instanceof RootPaneContainer) {
1509             return ((RootPaneContainer)c).getRootPane();
1510         }
1511         for( ; c != null; c = c.getParent()) {
1512             if (c instanceof JRootPane) {
1513                 return (JRootPane)c;
1514             }
1515         }
1516         return null;
1517     }
1518 
1519 
1520     /**
1521      * Returns the root component for the current component tree.
1522      * @return the first ancestor of c that's a Window or the last Applet ancestor
1523      */
1524     public static Component getRoot(Component c) {
1525         Component applet = null;
1526         for(Component p = c; p != null; p = p.getParent()) {
1527             if (p instanceof Window) {
1528                 return p;
1529             }
1530             if (p instanceof Applet) {
1531                 applet = p;
1532             }
1533         }
1534         return applet;
1535     }
1536 
1537     static JComponent getPaintingOrigin(JComponent c) {
1538         Container p = c;
1539         while ((p = p.getParent()) instanceof JComponent) {
1540             JComponent jp = (JComponent) p;
1541             if (jp.isPaintingOrigin()) {
1542                 return jp;
1543             }
1544         }
1545         return null;
1546     }
1547 
1548     /**
1549      * Process the key bindings for the <code>Component</code> associated with
1550      * <code>event</code>. This method is only useful if
1551      * <code>event.getComponent()</code> does not descend from
1552      * <code>JComponent</code>, or your are not invoking
1553      * <code>super.processKeyEvent</code> from within your
1554      * <code>JComponent</code> subclass. <code>JComponent</code>
1555      * automatically processes bindings from within its
1556      * <code>processKeyEvent</code> method, hence you rarely need
1557      * to directly invoke this method.
1558      *
1559      * @param event KeyEvent used to identify which bindings to process, as
1560      *              well as which Component has focus.
1561      * @return true if a binding has found and processed
1562      * @since 1.4
1563      */
1564     public static boolean processKeyBindings(KeyEvent event) {
1565         if (event != null) {
1566             if (event.isConsumed()) {
1567                 return false;
1568             }
1569 
1570             Component component = event.getComponent();
1571             boolean pressed = (event.getID() == KeyEvent.KEY_PRESSED);
1572 
1573             if (!isValidKeyEventForKeyBindings(event)) {
1574                 return false;
1575             }
1576             // Find the first JComponent in the ancestor hierarchy, and
1577             // invoke processKeyBindings on it
1578             while (component != null) {
1579                 if (component instanceof JComponent) {
1580                     return ((JComponent)component).processKeyBindings(
1581                                                    event, pressed);
1582                 }
1583                 if ((component instanceof Applet) ||
1584                     (component instanceof Window)) {
1585                     // No JComponents, if Window or Applet parent, process
1586                     // WHEN_IN_FOCUSED_WINDOW bindings.
1587                     return JComponent.processKeyBindingsForAllComponents(
1588                                   event, (Container)component, pressed);
1589                 }
1590                 component = component.getParent();
1591             }
1592         }
1593         return false;
1594     }
1595 
1596     /**
1597      * Returns true if the <code>e</code> is a valid KeyEvent to use in
1598      * processing the key bindings associated with JComponents.
1599      */
1600     static boolean isValidKeyEventForKeyBindings(KeyEvent e) {
1601         return true;
1602     }
1603 
1604     /**
1605      * Invokes <code>actionPerformed</code> on <code>action</code> if
1606      * <code>action</code> is enabled (and non-{@code null}). The command for the
1607      * ActionEvent is determined by:
1608      * <ol>
1609      *   <li>If the action was registered via
1610      *       <code>registerKeyboardAction</code>, then the command string
1611      *       passed in ({@code null} will be used if {@code null} was passed in).
1612      *   <li>Action value with name Action.ACTION_COMMAND_KEY, unless {@code null}.
1613      *   <li>String value of the KeyEvent, unless <code>getKeyChar</code>
1614      *       returns KeyEvent.CHAR_UNDEFINED..
1615      * </ol>
1616      * This will return true if <code>action</code> is non-{@code null} and
1617      * actionPerformed is invoked on it.
1618      *
1619      * @since 1.3
1620      */
1621     public static boolean notifyAction(Action action, KeyStroke ks,
1622                                        KeyEvent event, Object sender,
1623                                        int modifiers) {
1624         if (action == null) {
1625             return false;
1626         }
1627         if (action instanceof UIAction) {
1628             if (!((UIAction)action).isEnabled(sender)) {
1629                 return false;
1630             }
1631         }
1632         else if (!action.isEnabled()) {
1633             return false;
1634         }
1635         Object commandO;
1636         boolean stayNull;
1637 
1638         // Get the command object.
1639         commandO = action.getValue(Action.ACTION_COMMAND_KEY);
1640         if (commandO == null && (action instanceof JComponent.ActionStandin)) {
1641             // ActionStandin is used for historical reasons to support
1642             // registerKeyboardAction with a null value.
1643             stayNull = true;
1644         }
1645         else {
1646             stayNull = false;
1647         }
1648 
1649         // Convert it to a string.
1650         String command;
1651 
1652         if (commandO != null) {
1653             command = commandO.toString();
1654         }
1655         else if (!stayNull && event.getKeyChar() != KeyEvent.CHAR_UNDEFINED) {
1656             command = String.valueOf(event.getKeyChar());
1657         }
1658         else {
1659             // Do null for undefined chars, or if registerKeyboardAction
1660             // was called with a null.
1661             command = null;
1662         }
1663         action.actionPerformed(new ActionEvent(sender,
1664                         ActionEvent.ACTION_PERFORMED, command, event.getWhen(),
1665                         modifiers));
1666         return true;
1667     }
1668 
1669 
1670     /**
1671      * Convenience method to change the UI InputMap for <code>component</code>
1672      * to <code>uiInputMap</code>. If <code>uiInputMap</code> is {@code null},
1673      * this removes any previously installed UI InputMap.
1674      *
1675      * @since 1.3
1676      */
1677     public static void replaceUIInputMap(JComponent component, int type,
1678                                          InputMap uiInputMap) {
1679         InputMap map = component.getInputMap(type, (uiInputMap != null));
1680 
1681         while (map != null) {
1682             InputMap parent = map.getParent();
1683             if (parent == null || (parent instanceof UIResource)) {
1684                 map.setParent(uiInputMap);
1685                 return;
1686             }
1687             map = parent;
1688         }
1689     }
1690 
1691 
1692     /**
1693      * Convenience method to change the UI ActionMap for <code>component</code>
1694      * to <code>uiActionMap</code>. If <code>uiActionMap</code> is {@code null},
1695      * this removes any previously installed UI ActionMap.
1696      *
1697      * @since 1.3
1698      */
1699     public static void replaceUIActionMap(JComponent component,
1700                                           ActionMap uiActionMap) {
1701         ActionMap map = component.getActionMap((uiActionMap != null));
1702 
1703         while (map != null) {
1704             ActionMap parent = map.getParent();
1705             if (parent == null || (parent instanceof UIResource)) {
1706                 map.setParent(uiActionMap);
1707                 return;
1708             }
1709             map = parent;
1710         }
1711     }
1712 
1713 
1714     /**
1715      * Returns the InputMap provided by the UI for condition
1716      * <code>condition</code> in component <code>component</code>.
1717      * <p>This will return {@code null} if the UI has not installed a InputMap
1718      * of the specified type.
1719      *
1720      * @since 1.3
1721      */
1722     public static InputMap getUIInputMap(JComponent component, int condition) {
1723         InputMap map = component.getInputMap(condition, false);
1724         while (map != null) {
1725             InputMap parent = map.getParent();
1726             if (parent instanceof UIResource) {
1727                 return parent;
1728             }
1729             map = parent;
1730         }
1731         return null;
1732     }
1733 
1734     /**
1735      * Returns the ActionMap provided by the UI
1736      * in component <code>component</code>.
1737      * <p>This will return {@code null} if the UI has not installed an ActionMap.
1738      *
1739      * @since 1.3
1740      */
1741     public static ActionMap getUIActionMap(JComponent component) {
1742         ActionMap map = component.getActionMap(false);
1743         while (map != null) {
1744             ActionMap parent = map.getParent();
1745             if (parent instanceof UIResource) {
1746                 return parent;
1747             }
1748             map = parent;
1749         }
1750         return null;
1751     }
1752 
1753 
1754     // Don't use String, as it's not guaranteed to be unique in a Hashtable.
1755     private static final Object sharedOwnerFrameKey =
1756        new StringBuffer("SwingUtilities.sharedOwnerFrame");
1757 
1758     @SuppressWarnings("serial") // JDK-implementation class
1759     static class SharedOwnerFrame extends Frame implements WindowListener {
1760         public void addNotify() {
1761             super.addNotify();
1762             installListeners();
1763         }
1764 
1765         /**
1766          * Install window listeners on owned windows to watch for displayability changes
1767          */
1768         void installListeners() {
1769             Window[] windows = getOwnedWindows();
1770             for (Window window : windows) {
1771                 if (window != null) {
1772                     window.removeWindowListener(this);
1773                     window.addWindowListener(this);
1774                 }
1775             }
1776         }
1777 
1778         /**
1779          * Watches for displayability changes and disposes shared instance if there are no
1780          * displayable children left.
1781          */
1782         public void windowClosed(WindowEvent e) {
1783             synchronized(getTreeLock()) {
1784                 Window[] windows = getOwnedWindows();
1785                 for (Window window : windows) {
1786                     if (window != null) {
1787                         if (window.isDisplayable()) {
1788                             return;
1789                         }
1790                         window.removeWindowListener(this);
1791                     }
1792                 }
1793                 dispose();
1794             }
1795         }
1796         public void windowOpened(WindowEvent e) {
1797         }
1798         public void windowClosing(WindowEvent e) {
1799         }
1800         public void windowIconified(WindowEvent e) {
1801         }
1802         public void windowDeiconified(WindowEvent e) {
1803         }
1804         public void windowActivated(WindowEvent e) {
1805         }
1806         public void windowDeactivated(WindowEvent e) {
1807         }
1808 
1809         public void show() {
1810             // This frame can never be shown
1811         }
1812         public void dispose() {
1813             try {
1814                 getToolkit().getSystemEventQueue();
1815                 super.dispose();
1816             } catch (Exception e) {
1817                 // untrusted code not allowed to dispose
1818             }
1819         }
1820     }
1821 
1822     /**
1823      * Returns a toolkit-private, shared, invisible Frame
1824      * to be the owner for JDialogs and JWindows created with
1825      * {@code null} owners.
1826      * @exception HeadlessException if GraphicsEnvironment.isHeadless()
1827      * returns true.
1828      * @see java.awt.GraphicsEnvironment#isHeadless
1829      */
1830     static Frame getSharedOwnerFrame() throws HeadlessException {
1831         Frame sharedOwnerFrame =
1832             (Frame)SwingUtilities.appContextGet(sharedOwnerFrameKey);
1833         if (sharedOwnerFrame == null) {
1834             sharedOwnerFrame = new SharedOwnerFrame();
1835             SwingUtilities.appContextPut(sharedOwnerFrameKey,
1836                                          sharedOwnerFrame);
1837         }
1838         return sharedOwnerFrame;
1839     }
1840 
1841     /**
1842      * Returns a SharedOwnerFrame's shutdown listener to dispose the SharedOwnerFrame
1843      * if it has no more displayable children.
1844      * @exception HeadlessException if GraphicsEnvironment.isHeadless()
1845      * returns true.
1846      * @see java.awt.GraphicsEnvironment#isHeadless
1847      */
1848     static WindowListener getSharedOwnerFrameShutdownListener() throws HeadlessException {
1849         Frame sharedOwnerFrame = getSharedOwnerFrame();
1850         return (WindowListener)sharedOwnerFrame;
1851     }
1852 
1853     /* Don't make these AppContext accessors public or protected --
1854      * since AppContext is in sun.awt in 1.2, we shouldn't expose it
1855      * even indirectly with a public API.
1856      */
1857     // REMIND(aim): phase out use of 4 methods below since they
1858     // are just private covers for AWT methods (?)
1859 
1860     static Object appContextGet(Object key) {
1861         return AppContext.getAppContext().get(key);
1862     }
1863 
1864     static void appContextPut(Object key, Object value) {
1865         AppContext.getAppContext().put(key, value);
1866     }
1867 
1868     static void appContextRemove(Object key) {
1869         AppContext.getAppContext().remove(key);
1870     }
1871 
1872 
1873     static Class<?> loadSystemClass(String className) throws ClassNotFoundException {
1874         ReflectUtil.checkPackageAccess(className);
1875         return Class.forName(className, true, Thread.currentThread().
1876                              getContextClassLoader());
1877     }
1878 
1879 
1880    /*
1881      * Convenience function for determining ComponentOrientation.  Helps us
1882      * avoid having Munge directives throughout the code.
1883      */
1884     static boolean isLeftToRight( Component c ) {
1885         return c.getComponentOrientation().isLeftToRight();
1886     }
1887     private SwingUtilities() {
1888         throw new Error("SwingUtilities is just a container for static methods");
1889     }
1890 
1891     /**
1892      * Returns true if the Icon <code>icon</code> is an instance of
1893      * ImageIcon, and the image it contains is the same as <code>image</code>.
1894      */
1895     static boolean doesIconReferenceImage(Icon icon, Image image) {
1896         Image iconImage = (icon != null && (icon instanceof ImageIcon)) ?
1897                            ((ImageIcon)icon).getImage() : null;
1898         return (iconImage == image);
1899     }
1900 
1901     /**
1902      * Returns index of the first occurrence of <code>mnemonic</code>
1903      * within string <code>text</code>. Matching algorithm is not
1904      * case-sensitive.
1905      *
1906      * @param text The text to search through, may be {@code null}
1907      * @param mnemonic The mnemonic to find the character for.
1908      * @return index into the string if exists, otherwise -1
1909      */
1910     static int findDisplayedMnemonicIndex(String text, int mnemonic) {
1911         if (text == null || mnemonic == '\0') {
1912             return -1;
1913         }
1914 
1915         char uc = Character.toUpperCase((char)mnemonic);
1916         char lc = Character.toLowerCase((char)mnemonic);
1917 
1918         int uci = text.indexOf(uc);
1919         int lci = text.indexOf(lc);
1920 
1921         if (uci == -1) {
1922             return lci;
1923         } else if(lci == -1) {
1924             return uci;
1925         } else {
1926             return (lci < uci) ? lci : uci;
1927         }
1928     }
1929 
1930     /**
1931      * Stores the position and size of
1932      * the inner painting area of the specified component
1933      * in <code>r</code> and returns <code>r</code>.
1934      * The position and size specify the bounds of the component,
1935      * adjusted so as not to include the border area (the insets).
1936      * This method is useful for classes
1937      * that implement painting code.
1938      *
1939      * @param c  the JComponent in question; if {@code null}, this method returns {@code null}
1940      * @param r  the Rectangle instance to be modified;
1941      *           may be {@code null}
1942      * @return {@code null} if the Component is {@code null};
1943      *         otherwise, returns the passed-in rectangle (if non-{@code null})
1944      *         or a new rectangle specifying position and size information
1945      *
1946      * @since 1.4
1947      */
1948     public static Rectangle calculateInnerArea(JComponent c, Rectangle r) {
1949         if (c == null) {
1950             return null;
1951         }
1952         Rectangle rect = r;
1953         Insets insets = c.getInsets();
1954 
1955         if (rect == null) {
1956             rect = new Rectangle();
1957         }
1958 
1959         rect.x = insets.left;
1960         rect.y = insets.top;
1961         rect.width = c.getWidth() - insets.left - insets.right;
1962         rect.height = c.getHeight() - insets.top - insets.bottom;
1963 
1964         return rect;
1965     }
1966 
1967     static void updateRendererOrEditorUI(Object rendererOrEditor) {
1968         if (rendererOrEditor == null) {
1969             return;
1970         }
1971 
1972         Component component = null;
1973 
1974         if (rendererOrEditor instanceof Component) {
1975             component = (Component)rendererOrEditor;
1976         }
1977         if (rendererOrEditor instanceof DefaultCellEditor) {
1978             component = ((DefaultCellEditor)rendererOrEditor).getComponent();
1979         }
1980 
1981         if (component != null) {
1982             SwingUtilities.updateComponentTreeUI(component);
1983         }
1984     }
1985 
1986     /**
1987      * Returns the first ancestor of the {@code component}
1988      * which is not an instance of {@link JLayer}.
1989      *
1990      * @param component {@code Component} to get
1991      * the first ancestor of, which is not a {@link JLayer} instance.
1992      *
1993      * @return the first ancestor of the {@code component}
1994      * which is not an instance of {@link JLayer}.
1995      * If such an ancestor can not be found, {@code null} is returned.
1996      *
1997      * @throws NullPointerException if {@code component} is {@code null}
1998      * @see JLayer
1999      *
2000      * @since 1.7
2001      */
2002     public static Container getUnwrappedParent(Component component) {
2003         Container parent = component.getParent();
2004         while(parent instanceof JLayer) {
2005             parent = parent.getParent();
2006         }
2007         return parent;
2008     }
2009 
2010     /**
2011      * Returns the first {@code JViewport}'s descendant
2012      * which is not an instance of {@code JLayer}.
2013      * If such a descendant can not be found, {@code null} is returned.
2014      *
2015      * If the {@code viewport}'s view component is not a {@code JLayer},
2016      * this method is equivalent to {@link JViewport#getView()}
2017      * otherwise {@link JLayer#getView()} will be recursively
2018      * called on all descending {@code JLayer}s.
2019      *
2020      * @param viewport {@code JViewport} to get the first descendant of,
2021      * which in not a {@code JLayer} instance.
2022      *
2023      * @return the first {@code JViewport}'s descendant
2024      * which is not an instance of {@code JLayer}.
2025      * If such a descendant can not be found, {@code null} is returned.
2026      *
2027      * @throws NullPointerException if {@code viewport} is {@code null}
2028      * @see JViewport#getView()
2029      * @see JLayer
2030      *
2031      * @since 1.7
2032      */
2033     public static Component getUnwrappedView(JViewport viewport) {
2034         Component view = viewport.getView();
2035         while (view instanceof JLayer) {
2036             view = ((JLayer)view).getView();
2037         }
2038         return view;
2039     }
2040 
2041    /**
2042      * Retrieves the validate root of a given container.
2043      *
2044      * If the container is contained within a {@code CellRendererPane}, this
2045      * method returns {@code null} due to the synthetic nature of the {@code
2046      * CellRendererPane}.
2047      * <p>
2048      * The component hierarchy must be displayable up to the toplevel component
2049      * (either a {@code Frame} or an {@code Applet} object.) Otherwise this
2050      * method returns {@code null}.
2051      * <p>
2052      * If the {@code visibleOnly} argument is {@code true}, the found validate
2053      * root and all its parents up to the toplevel component must also be
2054      * visible. Otherwise this method returns {@code null}.
2055      *
2056      * @return the validate root of the given container or null
2057      * @see java.awt.Component#isDisplayable()
2058      * @see java.awt.Component#isVisible()
2059      * @since 1.7
2060      */
2061     static Container getValidateRoot(Container c, boolean visibleOnly) {
2062         Container root = null;
2063 
2064         for (; c != null; c = c.getParent())
2065         {
2066             if (!c.isDisplayable() || c instanceof CellRendererPane) {
2067                 return null;
2068             }
2069             if (c.isValidateRoot()) {
2070                 root = c;
2071                 break;
2072             }
2073         }
2074 
2075         if (root == null) {
2076             return null;
2077         }
2078 
2079         for (; c != null; c = c.getParent()) {
2080             if (!c.isDisplayable() || (visibleOnly && !c.isVisible())) {
2081                 return null;
2082             }
2083             if (c instanceof Window || c instanceof Applet) {
2084                 return root;
2085             }
2086         }
2087 
2088         return null;
2089     }
2090 }