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

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