| GNU Classpath (0.95) | |
| Frames | No Frames |
1: /* SwingUtilities.java -- 2: Copyright (C) 2002, 2004, 2005, 2006, Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package javax.swing; 40: 41: import java.applet.Applet; 42: import java.awt.Component; 43: import java.awt.Container; 44: import java.awt.FontMetrics; 45: import java.awt.Frame; 46: import java.awt.Graphics; 47: import java.awt.Insets; 48: import java.awt.KeyboardFocusManager; 49: import java.awt.Point; 50: import java.awt.Rectangle; 51: import java.awt.Shape; 52: import java.awt.Window; 53: import java.awt.event.ActionEvent; 54: import java.awt.event.InputEvent; 55: import java.awt.event.KeyEvent; 56: import java.awt.event.MouseEvent; 57: import java.lang.reflect.InvocationTargetException; 58: 59: import javax.accessibility.Accessible; 60: import javax.accessibility.AccessibleStateSet; 61: import javax.swing.plaf.ActionMapUIResource; 62: import javax.swing.plaf.InputMapUIResource; 63: import javax.swing.plaf.basic.BasicHTML; 64: import javax.swing.text.View; 65: 66: /** 67: * A number of static utility functions which are 68: * useful when drawing swing components, dispatching events, or calculating 69: * regions which need painting. 70: * 71: * @author Graydon Hoare (graydon@redhat.com) 72: * @author Andrew John Hughes (gnu_andrew@member.fsf.org) 73: */ 74: public class SwingUtilities 75: implements SwingConstants 76: { 77: /** 78: * This frame should be used as parent for JWindow or JDialog 79: * that doesn't an owner 80: */ 81: private static OwnerFrame ownerFrame; 82: 83: private SwingUtilities() 84: { 85: // Do nothing. 86: } 87: 88: /** 89: * Calculates the portion of the component's bounds which is inside the 90: * component's border insets. This area is usually the area a component 91: * should confine its painting to. The coordinates are returned in terms 92: * of the <em>component's</em> coordinate system, where (0,0) is the 93: * upper left corner of the component's bounds. 94: * 95: * @param c the component to measure the bounds of (if <code>null</code>, 96: * this method returns <code>null</code>). 97: * @param r a carrier to store the return value in (if <code>null</code>, a 98: * new <code>Rectangle</code> instance is created). 99: * 100: * @return The calculated area inside the component and its border insets. 101: */ 102: public static Rectangle calculateInnerArea(JComponent c, Rectangle r) 103: { 104: if (c == null) 105: return null; 106: r = c.getBounds(r); 107: Insets i = c.getInsets(); 108: r.x = i.left; 109: r.width = r.width - i.left - i.right; 110: r.y = i.top; 111: r.height = r.height - i.top - i.bottom; 112: return r; 113: } 114: 115: /** 116: * Returns the focus owner or <code>null</code> if <code>comp</code> is not 117: * the focus owner or a parent of it. 118: * 119: * @param comp the focus owner or a parent of it 120: * 121: * @return the focus owner, or <code>null</code> 122: * 123: * @deprecated 1.4 Replaced by 124: * <code>KeyboardFocusManager.getFocusOwner()</code>. 125: */ 126: public static Component findFocusOwner(Component comp) 127: { 128: // Get real focus owner. 129: Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager() 130: .getFocusOwner(); 131: 132: // Check if comp is the focus owner or a parent of it. 133: Component tmp = focusOwner; 134: 135: while (tmp != null) 136: { 137: if (tmp == comp) 138: return focusOwner; 139: 140: tmp = tmp.getParent(); 141: } 142: 143: return null; 144: } 145: 146: /** 147: * Returns the <code>Accessible</code> child of the specified component 148: * which appears at the supplied <code>Point</code>. If there is no 149: * child located at that particular pair of co-ordinates, null is returned 150: * instead. 151: * 152: * @param c the component whose children may be found at the specified 153: * point. 154: * @param p the point at which to look for the existence of children 155: * of the specified component. 156: * @return the <code>Accessible</code> child at the point, <code>p</code>, 157: * or null if there is no child at this point. 158: * @see javax.accessibility.AccessibleComponent#getAccessibleAt 159: */ 160: public static Accessible getAccessibleAt(Component c, Point p) 161: { 162: return c.getAccessibleContext().getAccessibleComponent().getAccessibleAt(p); 163: } 164: 165: /** 166: * <p> 167: * Returns the <code>Accessible</code> child of the specified component 168: * that has the supplied index within the parent component. The indexing 169: * of the children is zero-based, making the first child have an index of 170: * 0. 171: * </p> 172: * <p> 173: * Caution is advised when using this method, as its operation relies 174: * on the behaviour of varying implementations of an abstract method. 175: * For greater surety, direct use of the AWT component implementation 176: * of this method is advised. 177: * </p> 178: * 179: * @param c the component whose child should be returned. 180: * @param i the index of the child within the parent component. 181: * @return the <code>Accessible</code> child at index <code>i</code> 182: * in the component, <code>c</code>. 183: * @see javax.accessibility.AccessibleContext#getAccessibleChild 184: * @see java.awt.Component.AccessibleAWTComponent#getAccessibleChild 185: */ 186: public static Accessible getAccessibleChild(Component c, int i) 187: { 188: return c.getAccessibleContext().getAccessibleChild(i); 189: } 190: 191: /** 192: * <p> 193: * Returns the number of <code>Accessible</code> children within 194: * the supplied component. 195: * </p> 196: * <p> 197: * Caution is advised when using this method, as its operation relies 198: * on the behaviour of varying implementations of an abstract method. 199: * For greater surety, direct use of the AWT component implementation 200: * of this method is advised. 201: * </p> 202: * 203: * @param c the component whose children should be counted. 204: * @return the number of children belonging to the component, 205: * <code>c</code>. 206: * @see javax.accessibility.AccessibleContext#getAccessibleChildrenCount 207: * @see java.awt.Component.AccessibleAWTComponent#getAccessibleChildrenCount 208: */ 209: public static int getAccessibleChildrenCount(Component c) 210: { 211: return c.getAccessibleContext().getAccessibleChildrenCount(); 212: } 213: 214: /** 215: * <p> 216: * Returns the zero-based index of the specified component 217: * within its parent. If the component doesn't have a parent, 218: * -1 is returned. 219: * </p> 220: * <p> 221: * Caution is advised when using this method, as its operation relies 222: * on the behaviour of varying implementations of an abstract method. 223: * For greater surety, direct use of the AWT component implementation 224: * of this method is advised. 225: * </p> 226: * 227: * @param c the component whose parental index should be found. 228: * @return the index of the component within its parent, or -1 229: * if the component doesn't have a parent. 230: * @see javax.accessibility.AccessibleContext#getAccessibleIndexInParent 231: * @see java.awt.Component.AccessibleAWTComponent#getAccessibleIndexInParent 232: */ 233: public static int getAccessibleIndexInParent(Component c) 234: { 235: return c.getAccessibleContext().getAccessibleIndexInParent(); 236: } 237: 238: /** 239: * <p> 240: * Returns a set of <code>AccessibleState</code>s, which represent 241: * the state of the supplied component. 242: * </p> 243: * <p> 244: * Caution is advised when using this method, as its operation relies 245: * on the behaviour of varying implementations of an abstract method. 246: * For greater surety, direct use of the AWT component implementation 247: * of this method is advised. 248: * </p> 249: * 250: * @param c the component whose accessible state should be retrieved. 251: * @return a set of <code>AccessibleState</code> objects, which represent 252: * the state of the supplied component. 253: * @see javax.accessibility.AccessibleContext#getAccessibleStateSet 254: * @see java.awt.Component.AccessibleAWTComponent#getAccessibleStateSet 255: */ 256: public static AccessibleStateSet getAccessibleStateSet(Component c) 257: { 258: return c.getAccessibleContext().getAccessibleStateSet(); 259: } 260: 261: /** 262: * Calculates the bounds of a component in the component's own coordinate 263: * space. The result has the same height and width as the component's 264: * bounds, but its location is set to (0,0). 265: * 266: * @param aComponent The component to measure 267: * 268: * @return The component's bounds in its local coordinate space 269: */ 270: public static Rectangle getLocalBounds(Component aComponent) 271: { 272: Rectangle bounds = aComponent.getBounds(); 273: return new Rectangle(0, 0, bounds.width, bounds.height); 274: } 275: 276: /** 277: * If <code>comp</code> is a RootPaneContainer, return its JRootPane. 278: * Otherwise call <code>getAncestorOfClass(JRootPane.class, a)</code>. 279: * 280: * @param comp The component to get the JRootPane of 281: * 282: * @return a suitable JRootPane for <code>comp</code>, or <code>null</code> 283: * 284: * @see javax.swing.RootPaneContainer#getRootPane 285: * @see #getAncestorOfClass 286: */ 287: public static JRootPane getRootPane(Component comp) 288: { 289: if (comp instanceof RootPaneContainer) 290: return ((RootPaneContainer)comp).getRootPane(); 291: else 292: return (JRootPane) getAncestorOfClass(JRootPane.class, comp); 293: } 294: 295: /** 296: * Returns the least ancestor of <code>comp</code> which has the 297: * specified name. 298: * 299: * @param name The name to search for 300: * @param comp The component to search the ancestors of 301: * 302: * @return The nearest ancestor of <code>comp</code> with the given 303: * name, or <code>null</code> if no such ancestor exists 304: * 305: * @see java.awt.Component#getName 306: * @see #getAncestorOfClass 307: */ 308: public static Container getAncestorNamed(String name, Component comp) 309: { 310: while (comp != null && (comp.getName() != name)) 311: comp = comp.getParent(); 312: return (Container) comp; 313: } 314: 315: /** 316: * Returns the least ancestor of <code>comp</code> which is an instance 317: * of the specified class. 318: * 319: * @param c The class to search for 320: * @param comp The component to search the ancestors of 321: * 322: * @return The nearest ancestor of <code>comp</code> which is an instance 323: * of the given class, or <code>null</code> if no such ancestor exists 324: * 325: * @see #getAncestorOfClass 326: * @see #windowForComponent 327: */ 328: public static Container getAncestorOfClass(Class<?> c, Component comp) 329: { 330: while (comp != null && (! c.isInstance(comp))) 331: comp = comp.getParent(); 332: return (Container) comp; 333: } 334: 335: /** 336: * Returns the first ancestor of <code>comp</code> that is a {@link Window} 337: * or <code>null</code> if <code>comp</code> is not contained in a 338: * {@link Window}. 339: * 340: * This is equivalent to calling 341: * <code>getAncestorOfClass(Window, comp)</code> or 342: * <code>windowForComponent(comp)</code>. 343: * 344: * @param comp the component for which we are searching the ancestor Window 345: * 346: * @return the first ancestor Window of <code>comp</code> or 347: * <code>null</code> if <code>comp</code> is not contained in a Window 348: */ 349: public static Window getWindowAncestor(Component comp) 350: { 351: return (Window) getAncestorOfClass(Window.class, comp); 352: } 353: 354: /** 355: * Equivalent to calling <code>getAncestorOfClass(Window, comp)</code>. 356: * 357: * @param comp The component to search for an ancestor window 358: * 359: * @return An ancestral window, or <code>null</code> if none exists 360: */ 361: public static Window windowForComponent(Component comp) 362: { 363: return (Window) getAncestorOfClass(Window.class, comp); 364: } 365: 366: /** 367: * Returns the "root" of the component tree containint <code>comp</code> 368: * The root is defined as either the <em>least</em> ancestor of 369: * <code>comp</code> which is a {@link Window}, or the <em>greatest</em> 370: * ancestor of <code>comp</code> which is a {@link Applet} if no {@link 371: * Window} ancestors are found. 372: * 373: * @param comp The component to search for a root 374: * 375: * @return The root of the component's tree, or <code>null</code> 376: */ 377: public static Component getRoot(Component comp) 378: { 379: Applet app = null; 380: Window win = null; 381: 382: while (comp != null) 383: { 384: if (win == null && comp instanceof Window) 385: win = (Window) comp; 386: else if (comp instanceof Applet) 387: app = (Applet) comp; 388: comp = comp.getParent(); 389: } 390: 391: if (win != null) 392: return win; 393: return app; 394: } 395: 396: /** 397: * Return true if a descends from b, in other words if b is an ancestor of a. 398: * 399: * @param a The child to search the ancestry of 400: * @param b The potential ancestor to search for 401: * @return true if a is a descendent of b, false otherwise 402: */ 403: public static boolean isDescendingFrom(Component a, Component b) 404: { 405: while (true) 406: { 407: if (a == null || b == null) 408: return false; 409: if (a == b) 410: return true; 411: a = a.getParent(); 412: } 413: } 414: 415: /** 416: * Returns the deepest descendent of parent which is both visible and 417: * contains the point <code>(x,y)</code>. Returns parent when either 418: * parent is not a container, or has no children which contain 419: * <code>(x,y)</code>. Returns <code>null</code> when either 420: * <code>(x,y)</code> is outside the bounds of parent, or parent is 421: * <code>null</code>. 422: * 423: * @param parent The component to search the descendents of 424: * @param x Horizontal coordinate to search for 425: * @param y Vertical coordinate to search for 426: * 427: * @return A component containing <code>(x,y)</code>, or 428: * <code>null</code> 429: * 430: * @see java.awt.Container#findComponentAt(int, int) 431: */ 432: public static Component getDeepestComponentAt(Component parent, int x, int y) 433: { 434: if (parent == null || (! parent.contains(x, y))) 435: return null; 436: 437: if (! (parent instanceof Container)) 438: return parent; 439: 440: Container c = (Container) parent; 441: return c.findComponentAt(x, y); 442: } 443: 444: /** 445: * Converts a point from a component's local coordinate space to "screen" 446: * coordinates (such as the coordinate space mouse events are delivered 447: * in). This operation is equivalent to translating the point by the 448: * location of the component (which is the origin of its coordinate 449: * space). 450: * 451: * @param p The point to convert 452: * @param c The component which the point is expressed in terms of 453: * 454: * @see #convertPointFromScreen 455: */ 456: public static void convertPointToScreen(Point p, Component c) 457: { 458: Point c0 = c.getLocationOnScreen(); 459: p.translate(c0.x, c0.y); 460: } 461: 462: /** 463: * Converts a point from "screen" coordinates (such as the coordinate 464: * space mouse events are delivered in) to a component's local coordinate 465: * space. This operation is equivalent to translating the point by the 466: * negation of the component's location (which is the origin of its 467: * coordinate space). 468: * 469: * @param p The point to convert 470: * @param c The component which the point should be expressed in terms of 471: */ 472: public static void convertPointFromScreen(Point p, Component c) 473: { 474: Point c0 = c.getLocationOnScreen(); 475: p.translate(-c0.x, -c0.y); 476: } 477: 478: /** 479: * Converts a point <code>(x,y)</code> from the coordinate space of one 480: * component to another. This is equivalent to converting the point from 481: * <code>source</code> space to screen space, then back from screen space 482: * to <code>destination</code> space. If exactly one of the two 483: * Components is <code>null</code>, it is taken to refer to the root 484: * ancestor of the other component. If both are <code>null</code>, no 485: * transformation is done. 486: * 487: * @param source The component which the point is expressed in terms of 488: * @param x Horizontal coordinate of point to transform 489: * @param y Vertical coordinate of point to transform 490: * @param destination The component which the return value will be 491: * expressed in terms of 492: * 493: * @return The point <code>(x,y)</code> converted from the coordinate space of the 494: * source component to the coordinate space of the destination component 495: * 496: * @see #convertPointToScreen 497: * @see #convertPointFromScreen 498: * @see #convertRectangle 499: * @see #getRoot 500: */ 501: public static Point convertPoint(Component source, int x, int y, 502: Component destination) 503: { 504: Point pt = new Point(x, y); 505: 506: if (source == null && destination == null) 507: return pt; 508: 509: if (source == null) 510: source = getRoot(destination); 511: 512: if (destination == null) 513: destination = getRoot(source); 514: 515: if (source.isShowing() && destination.isShowing()) 516: { 517: convertPointToScreen(pt, source); 518: convertPointFromScreen(pt, destination); 519: } 520: 521: return pt; 522: } 523: 524: public static Point convertPoint(Component source, Point aPoint, Component destination) 525: { 526: return convertPoint(source, aPoint.x, aPoint.y, destination); 527: } 528: 529: /** 530: * Converts a rectangle from the coordinate space of one component to 531: * another. This is equivalent to converting the rectangle from 532: * <code>source</code> space to screen space, then back from screen space 533: * to <code>destination</code> space. If exactly one of the two 534: * Components is <code>null</code>, it is taken to refer to the root 535: * ancestor of the other component. If both are <code>null</code>, no 536: * transformation is done. 537: * 538: * @param source The component which the rectangle is expressed in terms of 539: * @param rect The rectangle to convert 540: * @param destination The component which the return value will be 541: * expressed in terms of 542: * 543: * @return A new rectangle, equal in size to the input rectangle, but 544: * with its position converted from the coordinate space of the source 545: * component to the coordinate space of the destination component 546: * 547: * @see #convertPointToScreen 548: * @see #convertPointFromScreen 549: * @see #convertPoint(Component, int, int, Component) 550: * @see #getRoot 551: */ 552: public static Rectangle convertRectangle(Component source, 553: Rectangle rect, 554: Component destination) 555: { 556: Point pt = convertPoint(source, rect.x, rect.y, destination); 557: return new Rectangle(pt.x, pt.y, rect.width, rect.height); 558: } 559: 560: /** 561: * Convert a mouse event which refrers to one component to another. This 562: * includes changing the mouse event's coordinate space, as well as the 563: * source property of the event. If <code>source</code> is 564: * <code>null</code>, it is taken to refer to <code>destination</code>'s 565: * root component. If <code>destination</code> is <code>null</code>, the 566: * new event will remain expressed in <code>source</code>'s coordinate 567: * system. 568: * 569: * @param source The component the mouse event currently refers to 570: * @param sourceEvent The mouse event to convert 571: * @param destination The component the new mouse event should refer to 572: * 573: * @return A new mouse event expressed in terms of the destination 574: * component's coordinate space, and with the destination component as 575: * its source 576: * 577: * @see #convertPoint(Component, int, int, Component) 578: */ 579: public static MouseEvent convertMouseEvent(Component source, 580: MouseEvent sourceEvent, 581: Component destination) 582: { 583: Point newpt = convertPoint(source, sourceEvent.getX(), sourceEvent.getY(), 584: destination); 585: 586: return new MouseEvent(destination, sourceEvent.getID(), 587: sourceEvent.getWhen(), sourceEvent.getModifiersEx(), 588: newpt.x, newpt.y, sourceEvent.getClickCount(), 589: sourceEvent.isPopupTrigger(), sourceEvent.getButton()); 590: } 591: 592: /** 593: * Recursively walk the component tree under <code>comp</code> calling 594: * <code>updateUI</code> on each {@link JComponent} found. This causes 595: * the entire tree to re-initialize its UI delegates. 596: * 597: * @param comp The component to walk the children of, calling <code>updateUI</code> 598: */ 599: public static void updateComponentTreeUI(Component comp) 600: { 601: updateComponentTreeUIImpl(comp); 602: if (comp instanceof JComponent) 603: { 604: JComponent jc = (JComponent) comp; 605: jc.revalidate(); 606: } 607: else 608: { 609: comp.invalidate(); 610: comp.validate(); 611: } 612: comp.repaint(); 613: } 614: 615: /** 616: * Performs the actual work for {@link #updateComponentTreeUI(Component)}. 617: * This calls updateUI() on c if it is a JComponent, and then walks down 618: * the component tree and calls this method on each child component. 619: * 620: * @param c the component to update the UI 621: */ 622: private static void updateComponentTreeUIImpl(Component c) 623: { 624: if (c instanceof JComponent) 625: { 626: JComponent jc = (JComponent) c; 627: jc.updateUI(); 628: } 629: 630: Component[] components = null; 631: if (c instanceof JMenu) 632: components = ((JMenu) c).getMenuComponents(); 633: else if (c instanceof Container) 634: components = ((Container) c).getComponents(); 635: if (components != null) 636: { 637: for (int i = 0; i < components.length; ++i) 638: updateComponentTreeUIImpl(components[i]); 639: } 640: } 641: 642: /** 643: * <p>Layout a "compound label" consisting of a text string and an icon 644: * which is to be placed near the rendered text. Once the text and icon 645: * are laid out, the text rectangle and icon rectangle parameters are 646: * altered to store the calculated positions.</p> 647: * 648: * <p>The size of the text is calculated from the provided font metrics 649: * object. This object should be the metrics of the font you intend to 650: * paint the label with.</p> 651: * 652: * <p>The position values control where the text is placed relative to 653: * the icon. The horizontal position value should be one of the constants 654: * <code>LEADING</code>, <code>TRAILING</code>, <code>LEFT</code>, 655: * <code>RIGHT</code> or <code>CENTER</code>. The vertical position value 656: * should be one fo the constants <code>TOP</code>, <code>BOTTOM</code> 657: * or <code>CENTER</code>.</p> 658: * 659: * <p>The text-icon gap value controls the number of pixels between the 660: * icon and the text.</p> 661: * 662: * <p>The alignment values control where the text and icon are placed, as 663: * a combined unit, within the view rectangle. The horizontal alignment 664: * value should be one of the constants <code>LEADING</code>, 665: * <code>TRAILING</code>, <code>LEFT</code>, <code>RIGHT</code> or 666: * <code>CENTER</code>. The vertical alignment valus should be one of the 667: * constants <code>TOP</code>, <code>BOTTOM</code> or 668: * <code>CENTER</code>.</p> 669: * 670: * <p>If the <code>LEADING</code> or <code>TRAILING</code> constants are 671: * given for horizontal alignment or horizontal text position, they are 672: * interpreted relative to the provided component's orientation property, 673: * a constant in the {@link java.awt.ComponentOrientation} class. For 674: * example, if the component's orientation is <code>LEFT_TO_RIGHT</code>, 675: * then the <code>LEADING</code> value is a synonym for <code>LEFT</code> 676: * and the <code>TRAILING</code> value is a synonym for 677: * <code>RIGHT</code></p> 678: * 679: * <p>If the text and icon are equal to or larger than the view 680: * rectangle, the horizontal and vertical alignment values have no 681: * affect.</p> 682: * 683: * @param c A component used for its orientation value 684: * @param fm The font metrics used to measure the text 685: * @param text The text to place in the compound label 686: * @param icon The icon to place next to the text 687: * @param verticalAlignment The vertical alignment of the label relative 688: * to its component 689: * @param horizontalAlignment The horizontal alignment of the label 690: * relative to its component 691: * @param verticalTextPosition The vertical position of the label's text 692: * relative to its icon 693: * @param horizontalTextPosition The horizontal position of the label's 694: * text relative to its icon 695: * @param viewR The view rectangle, specifying the area which layout is 696: * constrained to 697: * @param iconR A rectangle which is modified to hold the laid-out 698: * position of the icon 699: * @param textR A rectangle which is modified to hold the laid-out 700: * position of the text 701: * @param textIconGap The distance between text and icon 702: * 703: * @return The string of characters, possibly truncated with an elipsis, 704: * which is laid out in this label 705: */ 706: 707: public static String layoutCompoundLabel(JComponent c, 708: FontMetrics fm, 709: String text, 710: Icon icon, 711: int verticalAlignment, 712: int horizontalAlignment, 713: int verticalTextPosition, 714: int horizontalTextPosition, 715: Rectangle viewR, 716: Rectangle iconR, 717: Rectangle textR, 718: int textIconGap) 719: { 720: 721: // Fix up the orientation-based horizontal positions. 722: 723: boolean ltr = true; 724: if (c != null && ! c.getComponentOrientation().isLeftToRight()) 725: ltr = false; 726: 727: switch (horizontalTextPosition) 728: { 729: case LEADING: 730: horizontalTextPosition = ltr ? LEFT : RIGHT; 731: break; 732: case TRAILING: 733: horizontalTextPosition = ltr ? RIGHT : LEFT; 734: break; 735: default: 736: // Nothing to do in the other cases. 737: } 738: 739: // Fix up the orientation-based alignments. 740: switch (horizontalAlignment) 741: { 742: case LEADING: 743: horizontalAlignment = ltr ? LEFT : RIGHT; 744: break; 745: case TRAILING: 746: horizontalAlignment = ltr ? RIGHT : LEFT; 747: break; 748: default: 749: // Nothing to do in the other cases. 750: } 751: 752: return layoutCompoundLabelImpl(c, fm, text, icon, 753: verticalAlignment, 754: horizontalAlignment, 755: verticalTextPosition, 756: horizontalTextPosition, 757: viewR, iconR, textR, textIconGap); 758: } 759: 760: /** 761: * <p>Layout a "compound label" consisting of a text string and an icon 762: * which is to be placed near the rendered text. Once the text and icon 763: * are laid out, the text rectangle and icon rectangle parameters are 764: * altered to store the calculated positions.</p> 765: * 766: * <p>The size of the text is calculated from the provided font metrics 767: * object. This object should be the metrics of the font you intend to 768: * paint the label with.</p> 769: * 770: * <p>The position values control where the text is placed relative to 771: * the icon. The horizontal position value should be one of the constants 772: * <code>LEFT</code>, <code>RIGHT</code> or <code>CENTER</code>. The 773: * vertical position value should be one fo the constants 774: * <code>TOP</code>, <code>BOTTOM</code> or <code>CENTER</code>.</p> 775: * 776: * <p>The text-icon gap value controls the number of pixels between the 777: * icon and the text.</p> 778: * 779: * <p>The alignment values control where the text and icon are placed, as 780: * a combined unit, within the view rectangle. The horizontal alignment 781: * value should be one of the constants <code>LEFT</code>, <code>RIGHT</code> or 782: * <code>CENTER</code>. The vertical alignment valus should be one of the 783: * constants <code>TOP</code>, <code>BOTTOM</code> or 784: * <code>CENTER</code>.</p> 785: * 786: * <p>If the text and icon are equal to or larger than the view 787: * rectangle, the horizontal and vertical alignment values have no 788: * affect.</p> 789: * 790: * <p>Note that this method does <em>not</em> know how to deal with 791: * horizontal alignments or positions given as <code>LEADING</code> or 792: * <code>TRAILING</code> values. Use the other overloaded variant of this 793: * method if you wish to use such values. 794: * 795: * @param fm The font metrics used to measure the text 796: * @param text The text to place in the compound label 797: * @param icon The icon to place next to the text 798: * @param verticalAlignment The vertical alignment of the label relative 799: * to its component 800: * @param horizontalAlignment The horizontal alignment of the label 801: * relative to its component 802: * @param verticalTextPosition The vertical position of the label's text 803: * relative to its icon 804: * @param horizontalTextPosition The horizontal position of the label's 805: * text relative to its icon 806: * @param viewR The view rectangle, specifying the area which layout is 807: * constrained to 808: * @param iconR A rectangle which is modified to hold the laid-out 809: * position of the icon 810: * @param textR A rectangle which is modified to hold the laid-out 811: * position of the text 812: * @param textIconGap The distance between text and icon 813: * 814: * @return The string of characters, possibly truncated with an elipsis, 815: * which is laid out in this label 816: */ 817: 818: public static String layoutCompoundLabel(FontMetrics fm, 819: String text, 820: Icon icon, 821: int verticalAlignment, 822: int horizontalAlignment, 823: int verticalTextPosition, 824: int horizontalTextPosition, 825: Rectangle viewR, 826: Rectangle iconR, 827: Rectangle textR, 828: int textIconGap) 829: { 830: return layoutCompoundLabelImpl(null, fm, text, icon, verticalAlignment, 831: horizontalAlignment, verticalTextPosition, 832: horizontalTextPosition, viewR, iconR, textR, 833: textIconGap); 834: } 835: 836: /** 837: * <p>Layout a "compound label" consisting of a text string and an icon 838: * which is to be placed near the rendered text. Once the text and icon 839: * are laid out, the text rectangle and icon rectangle parameters are 840: * altered to store the calculated positions.</p> 841: * 842: * <p>The size of the text is calculated from the provided font metrics 843: * object. This object should be the metrics of the font you intend to 844: * paint the label with.</p> 845: * 846: * <p>The position values control where the text is placed relative to 847: * the icon. The horizontal position value should be one of the constants 848: * <code>LEFT</code>, <code>RIGHT</code> or <code>CENTER</code>. The 849: * vertical position value should be one fo the constants 850: * <code>TOP</code>, <code>BOTTOM</code> or <code>CENTER</code>.</p> 851: * 852: * <p>The text-icon gap value controls the number of pixels between the 853: * icon and the text.</p> 854: * 855: * <p>The alignment values control where the text and icon are placed, as 856: * a combined unit, within the view rectangle. The horizontal alignment 857: * value should be one of the constants <code>LEFT</code>, <code>RIGHT</code> or 858: * <code>CENTER</code>. The vertical alignment valus should be one of the 859: * constants <code>TOP</code>, <code>BOTTOM</code> or 860: * <code>CENTER</code>.</p> 861: * 862: * <p>If the text and icon are equal to or larger than the view 863: * rectangle, the horizontal and vertical alignment values have no 864: * affect.</p> 865: * 866: * <p>Note that this method does <em>not</em> know how to deal with 867: * horizontal alignments or positions given as <code>LEADING</code> or 868: * <code>TRAILING</code> values. Use the other overloaded variant of this 869: * method if you wish to use such values. 870: * 871: * @param fm The font metrics used to measure the text 872: * @param text The text to place in the compound label 873: * @param icon The icon to place next to the text 874: * @param verticalAlignment The vertical alignment of the label relative 875: * to its component 876: * @param horizontalAlignment The horizontal alignment of the label 877: * relative to its component 878: * @param verticalTextPosition The vertical position of the label's text 879: * relative to its icon 880: * @param horizontalTextPosition The horizontal position of the label's 881: * text relative to its icon 882: * @param viewR The view rectangle, specifying the area which layout is 883: * constrained to 884: * @param