Home » openjdk-7 » javax » swing » [javadoc | source]

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

Home » openjdk-7 » javax » swing » [javadoc | source]