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